[libvirt] [PATCH 2/3] storage: Add fs pool formatting
Daniel Veillard
veillard at redhat.com
Fri Sep 2 11:15:55 UTC 2011
On Wed, Aug 31, 2011 at 10:34:47PM +0800, Osier Yang wrote:
> This patch adds the ability to make the filesystem for a filesystem
> pool during a pool build.
>
> The patch adds two new flags, no overwrite and overwrite, to control
> when mkfs gets executed. By default, the patch preserves the
> current behavior, i.e., if no flags are specified, pool build on a
> filesystem pool only makes the directory on which the filesystem
> will be mounted.
>
> If the no overwrite flag is specified, the target device is checked
> to determine if a filesystem of the type specified in the pool is
> present. If a filesystem of that type is already present, mkfs is
> not executed and the build call returns an error. Otherwise, mkfs
> is executed and any data present on the device is overwritten.
>
> If the overwrite flag is specified, mkfs is always executed, and any
> existing data on the target device is overwritten unconditionally.
> ---
> include/libvirt/libvirt.h.in | 6 +-
> include/libvirt/virterror.h | 2 +
> src/Makefile.am | 4 +
> src/libvirt.c | 4 +
> src/storage/storage_backend_fs.c | 188 +++++++++++++++++++++++++++++++++++++-
> src/storage/storage_backend_fs.h | 5 +
> src/util/virterror.c | 12 +++
> 7 files changed, 215 insertions(+), 6 deletions(-)
>
> diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in
> index c51a5b9..92e1d62 100644
> --- a/include/libvirt/libvirt.h.in
> +++ b/include/libvirt/libvirt.h.in
> @@ -1666,8 +1666,10 @@ typedef enum {
>
> typedef enum {
> VIR_STORAGE_POOL_BUILD_NEW = 0, /* Regular build from scratch */
> - VIR_STORAGE_POOL_BUILD_REPAIR = 1, /* Repair / reinitialize */
> - VIR_STORAGE_POOL_BUILD_RESIZE = 2 /* Extend existing pool */
> + VIR_STORAGE_POOL_BUILD_REPAIR = (1 << 0), /* Repair / reinitialize */
> + VIR_STORAGE_POOL_BUILD_RESIZE = (1 << 1), /* Extend existing pool */
> + VIR_STORAGE_POOL_BUILD_NO_OVERWRITE = (1 << 2), /* Do not overwrite existing pool */
> + VIR_STORAGE_POOL_BUILD_OVERWRITE = (1 << 3), /* Overwrite data */
> } virStoragePoolBuildFlags;
>
> typedef enum {
> diff --git a/include/libvirt/virterror.h b/include/libvirt/virterror.h
> index c270b54..0aae622 100644
> --- a/include/libvirt/virterror.h
> +++ b/include/libvirt/virterror.h
> @@ -235,6 +235,8 @@ typedef enum {
> VIR_ERR_INVALID_STREAM = 73, /* stream pointer not valid */
> VIR_ERR_ARGUMENT_UNSUPPORTED = 74, /* valid API use but unsupported by
> the given driver */
> + VIR_ERR_STORAGE_PROBE_FAILED = 75, /* storage pool proble failed */
> + VIR_ERR_STORAGE_POOL_BUILT = 76, /* storage pool already built */
> } virErrorNumber;
>
> /**
> diff --git a/src/Makefile.am b/src/Makefile.am
> index 322c900..14f09e4 100644
> --- a/src/Makefile.am
> +++ b/src/Makefile.am
> @@ -954,6 +954,10 @@ endif
> if WITH_SECDRIVER_APPARMOR
> libvirt_driver_storage_la_LIBADD += $(APPARMOR_LIBS)
> endif
> +if HAVE_LIBBLKID
> +libvirt_driver_storage_la_CFLAGS += $(BLKID_CFLAGS)
> +libvirt_driver_storage_la_LIBADD += $(BLKID_LIBS)
> +endif
> if WITH_STORAGE_DIR
> if WITH_DRIVER_MODULES
> mod_LTLIBRARIES += libvirt_driver_storage.la
> diff --git a/src/libvirt.c b/src/libvirt.c
> index e4a21b6..b876b1c 100644
> --- a/src/libvirt.c
> +++ b/src/libvirt.c
> @@ -10466,6 +10466,10 @@ error:
> * virStoragePoolBuild:
> * @pool: pointer to storage pool
> * @flags: future flags, use 0 for now
> + * @flags: flags to control pool build behaviour
> + *
> + * Currently only filesystem pool accepts flags VIR_STORAGE_POOL_BUILD_OVERWRITE
> + * and VIR_STORAGE_POOL_BUILD_NO_OVERWRITE.
> *
> * Build the underlying storage pool
> *
> diff --git a/src/storage/storage_backend_fs.c b/src/storage/storage_backend_fs.c
> index 4f53d3f..36f1c60 100644
> --- a/src/storage/storage_backend_fs.c
> +++ b/src/storage/storage_backend_fs.c
> @@ -37,6 +37,10 @@
> #include <libxml/tree.h>
> #include <libxml/xpath.h>
>
> +#if HAVE_LIBBLKID
> +# include <blkid/blkid.h>
> +#endif
> +
> #include "virterror_internal.h"
> #include "storage_backend_fs.h"
> #include "storage_conf.h"
> @@ -45,6 +49,7 @@
> #include "memory.h"
> #include "xml.h"
> #include "virfile.h"
> +#include "logging.h"
>
> #define VIR_FROM_THIS VIR_FROM_STORAGE
>
> @@ -534,13 +539,172 @@ virStorageBackendFileSystemStart(virConnectPtr conn ATTRIBUTE_UNUSED,
> }
> #endif /* WITH_STORAGE_FS */
>
> +#if HAVE_LIBBLKID
> +static virStoragePoolProbeResult
> +virStorageBackendFileSystemProbe(const char *device,
> + const char *format) {
> +
> + virStoragePoolProbeResult ret = FILESYSTEM_PROBE_ERROR;
> + blkid_probe probe = NULL;
> + const char *fstype = NULL;
> + char *names[2], *libblkid_format = NULL;
> +
> + VIR_DEBUG("Probing for existing filesystem of type %s on device %s",
> + format, device);
> +
> + if (blkid_known_fstype(format) == 0) {
> + virStorageReportError(VIR_ERR_STORAGE_PROBE_FAILED,
> + _("Not capable of probing for "
> + "filesystem of type %s"),
> + format);
> + goto error;
> + }
> +
> + probe = blkid_new_probe_from_filename(device);
> + if (probe == NULL) {
> + virStorageReportError(VIR_ERR_STORAGE_PROBE_FAILED,
> + _("Failed to create filesystem probe "
> + "for device %s"),
> + device);
> + goto error;
> + }
> +
> + if ((libblkid_format = strdup(format)) == NULL) {
> + virReportOOMError();
> + goto error;
> + }
> +
> + names[0] = libblkid_format;
> + names[1] = NULL;
> +
> + blkid_probe_filter_superblocks_type(probe,
> + BLKID_FLTR_ONLYIN,
> + names);
> +
> + if (blkid_do_probe(probe) != 0) {
> + VIR_INFO("No filesystem of type '%s' found on device '%s'",
> + format, device);
> + ret = FILESYSTEM_PROBE_NOT_FOUND;
> + } else if (blkid_probe_lookup_value(probe, "TYPE", &fstype, NULL) == 0) {
> + virStorageReportError(VIR_ERR_STORAGE_POOL_BUILT,
> + _("Existing filesystem of type '%s' found on "
> + "device '%s'"),
> + fstype, device);
> + ret = FILESYSTEM_PROBE_FOUND;
> + }
> +
> + if (blkid_do_probe(probe) != 1) {
> + virStorageReportError(VIR_ERR_STORAGE_PROBE_FAILED,
> + _("Found additional probes to run, "
> + "filesystem probing may be incorrect"));
> + ret = FILESYSTEM_PROBE_ERROR;
> + }
> +
> +error:
> + VIR_FREE(libblkid_format);
> +
> + if (probe != NULL) {
> + blkid_free_probe(probe);
> + }
> +
> + return ret;
> +}
> +
> +#else /* #if HAVE_LIBBLKID */
> +
> +static virStoragePoolProbeResult
> +virStorageBackendFileSystemProbe(const char *device ATTRIBUTE_UNUSED,
> + const char *format ATTRIBUTE_UNUSED)
> +{
> + virStorageReportError(VIR_ERR_OPERATION_INVALID,
> + _("probing for filesystems is unsupported "
> + "by this build"));
> +
> + return FILESYSTEM_PROBE_ERROR;
> +}
> +
> +#endif /* #if HAVE_LIBBLKID */
> +
> +static int
> +virStorageBackendExecuteMKFS(const char *device,
> + const char *format)
> +{
> + int ret = 0;
> + virCommandPtr cmd = NULL;
> +
> + cmd = virCommandNewArgList(MKFS,
> + "-t",
> + format,
> + device,
> + NULL);
> +
> + if (virCommandRun(cmd, NULL) < 0) {
> + virReportSystemError(errno,
> + _("Failed to make filesystem of "
> + "type '%s' on device '%s'"),
> + format, device);
> + ret = -1;
> + }
> + return ret;
> +}
> +
> +static int
> +virStorageBackendMakeFileSystem(virStoragePoolObjPtr pool,
> + unsigned int flags)
> +{
> + const char *device = NULL, *format = NULL;
> + bool ok_to_mkfs = false;
> + int ret = -1;
> +
> + if (pool->def->source.devices == NULL) {
> + virStorageReportError(VIR_ERR_OPERATION_INVALID,
> + _("No source device specified when formatting pool '%s'"),
> + pool->def->name);
> + goto error;
> + }
> +
> + device = pool->def->source.devices[0].path;
> + format = virStoragePoolFormatFileSystemTypeToString(pool->def->source.format);
> + VIR_DEBUG("source device: '%s' format: '%s'", device, format);
> +
> + if (!virFileExists(device)) {
> + virStorageReportError(VIR_ERR_OPERATION_INVALID,
> + _("Source device does not exist when formatting pool '%s'"),
> + pool->def->name);
> + goto error;
> + }
> +
> + if (flags & VIR_STORAGE_POOL_BUILD_OVERWRITE) {
> + ok_to_mkfs = true;
> + } else if (flags & VIR_STORAGE_POOL_BUILD_NO_OVERWRITE &&
> + virStorageBackendFileSystemProbe(device, format) ==
> + FILESYSTEM_PROBE_NOT_FOUND) {
> + ok_to_mkfs = true;
> + }
> +
> + if (ok_to_mkfs) {
> + ret = virStorageBackendExecuteMKFS(device, format);
> + }
> +
> +error:
> + return ret;
> +}
> +
>
> /**
> * @conn connection to report errors against
> * @pool storage pool to build
> + * @flags controls the pool formating behaviour
> *
> * Build a directory or FS based storage pool.
> *
> + * If no flag is set, it only makes the directory; If
> + * VIR_STORAGE_POOL_BUILD_NO_OVERWRITE set, it probes to determine if
> + * filesystem already exists on the target device, renurning an error
> + * if exists, or using mkfs to format the target device if not; If
> + * VIR_STORAGE_POOL_BUILD_OVERWRITE is set, mkfs is always executed,
> + * any existed data on the target device is overwritten unconditionally.
> + *
> * - If it is a FS based pool, mounts the unlying source device on the pool
> *
> * Returns 0 on success, -1 on error
> @@ -551,10 +715,20 @@ virStorageBackendFileSystemBuild(virConnectPtr conn ATTRIBUTE_UNUSED,
> unsigned int flags)
> {
> int err, ret = -1;
> - char *parent;
> - char *p;
> + char *parent = NULL;
> + char *p = NULL;
>
> - virCheckFlags(0, -1);
> + virCheckFlags(VIR_STORAGE_POOL_BUILD_OVERWRITE |
> + VIR_STORAGE_POOL_BUILD_NO_OVERWRITE, ret);
> +
> + if (flags == (VIR_STORAGE_POOL_BUILD_OVERWRITE |
> + VIR_STORAGE_POOL_BUILD_NO_OVERWRITE)) {
> +
> + virStorageReportError(VIR_ERR_OPERATION_INVALID,
> + _("Overwrite and no overwrite flags"
> + " are mutually exclusive"));
> + goto error;
> + }
>
> if ((parent = strdup(pool->def->target.path)) == NULL) {
> virReportOOMError();
> @@ -604,7 +778,13 @@ virStorageBackendFileSystemBuild(virConnectPtr conn ATTRIBUTE_UNUSED,
> goto error;
> }
> }
> - ret = 0;
> +
> + if (flags != 0) {
> + ret = virStorageBackendMakeFileSystem(pool, flags);
> + } else {
> + ret = 0;
> + }
> +
> error:
> VIR_FREE(parent);
> return ret;
> diff --git a/src/storage/storage_backend_fs.h b/src/storage/storage_backend_fs.h
> index 7def53e..54c6739 100644
> --- a/src/storage/storage_backend_fs.h
> +++ b/src/storage/storage_backend_fs.h
> @@ -29,6 +29,11 @@
> # if WITH_STORAGE_FS
> extern virStorageBackend virStorageBackendFileSystem;
> extern virStorageBackend virStorageBackendNetFileSystem;
> +typedef enum {
> + FILESYSTEM_PROBE_FOUND,
> + FILESYSTEM_PROBE_NOT_FOUND,
> + FILESYSTEM_PROBE_ERROR,
> +} virStoragePoolProbeResult;
> # endif
> extern virStorageBackend virStorageBackendDirectory;
>
> diff --git a/src/util/virterror.c b/src/util/virterror.c
> index b50fbfd..26c4981 100644
> --- a/src/util/virterror.c
> +++ b/src/util/virterror.c
> @@ -1030,6 +1030,18 @@ virErrorMsg(virErrorNumber error, const char *info)
> else
> errmsg = _("Storage volume not found: %s");
> break;
> + case VIR_ERR_STORAGE_PROBE_FAILED:
> + if (info == NULL)
> + errmsg = _("Storage pool probe failed");
> + else
> + errmsg = _("Storage pool probe failed: %s");
> + break;
> + case VIR_ERR_STORAGE_POOL_BUILT:
> + if (info == NULL)
> + errmsg = _("Storage pool already built");
> + else
> + errmsg = _("Storage pool already built: %s");
> + break;
> case VIR_ERR_INVALID_STORAGE_POOL:
> if (info == NULL)
> errmsg = _("invalid storage pool pointer in");
ACK the logic looks right. I would love to see some ways to test
the various behaviours though,
Daniel
--
Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/
daniel at veillard.com | Rpmfind RPM search engine http://rpmfind.net/
http://veillard.com/ | virtualization library http://libvirt.org/
More information about the libvir-list
mailing list