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>
This commit is contained in:
parent
ba5e8f2e2d
commit
4082bd3d73
|
@ -157,18 +157,11 @@ static struct btrfs_qgroup *add_qgroup_rb(struct btrfs_fs_info *fs_info,
|
|||
return qgroup;
|
||||
}
|
||||
|
||||
/* must be called with qgroup_lock held */
|
||||
static int del_qgroup_rb(struct btrfs_fs_info *fs_info, u64 qgroupid)
|
||||
static void __del_qgroup_rb(struct btrfs_qgroup *qgroup)
|
||||
{
|
||||
struct btrfs_qgroup *qgroup = find_qgroup_rb(fs_info, qgroupid);
|
||||
struct btrfs_qgroup_list *list;
|
||||
|
||||
if (!qgroup)
|
||||
return -ENOENT;
|
||||
|
||||
rb_erase(&qgroup->node, &fs_info->qgroup_tree);
|
||||
list_del(&qgroup->dirty);
|
||||
|
||||
while (!list_empty(&qgroup->groups)) {
|
||||
list = list_first_entry(&qgroup->groups,
|
||||
struct btrfs_qgroup_list, next_group);
|
||||
|
@ -185,7 +178,18 @@ static int del_qgroup_rb(struct btrfs_fs_info *fs_info, u64 qgroupid)
|
|||
kfree(list);
|
||||
}
|
||||
kfree(qgroup);
|
||||
}
|
||||
|
||||
/* must be called with qgroup_lock held */
|
||||
static int del_qgroup_rb(struct btrfs_fs_info *fs_info, u64 qgroupid)
|
||||
{
|
||||
struct btrfs_qgroup *qgroup = find_qgroup_rb(fs_info, qgroupid);
|
||||
|
||||
if (!qgroup)
|
||||
return -ENOENT;
|
||||
|
||||
rb_erase(&qgroup->node, &fs_info->qgroup_tree);
|
||||
__del_qgroup_rb(qgroup);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -435,30 +439,11 @@ void btrfs_free_qgroup_config(struct btrfs_fs_info *fs_info)
|
|||
{
|
||||
struct rb_node *n;
|
||||
struct btrfs_qgroup *qgroup;
|
||||
struct btrfs_qgroup_list *list;
|
||||
|
||||
while ((n = rb_first(&fs_info->qgroup_tree))) {
|
||||
qgroup = rb_entry(n, struct btrfs_qgroup, node);
|
||||
rb_erase(n, &fs_info->qgroup_tree);
|
||||
|
||||
while (!list_empty(&qgroup->groups)) {
|
||||
list = list_first_entry(&qgroup->groups,
|
||||
struct btrfs_qgroup_list,
|
||||
next_group);
|
||||
list_del(&list->next_group);
|
||||
list_del(&list->next_member);
|
||||
kfree(list);
|
||||
}
|
||||
|
||||
while (!list_empty(&qgroup->members)) {
|
||||
list = list_first_entry(&qgroup->members,
|
||||
struct btrfs_qgroup_list,
|
||||
next_member);
|
||||
list_del(&list->next_group);
|
||||
list_del(&list->next_member);
|
||||
kfree(list);
|
||||
}
|
||||
kfree(qgroup);
|
||||
__del_qgroup_rb(qgroup);
|
||||
}
|
||||
/*
|
||||
* we call btrfs_free_qgroup_config() when umounting
|
||||
|
|
Loading…
Reference in New Issue