Btrfs: fix no reserved space for writing out inode cache
PATCH 2/6 Btrfs: fix no reserved space for writing out inode cache
I-node cache forgets to reserve the space when writing out it. And when we do some stress test, such as synctest, it will trigger WARN_ON() in use_block_rsv().
WARNING: at fs/btrfs/extent-tree.c:5718 btrfs_alloc_free_block+0xbf/0x281 [btrfs]() ... Call Trace: [<ffffffff8104df86>] warn_slowpath_common+0x80/0x98 [<ffffffff8104dfb3>] warn_slowpath_null+0x15/0x17 [<ffffffffa0369c60>] btrfs_alloc_free_block+0xbf/0x281 [btrfs] [<ffffffff810cbcb8>] ? __set_page_dirty_nobuffers+0xfe/0x108 [<ffffffffa035c040>] __btrfs_cow_block+0x118/0x3b5 [btrfs] [<ffffffffa035c7ba>] btrfs_cow_block+0x103/0x14e [btrfs] [<ffffffffa035e4c4>] btrfs_search_slot+0x249/0x6a4 [btrfs] [<ffffffffa036d086>] btrfs_lookup_inode+0x2a/0x8a [btrfs] [<ffffffffa03788b7>] btrfs_update_inode+0xaa/0x141 [btrfs] [<ffffffffa036d7ec>] btrfs_save_ino_cache+0xea/0x202 [btrfs] [<ffffffffa03a761e>] ? btrfs_update_reloc_root+0x17e/0x197 [btrfs] [<ffffffffa0373867>] commit_fs_roots+0xaa/0x158 [btrfs] [<ffffffffa03746a6>] btrfs_commit_transaction+0x405/0x731 [btrfs] [<ffffffff810690df>] ? wake_up_bit+0x25/0x25 [<ffffffffa039d652>] ? btrfs_log_dentry_safe+0x43/0x51 [btrfs] [<ffffffffa0381c5f>] btrfs_sync_file+0x16a/0x198 [btrfs] [<ffffffff81122806>] ? mntput+0x21/0x23 [<ffffffff8112d150>] vfs_fsync_range+0x18/0x21 [<ffffffff8112d170>] vfs_fsync+0x17/0x19 [<ffffffff8112d316>] do_fsync+0x29/0x3e [<ffffffff8112d348>] sys_fsync+0xb/0xf [<ffffffff81468352>] system_call_fastpath+0x16/0x1b
Sometimes it causes BUG_ON() in the reservation code of the delayed inode is triggered.
So we must reserve enough space for inode cache.
Note: If we can not reserve the enough space for inode cache, we will give up writing out it.
Signed-off-by Miao Xie <[email protected]>
--- fs/btrfs/inode-map.c | 28 ++++++++++++++++++++++++---- 1 files changed, 24 insertions(+), 4 deletions(-)
fs/btrfs/inode-map.c +24 -4
@@ -398,6 +398,8 @@ int btrfs_save_ino_cache(struct btrfs_root *root,struct btrfs_free_space_ctl *ctl = root->free_ino_ctl;struct btrfs_path *path;struct inode *inode; +struct btrfs_block_rsv *rsv; +u64 num_bytes;u64 alloc_hint =0 ;int ret;int prealloc;
@@ -421,11 +423,26 @@ int btrfs_save_ino_cache(struct btrfs_root *root,if (!path)return -ENOMEM ; + rsv = trans->block_rsv; + trans->block_rsv = &root->fs_info->trans_block_rsv; + + num_bytes = trans->bytes_reserved; +/* +* 1 item for inode item insertion if need +* 3 items for inode item update (in the worst case) +* 1 item for free space object +* 3 items for pre-allocation +*/ + trans->bytes_reserved =btrfs_calc_trans_metadata_size (root,8 ); + ret =btrfs_block_rsv_add_noflush (root, trans->block_rsv, + trans->bytes_reserved); +if (ret) + goto out; again: inode =lookup_free_ino_inode (root, path);if (IS_ERR (inode) &&PTR_ERR (inode) != -ENOENT ) { ret =PTR_ERR (inode); - goto out; + goto out_release; }if (IS_ERR (inode)) {
@@ -434,7 +451,7 @@ again: ret =create_free_ino_inode (root, trans, path);if (ret) - goto out; + goto out_release; goto again; }
@@ -477,11 +494,14 @@ again: }btrfs_free_reserved_data_space (inode, prealloc); + ret =btrfs_write_out_ino_cache (root, trans, path); out_put:iput (inode); +out_release: +btrfs_block_rsv_release (root, trans->block_rsv, trans->bytes_reserved); out: -if (ret ==0 ) - ret =btrfs_write_out_ino_cache (root, trans, path); + trans->block_rsv = rsv; + trans->bytes_reserved = num_bytes;btrfs_free_path (path);return ret;
Signature · 1 line
1.7.6.4