Signed-off-by: Olga Krishtal <okrishtal@xxxxxxxxxxxxx> --- 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@xxxxxxxxxxxxx> + * + * 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 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list