diff options
author | Wang Shilong <wangsl.fnst@cn.fujitsu.com> | 2013-08-13 21:13:36 -0400 |
---|---|---|
committer | Chris Mason <chris.mason@fusionio.com> | 2013-09-01 08:15:45 -0400 |
commit | 4082bd3d734c41b122a91d2a5aded4b76baa84b2 (patch) | |
tree | a4501aaa7647d46f757bf74141c3c329c1b7c577 /fs/btrfs/qgroup.c | |
parent | ba5e8f2e2d3074bf151dd222dae9bb400e621b82 (diff) |
Btrfs: fix oops when writing dirty qgroups to disk
When disabling quota, we should clear out list 'dirty_qgroups',otherwise,
we will get oops if enabling quota again. Fix this by abstracting similar
code from del_qgroup_rb().
Signed-off-by: Wang Shilong <wangsl.fnst@cn.fujitsu.com>
Reviewed-by: Miao Xie <miaox@cn.fujitsu.com>
Reviewed-by: Arne Jansen <sensille@gmx.net>
Signed-off-by: Josef Bacik <jbacik@fusionio.com>
Signed-off-by: Chris Mason <chris.mason@fusionio.com>
Diffstat (limited to 'fs/btrfs/qgroup.c')
-rw-r--r-- | fs/btrfs/qgroup.c | 41 |
1 files changed, 13 insertions, 28 deletions
diff --git a/fs/btrfs/qgroup.c b/fs/btrfs/qgroup.c index 64a9e3cb9453..57b9805873f7 100644 --- a/fs/btrfs/qgroup.c +++ b/fs/btrfs/qgroup.c | |||
@@ -157,18 +157,11 @@ static struct btrfs_qgroup *add_qgroup_rb(struct btrfs_fs_info *fs_info, | |||
157 | return qgroup; | 157 | return qgroup; |
158 | } | 158 | } |
159 | 159 | ||
160 | /* must be called with qgroup_lock held */ | 160 | static void __del_qgroup_rb(struct btrfs_qgroup *qgroup) |
161 | static int del_qgroup_rb(struct btrfs_fs_info *fs_info, u64 qgroupid) | ||
162 | { | 161 | { |
163 | struct btrfs_qgroup *qgroup = find_qgroup_rb(fs_info, qgroupid); | ||
164 | struct btrfs_qgroup_list *list; | 162 | struct btrfs_qgroup_list *list; |
165 | 163 | ||
166 | if (!qgroup) | ||
167 | return -ENOENT; | ||
168 | |||
169 | rb_erase(&qgroup->node, &fs_info->qgroup_tree); | ||
170 | list_del(&qgroup->dirty); | 164 | list_del(&qgroup->dirty); |
171 | |||
172 | while (!list_empty(&qgroup->groups)) { | 165 | while (!list_empty(&qgroup->groups)) { |
173 | list = list_first_entry(&qgroup->groups, | 166 | list = list_first_entry(&qgroup->groups, |
174 | struct btrfs_qgroup_list, next_group); | 167 | struct btrfs_qgroup_list, next_group); |
@@ -185,7 +178,18 @@ static int del_qgroup_rb(struct btrfs_fs_info *fs_info, u64 qgroupid) | |||
185 | kfree(list); | 178 | kfree(list); |
186 | } | 179 | } |
187 | kfree(qgroup); | 180 | kfree(qgroup); |
181 | } | ||
188 | 182 | ||
183 | /* must be called with qgroup_lock held */ | ||
184 | static int del_qgroup_rb(struct btrfs_fs_info *fs_info, u64 qgroupid) | ||
185 | { | ||
186 | struct btrfs_qgroup *qgroup = find_qgroup_rb(fs_info, qgroupid); | ||
187 | |||
188 | if (!qgroup) | ||
189 | return -ENOENT; | ||
190 | |||
191 | rb_erase(&qgroup->node, &fs_info->qgroup_tree); | ||
192 | __del_qgroup_rb(qgroup); | ||
189 | return 0; | 193 | return 0; |
190 | } | 194 | } |
191 | 195 | ||
@@ -435,30 +439,11 @@ void btrfs_free_qgroup_config(struct btrfs_fs_info *fs_info) | |||
435 | { | 439 | { |
436 | struct rb_node *n; | 440 | struct rb_node *n; |
437 | struct btrfs_qgroup *qgroup; | 441 | struct btrfs_qgroup *qgroup; |
438 | struct btrfs_qgroup_list *list; | ||
439 | 442 | ||
440 | while ((n = rb_first(&fs_info->qgroup_tree))) { | 443 | while ((n = rb_first(&fs_info->qgroup_tree))) { |
441 | qgroup = rb_entry(n, struct btrfs_qgroup, node); | 444 | qgroup = rb_entry(n, struct btrfs_qgroup, node); |
442 | rb_erase(n, &fs_info->qgroup_tree); | 445 | rb_erase(n, &fs_info->qgroup_tree); |
443 | 446 | __del_qgroup_rb(qgroup); | |
444 | while (!list_empty(&qgroup->groups)) { | ||
445 | list = list_first_entry(&qgroup->groups, | ||
446 | struct btrfs_qgroup_list, | ||
447 | next_group); | ||
448 | list_del(&list->next_group); | ||
449 | list_del(&list->next_member); | ||
450 | kfree(list); | ||
451 | } | ||
452 | |||
453 | while (!list_empty(&qgroup->members)) { | ||
454 | list = list_first_entry(&qgroup->members, | ||
455 | struct btrfs_qgroup_list, | ||
456 | next_member); | ||
457 | list_del(&list->next_group); | ||
458 | list_del(&list->next_member); | ||
459 | kfree(list); | ||
460 | } | ||
461 | kfree(qgroup); | ||
462 | } | 447 | } |
463 | /* | 448 | /* |
464 | * we call btrfs_free_qgroup_config() when umounting | 449 | * we call btrfs_free_qgroup_config() when umounting |