diff mbox series

[2/2] btrfs: forbid deleting live subvol qgroup

Message ID 8ef9980c0621c82737b646b2bcf9df7b5a6dc216.1705711967.git.boris@bur.io (mailing list archive)
State New, archived
Headers show
Series btrfs: subvol qgroup lifetime invariants | expand

Commit Message

Boris Burkov Jan. 20, 2024, 12:55 a.m. UTC
If a subvolume still exists, forbid deleting its qgroup.
This behavior generally leads to incorrect behavior in squotas and
doesn't have a legitimate purpose.

Signed-off-by: Boris Burkov <boris@bur.io>
---
 fs/btrfs/qgroup.c | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

Comments

Qu Wenruo Jan. 20, 2024, 2:58 a.m. UTC | #1
On 2024/1/20 11:25, Boris Burkov wrote:
> If a subvolume still exists, forbid deleting its qgroup.
> This behavior generally leads to incorrect behavior in squotas and
> doesn't have a legitimate purpose.
>
> Signed-off-by: Boris Burkov <boris@bur.io>

Reviewed-by: Qu Wenruo <wqu@suse.com>

Thanks,
Qu

> ---
>   fs/btrfs/qgroup.c | 15 +++++++++++++++
>   1 file changed, 15 insertions(+)
>
> diff --git a/fs/btrfs/qgroup.c b/fs/btrfs/qgroup.c
> index 63b426cc7798..672896b2b7a0 100644
> --- a/fs/btrfs/qgroup.c
> +++ b/fs/btrfs/qgroup.c
> @@ -29,6 +29,7 @@
>   #include "extent-tree.h"
>   #include "root-tree.h"
>   #include "tree-checker.h"
> +#include "super.h"
>
>   enum btrfs_qgroup_mode btrfs_qgroup_mode(struct btrfs_fs_info *fs_info)
>   {
> @@ -1736,6 +1737,15 @@ int btrfs_create_qgroup(struct btrfs_trans_handle *trans, u64 qgroupid)
>   	return ret;
>   }
>
> +static bool qgroup_has_usage(struct btrfs_qgroup *qgroup)
> +{
> +	return (qgroup->rfer > 0 || qgroup->rfer_cmpr > 0 ||
> +		qgroup->excl > 0 || qgroup->excl_cmpr > 0 ||
> +		qgroup->rsv.values[BTRFS_QGROUP_RSV_DATA] > 0 ||
> +		qgroup->rsv.values[BTRFS_QGROUP_RSV_META_PREALLOC] > 0 ||
> +		qgroup->rsv.values[BTRFS_QGROUP_RSV_META_PERTRANS] > 0);
> +}
> +
>   int btrfs_remove_qgroup(struct btrfs_trans_handle *trans, u64 qgroupid)
>   {
>   	struct btrfs_fs_info *fs_info = trans->fs_info;
> @@ -1755,6 +1765,11 @@ int btrfs_remove_qgroup(struct btrfs_trans_handle *trans, u64 qgroupid)
>   		goto out;
>   	}
>
> +	if (is_fstree(qgroupid) && qgroup_has_usage(qgroup)) {
> +		ret = -EBUSY;
> +		goto out;
> +	}
> +
>   	/* Check if there are no children of this qgroup */
>   	if (!list_empty(&qgroup->members)) {
>   		ret = -EBUSY;
David Sterba Jan. 22, 2024, 8:43 p.m. UTC | #2
On Fri, Jan 19, 2024 at 04:55:59PM -0800, Boris Burkov wrote:
> If a subvolume still exists, forbid deleting its qgroup.
> This behavior generally leads to incorrect behavior in squotas and
> doesn't have a legitimate purpose.
> 
> Signed-off-by: Boris Burkov <boris@bur.io>

Reviewed-by: David Sterba <dsterba@suse.com>
diff mbox series

Patch

diff --git a/fs/btrfs/qgroup.c b/fs/btrfs/qgroup.c
index 63b426cc7798..672896b2b7a0 100644
--- a/fs/btrfs/qgroup.c
+++ b/fs/btrfs/qgroup.c
@@ -29,6 +29,7 @@ 
 #include "extent-tree.h"
 #include "root-tree.h"
 #include "tree-checker.h"
+#include "super.h"
 
 enum btrfs_qgroup_mode btrfs_qgroup_mode(struct btrfs_fs_info *fs_info)
 {
@@ -1736,6 +1737,15 @@  int btrfs_create_qgroup(struct btrfs_trans_handle *trans, u64 qgroupid)
 	return ret;
 }
 
+static bool qgroup_has_usage(struct btrfs_qgroup *qgroup)
+{
+	return (qgroup->rfer > 0 || qgroup->rfer_cmpr > 0 ||
+		qgroup->excl > 0 || qgroup->excl_cmpr > 0 ||
+		qgroup->rsv.values[BTRFS_QGROUP_RSV_DATA] > 0 ||
+		qgroup->rsv.values[BTRFS_QGROUP_RSV_META_PREALLOC] > 0 ||
+		qgroup->rsv.values[BTRFS_QGROUP_RSV_META_PERTRANS] > 0);
+}
+
 int btrfs_remove_qgroup(struct btrfs_trans_handle *trans, u64 qgroupid)
 {
 	struct btrfs_fs_info *fs_info = trans->fs_info;
@@ -1755,6 +1765,11 @@  int btrfs_remove_qgroup(struct btrfs_trans_handle *trans, u64 qgroupid)
 		goto out;
 	}
 
+	if (is_fstree(qgroupid) && qgroup_has_usage(qgroup)) {
+		ret = -EBUSY;
+		goto out;
+	}
+
 	/* Check if there are no children of this qgroup */
 	if (!list_empty(&qgroup->members)) {
 		ret = -EBUSY;