Btrfs: prevent qgroup config corruption by qgroup destroy
cover Btrfs: prevent qgroup config corruption by qgroup destroy
When destroying an active qgroup with qgroup destroy, the internal config will become corrupt. This series adds 2 fixes: the first add a recovery, if the config is already corrupt, and the second prevents the destroy if it is still active.
Arne Jansen (2):
btrfs: ignore orphan qgroup relations
btrfs: prevent qgroup destroy when there are still relations
fs/btrfs/qgroup.c | 20 +++++++++++++++++++- 1 files changed, 19 insertions(+), 1 deletions(-)
Signature · 1 line
1.7.3.4
PATCH 1/2 Btrfs: ignore orphan qgroup relations
If a qgroup that has still assignments is deleted by the user, the corresponding relations are left in the tree. This leads to an unmountable filesystem. With this patch, those relations are simple ignored.
--- fs/btrfs/qgroup.c | 7 +++++++ 1 files changed, 7 insertions(+), 0 deletions(-)
fs/btrfs/qgroup.c +7 -0
@@ -379,6 +379,13 @@ next1: ret =add_relation_rb (fs_info, found_key.objectid, found_key.offset); +if (ret == -ENOENT ) { +printk (KERN_WARNING +"btrfs: orphan qgroup relation 0x%llx->0x%llx\n" , + (unsigned long long )found_key.objectid, + (unsigned long long )found_key.offset); + ret =0 ;/* ignore the error */ + }if (ret) goto out; next2:
Signature · 1 line
1.7.3.4
PATCH 2/2 Btrfs: prevent qgroup destroy when there are still relations
In reply to Arne JansenCurrently you can just destroy a qgroup even though it is in use by other qgroups or has qgroups assigned to it. This patch prevents destruction of qgroups unless they are completely unused. Otherwise destroy will return EBUSY.
--- fs/btrfs/qgroup.c | 13 ++++++++++++- 1 files changed, 12 insertions(+), 1 deletions(-)
fs/btrfs/qgroup.c +12 -1
@@ -963,17 +963,28 @@ int btrfs_remove_qgroup(struct btrfs_trans_handle *trans, struct btrfs_fs_info *fs_info, u64 qgroupid) {struct btrfs_root *quota_root; +struct btrfs_qgroup *qgroup;int ret =0 ; quota_root = fs_info->quota_root;if (!quota_root)return -EINVAL ; +/* check if there are no relations to this qgroup */ +spin_lock (&fs_info->qgroup_lock); + qgroup =find_qgroup_rb (fs_info, qgroupid); +if (qgroup) { +if (!list_empty (&qgroup->groups) || !list_empty (&qgroup->members)) { +spin_unlock (&fs_info->qgroup_lock); +return -EBUSY ; + } + } +spin_unlock (&fs_info->qgroup_lock); + ret =del_qgroup_item (trans, quota_root, qgroupid);spin_lock (&fs_info->qgroup_lock);del_qgroup_rb (quota_root->fs_info, qgroupid); -spin_unlock (&fs_info->qgroup_lock);return ret;
Signature · 1 line
1.7.3.4