[libvirt] [PATCH 2/2] storage: btrfs subvolumes for directory pools

Michal Privoznik mprivozn at redhat.com
Wed Oct 9 15:15:16 UTC 2013


On 10.09.2013 20:59, Oskari Saarenmaa wrote:
> This commit adds support for btrfs subvolumes as directory volumes.  The
> directory storage pool can be used to manage btrfs subvolumes on an existing
> btrfs filesystem.  The driver can create new blank subvolumes and snapshots
> of existing subvolumes as well as delete existing subvolumes.
> 
> The subvolumes created are automatically made visible on the host side
> and can be attached to domains using the <filesystem> tags as defined in
> 'format domain' documentation.
> 
> Subvolumes do not implement quotas at the moment because the current
> (btrfs-progs-0.20.rc1.20130501git7854c8b-4.fc20.x86_64) support for quota
> management in btrfs-progs is lacking the necessary features, for example
> it's not possible to see the quota assigned to a certain subvolume and
> usage information is only updated on syncfs(2).  Quota support will be
> implemented once the tools gain the necessary features.
> 
> Signed-off-by: Oskari Saarenmaa <os at ohmu.fi>
> ---
>  configure.ac                                      |  25 ++-
>  docs/schemas/storagevol.rng                       |   1 +
>  docs/storage.html.in                              |  30 ++-
>  libvirt.spec.in                                   |   4 +
>  src/conf/storage_conf.c                           |   3 +
>  src/conf/storage_conf.h                           |   1 +
>  src/storage/storage_backend.c                     |  15 +-
>  src/storage/storage_backend_fs.c                  | 222 ++++++++++++++++++++--
>  src/util/virstoragefile.c                         |   4 +-
>  src/util/virstoragefile.h                         |   1 +
>  tests/storagevolxml2xmlin/vol-btrfs-snapshot.xml  |  13 ++
>  tests/storagevolxml2xmlin/vol-btrfs.xml           |   9 +
>  tests/storagevolxml2xmlout/vol-btrfs-snapshot.xml |  26 +++
>  tests/storagevolxml2xmlout/vol-btrfs.xml          |  17 ++
>  tests/storagevolxml2xmltest.c                     |   2 +
>  15 files changed, 343 insertions(+), 30 deletions(-)
>  create mode 100644 tests/storagevolxml2xmlin/vol-btrfs-snapshot.xml
>  create mode 100644 tests/storagevolxml2xmlin/vol-btrfs.xml
>  create mode 100644 tests/storagevolxml2xmlout/vol-btrfs-snapshot.xml
>  create mode 100644 tests/storagevolxml2xmlout/vol-btrfs.xml
> 

> @@ -866,6 +901,23 @@ virStorageBackendFileSystemRefresh(virConnectPtr conn ATTRIBUTE_UNUSED,
>                  goto cleanup;
>          }
>  
> +#if WITH_STORAGE_BTRFS
> +        /* check for subvolumes */
> +        if (vol->target.format == VIR_STORAGE_FILE_DIR &&
> +            fstype != NULL && STREQ(fstype, "btrfs")) {

or STREQ_NULLABLE

> +            int vars[] = {2};
> +            const char *regexes[] = {"^\\s*([A-Za-z ]+):\\s*(.+)\\s*$"};
> +            virCommandPtr cmd = virCommandNewArgList(
> +                "btrfs", "subvolume", "show", vol->target.path, NULL);
> +            if (cmd == NULL)
> +                goto cleanup;
> +            virStorageBackendRunProgRegex(NULL, cmd, 1, regexes, vars,
> +                                          btrfsVolInfo, vol, NULL);
> +            if (vol->backingStore.format == VIR_STORAGE_FILE_VOLUME)
> +                missing_subvolume_info ++;
> +        }
> +#endif
> +

> +static int createVolumeDir(virConnectPtr conn ATTRIBUTE_UNUSED,
> +                           virStoragePoolObjPtr pool ATTRIBUTE_UNUSED,
> +                           virStorageVolDefPtr vol,
> +                           virStorageVolDefPtr inputvol,
> +                           unsigned int flags)
> +{
> +    int ret = -1;
> +    char *vol_dir_name = NULL;
> +    char *fstype = NULL;
> +    virCommandPtr cmd = NULL;
> +    struct stat st;
> +
> +    virCheckFlags(0, -1);
> +
> +    if (inputvol) {
> +        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
> +                _("cannot copy from volume to a subvolume"));
> +        return -1;
> +    }
> +
> +    if ((vol_dir_name = mdir_name(vol->target.path)) == NULL)
> +        goto cleanup;
> +
> +    fstype = virFileFsType(vol_dir_name);
> +    if (fstype == NULL) {
> +        virReportSystemError(errno,
> +                             _("cannot get filesystem type for %s"),
> +                             vol->target.path);
> +        goto cleanup;
> +    }
> +#if WITH_STORAGE_BTRFS
> +    else if (STREQ(fstype, "btrfs")) {
> +        cmd = virCommandNew("btrfs");
> +        if (!cmd)
> +            goto cleanup;
> +
> +        if (vol->backingStore.path == NULL) {
> +            virCommandAddArgList(cmd, "subvolume", "create", vol->target.path, NULL);
> +        } else {
> +            int accessRetCode = -1;
> +
> +            accessRetCode = access(vol->backingStore.path, R_OK | X_OK);

We need virDirIsExecutable or something like that. make syntax-check is
objecting to this line.

> +            if (accessRetCode != 0) {
> +                virReportSystemError(errno,
> +                                     _("inaccessible backing store volume %s"),
> +                                     vol->backingStore.path);
> +                goto cleanup;
> +            }
> +
> +            virCommandAddArgList(cmd, "subvolume", "snapshot", vol->backingStore.path,
> +                                 vol->target.path, NULL);
> +        }
> +        if (virCommandRun(cmd, NULL) < 0)
> +            goto cleanup;
> +    }
> +#endif
> +    else {
> +        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
> +                       _("subvolumes are not supported in %s"),
> +                       fstype);
> +        goto cleanup;
> +    }
> +
> +    if (stat(vol->target.path, &st) < 0) {
> +        virReportSystemError(errno,
> +                             _("failed to create %s"), vol->target.path);
> +        goto cleanup;
> +    }
> +    ret = 0;
> +
> +cleanup:
> +    VIR_FREE(vol_dir_name);
> +    VIR_FREE(fstype);
> +    virCommandFree(cmd);
> +    return ret;
> +}
> +

Michal




More information about the libvir-list mailing list