diff options
author | Chris Mason <chris.mason@oracle.com> | 2008-07-18 20:42:20 -0400 |
---|---|---|
committer | Chris Mason <chris.mason@oracle.com> | 2008-09-25 11:04:05 -0400 |
commit | e5a2217ef6ff088d08a27208929a6f9c635d672c (patch) | |
tree | 47dfed451e11357a5e066180eebba8db942af2b3 /fs/btrfs/ordered-data.c | |
parent | 7f3c74fb831fa19bafe087e817c0a5ff3883f1ea (diff) |
Fix btrfs_wait_ordered_extent_range to properly wait
Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs/ordered-data.c')
-rw-r--r-- | fs/btrfs/ordered-data.c | 45 |
1 files changed, 27 insertions, 18 deletions
diff --git a/fs/btrfs/ordered-data.c b/fs/btrfs/ordered-data.c index 1ddb7bceea99..c2b4a9c4ddb6 100644 --- a/fs/btrfs/ordered-data.c +++ b/fs/btrfs/ordered-data.c | |||
@@ -324,22 +324,37 @@ void btrfs_start_ordered_extent(struct inode *inode, | |||
324 | void btrfs_wait_ordered_range(struct inode *inode, u64 start, u64 len) | 324 | void btrfs_wait_ordered_range(struct inode *inode, u64 start, u64 len) |
325 | { | 325 | { |
326 | u64 end; | 326 | u64 end; |
327 | u64 orig_end; | ||
328 | u64 wait_end; | ||
327 | struct btrfs_ordered_extent *ordered; | 329 | struct btrfs_ordered_extent *ordered; |
328 | int found; | 330 | u64 mask = BTRFS_I(inode)->root->sectorsize - 1; |
329 | int should_wait = 0; | 331 | |
330 | 332 | if (start + len < start) { | |
331 | again: | 333 | wait_end = (inode->i_size + mask) & ~mask; |
332 | if (start + len < start) | 334 | orig_end = (u64)-1; |
333 | end = (u64)-1; | 335 | } else { |
334 | else | 336 | orig_end = start + len - 1; |
335 | end = start + len - 1; | 337 | wait_end = orig_end; |
336 | found = 0; | 338 | } |
339 | |||
340 | /* start IO across the range first to instantiate any delalloc | ||
341 | * extents | ||
342 | */ | ||
343 | #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22) | ||
344 | do_sync_file_range(file, start, wait_end, SYNC_FILE_RANGE_WRITE); | ||
345 | #else | ||
346 | do_sync_mapping_range(inode->i_mapping, start, wait_end, | ||
347 | SYNC_FILE_RANGE_WRITE); | ||
348 | #endif | ||
349 | end = orig_end; | ||
350 | wait_on_extent_writeback(&BTRFS_I(inode)->io_tree, start, orig_end); | ||
351 | |||
337 | while(1) { | 352 | while(1) { |
338 | ordered = btrfs_lookup_first_ordered_extent(inode, end); | 353 | ordered = btrfs_lookup_first_ordered_extent(inode, end); |
339 | if (!ordered) { | 354 | if (!ordered) { |
340 | break; | 355 | break; |
341 | } | 356 | } |
342 | if (ordered->file_offset >= start + len) { | 357 | if (ordered->file_offset > orig_end) { |
343 | btrfs_put_ordered_extent(ordered); | 358 | btrfs_put_ordered_extent(ordered); |
344 | break; | 359 | break; |
345 | } | 360 | } |
@@ -347,21 +362,15 @@ again: | |||
347 | btrfs_put_ordered_extent(ordered); | 362 | btrfs_put_ordered_extent(ordered); |
348 | break; | 363 | break; |
349 | } | 364 | } |
350 | btrfs_start_ordered_extent(inode, ordered, should_wait); | 365 | btrfs_start_ordered_extent(inode, ordered, 1); |
351 | found++; | ||
352 | end = ordered->file_offset; | 366 | end = ordered->file_offset; |
353 | btrfs_put_ordered_extent(ordered); | 367 | btrfs_put_ordered_extent(ordered); |
354 | if (end == 0) | 368 | if (end == 0 || end == start) |
355 | break; | 369 | break; |
356 | end--; | 370 | end--; |
357 | } | 371 | } |
358 | if (should_wait && found) { | ||
359 | should_wait = 0; | ||
360 | goto again; | ||
361 | } | ||
362 | } | 372 | } |
363 | 373 | ||
364 | |||
365 | /* | 374 | /* |
366 | * find an ordered extent corresponding to file_offset. return NULL if | 375 | * find an ordered extent corresponding to file_offset. return NULL if |
367 | * nothing is found, otherwise take a reference on the extent and return it | 376 | * nothing is found, otherwise take a reference on the extent and return it |