[libvirt] [PATCH 2/3] Storage: Add fs pool formatting

Osier Yang jyang at redhat.com
Fri Apr 8 09:06:35 UTC 2011


于 2011年04月08日 16:51, Osier Yang 写道:
> Previous description from Dave Allan.
>
> <QUOTE>
> 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.
>
> Changes per feedback from eblake:
> * Made probe&  overwrite flags exclusive
> * Changed LDFLAGS to LIBADD in Makefile.am
> * Added missing virCheckFlags()
> * Fixed copyright dates
> * Removed cast of char * passed to libblkid and replaced it with a strdup'd copy
> * Changed flags to an unsigned int in virsh.c
>
> Changes per feedback from Dan B.
> * Changed probe flag to no-overwrite
> * Moved libblkid probe code into storage_backend_fs.c
> </QUOTE>
>
> New changes: (per last feedback from Eric)
> * s/VIR_STORAGE_POOL_PROBE_BUILT/VIR_STORAGE_POOL_BUILT/
> * Remove the internal function exporting in libvirt_private.syms
> * Correct wonky spacing
>
> ---
>   include/libvirt/libvirt.h.in     |    6 +-
>   include/libvirt/virterror.h      |    2 +
>   src/libvirt.c                    |    5 +-
>   src/storage/storage_backend_fs.c |  191 +++++++++++++++++++++++++++++++++++++-
>   src/storage/storage_backend_fs.h |    7 ++
>   src/util/virterror.c             |   64 ++++++++-----
>   6 files changed, 242 insertions(+), 33 deletions(-)
>
> diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in
> index d765412..e43c98a 100644
> --- a/include/libvirt/libvirt.h.in
> +++ b/include/libvirt/libvirt.h.in
> @@ -1335,8 +1335,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 0708e02..33fbe9a 100644
> --- a/include/libvirt/virterror.h
> +++ b/include/libvirt/virterror.h
> @@ -231,6 +231,8 @@ typedef enum {
>       VIR_ERR_INVALID_DOMAIN_SNAPSHOT = 71,/* invalid domain snapshot */
>       VIR_ERR_NO_DOMAIN_SNAPSHOT = 72,	/* domain snapshot not found */
>       VIR_ERR_INVALID_STREAM = 73,        /* stream pointer not valid */
> +    VIR_ERR_STORAGE_PROBE_FAILED = 74,  /* storage pool proble failed */
> +    VIR_ERR_STORAGE_POOL_BUILT = 75,    /* storage pool already built */
>   } virErrorNumber;
>
>   /**
> diff --git a/src/libvirt.c b/src/libvirt.c
> index dde4bd4..03d870b 100644
> --- a/src/libvirt.c
> +++ b/src/libvirt.c
> @@ -8001,7 +8001,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 0a6b074..54afa7c 100644
> --- a/src/storage/storage_backend_fs.c
> +++ b/src/storage/storage_backend_fs.c
> @@ -33,6 +33,10 @@
>   #include<unistd.h>
>   #include<string.h>
>
> +#if HAVE_LIBBLKID
> +# include<blkid/blkid.h>
> +#endif
> +
>   #include<libxml/parser.h>
>   #include<libxml/tree.h>
>   #include<libxml/xpath.h>
> @@ -45,6 +49,7 @@
>   #include "memory.h"
>   #include "xml.h"
>   #include "files.h"
> +#include "logging.h"
>
>   #define VIR_FROM_THIS VIR_FROM_STORAGE
>
> @@ -533,13 +538,173 @@ 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;
> +    const char *mkfsargv[5] = { MKFS,
> +                                "-t",
> +                                format,
> +                                device,
> +                                NULL };

Ah, I kept in my mind to change this to virCommandRun, but
forgot finally.

> +
> +    if (virRun(mkfsargv, 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
> + * a filesystem already exists on the target device, returning 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
> @@ -547,11 +712,23 @@ virStorageBackendFileSystemStart(virConnectPtr conn ATTRIBUTE_UNUSED,
>   static int
>   virStorageBackendFileSystemBuild(virConnectPtr conn ATTRIBUTE_UNUSED,
>                                    virStoragePoolObjPtr pool,
> -                                 unsigned int flags ATTRIBUTE_UNUSED)
> +                                 unsigned int flags)
>   {
>       int err, ret = -1;
> -    char *parent;
> -    char *p;
> +    char *parent = NULL;
> +    char *p = NULL;
> +
> +    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();
> @@ -601,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..394e552 100644
> --- a/src/storage/storage_backend_fs.h
> +++ b/src/storage/storage_backend_fs.h
> @@ -29,6 +29,13 @@
>   # 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 b7d8924..4450a43 100644
> --- a/src/util/virterror.c
> +++ b/src/util/virterror.c
> @@ -1041,63 +1041,75 @@ virErrorMsg(virErrorNumber error, const char *info)
>               break;
>           case VIR_ERR_NO_STORAGE_POOL:
>               if (info == NULL)
> -                    errmsg = _("Storage pool not found");
> +                errmsg = _("Storage pool not found");
>               else
> -                    errmsg = _("Storage pool not found: %s");
> +                errmsg = _("Storage pool not found: %s");
>               break;
>           case VIR_ERR_NO_STORAGE_VOL:
>               if (info == NULL)
> -                    errmsg = _("Storage volume not found");
> +                errmsg = _("Storage volume not found");
>               else
> -                    errmsg = _("Storage volume not found: %s");
> +                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");
> +                errmsg = _("invalid storage pool pointer in");
>               else
> -                    errmsg = _("invalid storage pool pointer in %s");
> +                errmsg = _("invalid storage pool pointer in %s");
>               break;
>           case VIR_ERR_INVALID_STORAGE_VOL:
>               if (info == NULL)
> -                    errmsg = _("invalid storage volume pointer in");
> +                errmsg = _("invalid storage volume pointer in");
>               else
> -                    errmsg = _("invalid storage volume pointer in %s");
> +                errmsg = _("invalid storage volume pointer in %s");
>               break;
>           case VIR_WAR_NO_STORAGE:
>               if (info == NULL)
> -                    errmsg = _("Failed to find a storage driver");
> +                errmsg = _("Failed to find a storage driver");
>               else
> -                    errmsg = _("Failed to find a storage driver: %s");
> +                errmsg = _("Failed to find a storage driver: %s");
>               break;
>           case VIR_WAR_NO_NODE:
>               if (info == NULL)
> -                    errmsg = _("Failed to find a node driver");
> +                errmsg = _("Failed to find a node driver");
>               else
> -                    errmsg = _("Failed to find a node driver: %s");
> +                errmsg = _("Failed to find a node driver: %s");
>               break;
>           case VIR_ERR_INVALID_NODE_DEVICE:
>               if (info == NULL)
> -                    errmsg = _("invalid node device pointer");
> +                errmsg = _("invalid node device pointer");
>               else
> -                    errmsg = _("invalid node device pointer in %s");
> +                errmsg = _("invalid node device pointer in %s");
>               break;
>           case VIR_ERR_NO_NODE_DEVICE:
>               if (info == NULL)
> -                    errmsg = _("Node device not found");
> +                errmsg = _("Node device not found");
>               else
> -                    errmsg = _("Node device not found: %s");
> +                errmsg = _("Node device not found: %s");
>               break;
>           case VIR_ERR_NO_SECURITY_MODEL:
>               if (info == NULL)
> -                    errmsg = _("Security model not found");
> +                errmsg = _("Security model not found");
>               else
> -                    errmsg = _("Security model not found: %s");
> +                errmsg = _("Security model not found: %s");
>               break;
>           case VIR_ERR_OPERATION_INVALID:
>               if (info == NULL)
> -                    errmsg = _("Requested operation is not valid");
> +                errmsg = _("Requested operation is not valid");
>               else
> -                    errmsg = _("Requested operation is not valid: %s");
> +                errmsg = _("Requested operation is not valid: %s");
>               break;
>           case VIR_WAR_NO_INTERFACE:
>               if (info == NULL)
> @@ -1149,21 +1161,21 @@ virErrorMsg(virErrorNumber error, const char *info)
>               break;
>           case VIR_ERR_INVALID_NWFILTER:
>               if (info == NULL)
> -                    errmsg = _("Invalid network filter");
> +                errmsg = _("Invalid network filter");
>               else
> -                    errmsg = _("Invalid network filter: %s");
> +                errmsg = _("Invalid network filter: %s");
>               break;
>           case VIR_ERR_NO_NWFILTER:
>               if (info == NULL)
> -                    errmsg = _("Network filter not found");
> +                errmsg = _("Network filter not found");
>               else
> -                    errmsg = _("Network filter not found: %s");
> +                errmsg = _("Network filter not found: %s");
>               break;
>           case VIR_ERR_BUILD_FIREWALL:
>               if (info == NULL)
> -                    errmsg = _("Error while building firewall");
> +                errmsg = _("Error while building firewall");
>               else
> -                    errmsg = _("Error while building firewall: %s");
> +                errmsg = _("Error while building firewall: %s");
>               break;
>           case VIR_ERR_CONFIG_UNSUPPORTED:
>               if (info == NULL)




More information about the libvir-list mailing list