aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs
diff options
context:
space:
mode:
authorChris Mason <chris.mason@oracle.com>2008-07-18 20:42:20 -0400
committerChris Mason <chris.mason@oracle.com>2008-09-25 11:04:05 -0400
commite5a2217ef6ff088d08a27208929a6f9c635d672c (patch)
tree47dfed451e11357a5e066180eebba8db942af2b3 /fs/btrfs
parent7f3c74fb831fa19bafe087e817c0a5ff3883f1ea (diff)
Fix btrfs_wait_ordered_extent_range to properly wait
Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs')
-rw-r--r--fs/btrfs/file-item.c3
-rw-r--r--fs/btrfs/inode.c26
-rw-r--r--fs/btrfs/ordered-data.c45
3 files changed, 49 insertions, 25 deletions
diff --git a/fs/btrfs/file-item.c b/fs/btrfs/file-item.c
index d9c69e16d368..45127e4797c8 100644
--- a/fs/btrfs/file-item.c
+++ b/fs/btrfs/file-item.c
@@ -161,7 +161,8 @@ int btrfs_csum_one_bio(struct btrfs_root *root, struct inode *inode,
161 161
162 while(bio_index < bio->bi_vcnt) { 162 while(bio_index < bio->bi_vcnt) {
163 offset = page_offset(bvec->bv_page) + bvec->bv_offset; 163 offset = page_offset(bvec->bv_page) + bvec->bv_offset;
164 if (offset >= ordered->file_offset + ordered->len) { 164 if (offset >= ordered->file_offset + ordered->len ||
165 offset < ordered->file_offset) {
165 unsigned long bytes_left; 166 unsigned long bytes_left;
166 sums->len = this_sum_bytes; 167 sums->len = this_sum_bytes;
167 this_sum_bytes = 0; 168 this_sum_bytes = 0;
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index 08dbe738b512..50ee4befac8e 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -128,7 +128,9 @@ static int cow_file_range(struct inode *inode, u64 start, u64 end)
128 goto out; 128 goto out;
129 129
130 BUG_ON(num_bytes > btrfs_super_total_bytes(&root->fs_info->super_copy)); 130 BUG_ON(num_bytes > btrfs_super_total_bytes(&root->fs_info->super_copy));
131 mutex_lock(&BTRFS_I(inode)->extent_mutex);
131 btrfs_drop_extent_cache(inode, start, start + num_bytes - 1); 132 btrfs_drop_extent_cache(inode, start, start + num_bytes - 1);
133 mutex_unlock(&BTRFS_I(inode)->extent_mutex);
132 134
133 while(num_bytes > 0) { 135 while(num_bytes > 0) {
134 cur_alloc_size = min(num_bytes, root->fs_info->max_extent); 136 cur_alloc_size = min(num_bytes, root->fs_info->max_extent);
@@ -144,6 +146,7 @@ static int cow_file_range(struct inode *inode, u64 start, u64 end)
144 em->len = ins.offset; 146 em->len = ins.offset;
145 em->block_start = ins.objectid; 147 em->block_start = ins.objectid;
146 em->bdev = root->fs_info->fs_devices->latest_bdev; 148 em->bdev = root->fs_info->fs_devices->latest_bdev;
149 mutex_lock(&BTRFS_I(inode)->extent_mutex);
147 set_bit(EXTENT_FLAG_PINNED, &em->flags); 150 set_bit(EXTENT_FLAG_PINNED, &em->flags);
148 while(1) { 151 while(1) {
149 spin_lock(&em_tree->lock); 152 spin_lock(&em_tree->lock);
@@ -156,6 +159,7 @@ static int cow_file_range(struct inode *inode, u64 start, u64 end)
156 btrfs_drop_extent_cache(inode, start, 159 btrfs_drop_extent_cache(inode, start,
157 start + ins.offset - 1); 160 start + ins.offset - 1);
158 } 161 }
162 mutex_unlock(&BTRFS_I(inode)->extent_mutex);
159 163
160 cur_alloc_size = ins.offset; 164 cur_alloc_size = ins.offset;
161 ret = btrfs_add_ordered_extent(inode, start, ins.objectid, 165 ret = btrfs_add_ordered_extent(inode, start, ins.objectid,
@@ -487,6 +491,8 @@ static int btrfs_finish_ordered_io(struct inode *inode, u64 start, u64 end)
487 struct extent_map_tree *em_tree = &BTRFS_I(inode)->extent_tree; 491 struct extent_map_tree *em_tree = &BTRFS_I(inode)->extent_tree;
488 struct extent_map *em; 492 struct extent_map *em;
489 u64 alloc_hint = 0; 493 u64 alloc_hint = 0;
494 u64 clear_start;
495 u64 clear_end;
490 struct list_head list; 496 struct list_head list;
491 struct btrfs_key ins; 497 struct btrfs_key ins;
492 int ret; 498 int ret;
@@ -509,12 +515,14 @@ static int btrfs_finish_ordered_io(struct inode *inode, u64 start, u64 end)
509 ins.objectid = ordered_extent->start; 515 ins.objectid = ordered_extent->start;
510 ins.offset = ordered_extent->len; 516 ins.offset = ordered_extent->len;
511 ins.type = BTRFS_EXTENT_ITEM_KEY; 517 ins.type = BTRFS_EXTENT_ITEM_KEY;
518
512 ret = btrfs_alloc_reserved_extent(trans, root, root->root_key.objectid, 519 ret = btrfs_alloc_reserved_extent(trans, root, root->root_key.objectid,
513 trans->transid, inode->i_ino, 520 trans->transid, inode->i_ino,
514 ordered_extent->file_offset, &ins); 521 ordered_extent->file_offset, &ins);
515 BUG_ON(ret); 522 BUG_ON(ret);
516 523
517 mutex_lock(&BTRFS_I(inode)->extent_mutex); 524 mutex_lock(&BTRFS_I(inode)->extent_mutex);
525
518 ret = btrfs_drop_extents(trans, root, inode, 526 ret = btrfs_drop_extents(trans, root, inode,
519 ordered_extent->file_offset, 527 ordered_extent->file_offset,
520 ordered_extent->file_offset + 528 ordered_extent->file_offset +
@@ -528,13 +536,19 @@ static int btrfs_finish_ordered_io(struct inode *inode, u64 start, u64 end)
528 ordered_extent->len, 0); 536 ordered_extent->len, 0);
529 BUG_ON(ret); 537 BUG_ON(ret);
530 538
531
532 spin_lock(&em_tree->lock); 539 spin_lock(&em_tree->lock);
533 em = lookup_extent_mapping(em_tree, ordered_extent->file_offset, 540 clear_start = ordered_extent->file_offset;
534 ordered_extent->len); 541 clear_end = ordered_extent->file_offset + ordered_extent->len;
535 if (em) { 542 while(clear_start < clear_end) {
536 clear_bit(EXTENT_FLAG_PINNED, &em->flags); 543 em = lookup_extent_mapping(em_tree, clear_start,
537 free_extent_map(em); 544 clear_end - clear_start);
545 if (em) {
546 clear_bit(EXTENT_FLAG_PINNED, &em->flags);
547 clear_start = em->start + em->len;
548 free_extent_map(em);
549 } else {
550 break;
551 }
538 } 552 }
539 spin_unlock(&em_tree->lock); 553 spin_unlock(&em_tree->lock);
540 554
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,
324void btrfs_wait_ordered_range(struct inode *inode, u64 start, u64 len) 324void 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) {
331again: 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