From: Greg Kroah-Hartman Date: Sat, 20 Aug 2011 16:35:24 +0000 (-0700) Subject: 3.0 patches X-Git-Tag: v3.0.4~12 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=95f858546aec320a904842f9195d4b4c1c51f479;p=thirdparty%2Fkernel%2Fstable-queue.git 3.0 patches --- diff --git a/queue-3.0/btrfs-fix-an-oops-of-log-replay.patch b/queue-3.0/btrfs-fix-an-oops-of-log-replay.patch new file mode 100644 index 00000000000..c3fe8a8f6de --- /dev/null +++ b/queue-3.0/btrfs-fix-an-oops-of-log-replay.patch @@ -0,0 +1,88 @@ +From 34f3e4f23ca3d259fe078f62a128d97ca83508ef Mon Sep 17 00:00:00 2001 +From: liubo +Date: Sat, 6 Aug 2011 08:35:23 +0000 +Subject: Btrfs: fix an oops of log replay + +From: liubo + +commit 34f3e4f23ca3d259fe078f62a128d97ca83508ef upstream. + +When btrfs recovers from a crash, it may hit the oops below: + +------------[ cut here ]------------ +kernel BUG at fs/btrfs/inode.c:4580! +[...] +RIP: 0010:[] [] btrfs_add_link+0x161/0x1c0 [btrfs] +[...] +Call Trace: + [] ? btrfs_inode_ref_index+0x31/0x80 [btrfs] + [] add_inode_ref+0x319/0x3f0 [btrfs] + [] replay_one_buffer+0x2c7/0x390 [btrfs] + [] walk_down_log_tree+0x32a/0x480 [btrfs] + [] walk_log_tree+0xf5/0x240 [btrfs] + [] btrfs_recover_log_trees+0x250/0x350 [btrfs] + [] ? btrfs_recover_log_trees+0x350/0x350 [btrfs] + [] open_ctree+0x1442/0x17d0 [btrfs] +[...] + +This comes from that while replaying an inode ref item, we forget to +check those old conflicting DIR_ITEM and DIR_INDEX items in fs/file tree, +then we will come to conflict corners which lead to BUG_ON(). + +Signed-off-by: Liu Bo +Tested-by: Andy Lutomirski +Signed-off-by: Chris Mason +Signed-off-by: Greg Kroah-Hartman + +--- + fs/btrfs/tree-log.c | 28 ++++++++++++++++++++++++---- + 1 file changed, 24 insertions(+), 4 deletions(-) + +--- a/fs/btrfs/tree-log.c ++++ b/fs/btrfs/tree-log.c +@@ -799,14 +799,15 @@ static noinline int add_inode_ref(struct + struct extent_buffer *eb, int slot, + struct btrfs_key *key) + { +- struct inode *dir; +- int ret; + struct btrfs_inode_ref *ref; ++ struct btrfs_dir_item *di; ++ struct inode *dir; + struct inode *inode; +- char *name; +- int namelen; + unsigned long ref_ptr; + unsigned long ref_end; ++ char *name; ++ int namelen; ++ int ret; + int search_done = 0; + + /* +@@ -909,6 +910,25 @@ again: + } + btrfs_release_path(path); + ++ /* look for a conflicting sequence number */ ++ di = btrfs_lookup_dir_index_item(trans, root, path, btrfs_ino(dir), ++ btrfs_inode_ref_index(eb, ref), ++ name, namelen, 0); ++ if (di && !IS_ERR(di)) { ++ ret = drop_one_dir_item(trans, root, path, dir, di); ++ BUG_ON(ret); ++ } ++ btrfs_release_path(path); ++ ++ /* look for a conflicing name */ ++ di = btrfs_lookup_dir_item(trans, root, path, btrfs_ino(dir), ++ name, namelen, 0); ++ if (di && !IS_ERR(di)) { ++ ret = drop_one_dir_item(trans, root, path, dir, di); ++ BUG_ON(ret); ++ } ++ btrfs_release_path(path); ++ + insert: + /* insert our name */ + ret = btrfs_add_link(trans, dir, inode, name, namelen, 0, diff --git a/queue-3.0/series b/queue-3.0/series index a18651fede5..5661032c71c 100644 --- a/queue-3.0/series +++ b/queue-3.0/series @@ -12,3 +12,4 @@ nfsv4.1-return-nfs4err_badsession-to-callbacks-during.patch x86-mtrr-lock-stop-machine-during-mtrr-rendezvous-sequence.patch btrfs-detect-wether-a-device-supports-discard.patch loop-fix-deadlock-when-sysfs-and-loop_clr_fd-race-against.patch +btrfs-fix-an-oops-of-log-replay.patch