Commit ec051c0f authored by Yan Zheng's avatar Yan Zheng Committed by Chris Mason

Btrfs: avoid orphan inode caused by log replay

drop_one_dir_item does not properly update inode's link count. It can be
reproduced by executing following commands:

#touch test
#sync
#rm -f test
#dd if=/dev/zero bs=4k count=1 of=test conv=fsync
#echo b > /proc/sysrq-trigger

This fixes it by adding an BTRFS_ORPHAN_ITEM_KEY for the inode
Signed-off-by: default avatarYan Zheng <zheng.yan@oracle.com>
parent 2d69a0f8
...@@ -50,6 +50,9 @@ ...@@ -50,6 +50,9 @@
static int __btrfs_log_inode(struct btrfs_trans_handle *trans, static int __btrfs_log_inode(struct btrfs_trans_handle *trans,
struct btrfs_root *root, struct inode *inode, struct btrfs_root *root, struct inode *inode,
int inode_only); int inode_only);
static int link_to_fixup_dir(struct btrfs_trans_handle *trans,
struct btrfs_root *root,
struct btrfs_path *path, u64 objectid);
/* /*
* tree logging is a special write ahead log used to make sure that * tree logging is a special write ahead log used to make sure that
...@@ -638,8 +641,10 @@ static noinline int drop_one_dir_item(struct btrfs_trans_handle *trans, ...@@ -638,8 +641,10 @@ static noinline int drop_one_dir_item(struct btrfs_trans_handle *trans,
inode = read_one_inode(root, location.objectid); inode = read_one_inode(root, location.objectid);
BUG_ON(!inode); BUG_ON(!inode);
btrfs_inc_nlink(inode); ret = link_to_fixup_dir(trans, root, path, location.objectid);
BUG_ON(ret);
ret = btrfs_unlink_inode(trans, root, dir, inode, name, name_len); ret = btrfs_unlink_inode(trans, root, dir, inode, name, name_len);
BUG_ON(ret);
kfree(name); kfree(name);
iput(inode); iput(inode);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment