Signed-off-by: Olga Krishtal <okrishtal(a)virtuozzo.com>
---
m4/virt-driver-fspool.m4 | 14 ++-
po/POTFILES.in | 1 +
src/Makefile.am | 10 +-
src/fs/fs_backend_dir.c | 290 +++++++++++++++++++++++++++++++++++++++++++++++
src/fs/fs_backend_dir.h | 8 ++
src/fs/fs_driver.c | 10 +-
6 files changed, 328 insertions(+), 5 deletions(-)
create mode 100644 src/fs/fs_backend_dir.c
create mode 100644 src/fs/fs_backend_dir.h
diff --git a/m4/virt-driver-fspool.m4 b/m4/virt-driver-fspool.m4
index 634cb7f..2507879 100644
--- a/m4/virt-driver-fspool.m4
+++ b/m4/virt-driver-fspool.m4
@@ -17,17 +17,27 @@ dnl
AC_DEFUN([LIBVIRT_DRIVER_CHECK_FSPOOL],[
AC_ARG_WITH([fs],
- [AS_HELP_STRING([--with-fs],
+ [AS_HELP_STRING([--with-fs-dir],
[add FS driver @<:@default=check@:>@])])
- m4_divert_text([DEFAULTS], [with_fs=check])
+ m4_divert_text([DEFAULTS], [with_fs_dir=check])
if test "$with_fs" = "yes"; then
AC_DEFINE_UNQUOTED([WITH_FS], 1,
[whether fs driver is enabled])
fi
+
+ if test "$with_fs_dir" = "yes"; then
+ AC_DEFINE_UNQUOTED([WITH_FS], 1,
+ [whether fs driver is enabled])
+ AC_DEFINE_UNQUOTED([WITH_FS_DIR], 1,
+ [whether fs directory backend is enabled])
+ fi
+
AM_CONDITIONAL([WITH_FS], [test "$with_fs" = "yes"])
+ AM_CONDITIONAL([WITH_FS_DIR], [test "$with_fs_dir" = "yes"])
])
AC_DEFUN([LIBVIRT_DRIVER_RESULT_FSPOOL],[
AC_MSG_NOTICE([ FSPool: $with_fs])
+ AC_MSG_NOTICE([FSPool dir: $with_fs_dir])
])
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 942e099..cdb6296 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -60,6 +60,7 @@ src/esx/esx_vi.c
src/esx/esx_vi_methods.c
src/esx/esx_vi_types.c
src/fdstream.c
+src/fs/fs_backend_dir.c
src/fs/fs_driver.c
src/hyperv/hyperv_driver.c
src/hyperv/hyperv_util.c
diff --git a/src/Makefile.am b/src/Makefile.am
index d18d3f4..10e1161 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1119,6 +1119,10 @@ FS_DRIVER_SOURCES = \
fs/fs_driver.h fs/fs_driver.c \
fs/fs_backend.h
+FS_DRIVER_DIR_SOURCES = \
+ fs/fs_backend_dir.h fs/fs_backend_dir.c
+
+
pkgdata_DATA = cpu/cpu_map.xml
EXTRA_DIST += $(pkgdata_DATA)
@@ -1665,6 +1669,7 @@ noinst_LTLIBRARIES += libvirt_driver_fs.la
#libvirt_la_BUILT_LIBADD += libvirt_driver_fs.la
endif ! WITH_DRIVER_MODULES
libvirt_driver_fs_impl_la_SOURCES += $(FS_DRIVER_SOURCES)
+libvirt_driver_fs_impl_la_SOURCES += $(FS_DRIVER_DIR_SOURCES)
endif WITH_FS
# Needed to keep automake quiet about conditionals
@@ -1938,8 +1943,9 @@ EXTRA_DIST += \
$(BHYVE_DRIVER_SOURCES) \
$(NETWORK_DRIVER_SOURCES) \
$(INTERFACE_DRIVER_SOURCES) \
- $(FS_DRIVER_SOURCES) \
- $(STORAGE_DRIVER_SOURCES) \
+ $(FS_DRIVER_SOURCES) \
+ $(FS_DRIVER_DIR_SOURCES) \
+ $(STORAGE_DRIVER_SOURCES) \
$(STORAGE_DRIVER_FS_SOURCES) \
$(STORAGE_DRIVER_LVM_SOURCES) \
$(STORAGE_DRIVER_ISCSI_SOURCES) \
diff --git a/src/fs/fs_backend_dir.c b/src/fs/fs_backend_dir.c
new file mode 100644
index 0000000..814c2cb
--- /dev/null
+++ b/src/fs/fs_backend_dir.c
@@ -0,0 +1,290 @@
+/*
+ * fs_backend_dir.c: file system backend implementation
+ * Author: Olga Krishtal <okrishtal(a)virtuozzo.com>
+ *
+ * Copyright (C) 2016 Parallels IP Holdings GmbH
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see
+ * <
http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+
+#include <sys/statvfs.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdio.h>
+#include <dirent.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <string.h>
+
+#include <libxml/parser.h>
+#include <libxml/tree.h>
+#include <libxml/xpath.h>
+
+#include "virerror.h"
+#include "fs_backend_dir.h"
+#include "fs_conf.h"
+#include "vircommand.h"
+#include "viralloc.h"
+#include "virxml.h"
+#include "virfile.h"
+#include "virpoolcommon.h"
+#include "virlog.h"
+#include "virstring.h"
+#include "fdstream.h"
+#include "stat-time.h"
+
+#define VIR_FROM_THIS VIR_FROM_FSPOOL
+
+VIR_LOG_INIT("fs.fs_backend_dir");
+
+static int
+virFSDirBuild(virConnectPtr conn ATTRIBUTE_UNUSED,
+ virFSPoolObjPtr fspool,
+ unsigned int flags)
+{
+
+ virCheckFlags(VIR_STORAGE_POOL_BUILD_OVERWRITE |
+ VIR_STORAGE_POOL_BUILD_NO_OVERWRITE, -1);
+ return virDirPoolBuild(fspool->def, false);
+
+}
+
+static int
+virFSDirRefresh(virConnectPtr conn ATTRIBUTE_UNUSED,
+ virFSPoolObjPtr fspool)
+{
+ DIR *dir;
+ struct dirent *entry;
+ virFSItemDefPtr item = NULL;
+ struct statvfs sb;
+ struct stat statbuf;
+ int fd = 0;
+ int ret = -1;
+
+ if (virDirOpen(&dir, fspool->def->target.path) < 0)
+ goto cleanup;
+
+ while (virDirRead(dir, &entry, fspool->def->target.path) > 0) {
+ if (virStringHasControlChars(entry->d_name)) {
+ VIR_WARN("Ignoring control characters under '%s'",
+ fspool->def->target.path);
+ continue;
+ }
+
+ if (VIR_ALLOC(item) < 0)
+ goto cleanup;
+
+ if (VIR_STRDUP(item->name, entry->d_name) < 0)
+ goto cleanup;
+ item->type = VIR_FSITEM_DIR;
+ if (virAsprintf(&item->target.path, "%s/%s",
+ fspool->def->target.path,
+ item->name) == -1)
+ goto cleanup;
+
+ if (VIR_STRDUP(item->key, item->target.path) < 0)
+ goto cleanup;
+
+
+ if (VIR_APPEND_ELEMENT(fspool->items.objs, fspool->items.count, item) <
0)
+ goto cleanup;
+ }
+
+
+ if ((fd = open(fspool->def->target.path, O_RDONLY)) < 0) {
+ virReportSystemError(errno,
+ _("cannot open path '%s'"),
+ fspool->def->target.path);
+ goto cleanup;
+ }
+
+ if (fstat(fd, &statbuf) < 0) {
+ virReportSystemError(errno,
+ _("cannot stat path '%s'"),
+ fspool->def->target.path);
+ goto cleanup;
+ }
+
+ fspool->def->target.perms.mode = statbuf.st_mode & S_IRWXUGO;
+ fspool->def->target.perms.uid = statbuf.st_uid;
+ fspool->def->target.perms.gid = statbuf.st_gid;
+
+ if (statvfs(fspool->def->target.path, &sb) < 0) {
+ virReportSystemError(errno,
+ _("cannot statvfs path '%s'"),
+ fspool->def->target.path);
+ goto cleanup;
+ }
+
+ fspool->def->capacity = ((unsigned long long)sb.f_blocks *
+ (unsigned long long)sb.f_frsize);
+ fspool->def->available = ((unsigned long long)sb.f_bfree *
+ (unsigned long long)sb.f_frsize);
+ fspool->def->allocation = fspool->def->capacity -
fspool->def->available;
+
+ ret = 0;
+
+ cleanup:
+ VIR_DIR_CLOSE(dir);
+ VIR_FORCE_CLOSE(fd);
+ virFSItemDefFree(item);
+ if (ret < 0)
+ virFSPoolObjClearItems(fspool);
+ return ret;
+}
+
+static int
+virFSDirDelete(virConnectPtr conn ATTRIBUTE_UNUSED,
+ virFSPoolObjPtr fspool,
+ unsigned int flags)
+{
+ virCheckFlags(0, -1);
+ return virDirPoolDelete(fspool->def->target.path);
+
+}
+
+static int
+virFSDirItemBuild(virConnectPtr conn ATTRIBUTE_UNUSED,
+ virFSPoolObjPtr fspool ATTRIBUTE_UNUSED,
+ virFSItemDefPtr item,
+ unsigned int flags)
+{
+ virCheckFlags(0, -1);
+
+ if (item->type == VIR_FSITEM_DIR) {
+ if ((virDirCreate(item->target.path,
+ (item->target.perms->mode == (mode_t) -1 ?
+ VIR_FS_DEFAULT_ITEM_PERM_MODE:
+ item->target.perms->mode),
+ item->target.perms->uid,
+ item->target.perms->gid,
+ 0)) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("error creating item"));
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+static int
+virFSDirItemBuildFrom(virConnectPtr conn ATTRIBUTE_UNUSED,
+ virFSPoolObjPtr fspool ATTRIBUTE_UNUSED,
+ virFSItemDefPtr item,
+ virFSItemDefPtr inputitem,
+ unsigned int flags)
+{
+ virCommandPtr cmd = NULL;
+ int ret = -1;
+
+ virCheckFlags(0, -1);
+
+ item->target.capacity = inputitem->target.capacity;
+ cmd = virCommandNewArgList("cp", "-r",
inputitem->target.path,
+ item->target.path, NULL);
+ ret = virCommandRun(cmd, NULL);
+
+ virCommandFree(cmd);
+ return ret;
+}
+
+static int
+virFSDirItemCreate(virConnectPtr conn ATTRIBUTE_UNUSED,
+ virFSPoolObjPtr fspool,
+ virFSItemDefPtr item)
+{
+ VIR_FREE(item->target.path);
+ if (virDirItemCreate(item->name, &item->target.path,
+ fspool->def->target.path) < 0)
+ return -1;
+
+ VIR_FREE(item->key);
+ return VIR_STRDUP(item->key, item->target.path);
+}
+
+
+static int
+virFSDirItemRefresh(virConnectPtr conn ATTRIBUTE_UNUSED,
+ virFSPoolObjPtr fspool ATTRIBUTE_UNUSED,
+ virFSItemDefPtr item)
+{
+ int fd;
+ int ret = -1;
+ struct stat statbuf;
+ virCommandPtr cmd = NULL;
+ char *output = NULL, *end;
+
+ if ((fd = open(item->target.path, O_RDONLY)) < 0) {
+ virReportSystemError(errno, _("cannot open directory '%s'"),
+ item->target.path);
+ return -1;
+ }
+ if (fstat(fd, &statbuf) < 0) {
+ virReportSystemError(errno, _("cannot stat path '%s'"),
+ item->target.path);
+ goto cleanup;
+ }
+
+ cmd = virCommandNewArgList("du", "-sB1", item->target.path,
NULL);
+ virCommandSetOutputBuffer(cmd, &output);
+ if ((ret = virCommandRun(cmd, NULL)) < 0)
+ goto cleanup;
+
+ if (virStrToLong_ull(output, &end, 10, &item->target.allocation) < 0)
{
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Malformed du output: %s"), output);
+ goto cleanup;
+ }
+
+ if (&(item->target.perms) && VIR_ALLOC(*(&item->target.perms))
< 0)
+ goto cleanup;
+ item->target.perms->mode = statbuf.st_mode & S_IRWXUGO;
+ item->target.perms->uid = statbuf.st_uid;
+ item->target.perms->gid = statbuf.st_gid;
+
+ ret = 0;
+ cleanup:
+ VIR_FORCE_CLOSE(fd);
+ VIR_FREE(output);
+ virCommandFree(cmd);
+ return ret;
+}
+
+static int
+virFSDirItemDelete(virConnectPtr conn ATTRIBUTE_UNUSED,
+ virFSPoolObjPtr fspool ATTRIBUTE_UNUSED,
+ virFSItemDefPtr item,
+ unsigned int flags)
+{
+ virCheckFlags(0, -1);
+ return virFileDeleteTree(item->target.path);
+}
+
+virFSBackend virFSBackendDir = {
+ .type = VIR_FSPOOL_DIR,
+
+ .buildFSpool = virFSDirBuild,
+ .refreshFSpool = virFSDirRefresh,
+ .deleteFSpool = virFSDirDelete,
+ .buildItem = virFSDirItemBuild,
+ .buildItemFrom = virFSDirItemBuildFrom,
+ .createItem = virFSDirItemCreate,
+ .deleteItem = virFSDirItemDelete,
+ .refreshItem = virFSDirItemRefresh,
+};
diff --git a/src/fs/fs_backend_dir.h b/src/fs/fs_backend_dir.h
new file mode 100644
index 0000000..335e008
--- /dev/null
+++ b/src/fs/fs_backend_dir.h
@@ -0,0 +1,8 @@
+#ifndef __VIR_FS_BACKEND_DIR_H__
+# define __VIR_FS_BACKEND_DIR_H__
+
+# include "fs_backend.h"
+
+extern virFSBackend virFSBackendDir;
+
+#endif /* __VIR_FS_BACKEND_DIR_H__ */
diff --git a/src/fs/fs_driver.c b/src/fs/fs_driver.c
index f913ce5..b566893 100644
--- a/src/fs/fs_driver.c
+++ b/src/fs/fs_driver.c
@@ -48,6 +48,10 @@
#include "viraccessapicheck.h"
#include "dirname.h"
+#if WITH_FS_DIR
+# include "fs_backend_dir.h"
+#endif
+
#define VIR_FROM_THIS VIR_FROM_FSPOOL
VIR_LOG_INIT("fs.fs_driver");
@@ -65,7 +69,11 @@ static void fsDriverUnlock(void)
virMutexUnlock(&driver->lock);
}
-static virFSBackendPtr backends[] = {};
+static virFSBackendPtr backends[] = {
+#if WITH_FS_DIR
+ &virFSBackendDir,
+#endif
+};
static virFSBackendPtr
virFSBackendForType(int type)
--
1.8.3.1