all lists on lists.proxmox.com
 help / color / mirror / Atom feed
From: Wolfgang Bumiller <w.bumiller@proxmox.com>
To: pve-devel@lists.proxmox.com
Subject: [pve-devel] [PATCH v3 storage 1/3] btrfs: support quota-based subvols optionally
Date: Thu, 24 Jun 2021 12:01:40 +0200	[thread overview]
Message-ID: <20210624100142.108334-1-w.bumiller@proxmox.com> (raw)

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





             reply	other threads:[~2021-06-24 10:02 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-06-24 10:01 Wolfgang Bumiller [this message]
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

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20210624100142.108334-1-w.bumiller@proxmox.com \
    --to=w.bumiller@proxmox.com \
    --cc=pve-devel@lists.proxmox.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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