diff --git a/quota/linux-lib.pl b/quota/linux-lib.pl index 188c0fb05..f37bf804e 100755 --- a/quota/linux-lib.pl +++ b/quota/linux-lib.pl @@ -1482,9 +1482,9 @@ return defined($_[0]) && $_[0] =~ /^\d+\/\d+$/ ? 1 : 0; Sets the referenced or exclusive byte limit for a Btrfs qgroup. If qgroup is undef, path must be a subvolume and its level-0 qgroup is changed. If bytes -is undef, the limit is removed. If an exceeded limit blocks the update, quota -enforcement is temporarily overridden for one retry. Returns undef on success -or an error message on failure. +is undef, the limit is removed. If quota enforcement on path or one of its +parent qgroups blocks the transaction, it is temporarily overridden for one +retry. Returns undef on success or an error message on failure. =cut sub set_btrfs_qgroup_limit @@ -1502,9 +1502,10 @@ push(@args, $qgroup) if (defined($qgroup)); push(@args, $path); my ($out, $err) = &run_btrfs_command(1, @args); -# An exceeded qgroup can block the metadata write needed to raise or remove its -# own limit. Retry once with the kernel's administrative override, preserving -# the previous state and restoring enforcement immediately after the command. +# A limit on the command path or one of its parent qgroups can block the +# transaction needed to update any qgroup limit. Retry once with the kernel's +# administrative override, preserving the previous state and restoring +# enforcement immediately after the command. if ($err && $err =~ /disk quota exceeded/i) { my $uuid = &btrfs_filesystem_uuid($path); my $sysfs = $btrfs_sysfs_root || "/sys/fs/btrfs"; diff --git a/quota/save_btrfs.cgi b/quota/save_btrfs.cgi index 7ec2ef454..f49a7b97e 100755 --- a/quota/save_btrfs.cgi +++ b/quota/save_btrfs.cgi @@ -68,8 +68,8 @@ $same_referenced = &same_limit( $same_exclusive = &same_limit( $max_exclusive, $qgroup->{'max_exclusive'}); -# Apply only changed limits, keeping an unrelated existing over-limit setting -# from causing Btrfs to reject an otherwise valid update. +# Apply only changed limits so each independent setting is left untouched when +# the submitted value already matches it. if (!$same_referenced) { $err = &set_btrfs_qgroup_limit( $dir, $in{'qgroup'}, $max_referenced, 0); diff --git a/quota/t/run-tests.t b/quota/t/run-tests.t index 5939a9bda..3485f61f4 100644 --- a/quota/t/run-tests.t +++ b/quota/t/run-tests.t @@ -287,8 +287,8 @@ is(main::set_btrfs_qgroup_limit("/srv/btrfs", "1/100", "1M"), is(main::assign_btrfs_qgroup("/srv/btrfs", "bad", "1/100"), "Invalid child Btrfs qgroup ID", "invalid child assignment is rejected"); -# An existing over-limit qgroup must not prevent an administrator from raising -# or removing its limit. The kernel override is restored after the retry. +# A qgroup-limit transaction rejected by quota enforcement is retried once, +# and the kernel override is restored immediately afterward. my $override_root = tempdir(CLEANUP => 1); my $override_uuid = "abcdef01-2345-6789-abcd-ef0123456789"; make_path("$override_root/$override_uuid"); @@ -305,12 +305,12 @@ local $main::btrfs_sysfs_root = $override_root; { 'out' => "", 'status' => 0 }, ); is(main::set_btrfs_qgroup_limit("/srv/btrfs", "1/100", 2097152), - undef, "over-limit qgroup updates retry with the administrative override"); + undef, "an EDQUOT limit update retries with the administrative override"); open($override_fh, '<', "$override_root/$override_uuid/quota_override") or die $!; is(<$override_fh>, "0\n", "quota enforcement is restored after the retry"); close($override_fh); -is(scalar(@commands), 3, "one status lookup and one limit retry are run"); +is(scalar(@commands), 3, "one UUID lookup and one limit retry are run"); @responses = ({ 'out' => "ERROR: qgroup exists\n", 'status' => 1 }); is(main::create_btrfs_qgroup("/srv/btrfs", "1/100"),