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(a)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