diff options
author | Chris Mason <chris.mason@oracle.com> | 2008-09-23 20:19:49 -0400 |
---|---|---|
committer | Chris Mason <chris.mason@oracle.com> | 2008-09-25 11:04:07 -0400 |
commit | 34353029534a08e41cfb8be647d734b9ce9ebff8 (patch) | |
tree | 00aaf0f34c2bf5e4a11541ec5f2fff7bc5473df4 | |
parent | 31840ae1a6b433ca0e6a8d341756ff478bbf959e (diff) |
Btrfs: Fix race against disk_i_size updates
The code to update the on disk i_size happens before the
ordered_extent record is removed. So, it is possible for multiple
ordered_extent completion routines to run at the same time, and to
find each other in the ordered tree.
The end result is they both decide not to update disk_i_size, leaving
it too small. This temporary fix just puts the updates inside
the extent_mutex. A real solution would be stronger ordering of
disk_i_size updates against removing the ordered extent from the tree.
Signed-off-by: Chris Mason <chris.mason@oracle.com>
-rw-r--r-- | fs/btrfs/inode.c | 2 |
1 files changed, 2 insertions, 0 deletions
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 2e7d82ec5d18..adb169d739ce 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
@@ -608,9 +608,11 @@ nocow: | |||
608 | add_pending_csums(trans, inode, ordered_extent->file_offset, | 608 | add_pending_csums(trans, inode, ordered_extent->file_offset, |
609 | &ordered_extent->list); | 609 | &ordered_extent->list); |
610 | 610 | ||
611 | mutex_lock(&BTRFS_I(inode)->extent_mutex); | ||
611 | btrfs_ordered_update_i_size(inode, ordered_extent); | 612 | btrfs_ordered_update_i_size(inode, ordered_extent); |
612 | btrfs_update_inode(trans, root, inode); | 613 | btrfs_update_inode(trans, root, inode); |
613 | btrfs_remove_ordered_extent(inode, ordered_extent); | 614 | btrfs_remove_ordered_extent(inode, ordered_extent); |
615 | mutex_unlock(&BTRFS_I(inode)->extent_mutex); | ||
614 | 616 | ||
615 | /* once for us */ | 617 | /* once for us */ |
616 | btrfs_put_ordered_extent(ordered_extent); | 618 | btrfs_put_ordered_extent(ordered_extent); |