diff options
Diffstat (limited to 'fs/btrfs/ordered-data.c')
-rw-r--r-- | fs/btrfs/ordered-data.c | 89 |
1 files changed, 89 insertions, 0 deletions
diff --git a/fs/btrfs/ordered-data.c b/fs/btrfs/ordered-data.c index 6513270f054c..d86a953ae51d 100644 --- a/fs/btrfs/ordered-data.c +++ b/fs/btrfs/ordered-data.c | |||
@@ -406,3 +406,92 @@ out: | |||
406 | mutex_unlock(&tree->mutex); | 406 | mutex_unlock(&tree->mutex); |
407 | return entry; | 407 | return entry; |
408 | } | 408 | } |
409 | |||
410 | int btrfs_ordered_update_i_size(struct inode *inode, | ||
411 | struct btrfs_ordered_extent *ordered) | ||
412 | { | ||
413 | struct btrfs_ordered_inode_tree *tree = &BTRFS_I(inode)->ordered_tree; | ||
414 | struct extent_io_tree *io_tree = &BTRFS_I(inode)->io_tree; | ||
415 | u64 disk_i_size; | ||
416 | u64 new_i_size; | ||
417 | u64 i_size_test; | ||
418 | struct rb_node *node; | ||
419 | struct btrfs_ordered_extent *test; | ||
420 | |||
421 | mutex_lock(&tree->mutex); | ||
422 | disk_i_size = BTRFS_I(inode)->disk_i_size; | ||
423 | |||
424 | /* | ||
425 | * if the disk i_size is already at the inode->i_size, or | ||
426 | * this ordered extent is inside the disk i_size, we're done | ||
427 | */ | ||
428 | if (disk_i_size >= inode->i_size || | ||
429 | ordered->file_offset + ordered->len <= disk_i_size) { | ||
430 | goto out; | ||
431 | } | ||
432 | |||
433 | /* | ||
434 | * we can't update the disk_isize if there are delalloc bytes | ||
435 | * between disk_i_size and this ordered extent | ||
436 | */ | ||
437 | if (test_range_bit(io_tree, disk_i_size, | ||
438 | ordered->file_offset + ordered->len - 1, | ||
439 | EXTENT_DELALLOC, 0)) { | ||
440 | goto out; | ||
441 | } | ||
442 | /* | ||
443 | * walk backward from this ordered extent to disk_i_size. | ||
444 | * if we find an ordered extent then we can't update disk i_size | ||
445 | * yet | ||
446 | */ | ||
447 | while(1) { | ||
448 | node = rb_prev(&ordered->rb_node); | ||
449 | if (!node) | ||
450 | break; | ||
451 | test = rb_entry(node, struct btrfs_ordered_extent, rb_node); | ||
452 | if (test->file_offset + test->len <= disk_i_size) | ||
453 | break; | ||
454 | if (test->file_offset >= inode->i_size) | ||
455 | break; | ||
456 | if (test->file_offset >= disk_i_size) | ||
457 | goto out; | ||
458 | } | ||
459 | new_i_size = min_t(u64, entry_end(ordered), i_size_read(inode)); | ||
460 | |||
461 | /* | ||
462 | * at this point, we know we can safely update i_size to at least | ||
463 | * the offset from this ordered extent. But, we need to | ||
464 | * walk forward and see if ios from higher up in the file have | ||
465 | * finished. | ||
466 | */ | ||
467 | node = rb_next(&ordered->rb_node); | ||
468 | i_size_test = 0; | ||
469 | if (node) { | ||
470 | /* | ||
471 | * do we have an area where IO might have finished | ||
472 | * between our ordered extent and the next one. | ||
473 | */ | ||
474 | test = rb_entry(node, struct btrfs_ordered_extent, rb_node); | ||
475 | if (test->file_offset > entry_end(ordered)) { | ||
476 | i_size_test = test->file_offset - 1; | ||
477 | } | ||
478 | } else { | ||
479 | i_size_test = i_size_read(inode); | ||
480 | } | ||
481 | |||
482 | /* | ||
483 | * i_size_test is the end of a region after this ordered | ||
484 | * extent where there are no ordered extents. As long as there | ||
485 | * are no delalloc bytes in this area, it is safe to update | ||
486 | * disk_i_size to the end of the region. | ||
487 | */ | ||
488 | if (i_size_test > entry_end(ordered) && | ||
489 | !test_range_bit(io_tree, entry_end(ordered), i_size_test, | ||
490 | EXTENT_DELALLOC, 0)) { | ||
491 | new_i_size = min_t(u64, i_size_test, i_size_read(inode)); | ||
492 | } | ||
493 | BTRFS_I(inode)->disk_i_size = new_i_size; | ||
494 | out: | ||
495 | mutex_unlock(&tree->mutex); | ||
496 | return 0; | ||
497 | } | ||