-
Notifications
You must be signed in to change notification settings - Fork 0
/
0002-Btrfs-remove-subvolume-qgroup-automatically-with-qgr.patch
124 lines (119 loc) · 3.72 KB
/
0002-Btrfs-remove-subvolume-qgroup-automatically-with-qgr.patch
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
From 1cf50c0856473281d8c3ec3782bfb4d8e4b950a5 Mon Sep 17 00:00:00 2001
From: Wang Shilong <wangsl.fnst@cn.fujitsu.com>
Date: Sat, 2 Nov 2013 16:12:19 +0800
Subject: [PATCH 2/2] Btrfs: remove subvolume qgroup automatically with qgroup
enabled
When we delete subvolume, the corresponding qgroup will be dead,
because Qgroupid/Subvolumeid is not resued.
Qgroup accounting will also be triggered to update subvolume qgroup's
parent qgroup's referenced size.
Signed-off-by: Wang Shilong <wangsl.fnst@cn.fujitsu.com>
---
fs/btrfs/ctree.h | 2 ++
fs/btrfs/ioctl.c | 5 ++++-
fs/btrfs/qgroup.c | 65 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 71 insertions(+), 1 deletion(-)
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
index 941019d..19a6575 100644
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -3997,6 +3997,8 @@ int btrfs_create_qgroup(struct btrfs_trans_handle *trans,
char *name);
int btrfs_remove_qgroup(struct btrfs_trans_handle *trans,
struct btrfs_fs_info *fs_info, u64 qgroupid);
+int btrfs_remove_subvolume_qgroup(struct btrfs_trans_handle *trans,
+ struct btrfs_fs_info *fs_info, u64 qgroupid);
int btrfs_limit_qgroup(struct btrfs_trans_handle *trans,
struct btrfs_fs_info *fs_info, u64 qgroupid,
struct btrfs_qgroup_limit *limit);
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
index 6523108..fdff50d 100644
--- a/fs/btrfs/ioctl.c
+++ b/fs/btrfs/ioctl.c
@@ -2250,7 +2250,10 @@ static noinline int btrfs_ioctl_snap_destroy(struct file *file,
goto out_end_trans;
}
}
-
+ ret = btrfs_remove_subvolume_qgroup(trans, root->fs_info,
+ dest->root_key.objectid);
+ if (ret)
+ btrfs_abort_transaction(trans, root, ret);
out_end_trans:
trans->block_rsv = NULL;
trans->bytes_reserved = 0;
diff --git a/fs/btrfs/qgroup.c b/fs/btrfs/qgroup.c
index 81679cb..6521ced 100644
--- a/fs/btrfs/qgroup.c
+++ b/fs/btrfs/qgroup.c
@@ -1983,3 +1983,68 @@ btrfs_qgroup_rescan_resume(struct btrfs_fs_info *fs_info)
btrfs_queue_worker(&fs_info->qgroup_rescan_workers,
&fs_info->qgroup_rescan_work);
}
+
+int btrfs_remove_subvolume_qgroup(struct btrfs_trans_handle *trans,
+ struct btrfs_fs_info *fs_info,
+ u64 qgroupid)
+{
+ struct btrfs_root *quota_root;
+ struct btrfs_qgroup *qgroup;
+ struct btrfs_qgroup_list *list;
+ int ret = 0;
+
+ mutex_lock(&fs_info->qgroup_ioctl_lock);
+ quota_root = fs_info->quota_root;
+ if (!quota_root) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ qgroup = find_qgroup_rb(fs_info, qgroupid);
+ if (!qgroup) {
+ ret = -ENOENT;
+ goto out;
+ }
+
+ list_for_each_entry(list, &qgroup->groups, next_group) {
+ ret = del_qgroup_relation_item(trans, quota_root, qgroupid,
+ list->group->qgroupid);
+ if (ret && ret != -ENOENT)
+ goto out;
+ ret = del_qgroup_relation_item(trans, quota_root,
+ list->group->qgroupid, qgroupid);
+ if (ret && ret != -ENOENT)
+ goto out;
+ }
+
+ /*
+ * this should not happen with strict hierarchical level
+ * qgroup.
+ */
+ list_for_each_entry(list, &qgroup->members, next_group) {
+ ret = del_qgroup_relation_item(trans, quota_root,
+ list->member->qgroupid, qgroupid);
+ if (ret && ret != -ENOENT)
+ goto out;
+ ret = del_qgroup_relation_item(trans, quota_root,
+ qgroupid, list->member->qgroupid);
+ if (ret && ret != -ENOENT)
+ goto out;
+ }
+ ret = del_qgroup_item(trans, quota_root, qgroupid);
+ if (ret && ret != -ENOENT)
+ goto out;
+ spin_lock(&fs_info->qgroup_lock);
+ ret = qgroup_account_ref_step2(quota_root->fs_info,
+ quota_root->fs_info->qgroup_ulist, -1,
+ qgroup->rfer, qgroup);
+ del_qgroup_rb(quota_root->fs_info, qgroupid);
+ spin_unlock(&fs_info->qgroup_lock);
+out:
+ mutex_unlock(&fs_info->qgroup_ioctl_lock);
+ if (ret == -ENOENT)
+ ret = 0;
+ return ret;
+
+}
+
--
1.8.3.1