diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2018-02-16 12:26:18 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2018-02-16 12:26:18 -0500 |
commit | da370f1d63cd9fdc95b3867662026b2a5624e69a (patch) | |
tree | 7d594bf0d291e38379148ce3e3ec5cf02381bce8 | |
parent | c85b0b14341c51d8b8962c0d90d71923cad3a218 (diff) | |
parent | fd649f10c3d21ee9d7542c609f29978bdf73ab94 (diff) |
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
-rw-r--r-- | fs/btrfs/backref.c | 11 | ||||
-rw-r--r-- | fs/btrfs/delayed-ref.c | 3 | ||||
-rw-r--r-- | fs/btrfs/extent-tree.c | 4 | ||||
-rw-r--r-- | fs/btrfs/inode.c | 41 | ||||
-rw-r--r-- | fs/btrfs/qgroup.c | 9 | ||||
-rw-r--r-- | fs/btrfs/tree-log.c | 32 | ||||
-rw-r--r-- | fs/btrfs/volumes.c | 1 |
7 files changed, 80 insertions, 21 deletions
diff --git a/fs/btrfs/backref.c b/fs/btrfs/backref.c index e4054e533f6d..f94b2d8c744a 100644 --- a/fs/btrfs/backref.c +++ b/fs/btrfs/backref.c | |||
@@ -1264,7 +1264,16 @@ again: | |||
1264 | while (node) { | 1264 | while (node) { |
1265 | ref = rb_entry(node, struct prelim_ref, rbnode); | 1265 | ref = rb_entry(node, struct prelim_ref, rbnode); |
1266 | node = rb_next(&ref->rbnode); | 1266 | 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 | */ | ||
1268 | if (roots && ref->count && ref->root_id && ref->parent == 0) { | 1277 | if (roots && ref->count && ref->root_id && ref->parent == 0) { |
1269 | if (sc && sc->root_objectid && | 1278 | if (sc && sc->root_objectid && |
1270 | ref->root_id != sc->root_objectid) { | 1279 | ref->root_id != sc->root_objectid) { |
diff --git a/fs/btrfs/delayed-ref.c b/fs/btrfs/delayed-ref.c index a1a40cf382e3..7ab5e0128f0c 100644 --- a/fs/btrfs/delayed-ref.c +++ b/fs/btrfs/delayed-ref.c | |||
@@ -821,7 +821,8 @@ int btrfs_add_delayed_tree_ref(struct btrfs_fs_info *fs_info, | |||
821 | spin_unlock(&delayed_refs->lock); | 821 | spin_unlock(&delayed_refs->lock); |
822 | 822 | ||
823 | if (qrecord_inserted) | 823 | if (qrecord_inserted) |
824 | return btrfs_qgroup_trace_extent_post(fs_info, record); | 824 | btrfs_qgroup_trace_extent_post(fs_info, record); |
825 | |||
825 | return 0; | 826 | return 0; |
826 | 827 | ||
827 | free_head_ref: | 828 | free_head_ref: |
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 05751a677da4..c1618ab9fecf 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c | |||
@@ -2147,6 +2147,10 @@ int btrfs_discard_extent(struct btrfs_fs_info *fs_info, u64 bytenr, | |||
2147 | u64 bytes; | 2147 | u64 bytes; |
2148 | struct request_queue *req_q; | 2148 | struct request_queue *req_q; |
2149 | 2149 | ||
2150 | if (!stripe->dev->bdev) { | ||
2151 | ASSERT(btrfs_test_opt(fs_info, DEGRADED)); | ||
2152 | continue; | ||
2153 | } | ||
2150 | req_q = bdev_get_queue(stripe->dev->bdev); | 2154 | req_q = bdev_get_queue(stripe->dev->bdev); |
2151 | if (!blk_queue_discard(req_q)) | 2155 | if (!blk_queue_discard(req_q)) |
2152 | continue; | 2156 | continue; |
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 53ca025655fc..a79299a89b7d 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
@@ -1335,8 +1335,11 @@ next_slot: | |||
1335 | leaf = path->nodes[0]; | 1335 | leaf = path->nodes[0]; |
1336 | if (path->slots[0] >= btrfs_header_nritems(leaf)) { | 1336 | if (path->slots[0] >= btrfs_header_nritems(leaf)) { |
1337 | ret = btrfs_next_leaf(root, path); | 1337 | 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; | ||
1339 | goto error; | 1341 | goto error; |
1342 | } | ||
1340 | if (ret > 0) | 1343 | if (ret > 0) |
1341 | break; | 1344 | break; |
1342 | leaf = path->nodes[0]; | 1345 | leaf = path->nodes[0]; |
@@ -3385,6 +3388,11 @@ int btrfs_orphan_add(struct btrfs_trans_handle *trans, | |||
3385 | ret = btrfs_orphan_reserve_metadata(trans, inode); | 3388 | ret = btrfs_orphan_reserve_metadata(trans, inode); |
3386 | ASSERT(!ret); | 3389 | ASSERT(!ret); |
3387 | if (ret) { | 3390 | 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 | */ | ||
3388 | atomic_dec(&root->orphan_inodes); | 3396 | atomic_dec(&root->orphan_inodes); |
3389 | clear_bit(BTRFS_INODE_ORPHAN_META_RESERVED, | 3397 | clear_bit(BTRFS_INODE_ORPHAN_META_RESERVED, |
3390 | &inode->runtime_flags); | 3398 | &inode->runtime_flags); |
@@ -3399,12 +3407,17 @@ int btrfs_orphan_add(struct btrfs_trans_handle *trans, | |||
3399 | if (insert >= 1) { | 3407 | if (insert >= 1) { |
3400 | ret = btrfs_insert_orphan_item(trans, root, btrfs_ino(inode)); | 3408 | ret = btrfs_insert_orphan_item(trans, root, btrfs_ino(inode)); |
3401 | if (ret) { | 3409 | if (ret) { |
3402 | atomic_dec(&root->orphan_inodes); | ||
3403 | if (reserve) { | 3410 | if (reserve) { |
3404 | clear_bit(BTRFS_INODE_ORPHAN_META_RESERVED, | 3411 | clear_bit(BTRFS_INODE_ORPHAN_META_RESERVED, |
3405 | &inode->runtime_flags); | 3412 | &inode->runtime_flags); |
3406 | btrfs_orphan_release_metadata(inode); | 3413 | btrfs_orphan_release_metadata(inode); |
3407 | } | 3414 | } |
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); | ||
3408 | if (ret != -EEXIST) { | 3421 | if (ret != -EEXIST) { |
3409 | clear_bit(BTRFS_INODE_HAS_ORPHAN_ITEM, | 3422 | clear_bit(BTRFS_INODE_HAS_ORPHAN_ITEM, |
3410 | &inode->runtime_flags); | 3423 | &inode->runtime_flags); |
@@ -3436,28 +3449,26 @@ static int btrfs_orphan_del(struct btrfs_trans_handle *trans, | |||
3436 | { | 3449 | { |
3437 | struct btrfs_root *root = inode->root; | 3450 | struct btrfs_root *root = inode->root; |
3438 | int delete_item = 0; | 3451 | int delete_item = 0; |
3439 | int release_rsv = 0; | ||
3440 | int ret = 0; | 3452 | int ret = 0; |
3441 | 3453 | ||
3442 | spin_lock(&root->orphan_lock); | ||
3443 | if (test_and_clear_bit(BTRFS_INODE_HAS_ORPHAN_ITEM, | 3454 | if (test_and_clear_bit(BTRFS_INODE_HAS_ORPHAN_ITEM, |
3444 | &inode->runtime_flags)) | 3455 | &inode->runtime_flags)) |
3445 | delete_item = 1; | 3456 | delete_item = 1; |
3446 | 3457 | ||
3458 | if (delete_item && trans) | ||
3459 | ret = btrfs_del_orphan_item(trans, root, btrfs_ino(inode)); | ||
3460 | |||
3447 | if (test_and_clear_bit(BTRFS_INODE_ORPHAN_META_RESERVED, | 3461 | if (test_and_clear_bit(BTRFS_INODE_ORPHAN_META_RESERVED, |
3448 | &inode->runtime_flags)) | 3462 | &inode->runtime_flags)) |
3449 | release_rsv = 1; | 3463 | btrfs_orphan_release_metadata(inode); |
3450 | spin_unlock(&root->orphan_lock); | ||
3451 | 3464 | ||
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) | ||
3453 | atomic_dec(&root->orphan_inodes); | 3471 | 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); | ||
3461 | 3472 | ||
3462 | return ret; | 3473 | return ret; |
3463 | } | 3474 | } |
@@ -5281,7 +5292,7 @@ void btrfs_evict_inode(struct inode *inode) | |||
5281 | trace_btrfs_inode_evict(inode); | 5292 | trace_btrfs_inode_evict(inode); |
5282 | 5293 | ||
5283 | if (!root) { | 5294 | if (!root) { |
5284 | kmem_cache_free(btrfs_inode_cachep, BTRFS_I(inode)); | 5295 | clear_inode(inode); |
5285 | return; | 5296 | return; |
5286 | } | 5297 | } |
5287 | 5298 | ||
diff --git a/fs/btrfs/qgroup.c b/fs/btrfs/qgroup.c index 9e61dd624f7b..aa259d6986e1 100644 --- a/fs/btrfs/qgroup.c +++ b/fs/btrfs/qgroup.c | |||
@@ -1442,8 +1442,13 @@ int btrfs_qgroup_trace_extent_post(struct btrfs_fs_info *fs_info, | |||
1442 | int ret; | 1442 | int ret; |
1443 | 1443 | ||
1444 | ret = btrfs_find_all_roots(NULL, fs_info, bytenr, 0, &old_root, false); | 1444 | ret = btrfs_find_all_roots(NULL, fs_info, bytenr, 0, &old_root, false); |
1445 | if (ret < 0) | 1445 | if (ret < 0) { |
1446 | return ret; | 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 | } | ||
1447 | 1452 | ||
1448 | /* | 1453 | /* |
1449 | * Here we don't need to get the lock of | 1454 | * Here we don't need to get the lock of |
diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c index afadaadab18e..4fd19b4d6675 100644 --- a/fs/btrfs/tree-log.c +++ b/fs/btrfs/tree-log.c | |||
@@ -29,6 +29,7 @@ | |||
29 | #include "hash.h" | 29 | #include "hash.h" |
30 | #include "compression.h" | 30 | #include "compression.h" |
31 | #include "qgroup.h" | 31 | #include "qgroup.h" |
32 | #include "inode-map.h" | ||
32 | 33 | ||
33 | /* magic values for the inode_only field in btrfs_log_inode: | 34 | /* magic values for the inode_only field in btrfs_log_inode: |
34 | * | 35 | * |
@@ -2472,6 +2473,9 @@ static noinline int walk_down_log_tree(struct btrfs_trans_handle *trans, | |||
2472 | clean_tree_block(fs_info, next); | 2473 | clean_tree_block(fs_info, next); |
2473 | btrfs_wait_tree_block_writeback(next); | 2474 | btrfs_wait_tree_block_writeback(next); |
2474 | btrfs_tree_unlock(next); | 2475 | btrfs_tree_unlock(next); |
2476 | } else { | ||
2477 | if (test_and_clear_bit(EXTENT_BUFFER_DIRTY, &next->bflags)) | ||
2478 | clear_extent_buffer_dirty(next); | ||
2475 | } | 2479 | } |
2476 | 2480 | ||
2477 | WARN_ON(root_owner != | 2481 | WARN_ON(root_owner != |
@@ -2552,6 +2556,9 @@ static noinline int walk_up_log_tree(struct btrfs_trans_handle *trans, | |||
2552 | clean_tree_block(fs_info, next); | 2556 | clean_tree_block(fs_info, next); |
2553 | btrfs_wait_tree_block_writeback(next); | 2557 | btrfs_wait_tree_block_writeback(next); |
2554 | btrfs_tree_unlock(next); | 2558 | btrfs_tree_unlock(next); |
2559 | } else { | ||
2560 | if (test_and_clear_bit(EXTENT_BUFFER_DIRTY, &next->bflags)) | ||
2561 | clear_extent_buffer_dirty(next); | ||
2555 | } | 2562 | } |
2556 | 2563 | ||
2557 | WARN_ON(root_owner != BTRFS_TREE_LOG_OBJECTID); | 2564 | WARN_ON(root_owner != BTRFS_TREE_LOG_OBJECTID); |
@@ -2630,6 +2637,9 @@ static int walk_log_tree(struct btrfs_trans_handle *trans, | |||
2630 | clean_tree_block(fs_info, next); | 2637 | clean_tree_block(fs_info, next); |
2631 | btrfs_wait_tree_block_writeback(next); | 2638 | btrfs_wait_tree_block_writeback(next); |
2632 | btrfs_tree_unlock(next); | 2639 | btrfs_tree_unlock(next); |
2640 | } else { | ||
2641 | if (test_and_clear_bit(EXTENT_BUFFER_DIRTY, &next->bflags)) | ||
2642 | clear_extent_buffer_dirty(next); | ||
2633 | } | 2643 | } |
2634 | 2644 | ||
2635 | WARN_ON(log->root_key.objectid != | 2645 | WARN_ON(log->root_key.objectid != |
@@ -3018,13 +3028,14 @@ static void free_log_tree(struct btrfs_trans_handle *trans, | |||
3018 | 3028 | ||
3019 | while (1) { | 3029 | while (1) { |
3020 | ret = find_first_extent_bit(&log->dirty_log_pages, | 3030 | 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, | ||
3022 | NULL); | 3033 | NULL); |
3023 | if (ret) | 3034 | if (ret) |
3024 | break; | 3035 | break; |
3025 | 3036 | ||
3026 | clear_extent_bits(&log->dirty_log_pages, start, end, | 3037 | clear_extent_bits(&log->dirty_log_pages, start, end, |
3027 | EXTENT_DIRTY | EXTENT_NEW); | 3038 | EXTENT_DIRTY | EXTENT_NEW | EXTENT_NEED_WAIT); |
3028 | } | 3039 | } |
3029 | 3040 | ||
3030 | /* | 3041 | /* |
@@ -5677,6 +5688,23 @@ again: | |||
5677 | path); | 5688 | path); |
5678 | } | 5689 | } |
5679 | 5690 | ||
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 | |||
5680 | key.offset = found_key.offset - 1; | 5708 | key.offset = found_key.offset - 1; |
5681 | wc.replay_dest->log_root = NULL; | 5709 | wc.replay_dest->log_root = NULL; |
5682 | free_extent_buffer(log->node); | 5710 | free_extent_buffer(log->node); |
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index b5036bd69e6a..2ceb924ca0d6 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c | |||
@@ -645,6 +645,7 @@ static void btrfs_free_stale_devices(const char *path, | |||
645 | btrfs_sysfs_remove_fsid(fs_devs); | 645 | btrfs_sysfs_remove_fsid(fs_devs); |
646 | list_del(&fs_devs->list); | 646 | list_del(&fs_devs->list); |
647 | free_fs_devices(fs_devs); | 647 | free_fs_devices(fs_devs); |
648 | break; | ||
648 | } else { | 649 | } else { |
649 | fs_devs->num_devices--; | 650 | fs_devs->num_devices--; |
650 | list_del(&dev->dev_list); | 651 | list_del(&dev->dev_list); |