diff options
author | Miao Xie <miaox@cn.fujitsu.com> | 2012-10-25 05:31:03 -0400 |
---|---|---|
committer | Josef Bacik <jbacik@fusionio.com> | 2012-12-11 13:31:37 -0500 |
commit | 25287e0a16c0ad068aa89ab01aea6c699b31ec12 (patch) | |
tree | 3badf12a84d2e2e437fc4b432ea41c197a9cbc99 /fs/btrfs/ordered-data.c | |
parent | 8ccf6f19b67f7e0921063cc309f4672a6afcb528 (diff) |
Btrfs: make ordered operations be handled by multi-task
The process of the ordered operations is similar to the delalloc inode flush, so
we 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/ordered-data.c')
-rw-r--r-- | fs/btrfs/ordered-data.c | 46 |
1 files changed, 30 insertions, 16 deletions
diff --git a/fs/btrfs/ordered-data.c b/fs/btrfs/ordered-data.c index 7772f02ba28e..ab2a3c0c540f 100644 --- a/fs/btrfs/ordered-data.c +++ b/fs/btrfs/ordered-data.c | |||
@@ -519,13 +519,17 @@ void btrfs_wait_ordered_extents(struct btrfs_root *root, int delay_iput) | |||
519 | * extra check to make sure the ordered operation list really is empty | 519 | * extra check to make sure the ordered operation list really is empty |
520 | * before we return | 520 | * before we return |
521 | */ | 521 | */ |
522 | void btrfs_run_ordered_operations(struct btrfs_root *root, int wait) | 522 | int btrfs_run_ordered_operations(struct btrfs_root *root, int wait) |
523 | { | 523 | { |
524 | struct btrfs_inode *btrfs_inode; | 524 | struct btrfs_inode *btrfs_inode; |
525 | struct inode *inode; | 525 | struct inode *inode; |
526 | struct list_head splice; | 526 | struct list_head splice; |
527 | struct list_head works; | ||
528 | struct btrfs_delalloc_work *work, *next; | ||
529 | int ret = 0; | ||
527 | 530 | ||
528 | INIT_LIST_HEAD(&splice); | 531 | INIT_LIST_HEAD(&splice); |
532 | INIT_LIST_HEAD(&works); | ||
529 | 533 | ||
530 | mutex_lock(&root->fs_info->ordered_operations_mutex); | 534 | mutex_lock(&root->fs_info->ordered_operations_mutex); |
531 | spin_lock(&root->fs_info->ordered_extent_lock); | 535 | spin_lock(&root->fs_info->ordered_extent_lock); |
@@ -533,6 +537,7 @@ again: | |||
533 | list_splice_init(&root->fs_info->ordered_operations, &splice); | 537 | list_splice_init(&root->fs_info->ordered_operations, &splice); |
534 | 538 | ||
535 | while (!list_empty(&splice)) { | 539 | while (!list_empty(&splice)) { |
540 | |||
536 | btrfs_inode = list_entry(splice.next, struct btrfs_inode, | 541 | btrfs_inode = list_entry(splice.next, struct btrfs_inode, |
537 | ordered_operations); | 542 | ordered_operations); |
538 | 543 | ||
@@ -549,15 +554,26 @@ again: | |||
549 | list_add_tail(&BTRFS_I(inode)->ordered_operations, | 554 | list_add_tail(&BTRFS_I(inode)->ordered_operations, |
550 | &root->fs_info->ordered_operations); | 555 | &root->fs_info->ordered_operations); |
551 | } | 556 | } |
557 | |||
558 | if (!inode) | ||
559 | continue; | ||
552 | spin_unlock(&root->fs_info->ordered_extent_lock); | 560 | spin_unlock(&root->fs_info->ordered_extent_lock); |
553 | 561 | ||
554 | if (inode) { | 562 | work = btrfs_alloc_delalloc_work(inode, wait, 1); |
555 | if (wait) | 563 | if (!work) { |
556 | btrfs_wait_ordered_range(inode, 0, (u64)-1); | 564 | if (list_empty(&BTRFS_I(inode)->ordered_operations)) |
557 | else | 565 | list_add_tail(&btrfs_inode->ordered_operations, |
558 | filemap_flush(inode->i_mapping); | 566 | &splice); |
559 | btrfs_add_delayed_iput(inode); | 567 | spin_lock(&root->fs_info->ordered_extent_lock); |
568 | list_splice_tail(&splice, | ||
569 | &root->fs_info->ordered_operations); | ||
570 | spin_unlock(&root->fs_info->ordered_extent_lock); | ||
571 | ret = -ENOMEM; | ||
572 | goto out; | ||
560 | } | 573 | } |
574 | list_add_tail(&work->list, &works); | ||
575 | btrfs_queue_worker(&root->fs_info->flush_workers, | ||
576 | &work->work); | ||
561 | 577 | ||
562 | cond_resched(); | 578 | cond_resched(); |
563 | spin_lock(&root->fs_info->ordered_extent_lock); | 579 | spin_lock(&root->fs_info->ordered_extent_lock); |
@@ -566,7 +582,13 @@ again: | |||
566 | goto again; | 582 | goto again; |
567 | 583 | ||
568 | spin_unlock(&root->fs_info->ordered_extent_lock); | 584 | spin_unlock(&root->fs_info->ordered_extent_lock); |
585 | out: | ||
586 | list_for_each_entry_safe(work, next, &works, list) { | ||
587 | list_del_init(&work->list); | ||
588 | btrfs_wait_and_free_delalloc_work(work); | ||
589 | } | ||
569 | mutex_unlock(&root->fs_info->ordered_operations_mutex); | 590 | mutex_unlock(&root->fs_info->ordered_operations_mutex); |
591 | return ret; | ||
570 | } | 592 | } |
571 | 593 | ||
572 | /* | 594 | /* |
@@ -934,15 +956,6 @@ void btrfs_add_ordered_operation(struct btrfs_trans_handle *trans, | |||
934 | if (last_mod < root->fs_info->last_trans_committed) | 956 | if (last_mod < root->fs_info->last_trans_committed) |
935 | return; | 957 | return; |
936 | 958 | ||
937 | /* | ||
938 | * the transaction is already committing. Just start the IO and | ||
939 | * don't bother with all of this list nonsense | ||
940 | */ | ||
941 | if (trans && root->fs_info->running_transaction->blocked) { | ||
942 | btrfs_wait_ordered_range(inode, 0, (u64)-1); | ||
943 | return; | ||
944 | } | ||
945 | |||
946 | spin_lock(&root->fs_info->ordered_extent_lock); | 959 | spin_lock(&root->fs_info->ordered_extent_lock); |
947 | if (list_empty(&BTRFS_I(inode)->ordered_operations)) { | 960 | if (list_empty(&BTRFS_I(inode)->ordered_operations)) { |
948 | list_add_tail(&BTRFS_I(inode)->ordered_operations, | 961 | list_add_tail(&BTRFS_I(inode)->ordered_operations, |
@@ -959,6 +972,7 @@ int __init ordered_data_init(void) | |||
959 | NULL); | 972 | NULL); |
960 | if (!btrfs_ordered_extent_cache) | 973 | if (!btrfs_ordered_extent_cache) |
961 | return -ENOMEM; | 974 | return -ENOMEM; |
975 | |||
962 | return 0; | 976 | return 0; |
963 | } | 977 | } |
964 | 978 | ||