From e41ca5897489b1c18af75ff0cc8f5c80260b3281 Mon Sep 17 00:00:00 2001 From: Qu Wenruo Date: Wed, 6 Jun 2018 15:41:49 +0800 Subject: btrfs: Get rid of the confusing btrfs_file_extent_inline_len We used to call btrfs_file_extent_inline_len() to get the uncompressed data size of an inlined extent. However this function is hiding evil, for compressed extent, it has no choice but to directly read out ram_bytes from btrfs_file_extent_item. While for uncompressed extent, it uses item size to calculate the real data size, and ignoring ram_bytes completely. In fact, for corrupted ram_bytes, due to above behavior kernel btrfs_print_leaf() can't even print correct ram_bytes to expose the bug. Since we have the tree-checker to verify all EXTENT_DATA, such mismatch can be detected pretty easily, thus we can trust ram_bytes without the evil btrfs_file_extent_inline_len(). Signed-off-by: Qu Wenruo Reviewed-by: David Sterba Signed-off-by: David Sterba --- fs/btrfs/inode.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'fs/btrfs/inode.c') diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index eba61bcb9bb3..1ade43c02b81 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -1443,8 +1443,7 @@ next_slot: nocow = 1; } else if (extent_type == BTRFS_FILE_EXTENT_INLINE) { extent_end = found_key.offset + - btrfs_file_extent_inline_len(leaf, - path->slots[0], fi); + btrfs_file_extent_ram_bytes(leaf, fi); extent_end = ALIGN(extent_end, fs_info->sectorsize); } else { @@ -4643,8 +4642,8 @@ search_again: BTRFS_I(inode), leaf, fi, found_key.offset); } else if (extent_type == BTRFS_FILE_EXTENT_INLINE) { - item_end += btrfs_file_extent_inline_len(leaf, - path->slots[0], fi); + item_end += btrfs_file_extent_ram_bytes(leaf, + fi); trace_btrfs_truncate_show_fi_inline( BTRFS_I(inode), leaf, fi, path->slots[0], @@ -6943,7 +6942,8 @@ struct extent_map *btrfs_get_extent(struct btrfs_inode *inode, extent_start); } else if (found_type == BTRFS_FILE_EXTENT_INLINE) { size_t size; - size = btrfs_file_extent_inline_len(leaf, path->slots[0], item); + + size = btrfs_file_extent_ram_bytes(leaf, item); extent_end = ALIGN(extent_start + size, fs_info->sectorsize); @@ -6994,7 +6994,7 @@ next: if (new_inline) goto out; - size = btrfs_file_extent_inline_len(leaf, path->slots[0], item); + size = btrfs_file_extent_ram_bytes(leaf, item); extent_offset = page_offset(page) + pg_offset - extent_start; copy_size = min_t(u64, PAGE_SIZE - pg_offset, size - extent_offset); -- cgit From d3c6be6fdab48dd26af3d3e01c5972ffe20985b9 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Thu, 21 Jun 2018 18:04:06 +0200 Subject: btrfs: use timespec64 for i_otime While the regular inode timestamps all use timespec64 now, the i_otime field is btrfs specific and still needs to be converted to correctly represent times beyond 2038. Signed-off-by: Arnd Bergmann Reviewed-by: Nikolay Borisov Reviewed-by: David Sterba Signed-off-by: David Sterba --- fs/btrfs/inode.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'fs/btrfs/inode.c') diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 1ade43c02b81..2858bc355920 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -5744,7 +5744,7 @@ static struct inode *new_simple_dir(struct super_block *s, inode->i_mtime = current_time(inode); inode->i_atime = inode->i_mtime; inode->i_ctime = inode->i_mtime; - BTRFS_I(inode)->i_otime = timespec64_to_timespec(inode->i_mtime); + BTRFS_I(inode)->i_otime = inode->i_mtime; return inode; } @@ -6348,7 +6348,7 @@ static struct inode *btrfs_new_inode(struct btrfs_trans_handle *trans, inode->i_mtime = current_time(inode); inode->i_atime = inode->i_mtime; inode->i_ctime = inode->i_mtime; - BTRFS_I(inode)->i_otime = timespec64_to_timespec(inode->i_mtime); + BTRFS_I(inode)->i_otime = inode->i_mtime; inode_item = btrfs_item_ptr(path->nodes[0], path->slots[0], struct btrfs_inode_item); -- cgit From 37508515621551538addaf826ab4b8a9aaf0a382 Mon Sep 17 00:00:00 2001 From: David Sterba Date: Fri, 29 Jun 2018 10:56:40 +0200 Subject: btrfs: simplify some assignments of inode numbers There are several places when the btrfs inode is converted to the generic inode, back to btrfs and then passed to btrfs_ino. We can remove the extra back and forth conversions. Signed-off-by: David Sterba --- fs/btrfs/inode.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'fs/btrfs/inode.c') diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 2858bc355920..17816c455786 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -4242,9 +4242,9 @@ again: prev = node; entry = rb_entry(node, struct btrfs_inode, rb_node); - if (objectid < btrfs_ino(BTRFS_I(&entry->vfs_inode))) + if (objectid < btrfs_ino(entry)) node = node->rb_left; - else if (objectid > btrfs_ino(BTRFS_I(&entry->vfs_inode))) + else if (objectid > btrfs_ino(entry)) node = node->rb_right; else break; @@ -4252,7 +4252,7 @@ again: if (!node) { while (prev) { entry = rb_entry(prev, struct btrfs_inode, rb_node); - if (objectid <= btrfs_ino(BTRFS_I(&entry->vfs_inode))) { + if (objectid <= btrfs_ino(entry)) { node = prev; break; } @@ -4261,7 +4261,7 @@ again: } while (node) { entry = rb_entry(node, struct btrfs_inode, rb_node); - objectid = btrfs_ino(BTRFS_I(&entry->vfs_inode)) + 1; + objectid = btrfs_ino(entry) + 1; inode = igrab(&entry->vfs_inode); if (inode) { spin_unlock(&root->inode_lock); @@ -5614,9 +5614,9 @@ static void inode_tree_add(struct inode *inode) parent = *p; entry = rb_entry(parent, struct btrfs_inode, rb_node); - if (ino < btrfs_ino(BTRFS_I(&entry->vfs_inode))) + if (ino < btrfs_ino(entry)) p = &parent->rb_left; - else if (ino > btrfs_ino(BTRFS_I(&entry->vfs_inode))) + else if (ino > btrfs_ino(entry)) p = &parent->rb_right; else { WARN_ON(!(entry->vfs_inode.i_state & -- cgit From 3ffbd68c48320730ef64ebfb5e639220f1f65483 Mon Sep 17 00:00:00 2001 From: David Sterba Date: Fri, 29 Jun 2018 10:56:42 +0200 Subject: btrfs: simplify pointer chasing of local fs_info variables Functions that get btrfs inode can simply reach the fs_info by dereferencing the root and this looks a bit more straightforward compared to the btrfs_sb(...) indirection. If the transaction handle is available and not NULL it's used instead. Signed-off-by: David Sterba --- fs/btrfs/inode.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'fs/btrfs/inode.c') diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 17816c455786..32613dca13c1 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -1751,7 +1751,7 @@ static void btrfs_add_delalloc_inodes(struct btrfs_root *root, void __btrfs_del_delalloc_inode(struct btrfs_root *root, struct btrfs_inode *inode) { - struct btrfs_fs_info *fs_info = btrfs_sb(inode->vfs_inode.i_sb); + struct btrfs_fs_info *fs_info = root->fs_info; if (!list_empty(&inode->delalloc_inodes)) { list_del_init(&inode->delalloc_inodes); @@ -6418,7 +6418,7 @@ int btrfs_add_link(struct btrfs_trans_handle *trans, struct btrfs_inode *parent_inode, struct btrfs_inode *inode, const char *name, int name_len, int add_backref, u64 index) { - struct btrfs_fs_info *fs_info = btrfs_sb(inode->vfs_inode.i_sb); + struct btrfs_fs_info *fs_info = trans->fs_info; int ret = 0; struct btrfs_key key; struct btrfs_root *root = parent_inode->root; @@ -6846,7 +6846,7 @@ struct extent_map *btrfs_get_extent(struct btrfs_inode *inode, size_t pg_offset, u64 start, u64 len, int create) { - struct btrfs_fs_info *fs_info = btrfs_sb(inode->vfs_inode.i_sb); + struct btrfs_fs_info *fs_info = inode->root->fs_info; int ret; int err = 0; u64 extent_start = 0; -- cgit From d7f663fa3ff906247a979c1115bc92cbabfb19ba Mon Sep 17 00:00:00 2001 From: David Sterba Date: Fri, 29 Jun 2018 10:56:47 +0200 Subject: btrfs: prune unused includes Remove includes if none of the interfaces and exports is used in the given source file. Signed-off-by: David Sterba --- fs/btrfs/inode.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'fs/btrfs/inode.c') diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 32613dca13c1..ada8a698af10 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -14,17 +14,13 @@ #include #include #include -#include -#include #include #include -#include #include #include #include #include #include -#include #include #include #include -- cgit From ebcc326316f3d798e9715e5ca1451c3e457b95dd Mon Sep 17 00:00:00 2001 From: David Sterba Date: Fri, 29 Jun 2018 10:56:53 +0200 Subject: btrfs: open-code bio_set_op_attrs The helper is trivial and marked as deprecated. Signed-off-by: David Sterba --- fs/btrfs/inode.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'fs/btrfs/inode.c') diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index ada8a698af10..564ec00c765b 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -7861,7 +7861,7 @@ static blk_status_t dio_read_error(struct inode *inode, struct bio *failed_bio, isector >>= inode->i_sb->s_blocksize_bits; bio = btrfs_create_repair_bio(inode, failed_bio, failrec, page, pgoff, isector, repair_endio, repair_arg); - bio_set_op_attrs(bio, REQ_OP_READ, read_mode); + bio->bi_opf = REQ_OP_READ | read_mode; btrfs_debug(BTRFS_I(inode)->root->fs_info, "repair DIO read error: submitting new dio read[%#x] to this_mirror=%d, in_validation=%d", -- cgit From e288c080dddd1fdc3b7e0165cebd7af51a52d016 Mon Sep 17 00:00:00 2001 From: David Sterba Date: Wed, 18 Jul 2018 17:36:24 +0200 Subject: btrfs: unify end_io callbacks of async_submit_bio The end_io callbacks passed to btrfs_wq_submit_bio (btrfs_submit_bio_done and btree_submit_bio_done) are effectively the same code, there's no point to do the indirection. Export btrfs_submit_bio_done and call it directly. Reviewed-by: Nikolay Borisov Signed-off-by: David Sterba --- fs/btrfs/inode.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'fs/btrfs/inode.c') diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 564ec00c765b..6cb42e33fdc3 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -1957,7 +1957,7 @@ static blk_status_t btrfs_submit_bio_start(void *private_data, struct bio *bio, * At IO completion time the cums attached on the ordered extent record * are inserted into the btree */ -static blk_status_t btrfs_submit_bio_done(void *private_data, struct bio *bio, +blk_status_t btrfs_submit_bio_done(void *private_data, struct bio *bio, int mirror_num) { struct inode *inode = private_data; @@ -2030,8 +2030,7 @@ static blk_status_t btrfs_submit_bio_hook(void *private_data, struct bio *bio, /* we're doing a write, do the async checksumming */ ret = btrfs_wq_submit_bio(fs_info, bio, mirror_num, bio_flags, bio_offset, inode, - btrfs_submit_bio_start, - btrfs_submit_bio_done); + btrfs_submit_bio_start); goto out; } else if (!skip_sum) { ret = btrfs_csum_one_bio(inode, bio, 0, 0); @@ -8295,8 +8294,7 @@ static inline blk_status_t btrfs_submit_dio_bio(struct bio *bio, if (write && async_submit) { ret = btrfs_wq_submit_bio(fs_info, bio, 0, 0, file_offset, inode, - btrfs_submit_bio_start_direct_io, - btrfs_submit_bio_done); + btrfs_submit_bio_start_direct_io); goto err; } else if (write) { /* -- cgit From 05912a3c04ebca217507b4323b679c60eda4ac11 Mon Sep 17 00:00:00 2001 From: David Sterba Date: Wed, 18 Jul 2018 19:23:45 +0200 Subject: btrfs: drop extent_io_ops::tree_fs_info callback All implementations of the callback are trivial and do the same and there's only one user. Merge everything together. Reviewed-by: Nikolay Borisov Signed-off-by: David Sterba --- fs/btrfs/inode.c | 7 ------- 1 file changed, 7 deletions(-) (limited to 'fs/btrfs/inode.c') diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 6cb42e33fdc3..f279e380f36e 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -10473,12 +10473,6 @@ static int btrfs_readpage_io_failed_hook(struct page *page, int failed_mirror) return -EAGAIN; } -static struct btrfs_fs_info *iotree_fs_info(void *private_data) -{ - struct inode *inode = private_data; - return btrfs_sb(inode->i_sb); -} - static void btrfs_check_extent_io_range(void *private_data, const char *caller, u64 start, u64 end) { @@ -10553,7 +10547,6 @@ static const struct extent_io_ops btrfs_extent_io_ops = { .readpage_end_io_hook = btrfs_readpage_end_io_hook, .merge_bio_hook = btrfs_merge_bio_hook, .readpage_io_failed_hook = btrfs_readpage_io_failed_hook, - .tree_fs_info = iotree_fs_info, .set_range_writeback = btrfs_set_range_writeback, /* optional callbacks */ -- cgit From 00032d38eaa89c76de7d9c1ae6de8c48c14edd74 Mon Sep 17 00:00:00 2001 From: David Sterba Date: Wed, 18 Jul 2018 19:28:09 +0200 Subject: btrfs: drop extent_io_ops::merge_bio_hook callback The data and metadata callback implementation both use the same function. We can remove the call indirection completely. Reviewed-by: Nikolay Borisov Signed-off-by: David Sterba --- fs/btrfs/inode.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'fs/btrfs/inode.c') diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index f279e380f36e..a72784d5666f 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -1898,8 +1898,8 @@ static void btrfs_clear_bit_hook(void *private_data, } /* - * extent_io.c merge_bio_hook, this must check the chunk tree to make sure - * we don't create bios that span stripes or chunks + * Merge bio hook, this must check the chunk tree to make sure we don't create + * bios that span stripes or chunks * * return 1 if page cannot be merged to bio * return 0 if page can be merged to bio @@ -10545,7 +10545,6 @@ static const struct extent_io_ops btrfs_extent_io_ops = { /* mandatory callbacks */ .submit_bio_hook = btrfs_submit_bio_hook, .readpage_end_io_hook = btrfs_readpage_end_io_hook, - .merge_bio_hook = btrfs_merge_bio_hook, .readpage_io_failed_hook = btrfs_readpage_io_failed_hook, .set_range_writeback = btrfs_set_range_writeback, -- cgit From 5cdc84bfde22dc17b11ee7cb18cebd48f4a09f70 Mon Sep 17 00:00:00 2001 From: David Sterba Date: Wed, 18 Jul 2018 20:32:52 +0200 Subject: btrfs: drop extent_io_ops::set_range_writeback callback The data and metadata callback implementation both use the same function. We can remove the call indirection and intermediate helper completely. Reviewed-by: Nikolay Borisov Signed-off-by: David Sterba --- fs/btrfs/inode.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'fs/btrfs/inode.c') diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index a72784d5666f..4955e04da4c8 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -10487,9 +10487,9 @@ static void btrfs_check_extent_io_range(void *private_data, const char *caller, } } -void btrfs_set_range_writeback(void *private_data, u64 start, u64 end) +void btrfs_set_range_writeback(struct extent_io_tree *tree, u64 start, u64 end) { - struct inode *inode = private_data; + struct inode *inode = tree->private_data; unsigned long index = start >> PAGE_SHIFT; unsigned long end_index = end >> PAGE_SHIFT; struct page *page; @@ -10546,7 +10546,6 @@ static const struct extent_io_ops btrfs_extent_io_ops = { .submit_bio_hook = btrfs_submit_bio_hook, .readpage_end_io_hook = btrfs_readpage_end_io_hook, .readpage_io_failed_hook = btrfs_readpage_io_failed_hook, - .set_range_writeback = btrfs_set_range_writeback, /* optional callbacks */ .fill_delalloc = run_delalloc_range, -- cgit From 3c4276936f6fbe52884b4ea4e6cc120b890a0f9f Mon Sep 17 00:00:00 2001 From: Josef Bacik Date: Fri, 20 Jul 2018 11:46:10 -0700 Subject: Btrfs: fix btrfs_write_inode vs delayed iput deadlock We recently ran into the following deadlock involving btrfs_write_inode(): [ +0.005066] __schedule+0x38e/0x8c0 [ +0.007144] schedule+0x36/0x80 [ +0.006447] bit_wait+0x11/0x60 [ +0.006446] __wait_on_bit+0xbe/0x110 [ +0.007487] ? bit_wait_io+0x60/0x60 [ +0.007319] __inode_wait_for_writeback+0x96/0xc0 [ +0.009568] ? autoremove_wake_function+0x40/0x40 [ +0.009565] inode_wait_for_writeback+0x21/0x30 [ +0.009224] evict+0xb0/0x190 [ +0.006099] iput+0x1a8/0x210 [ +0.006103] btrfs_run_delayed_iputs+0x73/0xc0 [ +0.009047] btrfs_commit_transaction+0x799/0x8c0 [ +0.009567] btrfs_write_inode+0x81/0xb0 [ +0.008008] __writeback_single_inode+0x267/0x320 [ +0.009569] writeback_sb_inodes+0x25b/0x4e0 [ +0.008702] wb_writeback+0x102/0x2d0 [ +0.007487] wb_workfn+0xa4/0x310 [ +0.006794] ? wb_workfn+0xa4/0x310 [ +0.007143] process_one_work+0x150/0x410 [ +0.008179] worker_thread+0x6d/0x520 [ +0.007490] kthread+0x12c/0x160 [ +0.006620] ? put_pwq_unlocked+0x80/0x80 [ +0.008185] ? kthread_park+0xa0/0xa0 [ +0.007484] ? do_syscall_64+0x53/0x150 [ +0.007837] ret_from_fork+0x29/0x40 Writeback calls: btrfs_write_inode btrfs_commit_transaction btrfs_run_delayed_iputs If iput() is called on that same inode, evict() will wait for writeback forever. btrfs_write_inode() was originally added way back in 4730a4bc5bf3 ("btrfs_dirty_inode") to support O_SYNC writes. However, ->write_inode() hasn't been used for O_SYNC since 148f948ba877 ("vfs: Introduce new helpers for syncing after writing to O_SYNC file or IS_SYNC inode"), so btrfs_write_inode() is actually unnecessary (and leads to a bunch of unnecessary commits). Get rid of it, which also gets rid of the deadlock. CC: stable@vger.kernel.org # 3.2+ Signed-off-by: Josef Bacik [Omar: new commit message] Signed-off-by: Omar Sandoval Signed-off-by: David Sterba --- fs/btrfs/inode.c | 26 -------------------------- 1 file changed, 26 deletions(-) (limited to 'fs/btrfs/inode.c') diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 4955e04da4c8..472457795486 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -6021,32 +6021,6 @@ err: return ret; } -int btrfs_write_inode(struct inode *inode, struct writeback_control *wbc) -{ - struct btrfs_root *root = BTRFS_I(inode)->root; - struct btrfs_trans_handle *trans; - int ret = 0; - bool nolock = false; - - if (test_bit(BTRFS_INODE_DUMMY, &BTRFS_I(inode)->runtime_flags)) - return 0; - - if (btrfs_fs_closing(root->fs_info) && - btrfs_is_free_space_inode(BTRFS_I(inode))) - nolock = true; - - if (wbc->sync_mode == WB_SYNC_ALL) { - if (nolock) - trans = btrfs_join_transaction_nolock(root); - else - trans = btrfs_join_transaction(root); - if (IS_ERR(trans)) - return PTR_ERR(trans); - ret = btrfs_commit_transaction(trans); - } - return ret; -} - /* * This is somewhat expensive, updating the tree every time the * inode changes. But, it is most likely to find the inode in cache. -- cgit From 9add29457ac124e846cde4b875c632edaa722c08 Mon Sep 17 00:00:00 2001 From: Lu Fengqi Date: Wed, 1 Aug 2018 11:32:26 +0800 Subject: btrfs: Remove fs_info from btrfs_delete_delayed_dir_index It can be referenced from the passed transaction handle. Signed-off-by: Lu Fengqi Signed-off-by: David Sterba --- fs/btrfs/inode.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'fs/btrfs/inode.c') diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 472457795486..59b3ea32b6de 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -3978,7 +3978,7 @@ static int __btrfs_unlink_inode(struct btrfs_trans_handle *trans, goto err; } skip_backref: - ret = btrfs_delete_delayed_dir_index(trans, fs_info, dir, index); + ret = btrfs_delete_delayed_dir_index(trans, dir, index); if (ret) { btrfs_abort_transaction(trans, ret); goto err; @@ -4144,7 +4144,7 @@ static int btrfs_unlink_subvol(struct btrfs_trans_handle *trans, } btrfs_release_path(path); - ret = btrfs_delete_delayed_dir_index(trans, fs_info, BTRFS_I(dir), index); + ret = btrfs_delete_delayed_dir_index(trans, BTRFS_I(dir), index); if (ret) { btrfs_abort_transaction(trans, ret); goto out; -- cgit From 3ee1c5530e649182e602eb2f81193289c4d2e655 Mon Sep 17 00:00:00 2001 From: Lu Fengqi Date: Wed, 1 Aug 2018 11:32:28 +0800 Subject: btrfs: Remove fs_info from btrfs_del_root_ref It can be referenced from the passed transaction handle. Signed-off-by: Lu Fengqi Signed-off-by: David Sterba --- fs/btrfs/inode.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'fs/btrfs/inode.c') diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 59b3ea32b6de..7bf4a8d07e1e 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -4085,7 +4085,6 @@ static int btrfs_unlink_subvol(struct btrfs_trans_handle *trans, struct inode *dir, u64 objectid, const char *name, int name_len) { - struct btrfs_fs_info *fs_info = root->fs_info; struct btrfs_path *path; struct extent_buffer *leaf; struct btrfs_dir_item *di; @@ -4118,9 +4117,8 @@ static int btrfs_unlink_subvol(struct btrfs_trans_handle *trans, } btrfs_release_path(path); - ret = btrfs_del_root_ref(trans, fs_info, objectid, - root->root_key.objectid, dir_ino, - &index, name, name_len); + ret = btrfs_del_root_ref(trans, objectid, root->root_key.objectid, + dir_ino, &index, name, name_len); if (ret < 0) { if (ret != -ENOENT) { btrfs_abort_transaction(trans, ret); @@ -6439,7 +6437,7 @@ fail_dir_item: if (unlikely(ino == BTRFS_FIRST_FREE_OBJECTID)) { u64 local_index; int err; - err = btrfs_del_root_ref(trans, fs_info, key.objectid, + err = btrfs_del_root_ref(trans, key.objectid, root->root_key.objectid, parent_ino, &local_index, name, name_len); -- cgit From 6025c19fb208e93b99eafc304e7f16160e49fc88 Mon Sep 17 00:00:00 2001 From: Lu Fengqi Date: Wed, 1 Aug 2018 11:32:29 +0800 Subject: btrfs: Remove fs_info from btrfs_add_root_ref It can be referenced from the passed transaction handle. Signed-off-by: Lu Fengqi Signed-off-by: David Sterba --- fs/btrfs/inode.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'fs/btrfs/inode.c') diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 7bf4a8d07e1e..407d068d4208 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -6385,7 +6385,6 @@ int btrfs_add_link(struct btrfs_trans_handle *trans, struct btrfs_inode *parent_inode, struct btrfs_inode *inode, const char *name, int name_len, int add_backref, u64 index) { - struct btrfs_fs_info *fs_info = trans->fs_info; int ret = 0; struct btrfs_key key; struct btrfs_root *root = parent_inode->root; @@ -6401,7 +6400,7 @@ int btrfs_add_link(struct btrfs_trans_handle *trans, } if (unlikely(ino == BTRFS_FIRST_FREE_OBJECTID)) { - ret = btrfs_add_root_ref(trans, fs_info, key.objectid, + ret = btrfs_add_root_ref(trans, key.objectid, root->root_key.objectid, parent_ino, index, name, name_len); } else if (add_backref) { -- cgit From 401b3b19d592391b718b7a17295ae34eace973dd Mon Sep 17 00:00:00 2001 From: Lu Fengqi Date: Wed, 1 Aug 2018 11:32:30 +0800 Subject: btrfs: Remove root parameter from btrfs_unlink_subvol All callers pass the root tree of dir, we can push that down to the function itself. Signed-off-by: Lu Fengqi Reviewed-by: David Sterba Signed-off-by: David Sterba --- fs/btrfs/inode.c | 25 ++++++++++--------------- 1 file changed, 10 insertions(+), 15 deletions(-) (limited to 'fs/btrfs/inode.c') diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 407d068d4208..b8c131b82978 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -4081,10 +4081,10 @@ out: } static int btrfs_unlink_subvol(struct btrfs_trans_handle *trans, - struct btrfs_root *root, - struct inode *dir, u64 objectid, - const char *name, int name_len) + struct inode *dir, u64 objectid, + const char *name, int name_len) { + struct btrfs_root *root = BTRFS_I(dir)->root; struct btrfs_path *path; struct extent_buffer *leaf; struct btrfs_dir_item *di; @@ -4335,10 +4335,8 @@ int btrfs_delete_subvolume(struct inode *dir, struct dentry *dentry) btrfs_record_snapshot_destroy(trans, BTRFS_I(dir)); - ret = btrfs_unlink_subvol(trans, root, dir, - dest->root_key.objectid, - dentry->d_name.name, - dentry->d_name.len); + ret = btrfs_unlink_subvol(trans, dir, dest->root_key.objectid, + dentry->d_name.name, dentry->d_name.len); if (ret) { err = ret; btrfs_abort_transaction(trans, ret); @@ -4433,7 +4431,7 @@ static int btrfs_rmdir(struct inode *dir, struct dentry *dentry) return PTR_ERR(trans); if (unlikely(btrfs_ino(BTRFS_I(inode)) == BTRFS_EMPTY_SUBVOL_DIR_OBJECTID)) { - err = btrfs_unlink_subvol(trans, root, dir, + err = btrfs_unlink_subvol(trans, dir, BTRFS_I(inode)->location.objectid, dentry->d_name.name, dentry->d_name.len); @@ -9505,8 +9503,7 @@ static int btrfs_rename_exchange(struct inode *old_dir, /* src is a subvolume */ if (old_ino == BTRFS_FIRST_FREE_OBJECTID) { root_objectid = BTRFS_I(old_inode)->root->root_key.objectid; - ret = btrfs_unlink_subvol(trans, root, old_dir, - root_objectid, + ret = btrfs_unlink_subvol(trans, old_dir, root_objectid, old_dentry->d_name.name, old_dentry->d_name.len); } else { /* src is an inode */ @@ -9525,8 +9522,7 @@ static int btrfs_rename_exchange(struct inode *old_dir, /* dest is a subvolume */ if (new_ino == BTRFS_FIRST_FREE_OBJECTID) { root_objectid = BTRFS_I(new_inode)->root->root_key.objectid; - ret = btrfs_unlink_subvol(trans, dest, new_dir, - root_objectid, + ret = btrfs_unlink_subvol(trans, new_dir, root_objectid, new_dentry->d_name.name, new_dentry->d_name.len); } else { /* dest is an inode */ @@ -9786,7 +9782,7 @@ static int btrfs_rename(struct inode *old_dir, struct dentry *old_dentry, if (unlikely(old_ino == BTRFS_FIRST_FREE_OBJECTID)) { root_objectid = BTRFS_I(old_inode)->root->root_key.objectid; - ret = btrfs_unlink_subvol(trans, root, old_dir, root_objectid, + ret = btrfs_unlink_subvol(trans, old_dir, root_objectid, old_dentry->d_name.name, old_dentry->d_name.len); } else { @@ -9808,8 +9804,7 @@ static int btrfs_rename(struct inode *old_dir, struct dentry *old_dentry, if (unlikely(btrfs_ino(BTRFS_I(new_inode)) == BTRFS_EMPTY_SUBVOL_DIR_OBJECTID)) { root_objectid = BTRFS_I(new_inode)->location.objectid; - ret = btrfs_unlink_subvol(trans, dest, new_dir, - root_objectid, + ret = btrfs_unlink_subvol(trans, new_dir, root_objectid, new_dentry->d_name.name, new_dentry->d_name.len); BUG_ON(new_inode->i_nlink == 0); -- cgit From 5b7d687ad5913a56b6a8788435d7a53990b4176d Mon Sep 17 00:00:00 2001 From: Lu Fengqi Date: Wed, 1 Aug 2018 11:32:31 +0800 Subject: btrfs: Remove redundant btrfs_release_path from btrfs_unlink_subvol Although it is safe to call this on already released paths with no locks held or extent buffers, removing the redundant btrfs_release_path is reasonable. Signed-off-by: Lu Fengqi Reviewed-by: David Sterba Signed-off-by: David Sterba --- fs/btrfs/inode.c | 1 - 1 file changed, 1 deletion(-) (limited to 'fs/btrfs/inode.c') diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index b8c131b82978..7e56a203c109 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -4137,7 +4137,6 @@ static int btrfs_unlink_subvol(struct btrfs_trans_handle *trans, leaf = path->nodes[0]; btrfs_item_key_to_cpu(leaf, &key, path->slots[0]); - btrfs_release_path(path); index = key.offset; } btrfs_release_path(path); -- cgit From 9bc2ceff660580454f971ed3f891a2c82085433a Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 29 Jul 2018 23:04:50 +0100 Subject: btrfs: lift make_bad_inode into btrfs_iget We don't need to check is_bad_inode() after the call of btrfs_read_locked_inode() - it's exactly the same as checking return value for being non-zero. Signed-off-by: Al Viro Reviewed-by: David Sterba Reviewed-by: Nikolay Borisov Signed-off-by: David Sterba --- fs/btrfs/inode.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'fs/btrfs/inode.c') diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 7e56a203c109..cd99ce8583a8 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -3771,7 +3771,6 @@ cache_acl: make_bad: btrfs_free_path(path); - make_bad_inode(inode); return ret; } @@ -5697,12 +5696,13 @@ struct inode *btrfs_iget(struct super_block *s, struct btrfs_key *location, int ret; ret = btrfs_read_locked_inode(inode); - if (!is_bad_inode(inode)) { + if (!ret) { inode_tree_add(inode); unlock_new_inode(inode); if (new) *new = 1; } else { + make_bad_inode(inode); unlock_new_inode(inode); iput(inode); ASSERT(ret < 0); -- cgit From f5b3a4173ff624b766c56936bb315e1517603891 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 29 Jul 2018 23:04:51 +0100 Subject: btrfs: simplify btrfs_iget Don't open-code iget_failed(), don't bother with btrfs_free_path(NULL), move handling of positive return values of btrfs_lookup_inode() from btrfs_read_locked_inode() to btrfs_iget() and kill now obviously pointless ASSERT() in there. Signed-off-by: Al Viro Reviewed-by: Nikolay Borisov Reviewed-by: David Sterba Signed-off-by: David Sterba --- fs/btrfs/inode.c | 29 +++++++++++++---------------- 1 file changed, 13 insertions(+), 16 deletions(-) (limited to 'fs/btrfs/inode.c') diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index cd99ce8583a8..3f51ddc18f98 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -3604,18 +3604,15 @@ static int btrfs_read_locked_inode(struct inode *inode) filled = true; path = btrfs_alloc_path(); - if (!path) { - ret = -ENOMEM; - goto make_bad; - } + if (!path) + return -ENOMEM; memcpy(&location, &BTRFS_I(inode)->location, sizeof(location)); ret = btrfs_lookup_inode(NULL, root, path, &location, 0); if (ret) { - if (ret > 0) - ret = -ENOENT; - goto make_bad; + btrfs_free_path(path); + return ret; } leaf = path->nodes[0]; @@ -3768,10 +3765,6 @@ cache_acl: btrfs_sync_inode_flags_to_i_flags(inode); return 0; - -make_bad: - btrfs_free_path(path); - return ret; } /* @@ -5702,11 +5695,15 @@ struct inode *btrfs_iget(struct super_block *s, struct btrfs_key *location, if (new) *new = 1; } else { - make_bad_inode(inode); - unlock_new_inode(inode); - iput(inode); - ASSERT(ret < 0); - inode = ERR_PTR(ret < 0 ? ret : -ESTALE); + iget_failed(inode); + /* + * ret > 0 can come from btrfs_search_slot called by + * btrfs_read_locked_inode, this means the inode item + * was not found. + */ + if (ret > 0) + ret = -ENOENT; + inode = ERR_PTR(ret); } } -- cgit