aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/btrfs/ordered-data.c37
-rw-r--r--fs/btrfs/ordered-data.h6
-rw-r--r--fs/btrfs/tree-log.c41
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 */
427void btrfs_get_logged_extents(struct btrfs_root *log, struct inode *inode) 427void 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
446void 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
459void 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
448void btrfs_wait_logged_extents(struct btrfs_root *log, u64 transid) 469void 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);
198int btrfs_wait_ordered_extents(struct btrfs_root *root, int nr); 198int btrfs_wait_ordered_extents(struct btrfs_root *root, int nr);
199void btrfs_wait_ordered_roots(struct btrfs_fs_info *fs_info, int nr); 199void btrfs_wait_ordered_roots(struct btrfs_fs_info *fs_info, int nr);
200void btrfs_get_logged_extents(struct btrfs_root *log, struct inode *inode); 200void btrfs_get_logged_extents(struct inode *inode,
201 struct list_head *logged_list);
202void btrfs_put_logged_extents(struct list_head *logged_list);
203void btrfs_submit_logged_extents(struct list_head *logged_list,
204 struct btrfs_root *log);
201void btrfs_wait_logged_extents(struct btrfs_root *log, u64 transid); 205void btrfs_wait_logged_extents(struct btrfs_root *log, u64 transid);
202void btrfs_free_logged_extents(struct btrfs_root *log, u64 transid); 206void btrfs_free_logged_extents(struct btrfs_root *log, u64 transid);
203int __init ordered_data_init(void); 207int __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
3480static int log_one_extent(struct btrfs_trans_handle *trans, 3480static 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 */
3582again: 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]);
3660unlocked: 3644unlocked:
3661 3645
3662 if (!mod_len || ret) 3646 if (!mod_len || ret)
@@ -3694,7 +3678,8 @@ unlocked:
3694static int btrfs_log_changed_extents(struct btrfs_trans_handle *trans, 3678static 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;
3989out_unlock: 3976out_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);