diff options
author | Chris Mason <chris.mason@oracle.com> | 2008-07-24 11:57:52 -0400 |
---|---|---|
committer | Chris Mason <chris.mason@oracle.com> | 2008-09-25 11:04:05 -0400 |
commit | 3eaa2885276fd6dac7b076a793932428b7168e74 (patch) | |
tree | b06382bec68bf1755597a74ac8225f3bcddda5e5 /fs/btrfs/ioctl.c | |
parent | 64f26f745084872b916cd1bef6054e21b15c5784 (diff) |
Btrfs: Fix the defragmention code and the block relocation code for data=ordered
Before setting an extent to delalloc, the code needs to wait for
pending ordered extents.
Also, the relocation code needs to wait for ordered IO before scanning
the block group again. This is because the extents are not removed
until the IO for the new extents is finished
Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs/ioctl.c')
-rw-r--r-- | fs/btrfs/ioctl.c | 21 |
1 files changed, 14 insertions, 7 deletions
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index 83f17a5cbd6a..a61f2e7e2db5 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c | |||
@@ -213,6 +213,7 @@ int btrfs_defrag_file(struct file *file) | |||
213 | struct inode *inode = fdentry(file)->d_inode; | 213 | struct inode *inode = fdentry(file)->d_inode; |
214 | struct btrfs_root *root = BTRFS_I(inode)->root; | 214 | struct btrfs_root *root = BTRFS_I(inode)->root; |
215 | struct extent_io_tree *io_tree = &BTRFS_I(inode)->io_tree; | 215 | struct extent_io_tree *io_tree = &BTRFS_I(inode)->io_tree; |
216 | struct btrfs_ordered_extent *ordered; | ||
216 | struct page *page; | 217 | struct page *page; |
217 | unsigned long last_index; | 218 | unsigned long last_index; |
218 | unsigned long ra_pages = root->fs_info->bdi.ra_pages; | 219 | unsigned long ra_pages = root->fs_info->bdi.ra_pages; |
@@ -234,6 +235,7 @@ int btrfs_defrag_file(struct file *file) | |||
234 | min(last_index, i + ra_pages - 1)); | 235 | min(last_index, i + ra_pages - 1)); |
235 | } | 236 | } |
236 | total_read++; | 237 | total_read++; |
238 | again: | ||
237 | page = grab_cache_page(inode->i_mapping, i); | 239 | page = grab_cache_page(inode->i_mapping, i); |
238 | if (!page) | 240 | if (!page) |
239 | goto out_unlock; | 241 | goto out_unlock; |
@@ -247,18 +249,23 @@ int btrfs_defrag_file(struct file *file) | |||
247 | } | 249 | } |
248 | } | 250 | } |
249 | 251 | ||
250 | #if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,18) | ||
251 | ClearPageDirty(page); | ||
252 | #else | ||
253 | cancel_dirty_page(page, PAGE_CACHE_SIZE); | ||
254 | #endif | ||
255 | wait_on_page_writeback(page); | 252 | wait_on_page_writeback(page); |
256 | set_page_extent_mapped(page); | ||
257 | 253 | ||
258 | page_start = (u64)page->index << PAGE_CACHE_SHIFT; | 254 | page_start = (u64)page->index << PAGE_CACHE_SHIFT; |
259 | page_end = page_start + PAGE_CACHE_SIZE - 1; | 255 | page_end = page_start + PAGE_CACHE_SIZE - 1; |
260 | |||
261 | lock_extent(io_tree, page_start, page_end, GFP_NOFS); | 256 | lock_extent(io_tree, page_start, page_end, GFP_NOFS); |
257 | |||
258 | ordered = btrfs_lookup_ordered_extent(inode, page_start); | ||
259 | if (ordered) { | ||
260 | unlock_extent(io_tree, page_start, page_end, GFP_NOFS); | ||
261 | unlock_page(page); | ||
262 | page_cache_release(page); | ||
263 | btrfs_start_ordered_extent(inode, ordered, 1); | ||
264 | btrfs_put_ordered_extent(ordered); | ||
265 | goto again; | ||
266 | } | ||
267 | set_page_extent_mapped(page); | ||
268 | |||
262 | set_extent_delalloc(io_tree, page_start, | 269 | set_extent_delalloc(io_tree, page_start, |
263 | page_end, GFP_NOFS); | 270 | page_end, GFP_NOFS); |
264 | 271 | ||