aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/ioctl.c
diff options
context:
space:
mode:
authorChris Mason <chris.mason@oracle.com>2009-09-11 12:27:37 -0400
committerChris Mason <chris.mason@oracle.com>2009-09-11 13:31:07 -0400
commita1ed835e1ab5795f91b198d08c43e2f56848dcf3 (patch)
treeac3b370823fa76c5be7698e3663306badbbd622d /fs/btrfs/ioctl.c
parent8b62b72b26bcd72082c4a69d179dd906bcc22200 (diff)
Btrfs: Fix extent replacment race
Data COW means that whenever we write to a file, we replace any old extent pointers with new ones. There was a window where a readpage might find the old extent pointers on disk and cache them in the extent_map tree in ram in the middle of a given write replacing them. Even though both the readpage and the write had their respective bytes in the file locked, the extent readpage inserts may cover more bytes than it had locked down. This commit closes the race by keeping the new extent pinned in the extent map tree until after the on-disk btree is properly setup with the new extent pointers. Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs/ioctl.c')
-rw-r--r--fs/btrfs/ioctl.c5
1 files changed, 2 insertions, 3 deletions
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
index 9f4db848db10..e2d8e90259b0 100644
--- a/fs/btrfs/ioctl.c
+++ b/fs/btrfs/ioctl.c
@@ -597,9 +597,8 @@ again:
597 clear_page_dirty_for_io(page); 597 clear_page_dirty_for_io(page);
598 598
599 btrfs_set_extent_delalloc(inode, page_start, page_end); 599 btrfs_set_extent_delalloc(inode, page_start, page_end);
600
601 unlock_extent(io_tree, page_start, page_end, GFP_NOFS);
602 set_page_dirty(page); 600 set_page_dirty(page);
601 unlock_extent(io_tree, page_start, page_end, GFP_NOFS);
603 unlock_page(page); 602 unlock_page(page);
604 page_cache_release(page); 603 page_cache_release(page);
605 balance_dirty_pages_ratelimited_nr(inode->i_mapping, 1); 604 balance_dirty_pages_ratelimited_nr(inode->i_mapping, 1);
@@ -977,7 +976,7 @@ static long btrfs_ioctl_clone(struct file *file, unsigned long srcfd,
977 976
978 /* punch hole in destination first */ 977 /* punch hole in destination first */
979 btrfs_drop_extents(trans, root, inode, off, off + len, 978 btrfs_drop_extents(trans, root, inode, off, off + len,
980 off + len, 0, &hint_byte); 979 off + len, 0, &hint_byte, 1);
981 980
982 /* clone data */ 981 /* clone data */
983 key.objectid = src->i_ino; 982 key.objectid = src->i_ino;