aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/tree-log.c
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 /fs/btrfs/tree-log.c
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>
Diffstat (limited to 'fs/btrfs/tree-log.c')
-rw-r--r--fs/btrfs/tree-log.c41
1 files changed, 15 insertions, 26 deletions
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);