diff options
-rw-r--r-- | fs/btrfs/ordered-data.c | 37 | ||||
-rw-r--r-- | fs/btrfs/ordered-data.h | 6 | ||||
-rw-r--r-- | fs/btrfs/tree-log.c | 41 |
3 files changed, 49 insertions, 35 deletions
diff --git a/fs/btrfs/ordered-data.c b/fs/btrfs/ordered-data.c index b16450b840e7..138a7d7e9c90 100644 --- a/fs/btrfs/ordered-data.c +++ b/fs/btrfs/ordered-data.c | |||
@@ -424,27 +424,48 @@ out: | |||
424 | } | 424 | } |
425 | 425 | ||
426 | /* Needs to either be called under a log transaction or the log_mutex */ | 426 | /* Needs to either be called under a log transaction or the log_mutex */ |
427 | void btrfs_get_logged_extents(struct btrfs_root *log, struct inode *inode) | 427 | void btrfs_get_logged_extents(struct inode *inode, |
428 | struct list_head *logged_list) | ||
428 | { | 429 | { |
429 | struct btrfs_ordered_inode_tree *tree; | 430 | struct btrfs_ordered_inode_tree *tree; |
430 | struct btrfs_ordered_extent *ordered; | 431 | struct btrfs_ordered_extent *ordered; |
431 | struct rb_node *n; | 432 | struct rb_node *n; |
432 | int index = log->log_transid % 2; | ||
433 | 433 | ||
434 | tree = &BTRFS_I(inode)->ordered_tree; | 434 | tree = &BTRFS_I(inode)->ordered_tree; |
435 | spin_lock_irq(&tree->lock); | 435 | spin_lock_irq(&tree->lock); |
436 | for (n = rb_first(&tree->tree); n; n = rb_next(n)) { | 436 | for (n = rb_first(&tree->tree); n; n = rb_next(n)) { |
437 | ordered = rb_entry(n, struct btrfs_ordered_extent, rb_node); | 437 | ordered = rb_entry(n, struct btrfs_ordered_extent, rb_node); |
438 | spin_lock(&log->log_extents_lock[index]); | 438 | if (!list_empty(&ordered->log_list)) |
439 | if (list_empty(&ordered->log_list)) { | 439 | continue; |
440 | list_add_tail(&ordered->log_list, &log->logged_list[index]); | 440 | list_add_tail(&ordered->log_list, logged_list); |
441 | atomic_inc(&ordered->refs); | 441 | atomic_inc(&ordered->refs); |
442 | } | ||
443 | spin_unlock(&log->log_extents_lock[index]); | ||
444 | } | 442 | } |
445 | spin_unlock_irq(&tree->lock); | 443 | spin_unlock_irq(&tree->lock); |
446 | } | 444 | } |
447 | 445 | ||
446 | void btrfs_put_logged_extents(struct list_head *logged_list) | ||
447 | { | ||
448 | struct btrfs_ordered_extent *ordered; | ||
449 | |||
450 | while (!list_empty(logged_list)) { | ||
451 | ordered = list_first_entry(logged_list, | ||
452 | struct btrfs_ordered_extent, | ||
453 | log_list); | ||
454 | list_del_init(&ordered->log_list); | ||
455 | btrfs_put_ordered_extent(ordered); | ||
456 | } | ||
457 | } | ||
458 | |||
459 | void btrfs_submit_logged_extents(struct list_head *logged_list, | ||
460 | struct btrfs_root *log) | ||
461 | { | ||
462 | int index = log->log_transid % 2; | ||
463 | |||
464 | spin_lock_irq(&log->log_extents_lock[index]); | ||
465 | list_splice_tail(logged_list, &log->logged_list[index]); | ||
466 | spin_unlock_irq(&log->log_extents_lock[index]); | ||
467 | } | ||
468 | |||
448 | void btrfs_wait_logged_extents(struct btrfs_root *log, u64 transid) | 469 | void btrfs_wait_logged_extents(struct btrfs_root *log, u64 transid) |
449 | { | 470 | { |
450 | struct btrfs_ordered_extent *ordered; | 471 | struct btrfs_ordered_extent *ordered; |
diff --git a/fs/btrfs/ordered-data.h b/fs/btrfs/ordered-data.h index 9b0450f7ac20..246897058efb 100644 --- a/fs/btrfs/ordered-data.h +++ b/fs/btrfs/ordered-data.h | |||
@@ -197,7 +197,11 @@ void btrfs_add_ordered_operation(struct btrfs_trans_handle *trans, | |||
197 | struct inode *inode); | 197 | struct inode *inode); |
198 | int btrfs_wait_ordered_extents(struct btrfs_root *root, int nr); | 198 | int btrfs_wait_ordered_extents(struct btrfs_root *root, int nr); |
199 | void btrfs_wait_ordered_roots(struct btrfs_fs_info *fs_info, int nr); | 199 | void btrfs_wait_ordered_roots(struct btrfs_fs_info *fs_info, int nr); |
200 | void btrfs_get_logged_extents(struct btrfs_root *log, struct inode *inode); | 200 | void btrfs_get_logged_extents(struct inode *inode, |
201 | struct list_head *logged_list); | ||
202 | void btrfs_put_logged_extents(struct list_head *logged_list); | ||
203 | void btrfs_submit_logged_extents(struct list_head *logged_list, | ||
204 | struct btrfs_root *log); | ||
201 | void btrfs_wait_logged_extents(struct btrfs_root *log, u64 transid); | 205 | void btrfs_wait_logged_extents(struct btrfs_root *log, u64 transid); |
202 | void btrfs_free_logged_extents(struct btrfs_root *log, u64 transid); | 206 | void btrfs_free_logged_extents(struct btrfs_root *log, u64 transid); |
203 | int __init ordered_data_init(void); | 207 | int __init ordered_data_init(void); |
diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c index 39d83da03e03..7c449c699bed 100644 --- a/fs/btrfs/tree-log.c +++ b/fs/btrfs/tree-log.c | |||
@@ -3479,7 +3479,8 @@ static int extent_cmp(void *priv, struct list_head *a, struct list_head *b) | |||
3479 | 3479 | ||
3480 | static int log_one_extent(struct btrfs_trans_handle *trans, | 3480 | static int log_one_extent(struct btrfs_trans_handle *trans, |
3481 | struct inode *inode, struct btrfs_root *root, | 3481 | struct inode *inode, struct btrfs_root *root, |
3482 | struct extent_map *em, struct btrfs_path *path) | 3482 | struct extent_map *em, struct btrfs_path *path, |
3483 | struct list_head *logged_list) | ||
3483 | { | 3484 | { |
3484 | struct btrfs_root *log = root->log_root; | 3485 | struct btrfs_root *log = root->log_root; |
3485 | struct btrfs_file_extent_item *fi; | 3486 | struct btrfs_file_extent_item *fi; |
@@ -3495,7 +3496,6 @@ static int log_one_extent(struct btrfs_trans_handle *trans, | |||
3495 | u64 extent_offset = em->start - em->orig_start; | 3496 | u64 extent_offset = em->start - em->orig_start; |
3496 | u64 block_len; | 3497 | u64 block_len; |
3497 | int ret; | 3498 | int ret; |
3498 | int index = log->log_transid % 2; | ||
3499 | bool skip_csum = BTRFS_I(inode)->flags & BTRFS_INODE_NODATASUM; | 3499 | bool skip_csum = BTRFS_I(inode)->flags & BTRFS_INODE_NODATASUM; |
3500 | int extent_inserted = 0; | 3500 | int extent_inserted = 0; |
3501 | 3501 | ||
@@ -3579,17 +3579,12 @@ static int log_one_extent(struct btrfs_trans_handle *trans, | |||
3579 | * First check and see if our csums are on our outstanding ordered | 3579 | * First check and see if our csums are on our outstanding ordered |
3580 | * extents. | 3580 | * extents. |
3581 | */ | 3581 | */ |
3582 | again: | 3582 | list_for_each_entry(ordered, logged_list, log_list) { |
3583 | spin_lock_irq(&log->log_extents_lock[index]); | ||
3584 | list_for_each_entry(ordered, &log->logged_list[index], log_list) { | ||
3585 | struct btrfs_ordered_sum *sum; | 3583 | struct btrfs_ordered_sum *sum; |
3586 | 3584 | ||
3587 | if (!mod_len) | 3585 | if (!mod_len) |
3588 | break; | 3586 | break; |
3589 | 3587 | ||
3590 | if (ordered->inode != inode) | ||
3591 | continue; | ||
3592 | |||
3593 | if (ordered->file_offset + ordered->len <= mod_start || | 3588 | if (ordered->file_offset + ordered->len <= mod_start || |
3594 | mod_start + mod_len <= ordered->file_offset) | 3589 | mod_start + mod_len <= ordered->file_offset) |
3595 | continue; | 3590 | continue; |
@@ -3632,12 +3627,6 @@ again: | |||
3632 | if (test_and_set_bit(BTRFS_ORDERED_LOGGED_CSUM, | 3627 | if (test_and_set_bit(BTRFS_ORDERED_LOGGED_CSUM, |
3633 | &ordered->flags)) | 3628 | &ordered->flags)) |
3634 | continue; | 3629 | continue; |
3635 | atomic_inc(&ordered->refs); | ||
3636 | spin_unlock_irq(&log->log_extents_lock[index]); | ||
3637 | /* | ||
3638 | * we've dropped the lock, we must either break or | ||
3639 | * start over after this. | ||
3640 | */ | ||
3641 | 3630 | ||
3642 | if (ordered->csum_bytes_left) { | 3631 | if (ordered->csum_bytes_left) { |
3643 | btrfs_start_ordered_extent(inode, ordered, 0); | 3632 | btrfs_start_ordered_extent(inode, ordered, 0); |
@@ -3647,16 +3636,11 @@ again: | |||
3647 | 3636 | ||
3648 | list_for_each_entry(sum, &ordered->list, list) { | 3637 | list_for_each_entry(sum, &ordered->list, list) { |
3649 | ret = btrfs_csum_file_blocks(trans, log, sum); | 3638 | ret = btrfs_csum_file_blocks(trans, log, sum); |
3650 | if (ret) { | 3639 | if (ret) |
3651 | btrfs_put_ordered_extent(ordered); | ||
3652 | goto unlocked; | 3640 | goto unlocked; |
3653 | } | ||
3654 | } | 3641 | } |
3655 | btrfs_put_ordered_extent(ordered); | ||
3656 | goto again; | ||
3657 | 3642 | ||
3658 | } | 3643 | } |
3659 | spin_unlock_irq(&log->log_extents_lock[index]); | ||
3660 | unlocked: | 3644 | unlocked: |
3661 | 3645 | ||
3662 | if (!mod_len || ret) | 3646 | if (!mod_len || ret) |
@@ -3694,7 +3678,8 @@ unlocked: | |||
3694 | static int btrfs_log_changed_extents(struct btrfs_trans_handle *trans, | 3678 | static int btrfs_log_changed_extents(struct btrfs_trans_handle *trans, |
3695 | struct btrfs_root *root, | 3679 | struct btrfs_root *root, |
3696 | struct inode *inode, | 3680 | struct inode *inode, |
3697 | struct btrfs_path *path) | 3681 | struct btrfs_path *path, |
3682 | struct list_head *logged_list) | ||
3698 | { | 3683 | { |
3699 | struct extent_map *em, *n; | 3684 | struct extent_map *em, *n; |
3700 | struct list_head extents; | 3685 | struct list_head extents; |
@@ -3752,7 +3737,7 @@ process: | |||
3752 | 3737 | ||
3753 | write_unlock(&tree->lock); | 3738 | write_unlock(&tree->lock); |
3754 | 3739 | ||
3755 | ret = log_one_extent(trans, inode, root, em, path); | 3740 | ret = log_one_extent(trans, inode, root, em, path, logged_list); |
3756 | write_lock(&tree->lock); | 3741 | write_lock(&tree->lock); |
3757 | clear_em_logging(tree, em); | 3742 | clear_em_logging(tree, em); |
3758 | free_extent_map(em); | 3743 | free_extent_map(em); |
@@ -3788,6 +3773,7 @@ static int btrfs_log_inode(struct btrfs_trans_handle *trans, | |||
3788 | struct btrfs_key max_key; | 3773 | struct btrfs_key max_key; |
3789 | struct btrfs_root *log = root->log_root; | 3774 | struct btrfs_root *log = root->log_root; |
3790 | struct extent_buffer *src = NULL; | 3775 | struct extent_buffer *src = NULL; |
3776 | LIST_HEAD(logged_list); | ||
3791 | u64 last_extent = 0; | 3777 | u64 last_extent = 0; |
3792 | int err = 0; | 3778 | int err = 0; |
3793 | int ret; | 3779 | int ret; |
@@ -3836,7 +3822,7 @@ static int btrfs_log_inode(struct btrfs_trans_handle *trans, | |||
3836 | 3822 | ||
3837 | mutex_lock(&BTRFS_I(inode)->log_mutex); | 3823 | mutex_lock(&BTRFS_I(inode)->log_mutex); |
3838 | 3824 | ||
3839 | btrfs_get_logged_extents(log, inode); | 3825 | btrfs_get_logged_extents(inode, &logged_list); |
3840 | 3826 | ||
3841 | /* | 3827 | /* |
3842 | * a brute force approach to making sure we get the most uptodate | 3828 | * a brute force approach to making sure we get the most uptodate |
@@ -3962,7 +3948,8 @@ log_extents: | |||
3962 | btrfs_release_path(path); | 3948 | btrfs_release_path(path); |
3963 | btrfs_release_path(dst_path); | 3949 | btrfs_release_path(dst_path); |
3964 | if (fast_search) { | 3950 | if (fast_search) { |
3965 | ret = btrfs_log_changed_extents(trans, root, inode, dst_path); | 3951 | ret = btrfs_log_changed_extents(trans, root, inode, dst_path, |
3952 | &logged_list); | ||
3966 | if (ret) { | 3953 | if (ret) { |
3967 | err = ret; | 3954 | err = ret; |
3968 | goto out_unlock; | 3955 | goto out_unlock; |
@@ -3987,8 +3974,10 @@ log_extents: | |||
3987 | BTRFS_I(inode)->logged_trans = trans->transid; | 3974 | BTRFS_I(inode)->logged_trans = trans->transid; |
3988 | BTRFS_I(inode)->last_log_commit = BTRFS_I(inode)->last_sub_trans; | 3975 | BTRFS_I(inode)->last_log_commit = BTRFS_I(inode)->last_sub_trans; |
3989 | out_unlock: | 3976 | out_unlock: |
3990 | if (err) | 3977 | if (unlikely(err)) |
3991 | btrfs_free_logged_extents(log, log->log_transid); | 3978 | btrfs_put_logged_extents(&logged_list); |
3979 | else | ||
3980 | btrfs_submit_logged_extents(&logged_list, log); | ||
3992 | mutex_unlock(&BTRFS_I(inode)->log_mutex); | 3981 | mutex_unlock(&BTRFS_I(inode)->log_mutex); |
3993 | 3982 | ||
3994 | btrfs_free_path(path); | 3983 | btrfs_free_path(path); |