aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/file.c
diff options
context:
space:
mode:
authorChris Mason <chris.mason@oracle.com>2009-04-21 11:53:38 -0400
committerChris Mason <chris.mason@oracle.com>2009-04-21 12:45:12 -0400
commit546888da82082555a56528730a83f0afd12f33bf (patch)
tree98ee868d1b8a4bd390a980fed707f91419b79fb5 /fs/btrfs/file.c
parent8c594ea81d7abbbffdda447b127f8ba8d76f319d (diff)
Btrfs: fix btrfs fallocate oops and deadlock
Btrfs fallocate was incorrectly starting a transaction with a lock held on the extent_io tree for the file, which could deadlock. Strictly speaking it was using join_transaction which would be safe, but it is better to move the transaction outside of the lock. When preallocated extents are overwritten, btrfs_mark_buffer_dirty was being called on an unlocked buffer. This was triggering an assertion and oops because the lock is supposed to be held. The bug was calling btrfs_mark_buffer_dirty on a leaf after btrfs_del_item had been run. btrfs_del_item takes care of dirtying things, so the solution is a to skip the btrfs_mark_buffer_dirty call in this case. Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs/file.c')
-rw-r--r--fs/btrfs/file.c4
1 files changed, 3 insertions, 1 deletions
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c
index e21c0060ee73..482f8db2cfd0 100644
--- a/fs/btrfs/file.c
+++ b/fs/btrfs/file.c
@@ -830,7 +830,7 @@ again:
830 830
831 ret = btrfs_del_items(trans, root, path, del_slot, del_nr); 831 ret = btrfs_del_items(trans, root, path, del_slot, del_nr);
832 BUG_ON(ret); 832 BUG_ON(ret);
833 goto done; 833 goto release;
834 } else if (split == start) { 834 } else if (split == start) {
835 if (locked_end < extent_end) { 835 if (locked_end < extent_end) {
836 ret = try_lock_extent(&BTRFS_I(inode)->io_tree, 836 ret = try_lock_extent(&BTRFS_I(inode)->io_tree,
@@ -926,6 +926,8 @@ again:
926 } 926 }
927done: 927done:
928 btrfs_mark_buffer_dirty(leaf); 928 btrfs_mark_buffer_dirty(leaf);
929
930release:
929 btrfs_release_path(root, path); 931 btrfs_release_path(root, path);
930 if (split_end && split == start) { 932 if (split_end && split == start) {
931 split = end; 933 split = end;