aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/ioctl.c
diff options
context:
space:
mode:
authorChris Mason <chris.mason@oracle.com>2011-10-11 11:41:40 -0400
committerChris Mason <chris.mason@oracle.com>2011-10-11 11:45:55 -0400
commitf7f43cc84152e53b5687cd0eb8823310ba065524 (patch)
tree2ae66461455a750baa970d02589cb393d27ffbd1 /fs/btrfs/ioctl.c
parent2a0f7f5769992bae5b3f97157fd80b2b943be485 (diff)
Btrfs: make sure not to defrag extents past i_size
The btrfs file defrag code will loop through the extents and force COW on them. But there is a concurrent truncate in the middle of the defrag, it might end up defragging the same range over and over again. The problem is that writepage won't go through and do anything on pages past i_size, so the cow won't happen, so the file will appear to still be fragmented. defrag will end up hitting the same extents again and again. In the worst case, the truncate can actually live lock with the defrag because the defrag keeps creating new ordered extents which the truncate code keeps waiting on. The fix here is to make defrag check for i_size inside the main loop, instead of just once before the looping starts. Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs/ioctl.c')
-rw-r--r--fs/btrfs/ioctl.c4
1 files changed, 3 insertions, 1 deletions
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
index df40b7c5f06b..efc4e4a85a69 100644
--- a/fs/btrfs/ioctl.c
+++ b/fs/btrfs/ioctl.c
@@ -1062,7 +1062,9 @@ int btrfs_defrag_file(struct inode *inode, struct file *file,
1062 if (i < inode->i_mapping->writeback_index) 1062 if (i < inode->i_mapping->writeback_index)
1063 inode->i_mapping->writeback_index = i; 1063 inode->i_mapping->writeback_index = i;
1064 1064
1065 while (i <= last_index && defrag_count < max_to_defrag) { 1065 while (i <= last_index && defrag_count < max_to_defrag &&
1066 (i < (i_size_read(inode) + PAGE_CACHE_SIZE - 1) >>
1067 PAGE_CACHE_SHIFT)) {
1066 /* 1068 /*
1067 * make sure we stop running if someone unmounts 1069 * make sure we stop running if someone unmounts
1068 * the FS 1070 * the FS