diff options
author | Miao Xie <miaox@cn.fujitsu.com> | 2012-10-25 05:41:36 -0400 |
---|---|---|
committer | Josef Bacik <jbacik@fusionio.com> | 2012-12-11 13:31:38 -0500 |
commit | 9afab8820bb8b55af669b199597d6716e04d1ba8 (patch) | |
tree | cdd61b6cefaa048dc140835cb08b2ee40d67f37d /fs/btrfs | |
parent | 25287e0a16c0ad068aa89ab01aea6c699b31ec12 (diff) |
Btrfs: make ordered extent be flushed by multi-task
Though the process of the ordered extents is a bit different with the delalloc inode
flush, but we can see it as a subset of the delalloc inode flush, so we also handle
them by flush workers.
Signed-off-by: Miao Xie <miaox@cn.fujitsu.com>
Signed-off-by: Chris Mason <chris.mason@fusionio.com>
Diffstat (limited to 'fs/btrfs')
-rw-r--r-- | fs/btrfs/ordered-data.c | 41 | ||||
-rw-r--r-- | fs/btrfs/ordered-data.h | 5 |
2 files changed, 37 insertions, 9 deletions
diff --git a/fs/btrfs/ordered-data.c b/fs/btrfs/ordered-data.c index ab2a3c0c540f..eecc20f14cfa 100644 --- a/fs/btrfs/ordered-data.c +++ b/fs/btrfs/ordered-data.c | |||
@@ -211,6 +211,8 @@ static int __btrfs_add_ordered_extent(struct inode *inode, u64 file_offset, | |||
211 | init_waitqueue_head(&entry->wait); | 211 | init_waitqueue_head(&entry->wait); |
212 | INIT_LIST_HEAD(&entry->list); | 212 | INIT_LIST_HEAD(&entry->list); |
213 | INIT_LIST_HEAD(&entry->root_extent_list); | 213 | INIT_LIST_HEAD(&entry->root_extent_list); |
214 | INIT_LIST_HEAD(&entry->work_list); | ||
215 | init_completion(&entry->completion); | ||
214 | 216 | ||
215 | trace_btrfs_ordered_extent_add(inode, entry); | 217 | trace_btrfs_ordered_extent_add(inode, entry); |
216 | 218 | ||
@@ -464,18 +466,28 @@ void btrfs_remove_ordered_extent(struct inode *inode, | |||
464 | wake_up(&entry->wait); | 466 | wake_up(&entry->wait); |
465 | } | 467 | } |
466 | 468 | ||
469 | static void btrfs_run_ordered_extent_work(struct btrfs_work *work) | ||
470 | { | ||
471 | struct btrfs_ordered_extent *ordered; | ||
472 | |||
473 | ordered = container_of(work, struct btrfs_ordered_extent, flush_work); | ||
474 | btrfs_start_ordered_extent(ordered->inode, ordered, 1); | ||
475 | complete(&ordered->completion); | ||
476 | } | ||
477 | |||
467 | /* | 478 | /* |
468 | * wait for all the ordered extents in a root. This is done when balancing | 479 | * wait for all the ordered extents in a root. This is done when balancing |
469 | * space between drives. | 480 | * space between drives. |
470 | */ | 481 | */ |
471 | void btrfs_wait_ordered_extents(struct btrfs_root *root, int delay_iput) | 482 | void btrfs_wait_ordered_extents(struct btrfs_root *root, int delay_iput) |
472 | { | 483 | { |
473 | struct list_head splice; | 484 | struct list_head splice, works; |
474 | struct list_head *cur; | 485 | struct list_head *cur; |
475 | struct btrfs_ordered_extent *ordered; | 486 | struct btrfs_ordered_extent *ordered, *next; |
476 | struct inode *inode; | 487 | struct inode *inode; |
477 | 488 | ||
478 | INIT_LIST_HEAD(&splice); | 489 | INIT_LIST_HEAD(&splice); |
490 | INIT_LIST_HEAD(&works); | ||
479 | 491 | ||
480 | spin_lock(&root->fs_info->ordered_extent_lock); | 492 | spin_lock(&root->fs_info->ordered_extent_lock); |
481 | list_splice_init(&root->fs_info->ordered_extents, &splice); | 493 | list_splice_init(&root->fs_info->ordered_extents, &splice); |
@@ -494,19 +506,32 @@ void btrfs_wait_ordered_extents(struct btrfs_root *root, int delay_iput) | |||
494 | spin_unlock(&root->fs_info->ordered_extent_lock); | 506 | spin_unlock(&root->fs_info->ordered_extent_lock); |
495 | 507 | ||
496 | if (inode) { | 508 | if (inode) { |
497 | btrfs_start_ordered_extent(inode, ordered, 1); | 509 | ordered->flush_work.func = btrfs_run_ordered_extent_work; |
498 | btrfs_put_ordered_extent(ordered); | 510 | list_add_tail(&ordered->work_list, &works); |
499 | if (delay_iput) | 511 | btrfs_queue_worker(&root->fs_info->flush_workers, |
500 | btrfs_add_delayed_iput(inode); | 512 | &ordered->flush_work); |
501 | else | ||
502 | iput(inode); | ||
503 | } else { | 513 | } else { |
504 | btrfs_put_ordered_extent(ordered); | 514 | btrfs_put_ordered_extent(ordered); |
505 | } | 515 | } |
506 | 516 | ||
517 | cond_resched(); | ||
507 | spin_lock(&root->fs_info->ordered_extent_lock); | 518 | spin_lock(&root->fs_info->ordered_extent_lock); |
508 | } | 519 | } |
509 | spin_unlock(&root->fs_info->ordered_extent_lock); | 520 | spin_unlock(&root->fs_info->ordered_extent_lock); |
521 | |||
522 | list_for_each_entry_safe(ordered, next, &works, work_list) { | ||
523 | list_del_init(&ordered->work_list); | ||
524 | wait_for_completion(&ordered->completion); | ||
525 | |||
526 | inode = ordered->inode; | ||
527 | btrfs_put_ordered_extent(ordered); | ||
528 | if (delay_iput) | ||
529 | btrfs_add_delayed_iput(inode); | ||
530 | else | ||
531 | iput(inode); | ||
532 | |||
533 | cond_resched(); | ||
534 | } | ||
510 | } | 535 | } |
511 | 536 | ||
512 | /* | 537 | /* |
diff --git a/fs/btrfs/ordered-data.h b/fs/btrfs/ordered-data.h index e8dcec635112..efc7c2930c17 100644 --- a/fs/btrfs/ordered-data.h +++ b/fs/btrfs/ordered-data.h | |||
@@ -128,8 +128,11 @@ struct btrfs_ordered_extent { | |||
128 | struct list_head root_extent_list; | 128 | struct list_head root_extent_list; |
129 | 129 | ||
130 | struct btrfs_work work; | 130 | struct btrfs_work work; |
131 | }; | ||
132 | 131 | ||
132 | struct completion completion; | ||
133 | struct btrfs_work flush_work; | ||
134 | struct list_head work_list; | ||
135 | }; | ||
133 | 136 | ||
134 | /* | 137 | /* |
135 | * calculates the total size you need to allocate for an ordered sum | 138 | * calculates the total size you need to allocate for an ordered sum |