mirror of
https://github.com/torvalds/linux.git
synced 2024-11-18 01:51:53 +00:00
btrfs: Add check to avoid cleanup roots already in fs_info->dead_roots.
Current btrfs_orphan_cleanup will also cleanup roots which is already in fs_info->dead_roots without protection. This will have conditional race with fs_info->cleaner_kthread. This patch will use refs in root->root_item to detect roots in dead_roots and avoid conflicts. Signed-off-by: Qu Wenruo <quwenruo@cn.fujitsu.com> Signed-off-by: Chris Mason <clm@fb.com>
This commit is contained in:
parent
21c7e75654
commit
65d33fd7a6
@ -3534,28 +3534,51 @@ int btrfs_cleanup_fs_roots(struct btrfs_fs_info *fs_info)
|
|||||||
{
|
{
|
||||||
u64 root_objectid = 0;
|
u64 root_objectid = 0;
|
||||||
struct btrfs_root *gang[8];
|
struct btrfs_root *gang[8];
|
||||||
int i;
|
int i = 0;
|
||||||
int ret;
|
int err = 0;
|
||||||
|
unsigned int ret = 0;
|
||||||
|
int index;
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
|
index = srcu_read_lock(&fs_info->subvol_srcu);
|
||||||
ret = radix_tree_gang_lookup(&fs_info->fs_roots_radix,
|
ret = radix_tree_gang_lookup(&fs_info->fs_roots_radix,
|
||||||
(void **)gang, root_objectid,
|
(void **)gang, root_objectid,
|
||||||
ARRAY_SIZE(gang));
|
ARRAY_SIZE(gang));
|
||||||
if (!ret)
|
if (!ret) {
|
||||||
|
srcu_read_unlock(&fs_info->subvol_srcu, index);
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
root_objectid = gang[ret - 1]->root_key.objectid + 1;
|
root_objectid = gang[ret - 1]->root_key.objectid + 1;
|
||||||
for (i = 0; i < ret; i++) {
|
|
||||||
int err;
|
|
||||||
|
|
||||||
|
for (i = 0; i < ret; i++) {
|
||||||
|
/* Avoid to grab roots in dead_roots */
|
||||||
|
if (btrfs_root_refs(&gang[i]->root_item) == 0) {
|
||||||
|
gang[i] = NULL;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
/* grab all the search result for later use */
|
||||||
|
gang[i] = btrfs_grab_fs_root(gang[i]);
|
||||||
|
}
|
||||||
|
srcu_read_unlock(&fs_info->subvol_srcu, index);
|
||||||
|
|
||||||
|
for (i = 0; i < ret; i++) {
|
||||||
|
if (!gang[i])
|
||||||
|
continue;
|
||||||
root_objectid = gang[i]->root_key.objectid;
|
root_objectid = gang[i]->root_key.objectid;
|
||||||
err = btrfs_orphan_cleanup(gang[i]);
|
err = btrfs_orphan_cleanup(gang[i]);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
break;
|
||||||
|
btrfs_put_fs_root(gang[i]);
|
||||||
}
|
}
|
||||||
root_objectid++;
|
root_objectid++;
|
||||||
}
|
}
|
||||||
return 0;
|
|
||||||
|
/* release the uncleaned roots due to error */
|
||||||
|
for (; i < ret; i++) {
|
||||||
|
if (gang[i])
|
||||||
|
btrfs_put_fs_root(gang[i]);
|
||||||
|
}
|
||||||
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
int btrfs_commit_super(struct btrfs_root *root)
|
int btrfs_commit_super(struct btrfs_root *root)
|
||||||
|
Loading…
Reference in New Issue
Block a user