Skip to content

Commit 92825b0

Browse files
committed
Merge tag 'for-5.1-part2-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux
Pull btrfs fixes from David Sterba: "Correctness and a deadlock fixes" * tag 'for-5.1-part2-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux: btrfs: zstd: ensure reclaim timer is properly cleaned up btrfs: move ulist allocation out of transaction in quota enable btrfs: save drop_progress if we drop refs at all btrfs: check for refs on snapshot delete resume Btrfs: fix deadlock between clone/dedupe and rename Btrfs: fix corruption reading shared and compressed extents after hole punching
2 parents 1fbf3e4 + d386515 commit 92825b0

File tree

7 files changed

+90
-38
lines changed

7 files changed

+90
-38
lines changed

fs/btrfs/ctree.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1210,6 +1210,8 @@ enum {
12101210
* Set for the subvolume tree owning the reloc tree.
12111211
*/
12121212
BTRFS_ROOT_DEAD_RELOC_TREE,
1213+
/* Mark dead root stored on device whose cleanup needs to be resumed */
1214+
BTRFS_ROOT_DEAD_TREE,
12131215
};
12141216

12151217
/*

fs/btrfs/extent-tree.c

Lines changed: 67 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8764,13 +8764,16 @@ struct walk_control {
87648764
u64 refs[BTRFS_MAX_LEVEL];
87658765
u64 flags[BTRFS_MAX_LEVEL];
87668766
struct btrfs_key update_progress;
8767+
struct btrfs_key drop_progress;
8768+
int drop_level;
87678769
int stage;
87688770
int level;
87698771
int shared_level;
87708772
int update_ref;
87718773
int keep_locks;
87728774
int reada_slot;
87738775
int reada_count;
8776+
int restarted;
87748777
};
87758778

87768779
#define DROP_REFERENCE 1
@@ -8933,6 +8936,33 @@ static noinline int walk_down_proc(struct btrfs_trans_handle *trans,
89338936
return 0;
89348937
}
89358938

8939+
/*
8940+
* This is used to verify a ref exists for this root to deal with a bug where we
8941+
* would have a drop_progress key that hadn't been updated properly.
8942+
*/
8943+
static int check_ref_exists(struct btrfs_trans_handle *trans,
8944+
struct btrfs_root *root, u64 bytenr, u64 parent,
8945+
int level)
8946+
{
8947+
struct btrfs_path *path;
8948+
struct btrfs_extent_inline_ref *iref;
8949+
int ret;
8950+
8951+
path = btrfs_alloc_path();
8952+
if (!path)
8953+
return -ENOMEM;
8954+
8955+
ret = lookup_extent_backref(trans, path, &iref, bytenr,
8956+
root->fs_info->nodesize, parent,
8957+
root->root_key.objectid, level, 0);
8958+
btrfs_free_path(path);
8959+
if (ret == -ENOENT)
8960+
return 0;
8961+
if (ret < 0)
8962+
return ret;
8963+
return 1;
8964+
}
8965+
89368966
/*
89378967
* helper to process tree block pointer.
89388968
*
@@ -9087,6 +9117,23 @@ static noinline int do_walk_down(struct btrfs_trans_handle *trans,
90879117
parent = 0;
90889118
}
90899119

9120+
/*
9121+
* If we had a drop_progress we need to verify the refs are set
9122+
* as expected. If we find our ref then we know that from here
9123+
* on out everything should be correct, and we can clear the
9124+
* ->restarted flag.
9125+
*/
9126+
if (wc->restarted) {
9127+
ret = check_ref_exists(trans, root, bytenr, parent,
9128+
level - 1);
9129+
if (ret < 0)
9130+
goto out_unlock;
9131+
if (ret == 0)
9132+
goto no_delete;
9133+
ret = 0;
9134+
wc->restarted = 0;
9135+
}
9136+
90909137
/*
90919138
* Reloc tree doesn't contribute to qgroup numbers, and we have
90929139
* already accounted them at merge time (replace_path),
@@ -9102,13 +9149,23 @@ static noinline int do_walk_down(struct btrfs_trans_handle *trans,
91029149
ret);
91039150
}
91049151
}
9152+
9153+
/*
9154+
* We need to update the next key in our walk control so we can
9155+
* update the drop_progress key accordingly. We don't care if
9156+
* find_next_key doesn't find a key because that means we're at
9157+
* the end and are going to clean up now.
9158+
*/
9159+
wc->drop_level = level;
9160+
find_next_key(path, level, &wc->drop_progress);
9161+
91059162
ret = btrfs_free_extent(trans, root, bytenr, fs_info->nodesize,
91069163
parent, root->root_key.objectid,
91079164
level - 1, 0);
91089165
if (ret)
91099166
goto out_unlock;
91109167
}
9111-
9168+
no_delete:
91129169
*lookup_info = 1;
91139170
ret = 1;
91149171

@@ -9425,6 +9482,7 @@ int btrfs_drop_snapshot(struct btrfs_root *root,
94259482
}
94269483
}
94279484

9485+
wc->restarted = test_bit(BTRFS_ROOT_DEAD_TREE, &root->state);
94289486
wc->level = level;
94299487
wc->shared_level = -1;
94309488
wc->stage = DROP_REFERENCE;
@@ -9452,12 +9510,14 @@ int btrfs_drop_snapshot(struct btrfs_root *root,
94529510
}
94539511

94549512
if (wc->stage == DROP_REFERENCE) {
9455-
level = wc->level;
9456-
btrfs_node_key(path->nodes[level],
9457-
&root_item->drop_progress,
9458-
path->slots[level]);
9459-
root_item->drop_level = level;
9460-
}
9513+
wc->drop_level = wc->level;
9514+
btrfs_node_key_to_cpu(path->nodes[wc->drop_level],
9515+
&wc->drop_progress,
9516+
path->slots[wc->drop_level]);
9517+
}
9518+
btrfs_cpu_key_to_disk(&root_item->drop_progress,
9519+
&wc->drop_progress);
9520+
root_item->drop_level = wc->drop_level;
94619521

94629522
BUG_ON(wc->level == 0);
94639523
if (btrfs_should_end_transaction(trans) ||

fs/btrfs/extent_io.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2995,11 +2995,11 @@ static int __do_readpage(struct extent_io_tree *tree,
29952995
*/
29962996
if (test_bit(EXTENT_FLAG_COMPRESSED, &em->flags) &&
29972997
prev_em_start && *prev_em_start != (u64)-1 &&
2998-
*prev_em_start != em->orig_start)
2998+
*prev_em_start != em->start)
29992999
force_bio_submit = true;
30003000

30013001
if (prev_em_start)
3002-
*prev_em_start = em->orig_start;
3002+
*prev_em_start = em->start;
30033003

30043004
free_extent_map(em);
30053005
em = NULL;

fs/btrfs/ioctl.c

Lines changed: 3 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -3207,21 +3207,6 @@ static long btrfs_ioctl_dev_info(struct btrfs_fs_info *fs_info,
32073207
return ret;
32083208
}
32093209

3210-
static void btrfs_double_inode_unlock(struct inode *inode1, struct inode *inode2)
3211-
{
3212-
inode_unlock(inode1);
3213-
inode_unlock(inode2);
3214-
}
3215-
3216-
static void btrfs_double_inode_lock(struct inode *inode1, struct inode *inode2)
3217-
{
3218-
if (inode1 < inode2)
3219-
swap(inode1, inode2);
3220-
3221-
inode_lock_nested(inode1, I_MUTEX_PARENT);
3222-
inode_lock_nested(inode2, I_MUTEX_CHILD);
3223-
}
3224-
32253210
static void btrfs_double_extent_unlock(struct inode *inode1, u64 loff1,
32263211
struct inode *inode2, u64 loff2, u64 len)
32273212
{
@@ -3956,7 +3941,7 @@ static int btrfs_remap_file_range_prep(struct file *file_in, loff_t pos_in,
39563941
if (same_inode)
39573942
inode_lock(inode_in);
39583943
else
3959-
btrfs_double_inode_lock(inode_in, inode_out);
3944+
lock_two_nondirectories(inode_in, inode_out);
39603945

39613946
/* don't make the dst file partly checksummed */
39623947
if ((BTRFS_I(inode_in)->flags & BTRFS_INODE_NODATASUM) !=
@@ -4013,7 +3998,7 @@ static int btrfs_remap_file_range_prep(struct file *file_in, loff_t pos_in,
40133998
if (same_inode)
40143999
inode_unlock(inode_in);
40154000
else
4016-
btrfs_double_inode_unlock(inode_in, inode_out);
4001+
unlock_two_nondirectories(inode_in, inode_out);
40174002

40184003
return ret;
40194004
}
@@ -4043,7 +4028,7 @@ loff_t btrfs_remap_file_range(struct file *src_file, loff_t off,
40434028
if (same_inode)
40444029
inode_unlock(src_inode);
40454030
else
4046-
btrfs_double_inode_unlock(src_inode, dst_inode);
4031+
unlock_two_nondirectories(src_inode, dst_inode);
40474032

40484033
return ret < 0 ? ret : len;
40494034
}

fs/btrfs/qgroup.c

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -894,6 +894,12 @@ int btrfs_quota_enable(struct btrfs_fs_info *fs_info)
894894
if (fs_info->quota_root)
895895
goto out;
896896

897+
fs_info->qgroup_ulist = ulist_alloc(GFP_KERNEL);
898+
if (!fs_info->qgroup_ulist) {
899+
ret = -ENOMEM;
900+
goto out;
901+
}
902+
897903
/*
898904
* 1 for quota root item
899905
* 1 for BTRFS_QGROUP_STATUS item
@@ -909,13 +915,6 @@ int btrfs_quota_enable(struct btrfs_fs_info *fs_info)
909915
goto out;
910916
}
911917

912-
fs_info->qgroup_ulist = ulist_alloc(GFP_KERNEL);
913-
if (!fs_info->qgroup_ulist) {
914-
ret = -ENOMEM;
915-
btrfs_abort_transaction(trans, ret);
916-
goto out;
917-
}
918-
919918
/*
920919
* initially create the quota tree
921920
*/

fs/btrfs/root-tree.c

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -263,8 +263,10 @@ int btrfs_find_orphan_roots(struct btrfs_fs_info *fs_info)
263263
if (root) {
264264
WARN_ON(!test_bit(BTRFS_ROOT_ORPHAN_ITEM_INSERTED,
265265
&root->state));
266-
if (btrfs_root_refs(&root->root_item) == 0)
266+
if (btrfs_root_refs(&root->root_item) == 0) {
267+
set_bit(BTRFS_ROOT_DEAD_TREE, &root->state);
267268
btrfs_add_dead_root(root);
269+
}
268270
continue;
269271
}
270272

@@ -310,8 +312,10 @@ int btrfs_find_orphan_roots(struct btrfs_fs_info *fs_info)
310312
break;
311313
}
312314

313-
if (btrfs_root_refs(&root->root_item) == 0)
315+
if (btrfs_root_refs(&root->root_item) == 0) {
316+
set_bit(BTRFS_ROOT_DEAD_TREE, &root->state);
314317
btrfs_add_dead_root(root);
318+
}
315319
}
316320

317321
btrfs_free_path(path);

fs/btrfs/zstd.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -195,8 +195,7 @@ static void zstd_cleanup_workspace_manager(void)
195195
struct workspace *workspace;
196196
int i;
197197

198-
del_timer(&wsm.timer);
199-
198+
spin_lock(&wsm.lock);
200199
for (i = 0; i < ZSTD_BTRFS_MAX_LEVEL; i++) {
201200
while (!list_empty(&wsm.idle_ws[i])) {
202201
workspace = container_of(wsm.idle_ws[i].next,
@@ -206,6 +205,9 @@ static void zstd_cleanup_workspace_manager(void)
206205
wsm.ops->free_workspace(&workspace->list);
207206
}
208207
}
208+
spin_unlock(&wsm.lock);
209+
210+
del_timer_sync(&wsm.timer);
209211
}
210212

211213
/*

0 commit comments

Comments
 (0)