Signed-off-by: Wolfgang Bumiller <w.bumil...@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 _______________________________________________ pve-devel mailing list pve-devel@lists.proxmox.com https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel