all lists on lists.proxmox.com
 help / color / mirror / Atom feed
* [pve-devel] [PATCH v3 storage 1/3] btrfs: support quota-based subvols optionally
@ 2021-06-24 10:01 Wolfgang Bumiller
  2021-06-24 10:01 ` [pve-devel] [PATCH storage 2/3] btrfs: cleanup after qgroups when deleting subvolumes Wolfgang Bumiller
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: Wolfgang Bumiller @ 2021-06-24 10:01 UTC (permalink / raw)
  To: pve-devel

Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
---
Difference to the main btrfs series v2:
  * removed double-eval to catch errors when setting limits in
    alloc_image
  Note that the issue that subvols are created with size zero was an
  issue in pve-container.
  Volume resizing is fixed in patch 3

 PVE/Storage/BTRFSPlugin.pm | 93 +++++++++++++++++++++++---------------
 1 file changed, 57 insertions(+), 36 deletions(-)

diff --git a/PVE/Storage/BTRFSPlugin.pm b/PVE/Storage/BTRFSPlugin.pm
index 5360dca..179186b 100644
--- a/PVE/Storage/BTRFSPlugin.pm
+++ b/PVE/Storage/BTRFSPlugin.pm
@@ -57,6 +57,14 @@ sub properties {
 	    type => 'boolean',
 	    default => 0,
 	},
+	quotas => {
+	    description => "If enabled, containers will use subvolumes directly, using quotas"
+		. " for space accounting, instead of using ext4 formatted images files."
+		. " While this removes a file system layer for containers, there is a risk of"
+		. " performance degrading over time.",
+	    type => 'boolean',
+	    default => 0,
+	},
     };
 }
 
@@ -71,6 +79,7 @@ sub options {
 	format => { optional => 1 },
 	is_mountpoint => { optional => 1 },
 	nocow => { optional => 1 },
+	quotas => { optional => 1 },
 	# TODO: The new variant of mkdir with  `populate` vs `create`...
     };
 }
@@ -336,27 +345,20 @@ sub alloc_image {
 	$path = "$subvol/disk.raw";
     }
 
-    if ($fmt eq 'subvol' && !!$size) {
+    if ($fmt eq 'subvol' && !!$size && !$scfg->{quotas}) {
 	# NOTE: `btrfs send/recv` actually drops quota information so supporting subvolumes with
 	# quotas doesn't play nice with send/recv.
-	die "btrfs quotas are currently not supported, use an unsized subvolume or a raw file\n";
+	die "btrfs quotas are currently disabled, use an unsized subvolume or a raw file\n";
     }
 
     $class->btrfs_cmd(['subvolume', 'create', '--', $subvol]);
 
     eval {
 	if ($fmt eq 'subvol') {
-	    # Nothing to do for now...
-
-	    # This is how we *would* do it:
-	    # # Use the subvol's default 0/$id qgroup
-	    # eval {
-	    #     # This call should happen at storage creation instead and therefore governed by a
-	    #     # configuration option!
-	    #     # $class->btrfs_cmd(['quota', 'enable', $subvol]);
-	    #     my $id = $class->btrfs_get_subvol_id($subvol);
-	    #     $class->btrfs_cmd(['qgroup', 'limit', "${size}k", "0/$id", $subvol]);
-	    # };
+	    if (!!$size) {
+		my $id = $class->btrfs_get_subvol_id($subvol);
+		$class->btrfs_cmd(['qgroup', 'limit', "${size}k", "0/$id", $subvol]);
+	    }
 	} elsif ($fmt eq 'raw') {
 	    sysopen my $fh, $path, O_WRONLY | O_CREAT | O_EXCL
 		or die "failed to create raw file '$path' - $!\n";
@@ -434,27 +436,26 @@ sub free_image {
     return undef;
 }
 
-# Currently not used because quotas clash with send/recv.
-# my sub btrfs_subvol_quota {
-#     my ($class, $path) = @_;
-#     my $id = '0/' . $class->btrfs_get_subvol_id($path);
-#     my $search = qr/^\Q$id\E\s+(\d)+\s+\d+\s+(\d+)\s*$/;
-#     my ($used, $size);
-#     $class->btrfs_cmd(['qgroup', 'show', '--raw', '-rf', '--', $path], sub {
-# 	return if defined($size);
-# 	if ($_[0] =~ $search) {
-# 	    ($used, $size) = ($1, $2);
-# 	}
-#     });
-#     if (!defined($size)) {
-# 	# syslog should include more information:
-# 	syslog('err', "failed to get subvolume size for: $path (id $id)");
-# 	# UI should only see the last path component:
-# 	$path =~ s|^.*/||;
-# 	die "failed to get subvolume size for $path\n";
-#     }
-#     return wantarray ? ($used, $size) : $size;
-# }
+my sub btrfs_subvol_quota {
+    my ($class, $path) = @_;
+    my $id = '0/' . $class->btrfs_get_subvol_id($path);
+    my $search = qr/^\Q$id\E\s+(\d)+\s+\d+\s+(\d+)\s*$/;
+    my ($used, $size);
+    $class->btrfs_cmd(['qgroup', 'show', '--raw', '-rf', '--', $path], sub {
+	return if defined($size);
+	if ($_[0] =~ $search) {
+	    ($used, $size) = ($1, $2);
+	}
+    });
+    if (!defined($size)) {
+	# syslog should include more information:
+	syslog('err', "failed to get subvolume size for: $path (id $id)");
+	# UI should only see the last path component:
+	$path =~ s|^.*/||;
+	die "failed to get subvolume size for $path\n";
+    }
+    return wantarray ? ($used, $size) : $size;
+}
 
 sub volume_size_info {
     my ($class, $scfg, $storeid, $volname, $timeout) = @_;
@@ -466,7 +467,9 @@ sub volume_size_info {
     if ($format eq 'subvol') {
 	my $ctime = (stat($path))[10];
 	my ($used, $size) = (0, 0);
-	#my ($used, $size) = btrfs_subvol_quota($class, $path); # uses wantarray
+	if ($scfg->{quotas}) {
+	    ($used, $size) = btrfs_subvol_quota($class, $path);
+	}
 	return wantarray ? ($size, 'subvol', $used, undef, $ctime) : 1;
     }
 
@@ -478,6 +481,9 @@ sub volume_resize {
 
     my $format = ($class->parse_volname($volname))[6];
     if ($format eq 'subvol') {
+	die "subvolumes can only be resized with quotas enabled\n"
+	    if !$scfg->{quotas};
+
 	my $path = $class->filesystem_path($scfg, $volname);
 	my $id = '0/' . $class->btrfs_get_subvol_id($path);
 	$class->btrfs_cmd(['qgroup', 'limit', '--', "${size}k", "0/$id", $path]);
@@ -638,7 +644,9 @@ sub list_images {
 	    ($size, $format, $used, $parent, $ctime) = PVE::Storage::Plugin::file_size_info("$fn/disk.raw");
 	} elsif ($ext eq 'subvol') {
 	    ($used, $size) = (0, 0);
-	    #($used, $size) = btrfs_subvol_quota($class, $fn);
+	    if ($scfg->{quotas}) {
+		($used, $size) = btrfs_subvol_quota($class, $fn);
+	    }
 	    $format = 'subvol';
 	} else {
 	    ($size, $format, $used, $parent, $ctime) = PVE::Storage::Plugin::file_size_info($fn);
@@ -680,6 +688,9 @@ sub volume_export_formats {
     my $format = ($class->parse_volname($volname))[6];
     return @result if $format ne 'raw' && $format ne 'subvol';
 
+    # Currently we don't allow using btrfs-send/recv with quotas on subvolumes.
+    return @result if $scfg->{quotas} && $format eq 'subvol';
+
     return ('btrfs', @result);
 }
 
@@ -726,6 +737,11 @@ sub volume_export {
     die "btrfs-sending volumes of type $volume_format ('$volname') is not supported\n"
 	if $volume_format ne 'raw' && $volume_format ne 'subvol';
 
+    if ($scfg->{quotas} && $format eq 'subvol') {
+	die "btrfs-sending volumes of type $volume_format ('$volname') with quotas enabled is"
+	    . " currently not supported\n";
+    }
+
     my $path = $class->path($scfg, $volname, $storeid);
 
     if ($volume_format eq 'raw') {
@@ -782,6 +798,11 @@ sub volume_import {
     die "btrfs-receiving volumes of type $volume_format ('$volname') is not supported\n"
 	if $volume_format ne 'raw' && $volume_format ne 'subvol';
 
+    if ($scfg->{quotas} && $format eq 'subvol') {
+	die "btrfs-receiving volumes of type $volume_format ('$volname') with quotas enabled is"
+	    . " currently not supported\n";
+    }
+
     if (defined($base_snapshot)) {
 	my $path = $class->path($scfg, $volname, $storeid, $base_snapshot);
 	die "base snapshot '$base_snapshot' not found - no such directory '$path'\n"
-- 
2.30.2





^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2021-06-24 10:18 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-06-24 10:01 [pve-devel] [PATCH v3 storage 1/3] btrfs: support quota-based subvols optionally Wolfgang Bumiller
2021-06-24 10:01 ` [pve-devel] [PATCH storage 2/3] btrfs: cleanup after qgroups when deleting subvolumes Wolfgang Bumiller
2021-06-24 10:01 ` [pve-devel] [PATCH storage 3/3] btrfs: fix qgroup id and size in volume resize Wolfgang Bumiller
2021-06-24 10:18 ` [pve-devel] [PATCH v3 storage 1/3] btrfs: support quota-based subvols optionally Fabian Grünbichler

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.
Service provided by Proxmox Server Solutions GmbH | Privacy | Legal