public inbox for pve-devel@lists.proxmox.com
 help / color / mirror / Atom feed
* [pve-devel] [PATCH-SERIES v2 storage 0/5] unsized subvol regression fix and improvements
@ 2025-03-03  9:24 Fiona Ebner
  2025-03-03  9:24 ` [pve-devel] [PATCH v2 storage 1/5] plugin: file size info: be consistent about size of directory subvol Fiona Ebner
                   ` (4 more replies)
  0 siblings, 5 replies; 6+ messages in thread
From: Fiona Ebner @ 2025-03-03  9:24 UTC (permalink / raw)
  To: pve-devel

Changes in v2:
* comment out dead code in BTRFS plugin
* improve commit messages regarding clone
* squash patches 5/6 and 6/6 from v1

In list context, the file_size_info() function in Plugin.pm and the
volume_size_info() function in BTRFSPlugin.pm would return 0 for the
size, but in scalar context 1. As reported in the community forum [0],
the change in commit e50dde0 ("volume export: rely on storage plugin's
format"), changing the caller in volume_export() to scalar context
exposed the inconsistency in the return value for the size. This led
to breakage of migration with unsized btrfs subvolumes.

The first patch is the regression fix. Second patch fixes cloning
containers with unsized subvolumes on BTFRS. The rest are independent
further cleanups or improvements in the context of unsized subvols.

[0]: https://forum.proxmox.com/threads/162943/


Fiona Ebner (5):
  plugin: file size info: be consistent about size of directory subvol
  btrfs: fix volume size info for subvolumes in scalar context
  plugin: volume export formats: avoid superfluous file_size_info() call
  api: volume info: do not fail for zero-sized subvolumes
  btrfs: die early for broken subvolume resize

 src/PVE/API2/Storage/Content.pm |  4 +++-
 src/PVE/Storage/BTRFSPlugin.pm  | 30 +++++++++++++++++-------------
 src/PVE/Storage/Plugin.pm       |  5 +----
 3 files changed, 21 insertions(+), 18 deletions(-)

-- 
2.39.5



_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel


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

* [pve-devel] [PATCH v2 storage 1/5] plugin: file size info: be consistent about size of directory subvol
  2025-03-03  9:24 [pve-devel] [PATCH-SERIES v2 storage 0/5] unsized subvol regression fix and improvements Fiona Ebner
@ 2025-03-03  9:24 ` Fiona Ebner
  2025-03-03  9:24 ` [pve-devel] [PATCH v2 storage 2/5] btrfs: fix volume size info for subvolumes in scalar context Fiona Ebner
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: Fiona Ebner @ 2025-03-03  9:24 UTC (permalink / raw)
  To: pve-devel

In list context, the file_size_info() function in Plugin.pm would
return 0 for the size of a subvol directory, but in scalar context 1.
As reported in the community forum [0], the change in commit e50dde0
("volume export: rely on storage plugin's format"), changing the
caller in volume_export() to scalar context exposed the inconsistency
in the return value for the size. This led to breakage of migration
with unsized btrfs subvolumes.

Align the returned values to avoid such surprises. Caller that would
treat 0 as an error should use list context and check if it is a
subvol, if they are able to handle them.

NOTE: it is not possible to attach either a subvol, or a volume with
zero size to a VM.

Existing callers of file_size_info() do not break with this change:
GuestImport/OVF.pm - parse_ovf() +
API/Qemu.pm - create_disks():
  Doesn't support subvol directories, dies if size is 0.
Storage/Plugin.pm - create_base() +
Storage/{BTRFS,}Plugin.pm - list_images():
  Checks for definedness of $size.
Storage/{BTRFS,ESXi,}Plugin.pm - volume_size_info():
  Transitive, see below.
Storage/Plugin.pm - volume_export():
  Regressed by commit e50dde0, this change will restore previous
  behavior.
Storage/Plugin.pm - volume_export_formats() +
GuestImport.pm - extract_disk_from_import_file() +
Storage.pm - assert_iso_content():
  Doesn't use the result.
CLI/qm.pm - importdisk:
  Dies early if source is a directory.
CLI/qm.pm - importovf:
  Calls parse_ovf() earlier.

Existing callers of volume_size_info() do not break with this change:
API2/Storage/Content.pm - info:
  Uses list context, not affected by change.
QemuMigrate.pm - scan_local_volumes() +
API2/Qemu.pm - create_disks(), first call:
  Uses list context, not affected by change, does not support subvol
  directories.
API2/Qemu.pm - create_disks(), second call +
API2/Qemu.pm - import_from_volid():
  Doesn't support subvol directories, dies if size is 0.
API2/Qemu.pm - resize_vm +
VZDump/QemuServer.pm - prepare() +
QemuServer.pm - clone_disk() +
QemuServer.pm - create_efidisk():
  Doesn't support subvol directories (see NOTE above), but would not
  die directly if size is 0. (In case of create_efidisk(), the size of
  the just created disk is queried.)
API2/LXC.pm - resize_vm:
  For directory plugins, the subsequent call to resize_volume() fails
  with "can't resize this image format".
  For BTRFS, quotas are currently not supported and the call to
  resize_volume() fails with "failed to get btrfs subvolume ID from:".
  This is because the btrfs 'subvol show' command is invoked with
  '-q', so there is no output. Even if it would work, it would be more
  correct to use 0 as the current size to add to the new quota rather
  than 1.
LXC/Config.pm - rescan_volume():
  This will happily use size=1 from before this change, but that is
  not correct. A subsequent 'pct rescan' will correct the size to 0.
  It is only used when hotplugging an existing subvol directory.
LXC.pm - copy_volume():
  This will happily use size=1 from before this change, but that is
  not correct and will lead to failure "mkfs.ext4: Device size
  reported to be zero.". That is because with non-zero size, the
  allocation of the volume for the clone will be done with 'raw'
  format by the alloc_disk() helper in LXC.pm rather than 'subvol'.
  This change will make cloning containers with unsized subvol
  directories possible.
QemuServer/Cloudinit.pm - commit_cloudinit_disk():
  Doesn't support subvol directories (see NOTE above), will allocate
  a new volume when size is 0.

[0]: https://forum.proxmox.com/threads/162943/

Fixes: e50dde0 ("volume export: rely on storage plugin's format")
Signed-off-by: Fiona Ebner <f.ebner@proxmox.com>
---

Changes in v2:
* Improve commit message regarding clone

 src/PVE/Storage/Plugin.pm | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/PVE/Storage/Plugin.pm b/src/PVE/Storage/Plugin.pm
index 65cf43f..ce1530e 100644
--- a/src/PVE/Storage/Plugin.pm
+++ b/src/PVE/Storage/Plugin.pm
@@ -1007,7 +1007,7 @@ sub file_size_info {
     if (S_ISDIR($st->mode)) {
 	$handle_error->("expected format '$file_format', but '$filename' is a directory\n")
 	    if $file_format && $file_format ne 'subvol';
-	return wantarray ? (0, 'subvol', 0, undef, $st->ctime) : 1;
+	return wantarray ? (0, 'subvol', 0, undef, $st->ctime) : 0;
     } elsif ($file_format && $file_format eq 'subvol') {
 	$handle_error->("expected format '$file_format', but '$filename' is not a directory\n");
     }
-- 
2.39.5



_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel


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

* [pve-devel] [PATCH v2 storage 2/5] btrfs: fix volume size info for subvolumes in scalar context
  2025-03-03  9:24 [pve-devel] [PATCH-SERIES v2 storage 0/5] unsized subvol regression fix and improvements Fiona Ebner
  2025-03-03  9:24 ` [pve-devel] [PATCH v2 storage 1/5] plugin: file size info: be consistent about size of directory subvol Fiona Ebner
@ 2025-03-03  9:24 ` Fiona Ebner
  2025-03-03  9:24 ` [pve-devel] [PATCH v2 storage 3/5] plugin: volume export formats: avoid superfluous file_size_info() call Fiona Ebner
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: Fiona Ebner @ 2025-03-03  9:24 UTC (permalink / raw)
  To: pve-devel

Return the same size as in list context. See also commit "plugin: file
size info: be consistent about size of directory subvol".

Fixes cloning containers with unsized subvolumes on BTRFS. Before the
change, this would fail with "mkfs.ext4: Device size reported to be
zero.". That is because with non-zero size, the allocation of the
volume for the clone will be done with 'raw' format by the
alloc_disk() helper in LXC.pm rather than 'subvol'. This change will
make cloning containers with unsized subvol directories possible.

Signed-off-by: Fiona Ebner <f.ebner@proxmox.com>
---

Changes in v2:
* Improve commit message regarding clone

 src/PVE/Storage/BTRFSPlugin.pm | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/PVE/Storage/BTRFSPlugin.pm b/src/PVE/Storage/BTRFSPlugin.pm
index 1966b6f..b1f7912 100644
--- a/src/PVE/Storage/BTRFSPlugin.pm
+++ b/src/PVE/Storage/BTRFSPlugin.pm
@@ -486,7 +486,7 @@ sub volume_size_info {
 	my $ctime = (stat($path))[10];
 	my ($used, $size) = (0, 0);
 	#my ($used, $size) = btrfs_subvol_quota($class, $path); # uses wantarray
-	return wantarray ? ($size, 'subvol', $used, undef, $ctime) : 1;
+	return wantarray ? ($size, 'subvol', $used, undef, $ctime) : $size;
     }
 
     return PVE::Storage::Plugin::file_size_info($path, $timeout, $format);
-- 
2.39.5



_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel


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

* [pve-devel] [PATCH v2 storage 3/5] plugin: volume export formats: avoid superfluous file_size_info() call
  2025-03-03  9:24 [pve-devel] [PATCH-SERIES v2 storage 0/5] unsized subvol regression fix and improvements Fiona Ebner
  2025-03-03  9:24 ` [pve-devel] [PATCH v2 storage 1/5] plugin: file size info: be consistent about size of directory subvol Fiona Ebner
  2025-03-03  9:24 ` [pve-devel] [PATCH v2 storage 2/5] btrfs: fix volume size info for subvolumes in scalar context Fiona Ebner
@ 2025-03-03  9:24 ` Fiona Ebner
  2025-03-03  9:24 ` [pve-devel] [PATCH v2 storage 4/5] api: volume info: do not fail for zero-sized subvolumes Fiona Ebner
  2025-03-03  9:24 ` [pve-devel] [PATCH v2 storage 5/5] btrfs: die early for broken subvolume resize Fiona Ebner
  4 siblings, 0 replies; 6+ messages in thread
From: Fiona Ebner @ 2025-03-03  9:24 UTC (permalink / raw)
  To: pve-devel

The result from the file_size_info() call is not used by
volume_export_formats() and most failure scenarios of file_size_info()
lead to an undefined return value rather than a failure. This includes
the case for a non-existent file. The default path() implementation
doesn't do any existence check either.

An interesting scenario where file_size_info() does fail, is when the
volume is corrupted or not in the queried format. But this is a rare
edge case, so an early check doesn't seem worth it. It will be caught
by volume_export() itself, or in case of VM migration, also when
querying the size during scanning of local volumes.

While checking for the definedness of $size could serve as an early
sanity check, it is not currently done and other plugins don't do such
early checks in their implementation of volume_export_formats()
either. Keep the implementation abstract in Plugin.pm too and avoid
doing IO. Callers that want to do early existence checks or similar
can do so themselves explicitly, covering all plugins.

Signed-off-by: Fiona Ebner <f.ebner@proxmox.com>
---
 src/PVE/Storage/Plugin.pm | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/src/PVE/Storage/Plugin.pm b/src/PVE/Storage/Plugin.pm
index ce1530e..ca70c03 100644
--- a/src/PVE/Storage/Plugin.pm
+++ b/src/PVE/Storage/Plugin.pm
@@ -1733,10 +1733,7 @@ sub volume_export {
 sub volume_export_formats {
     my ($class, $scfg, $storeid, $volname, $snapshot, $base_snapshot, $with_snapshots) = @_;
     if ($scfg->{path} && !defined($snapshot) && !defined($base_snapshot)) {
-	my ($file) = $class->path($scfg, $volname, $storeid)
-	    or return;
 	my $format = ($class->parse_volname($volname))[6];
-	my $size = file_size_info($file, undef, $format);
 
 	if ($with_snapshots) {
 	    return ($format.'+size') if ($format eq 'qcow2' || $format eq 'vmdk');
-- 
2.39.5



_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel


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

* [pve-devel] [PATCH v2 storage 4/5] api: volume info: do not fail for zero-sized subvolumes
  2025-03-03  9:24 [pve-devel] [PATCH-SERIES v2 storage 0/5] unsized subvol regression fix and improvements Fiona Ebner
                   ` (2 preceding siblings ...)
  2025-03-03  9:24 ` [pve-devel] [PATCH v2 storage 3/5] plugin: volume export formats: avoid superfluous file_size_info() call Fiona Ebner
@ 2025-03-03  9:24 ` Fiona Ebner
  2025-03-03  9:24 ` [pve-devel] [PATCH v2 storage 5/5] btrfs: die early for broken subvolume resize Fiona Ebner
  4 siblings, 0 replies; 6+ messages in thread
From: Fiona Ebner @ 2025-03-03  9:24 UTC (permalink / raw)
  To: pve-devel

The special case of size being zero is supported if the volume is of
format 'subvol' is a special use case supported in Proxmox VE.

Signed-off-by: Fiona Ebner <f.ebner@proxmox.com>
---
 src/PVE/API2/Storage/Content.pm | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/src/PVE/API2/Storage/Content.pm b/src/PVE/API2/Storage/Content.pm
index fe0ad4a..fbd371c 100644
--- a/src/PVE/API2/Storage/Content.pm
+++ b/src/PVE/API2/Storage/Content.pm
@@ -324,7 +324,9 @@ __PACKAGE__->register_method ({
 
 	my $path = PVE::Storage::path($cfg, $volid);
 	my ($size, $format, $used, $parent) =  PVE::Storage::volume_size_info($cfg, $volid);
-	die "volume_size_info on '$volid' failed\n" if !($format && $size);
+	die "volume_size_info on '$volid' failed - no format\n" if !$format;
+	die "volume_size_info on '$volid' failed - no size\n" if !defined($size);
+	die "volume '$volid' has size zero\n" if !$size && $format ne 'subvol';
 
 	my $entry = {
 	    path => $path,
-- 
2.39.5



_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel


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

* [pve-devel] [PATCH v2 storage 5/5] btrfs: die early for broken subvolume resize
  2025-03-03  9:24 [pve-devel] [PATCH-SERIES v2 storage 0/5] unsized subvol regression fix and improvements Fiona Ebner
                   ` (3 preceding siblings ...)
  2025-03-03  9:24 ` [pve-devel] [PATCH v2 storage 4/5] api: volume info: do not fail for zero-sized subvolumes Fiona Ebner
@ 2025-03-03  9:24 ` Fiona Ebner
  4 siblings, 0 replies; 6+ messages in thread
From: Fiona Ebner @ 2025-03-03  9:24 UTC (permalink / raw)
  To: pve-devel

In the BTRFS plugin, resize_volume() for a subovlume currently fails
with "failed to get btrfs subvolume ID from: ". This is because the
btrfs 'subvol show' command is invoked with '-q', so there is no
output.

As btrfs quotas are currently not implemented, die early with a clean
error instead and comment out the unused code for now.

Signed-off-by: Fiona Ebner <f.ebner@proxmox.com>
---

Changes in v2:
* comment out dead code, squash patches

 src/PVE/Storage/BTRFSPlugin.pm | 28 ++++++++++++++++------------
 1 file changed, 16 insertions(+), 12 deletions(-)

diff --git a/src/PVE/Storage/BTRFSPlugin.pm b/src/PVE/Storage/BTRFSPlugin.pm
index b1f7912..ce21297 100644
--- a/src/PVE/Storage/BTRFSPlugin.pm
+++ b/src/PVE/Storage/BTRFSPlugin.pm
@@ -232,14 +232,15 @@ sub btrfs_cmd {
     return $msg;
 }
 
-sub btrfs_get_subvol_id {
-    my ($class, $path) = @_;
-    my $info = $class->btrfs_cmd(['subvolume', 'show', '--', $path]);
-    if ($info !~ /^\s*(?:Object|Subvolume) ID:\s*(\d+)$/m) {
-	die "failed to get btrfs subvolume ID from: $info\n";
-    }
-    return $1;
-}
+# NOTE: this function is currently boken, because btrfs_cmd uses '-q' so there will be no output.
+#sub btrfs_get_subvol_id {
+#    my ($class, $path) = @_;
+#    my $info = $class->btrfs_cmd(['subvolume', 'show', '--', $path]);
+#    if ($info !~ /^\s*(?:Object|Subvolume) ID:\s*(\d+)$/m) {
+#	die "failed to get btrfs subvolume ID from: $info\n";
+#    }
+#    return $1;
+#}
 
 my sub chattr : prototype($$$) {
     my ($fh, $mask, $xor) = @_;
@@ -497,10 +498,13 @@ sub volume_resize {
 
     my $format = ($class->parse_volname($volname))[6];
     if ($format eq 'subvol') {
-	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]);
-	return undef;
+	# NOTE: `btrfs send/recv` actually drops quota information so supporting subvolumes with
+	# quotas doesn't play nice with send/recv.
+	die "cannot resize subvolume - btrfs quotas are currently not supported\n";
+	# 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]);
+	# return undef;
     }
 
     return PVE::Storage::Plugin::volume_resize(@_);
-- 
2.39.5



_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel


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

end of thread, other threads:[~2025-03-03  9:25 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2025-03-03  9:24 [pve-devel] [PATCH-SERIES v2 storage 0/5] unsized subvol regression fix and improvements Fiona Ebner
2025-03-03  9:24 ` [pve-devel] [PATCH v2 storage 1/5] plugin: file size info: be consistent about size of directory subvol Fiona Ebner
2025-03-03  9:24 ` [pve-devel] [PATCH v2 storage 2/5] btrfs: fix volume size info for subvolumes in scalar context Fiona Ebner
2025-03-03  9:24 ` [pve-devel] [PATCH v2 storage 3/5] plugin: volume export formats: avoid superfluous file_size_info() call Fiona Ebner
2025-03-03  9:24 ` [pve-devel] [PATCH v2 storage 4/5] api: volume info: do not fail for zero-sized subvolumes Fiona Ebner
2025-03-03  9:24 ` [pve-devel] [PATCH v2 storage 5/5] btrfs: die early for broken subvolume resize Fiona Ebner

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
Service provided by Proxmox Server Solutions GmbH | Privacy | Legal