[libvirt] [PATCH RFC v3 14/15] FSPool: directory backend inplementation

Olga Krishtal okrishtal at virtuozzo.com
Fri Dec 2 15:38:19 UTC 2016


Signed-off-by: Olga Krishtal <okrishtal at 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 at 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




More information about the libvir-list mailing list