summaryrefslogtreecommitdiff
path: root/src/shared/machine-image.c
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2015-10-21 19:38:21 +0200
committerLennart Poettering <lennart@poettering.net>2015-10-22 01:59:25 +0200
commit5bcd08db289cd02aad8a89b37b2a46244a7bd473 (patch)
treea34bbcc4df2824efe169bf041572b0f78dc2620a /src/shared/machine-image.c
parent16597ac3903ddb68d5ef75e6aaa37e43866a376d (diff)
btrfs: beef-up btrfs support with a limited understanding of quota
With this change we understand more than just leaf quota groups for btrfs file systems. Specifically: - When we create a subvolume we can now optionally add the new subvolume to all qgroups its parent subvolume was member of too. Alternatively it is also possible to insert an intermediary quota group between the parent's qgroups and the subvolume's leaf qgroup, which is useful for a concept of "subtree" qgroups, that contain a subvolume and all its children. - The remove logic for subvolumes has been updated to optionally remove any leaf qgroups or "subtree" qgroups, following the logic above. - The snapshot logic for subvolumes has been updated to replicate the original qgroup setup of the source, if it follows the "subtree" design described above. It will not cover qgroup setups that introduce arbitrary qgroups, especially those orthogonal to the subvolume hierarchy. This also tries to be more graceful when setting up /var/lib/machines as btrfs. For example, if mkfs.btrfs is missing we don't even try to set it up as loopback device. Fixes #1559 Fixes #1129
Diffstat (limited to 'src/shared/machine-image.c')
-rw-r--r--src/shared/machine-image.c41
1 files changed, 30 insertions, 11 deletions
diff --git a/src/shared/machine-image.c b/src/shared/machine-image.c
index 9c1e4d5e13..8ed3ad7f44 100644
--- a/src/shared/machine-image.c
+++ b/src/shared/machine-image.c
@@ -176,11 +176,10 @@ static int image_make(
return r;
if (r) {
BtrfsSubvolInfo info;
- BtrfsQuotaInfo quota;
/* It's a btrfs subvolume */
- r = btrfs_subvol_get_info_fd(fd, &info);
+ r = btrfs_subvol_get_info_fd(fd, 0, &info);
if (r < 0)
return r;
@@ -195,13 +194,17 @@ static int image_make(
if (r < 0)
return r;
- r = btrfs_subvol_get_quota_fd(fd, &quota);
- if (r >= 0) {
- (*ret)->usage = quota.referenced;
- (*ret)->usage_exclusive = quota.exclusive;
+ if (btrfs_quota_scan_ongoing(fd) == 0) {
+ BtrfsQuotaInfo quota;
- (*ret)->limit = quota.referenced_max;
- (*ret)->limit_exclusive = quota.exclusive_max;
+ r = btrfs_subvol_get_subtree_quota_fd(fd, 0, &quota);
+ if (r >= 0) {
+ (*ret)->usage = quota.referenced;
+ (*ret)->usage_exclusive = quota.exclusive;
+
+ (*ret)->limit = quota.referenced_max;
+ (*ret)->limit_exclusive = quota.exclusive_max;
+ }
}
return 1;
@@ -397,7 +400,7 @@ int image_remove(Image *i) {
switch (i->type) {
case IMAGE_SUBVOLUME:
- r = btrfs_subvol_remove(i->path, true);
+ r = btrfs_subvol_remove(i->path, BTRFS_REMOVE_RECURSIVE|BTRFS_REMOVE_QUOTA);
if (r < 0)
return r;
break;
@@ -587,7 +590,12 @@ int image_clone(Image *i, const char *new_name, bool read_only) {
case IMAGE_DIRECTORY:
new_path = strjoina("/var/lib/machines/", new_name);
- r = btrfs_subvol_snapshot(i->path, new_path, (read_only ? BTRFS_SNAPSHOT_READ_ONLY : 0) | BTRFS_SNAPSHOT_FALLBACK_COPY | BTRFS_SNAPSHOT_RECURSIVE);
+ r = btrfs_subvol_snapshot(i->path, new_path, (read_only ? BTRFS_SNAPSHOT_READ_ONLY : 0) | BTRFS_SNAPSHOT_FALLBACK_COPY | BTRFS_SNAPSHOT_RECURSIVE | BTRFS_SNAPSHOT_QUOTA);
+
+ /* Enable "subtree" quotas for the copy, if we didn't
+ * copy any quota from the source. */
+ (void) btrfs_subvol_auto_qgroup(i->path, 0, true);
+
break;
case IMAGE_RAW:
@@ -629,6 +637,10 @@ int image_read_only(Image *i, bool b) {
switch (i->type) {
case IMAGE_SUBVOLUME:
+
+ /* Note that we set the flag only on the top-level
+ * subvolume of the image. */
+
r = btrfs_subvol_set_read_only(i->path, b);
if (r < 0)
return r;
@@ -729,7 +741,14 @@ int image_set_limit(Image *i, uint64_t referenced_max) {
if (i->type != IMAGE_SUBVOLUME)
return -EOPNOTSUPP;
- return btrfs_quota_limit(i->path, referenced_max);
+ /* We set the quota both for the subvolume as well as for the
+ * subtree. The latter is mostly for historical reasons, since
+ * we didn't use to have a concept of subtree quota, and hence
+ * only modified the subvolume quota. */
+
+ (void) btrfs_qgroup_set_limit(i->path, 0, referenced_max);
+ (void) btrfs_subvol_auto_qgroup(i->path, 0, true);
+ return btrfs_subvol_set_subtree_quota_limit(i->path, 0, referenced_max);
}
int image_name_lock(const char *name, int operation, LockFile *ret) {