aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMiao Xie <miaox@cn.fujitsu.com>2014-01-14 07:31:51 -0500
committerJosef Bacik <jbacik@fb.com>2014-03-10 15:15:36 -0400
commit827463c49f29111efd22148d24c9ca44d648acfa (patch)
treee7e63c42f7d41ca03ea95b75620248055595165e
parent93de4ba86480a9e0d1062cb1d535fa97fb81af48 (diff)
Btrfs: don't mix the ordered extents of all files together during logging the inodes
There was a problem in the old code: If we failed to log the csum, we would free all the ordered extents in the log list including those ordered extents that were logged successfully, it would make the log committer not to wait for the completion of the ordered extents. This patch doesn't insert the ordered extents that is about to be logged into a global list, instead, we insert them into a local list. If we log the ordered extents successfully, we splice them with the global list, or we will throw them away, then do full sync. It can also reduce the lock contention and the traverse time of list. Signed-off-by: Miao Xie <miaox@cn.fujitsu.com> Signed-off-by: Josef Bacik <jbacik@fb.com>
-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);