aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/ordered-data.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/ordered-data.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/ordered-data.c')
-rw-r--r--fs/btrfs/ordered-data.c37
1 files changed, 29 insertions, 8 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;