aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorYan Zheng <zheng.yan@oracle.com>2009-01-05 15:43:42 -0500
committerChris Mason <chris.mason@oracle.com>2009-01-05 15:43:42 -0500
commitec051c0f929afe5c42c24bb07abf577c616c208c (patch)
treea9b75cd422cf7dde92c9dbb8828feb062e2c35ec /fs
parent2d69a0f88459fae35df3ddef4934a2dad67e2765 (diff)
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: Yan Zheng <zheng.yan@oracle.com>
Diffstat (limited to 'fs')
-rw-r--r--fs/btrfs/tree-log.c7
1 files changed, 6 insertions, 1 deletions
diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c
index 33eee256ee81..b1c2921f5bef 100644
--- a/fs/btrfs/tree-log.c
+++ b/fs/btrfs/tree-log.c
@@ -50,6 +50,9 @@
50static int __btrfs_log_inode(struct btrfs_trans_handle *trans, 50static int __btrfs_log_inode(struct btrfs_trans_handle *trans,
51 struct btrfs_root *root, struct inode *inode, 51 struct btrfs_root *root, struct inode *inode,
52 int inode_only); 52 int inode_only);
53static int link_to_fixup_dir(struct btrfs_trans_handle *trans,
54 struct btrfs_root *root,
55 struct btrfs_path *path, u64 objectid);
53 56
54/* 57/*
55 * tree logging is a special write ahead log used to make sure that 58 * 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 inode = read_one_inode(root, location.objectid); 641 inode = read_one_inode(root, location.objectid);
639 BUG_ON(!inode); 642 BUG_ON(!inode);
640 643
641 btrfs_inc_nlink(inode); 644 ret = link_to_fixup_dir(trans, root, path, location.objectid);
645 BUG_ON(ret);
642 ret = btrfs_unlink_inode(trans, root, dir, inode, name, name_len); 646 ret = btrfs_unlink_inode(trans, root, dir, inode, name, name_len);
647 BUG_ON(ret);
643 kfree(name); 648 kfree(name);
644 649
645 iput(inode); 650 iput(inode);