Btrfs: avoid orphan inode caused by log replay
authorYan Zheng <zheng.yan@oracle.com>
Mon, 5 Jan 2009 20:43:42 +0000 (15:43 -0500)
committerChris Mason <chris.mason@oracle.com>
Mon, 5 Jan 2009 20:43:42 +0000 (15:43 -0500)
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: Yan Zheng <zheng.yan@oracle.com>
fs/btrfs/tree-log.c

index 33eee256ee818ab52fe7189ffa2d03f20e79cc63..b1c2921f5befcf1f5619df64e54f0aa0281e82b0 100644 (file)
@@ -50,6 +50,9 @@
 static int __btrfs_log_inode(struct btrfs_trans_handle *trans,
                             struct btrfs_root *root, struct inode *inode,
                             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
@@ -638,8 +641,10 @@ static noinline int drop_one_dir_item(struct btrfs_trans_handle *trans,
        inode = read_one_inode(root, location.objectid);
        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);
+       BUG_ON(ret);
        kfree(name);
 
        iput(inode);