Skip to content

Commit da370f1

Browse files
committed
Merge tag 'for-4.16-rc1-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux
Pull btrfs fixes from David Sterba: "We have a few assorted fixes, some of them show up during fstests so I gave them more testing" * tag 'for-4.16-rc1-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux: btrfs: Fix use-after-free when cleaning up fs_devs with a single stale device Btrfs: fix null pointer dereference when replacing missing device btrfs: remove spurious WARN_ON(ref->count < 0) in find_parent_nodes btrfs: Ignore errors from btrfs_qgroup_trace_extent_post Btrfs: fix unexpected -EEXIST when creating new inode Btrfs: fix use-after-free on root->orphan_block_rsv Btrfs: fix btrfs_evict_inode to handle abnormal inodes correctly Btrfs: fix extent state leak from tree log Btrfs: fix crash due to not cleaning up tree log block's dirty bits Btrfs: fix deadlock in run_delalloc_nocow
2 parents c85b0b1 + fd649f1 commit da370f1

File tree

7 files changed

+80
-21
lines changed

7 files changed

+80
-21
lines changed

fs/btrfs/backref.c

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1264,7 +1264,16 @@ static int find_parent_nodes(struct btrfs_trans_handle *trans,
12641264
while (node) {
12651265
ref = rb_entry(node, struct prelim_ref, rbnode);
12661266
node = rb_next(&ref->rbnode);
1267-
WARN_ON(ref->count < 0);
1267+
/*
1268+
* ref->count < 0 can happen here if there are delayed
1269+
* refs with a node->action of BTRFS_DROP_DELAYED_REF.
1270+
* prelim_ref_insert() relies on this when merging
1271+
* identical refs to keep the overall count correct.
1272+
* prelim_ref_insert() will merge only those refs
1273+
* which compare identically. Any refs having
1274+
* e.g. different offsets would not be merged,
1275+
* and would retain their original ref->count < 0.
1276+
*/
12681277
if (roots && ref->count && ref->root_id && ref->parent == 0) {
12691278
if (sc && sc->root_objectid &&
12701279
ref->root_id != sc->root_objectid) {

fs/btrfs/delayed-ref.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -821,7 +821,8 @@ int btrfs_add_delayed_tree_ref(struct btrfs_fs_info *fs_info,
821821
spin_unlock(&delayed_refs->lock);
822822

823823
if (qrecord_inserted)
824-
return btrfs_qgroup_trace_extent_post(fs_info, record);
824+
btrfs_qgroup_trace_extent_post(fs_info, record);
825+
825826
return 0;
826827

827828
free_head_ref:

fs/btrfs/extent-tree.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2147,6 +2147,10 @@ int btrfs_discard_extent(struct btrfs_fs_info *fs_info, u64 bytenr,
21472147
u64 bytes;
21482148
struct request_queue *req_q;
21492149

2150+
if (!stripe->dev->bdev) {
2151+
ASSERT(btrfs_test_opt(fs_info, DEGRADED));
2152+
continue;
2153+
}
21502154
req_q = bdev_get_queue(stripe->dev->bdev);
21512155
if (!blk_queue_discard(req_q))
21522156
continue;

fs/btrfs/inode.c

Lines changed: 26 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1335,8 +1335,11 @@ static noinline int run_delalloc_nocow(struct inode *inode,
13351335
leaf = path->nodes[0];
13361336
if (path->slots[0] >= btrfs_header_nritems(leaf)) {
13371337
ret = btrfs_next_leaf(root, path);
1338-
if (ret < 0)
1338+
if (ret < 0) {
1339+
if (cow_start != (u64)-1)
1340+
cur_offset = cow_start;
13391341
goto error;
1342+
}
13401343
if (ret > 0)
13411344
break;
13421345
leaf = path->nodes[0];
@@ -3385,6 +3388,11 @@ int btrfs_orphan_add(struct btrfs_trans_handle *trans,
33853388
ret = btrfs_orphan_reserve_metadata(trans, inode);
33863389
ASSERT(!ret);
33873390
if (ret) {
3391+
/*
3392+
* dec doesn't need spin_lock as ->orphan_block_rsv
3393+
* would be released only if ->orphan_inodes is
3394+
* zero.
3395+
*/
33883396
atomic_dec(&root->orphan_inodes);
33893397
clear_bit(BTRFS_INODE_ORPHAN_META_RESERVED,
33903398
&inode->runtime_flags);
@@ -3399,12 +3407,17 @@ int btrfs_orphan_add(struct btrfs_trans_handle *trans,
33993407
if (insert >= 1) {
34003408
ret = btrfs_insert_orphan_item(trans, root, btrfs_ino(inode));
34013409
if (ret) {
3402-
atomic_dec(&root->orphan_inodes);
34033410
if (reserve) {
34043411
clear_bit(BTRFS_INODE_ORPHAN_META_RESERVED,
34053412
&inode->runtime_flags);
34063413
btrfs_orphan_release_metadata(inode);
34073414
}
3415+
/*
3416+
* btrfs_orphan_commit_root may race with us and set
3417+
* ->orphan_block_rsv to zero, in order to avoid that,
3418+
* decrease ->orphan_inodes after everything is done.
3419+
*/
3420+
atomic_dec(&root->orphan_inodes);
34083421
if (ret != -EEXIST) {
34093422
clear_bit(BTRFS_INODE_HAS_ORPHAN_ITEM,
34103423
&inode->runtime_flags);
@@ -3436,28 +3449,26 @@ static int btrfs_orphan_del(struct btrfs_trans_handle *trans,
34363449
{
34373450
struct btrfs_root *root = inode->root;
34383451
int delete_item = 0;
3439-
int release_rsv = 0;
34403452
int ret = 0;
34413453

3442-
spin_lock(&root->orphan_lock);
34433454
if (test_and_clear_bit(BTRFS_INODE_HAS_ORPHAN_ITEM,
34443455
&inode->runtime_flags))
34453456
delete_item = 1;
34463457

3458+
if (delete_item && trans)
3459+
ret = btrfs_del_orphan_item(trans, root, btrfs_ino(inode));
3460+
34473461
if (test_and_clear_bit(BTRFS_INODE_ORPHAN_META_RESERVED,
34483462
&inode->runtime_flags))
3449-
release_rsv = 1;
3450-
spin_unlock(&root->orphan_lock);
3463+
btrfs_orphan_release_metadata(inode);
34513464

3452-
if (delete_item) {
3465+
/*
3466+
* btrfs_orphan_commit_root may race with us and set ->orphan_block_rsv
3467+
* to zero, in order to avoid that, decrease ->orphan_inodes after
3468+
* everything is done.
3469+
*/
3470+
if (delete_item)
34533471
atomic_dec(&root->orphan_inodes);
3454-
if (trans)
3455-
ret = btrfs_del_orphan_item(trans, root,
3456-
btrfs_ino(inode));
3457-
}
3458-
3459-
if (release_rsv)
3460-
btrfs_orphan_release_metadata(inode);
34613472

34623473
return ret;
34633474
}
@@ -5281,7 +5292,7 @@ void btrfs_evict_inode(struct inode *inode)
52815292
trace_btrfs_inode_evict(inode);
52825293

52835294
if (!root) {
5284-
kmem_cache_free(btrfs_inode_cachep, BTRFS_I(inode));
5295+
clear_inode(inode);
52855296
return;
52865297
}
52875298

fs/btrfs/qgroup.c

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1442,8 +1442,13 @@ int btrfs_qgroup_trace_extent_post(struct btrfs_fs_info *fs_info,
14421442
int ret;
14431443

14441444
ret = btrfs_find_all_roots(NULL, fs_info, bytenr, 0, &old_root, false);
1445-
if (ret < 0)
1446-
return ret;
1445+
if (ret < 0) {
1446+
fs_info->qgroup_flags |= BTRFS_QGROUP_STATUS_FLAG_INCONSISTENT;
1447+
btrfs_warn(fs_info,
1448+
"error accounting new delayed refs extent (err code: %d), quota inconsistent",
1449+
ret);
1450+
return 0;
1451+
}
14471452

14481453
/*
14491454
* Here we don't need to get the lock of

fs/btrfs/tree-log.c

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
#include "hash.h"
3030
#include "compression.h"
3131
#include "qgroup.h"
32+
#include "inode-map.h"
3233

3334
/* magic values for the inode_only field in btrfs_log_inode:
3435
*
@@ -2472,6 +2473,9 @@ static noinline int walk_down_log_tree(struct btrfs_trans_handle *trans,
24722473
clean_tree_block(fs_info, next);
24732474
btrfs_wait_tree_block_writeback(next);
24742475
btrfs_tree_unlock(next);
2476+
} else {
2477+
if (test_and_clear_bit(EXTENT_BUFFER_DIRTY, &next->bflags))
2478+
clear_extent_buffer_dirty(next);
24752479
}
24762480

24772481
WARN_ON(root_owner !=
@@ -2552,6 +2556,9 @@ static noinline int walk_up_log_tree(struct btrfs_trans_handle *trans,
25522556
clean_tree_block(fs_info, next);
25532557
btrfs_wait_tree_block_writeback(next);
25542558
btrfs_tree_unlock(next);
2559+
} else {
2560+
if (test_and_clear_bit(EXTENT_BUFFER_DIRTY, &next->bflags))
2561+
clear_extent_buffer_dirty(next);
25552562
}
25562563

25572564
WARN_ON(root_owner != BTRFS_TREE_LOG_OBJECTID);
@@ -2630,6 +2637,9 @@ static int walk_log_tree(struct btrfs_trans_handle *trans,
26302637
clean_tree_block(fs_info, next);
26312638
btrfs_wait_tree_block_writeback(next);
26322639
btrfs_tree_unlock(next);
2640+
} else {
2641+
if (test_and_clear_bit(EXTENT_BUFFER_DIRTY, &next->bflags))
2642+
clear_extent_buffer_dirty(next);
26332643
}
26342644

26352645
WARN_ON(log->root_key.objectid !=
@@ -3018,13 +3028,14 @@ static void free_log_tree(struct btrfs_trans_handle *trans,
30183028

30193029
while (1) {
30203030
ret = find_first_extent_bit(&log->dirty_log_pages,
3021-
0, &start, &end, EXTENT_DIRTY | EXTENT_NEW,
3031+
0, &start, &end,
3032+
EXTENT_DIRTY | EXTENT_NEW | EXTENT_NEED_WAIT,
30223033
NULL);
30233034
if (ret)
30243035
break;
30253036

30263037
clear_extent_bits(&log->dirty_log_pages, start, end,
3027-
EXTENT_DIRTY | EXTENT_NEW);
3038+
EXTENT_DIRTY | EXTENT_NEW | EXTENT_NEED_WAIT);
30283039
}
30293040

30303041
/*
@@ -5677,6 +5688,23 @@ int btrfs_recover_log_trees(struct btrfs_root *log_root_tree)
56775688
path);
56785689
}
56795690

5691+
if (!ret && wc.stage == LOG_WALK_REPLAY_ALL) {
5692+
struct btrfs_root *root = wc.replay_dest;
5693+
5694+
btrfs_release_path(path);
5695+
5696+
/*
5697+
* We have just replayed everything, and the highest
5698+
* objectid of fs roots probably has changed in case
5699+
* some inode_item's got replayed.
5700+
*
5701+
* root->objectid_mutex is not acquired as log replay
5702+
* could only happen during mount.
5703+
*/
5704+
ret = btrfs_find_highest_objectid(root,
5705+
&root->highest_objectid);
5706+
}
5707+
56805708
key.offset = found_key.offset - 1;
56815709
wc.replay_dest->log_root = NULL;
56825710
free_extent_buffer(log->node);

fs/btrfs/volumes.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -645,6 +645,7 @@ static void btrfs_free_stale_devices(const char *path,
645645
btrfs_sysfs_remove_fsid(fs_devs);
646646
list_del(&fs_devs->list);
647647
free_fs_devices(fs_devs);
648+
break;
648649
} else {
649650
fs_devs->num_devices--;
650651
list_del(&dev->dev_list);

0 commit comments

Comments
 (0)