diff options
author | Qu Wenruo <quwenruo@cn.fujitsu.com> | 2014-02-27 21:46:10 -0500 |
---|---|---|
committer | Josef Bacik <jbacik@fb.com> | 2014-03-10 15:17:08 -0400 |
commit | fccb5d86d8f52161e013025ccf3101d8fab99a32 (patch) | |
tree | dbec54a51b5c4a1f459ea373fe056bcb6699c154 | |
parent | a44903abe9dc23ffa305898368a7a910dbae13c5 (diff) |
btrfs: Replace fs_info->endio_* workqueue with btrfs_workqueue.
Replace the fs_info->endio_* workqueues with the newly created
btrfs_workqueue.
Signed-off-by: Qu Wenruo <quwenruo@cn.fujitsu.com>
Tested-by: David Sterba <dsterba@suse.cz>
Signed-off-by: Josef Bacik <jbacik@fb.com>
-rw-r--r-- | fs/btrfs/ctree.h | 12 | ||||
-rw-r--r-- | fs/btrfs/disk-io.c | 104 | ||||
-rw-r--r-- | fs/btrfs/inode.c | 20 | ||||
-rw-r--r-- | fs/btrfs/ordered-data.h | 2 | ||||
-rw-r--r-- | fs/btrfs/super.c | 11 |
5 files changed, 68 insertions, 81 deletions
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index c31a102d34de..42bf0da250f5 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h | |||
@@ -1508,13 +1508,13 @@ struct btrfs_fs_info { | |||
1508 | struct btrfs_workqueue_struct *workers; | 1508 | struct btrfs_workqueue_struct *workers; |
1509 | struct btrfs_workqueue_struct *delalloc_workers; | 1509 | struct btrfs_workqueue_struct *delalloc_workers; |
1510 | struct btrfs_workqueue_struct *flush_workers; | 1510 | struct btrfs_workqueue_struct *flush_workers; |
1511 | struct btrfs_workers endio_workers; | 1511 | struct btrfs_workqueue_struct *endio_workers; |
1512 | struct btrfs_workers endio_meta_workers; | 1512 | struct btrfs_workqueue_struct *endio_meta_workers; |
1513 | struct btrfs_workers endio_raid56_workers; | 1513 | struct btrfs_workqueue_struct *endio_raid56_workers; |
1514 | struct btrfs_workers rmw_workers; | 1514 | struct btrfs_workers rmw_workers; |
1515 | struct btrfs_workers endio_meta_write_workers; | 1515 | struct btrfs_workqueue_struct *endio_meta_write_workers; |
1516 | struct btrfs_workers endio_write_workers; | 1516 | struct btrfs_workqueue_struct *endio_write_workers; |
1517 | struct btrfs_workers endio_freespace_worker; | 1517 | struct btrfs_workqueue_struct *endio_freespace_worker; |
1518 | struct btrfs_workqueue_struct *submit_workers; | 1518 | struct btrfs_workqueue_struct *submit_workers; |
1519 | struct btrfs_workers caching_workers; | 1519 | struct btrfs_workers caching_workers; |
1520 | struct btrfs_workers readahead_workers; | 1520 | struct btrfs_workers readahead_workers; |
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 5b82b0b31ec8..8ce0214e3bac 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c | |||
@@ -55,7 +55,7 @@ | |||
55 | #endif | 55 | #endif |
56 | 56 | ||
57 | static struct extent_io_ops btree_extent_io_ops; | 57 | static struct extent_io_ops btree_extent_io_ops; |
58 | static void end_workqueue_fn(struct btrfs_work *work); | 58 | static void end_workqueue_fn(struct btrfs_work_struct *work); |
59 | static void free_fs_root(struct btrfs_root *root); | 59 | static void free_fs_root(struct btrfs_root *root); |
60 | static int btrfs_check_super_valid(struct btrfs_fs_info *fs_info, | 60 | static int btrfs_check_super_valid(struct btrfs_fs_info *fs_info, |
61 | int read_only); | 61 | int read_only); |
@@ -86,7 +86,7 @@ struct end_io_wq { | |||
86 | int error; | 86 | int error; |
87 | int metadata; | 87 | int metadata; |
88 | struct list_head list; | 88 | struct list_head list; |
89 | struct btrfs_work work; | 89 | struct btrfs_work_struct work; |
90 | }; | 90 | }; |
91 | 91 | ||
92 | /* | 92 | /* |
@@ -678,32 +678,31 @@ static void end_workqueue_bio(struct bio *bio, int err) | |||
678 | 678 | ||
679 | fs_info = end_io_wq->info; | 679 | fs_info = end_io_wq->info; |
680 | end_io_wq->error = err; | 680 | end_io_wq->error = err; |
681 | end_io_wq->work.func = end_workqueue_fn; | 681 | btrfs_init_work(&end_io_wq->work, end_workqueue_fn, NULL, NULL); |
682 | end_io_wq->work.flags = 0; | ||
683 | 682 | ||
684 | if (bio->bi_rw & REQ_WRITE) { | 683 | if (bio->bi_rw & REQ_WRITE) { |
685 | if (end_io_wq->metadata == BTRFS_WQ_ENDIO_METADATA) | 684 | if (end_io_wq->metadata == BTRFS_WQ_ENDIO_METADATA) |
686 | btrfs_queue_worker(&fs_info->endio_meta_write_workers, | 685 | btrfs_queue_work(fs_info->endio_meta_write_workers, |
687 | &end_io_wq->work); | 686 | &end_io_wq->work); |
688 | else if (end_io_wq->metadata == BTRFS_WQ_ENDIO_FREE_SPACE) | 687 | else if (end_io_wq->metadata == BTRFS_WQ_ENDIO_FREE_SPACE) |
689 | btrfs_queue_worker(&fs_info->endio_freespace_worker, | 688 | btrfs_queue_work(fs_info->endio_freespace_worker, |
690 | &end_io_wq->work); | 689 | &end_io_wq->work); |
691 | else if (end_io_wq->metadata == BTRFS_WQ_ENDIO_RAID56) | 690 | else if (end_io_wq->metadata == BTRFS_WQ_ENDIO_RAID56) |
692 | btrfs_queue_worker(&fs_info->endio_raid56_workers, | 691 | btrfs_queue_work(fs_info->endio_raid56_workers, |
693 | &end_io_wq->work); | 692 | &end_io_wq->work); |
694 | else | 693 | else |
695 | btrfs_queue_worker(&fs_info->endio_write_workers, | 694 | btrfs_queue_work(fs_info->endio_write_workers, |
696 | &end_io_wq->work); | 695 | &end_io_wq->work); |
697 | } else { | 696 | } else { |
698 | if (end_io_wq->metadata == BTRFS_WQ_ENDIO_RAID56) | 697 | if (end_io_wq->metadata == BTRFS_WQ_ENDIO_RAID56) |
699 | btrfs_queue_worker(&fs_info->endio_raid56_workers, | 698 | btrfs_queue_work(fs_info->endio_raid56_workers, |
700 | &end_io_wq->work); | 699 | &end_io_wq->work); |
701 | else if (end_io_wq->metadata) | 700 | else if (end_io_wq->metadata) |
702 | btrfs_queue_worker(&fs_info->endio_meta_workers, | 701 | btrfs_queue_work(fs_info->endio_meta_workers, |
703 | &end_io_wq->work); | 702 | &end_io_wq->work); |
704 | else | 703 | else |
705 | btrfs_queue_worker(&fs_info->endio_workers, | 704 | btrfs_queue_work(fs_info->endio_workers, |
706 | &end_io_wq->work); | 705 | &end_io_wq->work); |
707 | } | 706 | } |
708 | } | 707 | } |
709 | 708 | ||
@@ -1669,7 +1668,7 @@ static int setup_bdi(struct btrfs_fs_info *info, struct backing_dev_info *bdi) | |||
1669 | * called by the kthread helper functions to finally call the bio end_io | 1668 | * called by the kthread helper functions to finally call the bio end_io |
1670 | * functions. This is where read checksum verification actually happens | 1669 | * functions. This is where read checksum verification actually happens |
1671 | */ | 1670 | */ |
1672 | static void end_workqueue_fn(struct btrfs_work *work) | 1671 | static void end_workqueue_fn(struct btrfs_work_struct *work) |
1673 | { | 1672 | { |
1674 | struct bio *bio; | 1673 | struct bio *bio; |
1675 | struct end_io_wq *end_io_wq; | 1674 | struct end_io_wq *end_io_wq; |
@@ -1999,13 +1998,13 @@ static void btrfs_stop_all_workers(struct btrfs_fs_info *fs_info) | |||
1999 | btrfs_stop_workers(&fs_info->fixup_workers); | 1998 | btrfs_stop_workers(&fs_info->fixup_workers); |
2000 | btrfs_destroy_workqueue(fs_info->delalloc_workers); | 1999 | btrfs_destroy_workqueue(fs_info->delalloc_workers); |
2001 | btrfs_destroy_workqueue(fs_info->workers); | 2000 | btrfs_destroy_workqueue(fs_info->workers); |
2002 | btrfs_stop_workers(&fs_info->endio_workers); | 2001 | btrfs_destroy_workqueue(fs_info->endio_workers); |
2003 | btrfs_stop_workers(&fs_info->endio_meta_workers); | 2002 | btrfs_destroy_workqueue(fs_info->endio_meta_workers); |
2004 | btrfs_stop_workers(&fs_info->endio_raid56_workers); | 2003 | btrfs_destroy_workqueue(fs_info->endio_raid56_workers); |
2005 | btrfs_stop_workers(&fs_info->rmw_workers); | 2004 | btrfs_stop_workers(&fs_info->rmw_workers); |
2006 | btrfs_stop_workers(&fs_info->endio_meta_write_workers); | 2005 | btrfs_destroy_workqueue(fs_info->endio_meta_write_workers); |
2007 | btrfs_stop_workers(&fs_info->endio_write_workers); | 2006 | btrfs_destroy_workqueue(fs_info->endio_write_workers); |
2008 | btrfs_stop_workers(&fs_info->endio_freespace_worker); | 2007 | btrfs_destroy_workqueue(fs_info->endio_freespace_worker); |
2009 | btrfs_destroy_workqueue(fs_info->submit_workers); | 2008 | btrfs_destroy_workqueue(fs_info->submit_workers); |
2010 | btrfs_stop_workers(&fs_info->delayed_workers); | 2009 | btrfs_stop_workers(&fs_info->delayed_workers); |
2011 | btrfs_stop_workers(&fs_info->caching_workers); | 2010 | btrfs_stop_workers(&fs_info->caching_workers); |
@@ -2501,26 +2500,26 @@ int open_ctree(struct super_block *sb, | |||
2501 | 2500 | ||
2502 | btrfs_init_workers(&fs_info->fixup_workers, "fixup", 1, | 2501 | btrfs_init_workers(&fs_info->fixup_workers, "fixup", 1, |
2503 | &fs_info->generic_worker); | 2502 | &fs_info->generic_worker); |
2504 | btrfs_init_workers(&fs_info->endio_workers, "endio", | 2503 | |
2505 | fs_info->thread_pool_size, | 2504 | /* |
2506 | &fs_info->generic_worker); | 2505 | * endios are largely parallel and should have a very |
2507 | btrfs_init_workers(&fs_info->endio_meta_workers, "endio-meta", | 2506 | * low idle thresh |
2508 | fs_info->thread_pool_size, | 2507 | */ |
2509 | &fs_info->generic_worker); | 2508 | fs_info->endio_workers = |
2510 | btrfs_init_workers(&fs_info->endio_meta_write_workers, | 2509 | btrfs_alloc_workqueue("endio", flags, max_active, 4); |
2511 | "endio-meta-write", fs_info->thread_pool_size, | 2510 | fs_info->endio_meta_workers = |
2512 | &fs_info->generic_worker); | 2511 | btrfs_alloc_workqueue("endio-meta", flags, max_active, 4); |
2513 | btrfs_init_workers(&fs_info->endio_raid56_workers, | 2512 | fs_info->endio_meta_write_workers = |
2514 | "endio-raid56", fs_info->thread_pool_size, | 2513 | btrfs_alloc_workqueue("endio-meta-write", flags, max_active, 2); |
2515 | &fs_info->generic_worker); | 2514 | fs_info->endio_raid56_workers = |
2515 | btrfs_alloc_workqueue("endio-raid56", flags, max_active, 4); | ||
2516 | btrfs_init_workers(&fs_info->rmw_workers, | 2516 | btrfs_init_workers(&fs_info->rmw_workers, |
2517 | "rmw", fs_info->thread_pool_size, | 2517 | "rmw", fs_info->thread_pool_size, |
2518 | &fs_info->generic_worker); | 2518 | &fs_info->generic_worker); |
2519 | btrfs_init_workers(&fs_info->endio_write_workers, "endio-write", | 2519 | fs_info->endio_write_workers = |
2520 | fs_info->thread_pool_size, | 2520 | btrfs_alloc_workqueue("endio-write", flags, max_active, 2); |
2521 | &fs_info->generic_worker); | 2521 | fs_info->endio_freespace_worker = |
2522 | btrfs_init_workers(&fs_info->endio_freespace_worker, "freespace-write", | 2522 | btrfs_alloc_workqueue("freespace-write", flags, max_active, 0); |
2523 | 1, &fs_info->generic_worker); | ||
2524 | btrfs_init_workers(&fs_info->delayed_workers, "delayed-meta", | 2523 | btrfs_init_workers(&fs_info->delayed_workers, "delayed-meta", |
2525 | fs_info->thread_pool_size, | 2524 | fs_info->thread_pool_size, |
2526 | &fs_info->generic_worker); | 2525 | &fs_info->generic_worker); |
@@ -2530,17 +2529,8 @@ int open_ctree(struct super_block *sb, | |||
2530 | btrfs_init_workers(&fs_info->qgroup_rescan_workers, "qgroup-rescan", 1, | 2529 | btrfs_init_workers(&fs_info->qgroup_rescan_workers, "qgroup-rescan", 1, |
2531 | &fs_info->generic_worker); | 2530 | &fs_info->generic_worker); |
2532 | 2531 | ||
2533 | /* | ||
2534 | * endios are largely parallel and should have a very | ||
2535 | * low idle thresh | ||
2536 | */ | ||
2537 | fs_info->endio_workers.idle_thresh = 4; | ||
2538 | fs_info->endio_meta_workers.idle_thresh = 4; | ||
2539 | fs_info->endio_raid56_workers.idle_thresh = 4; | ||
2540 | fs_info->rmw_workers.idle_thresh = 2; | 2532 | fs_info->rmw_workers.idle_thresh = 2; |
2541 | 2533 | ||
2542 | fs_info->endio_write_workers.idle_thresh = 2; | ||
2543 | fs_info->endio_meta_write_workers.idle_thresh = 2; | ||
2544 | fs_info->readahead_workers.idle_thresh = 2; | 2534 | fs_info->readahead_workers.idle_thresh = 2; |
2545 | 2535 | ||
2546 | /* | 2536 | /* |
@@ -2549,13 +2539,7 @@ int open_ctree(struct super_block *sb, | |||
2549 | */ | 2539 | */ |
2550 | ret = btrfs_start_workers(&fs_info->generic_worker); | 2540 | ret = btrfs_start_workers(&fs_info->generic_worker); |
2551 | ret |= btrfs_start_workers(&fs_info->fixup_workers); | 2541 | ret |= btrfs_start_workers(&fs_info->fixup_workers); |
2552 | ret |= btrfs_start_workers(&fs_info->endio_workers); | ||
2553 | ret |= btrfs_start_workers(&fs_info->endio_meta_workers); | ||
2554 | ret |= btrfs_start_workers(&fs_info->rmw_workers); | 2542 | ret |= btrfs_start_workers(&fs_info->rmw_workers); |
2555 | ret |= btrfs_start_workers(&fs_info->endio_raid56_workers); | ||
2556 | ret |= btrfs_start_workers(&fs_info->endio_meta_write_workers); | ||
2557 | ret |= btrfs_start_workers(&fs_info->endio_write_workers); | ||
2558 | ret |= btrfs_start_workers(&fs_info->endio_freespace_worker); | ||
2559 | ret |= btrfs_start_workers(&fs_info->delayed_workers); | 2543 | ret |= btrfs_start_workers(&fs_info->delayed_workers); |
2560 | ret |= btrfs_start_workers(&fs_info->caching_workers); | 2544 | ret |= btrfs_start_workers(&fs_info->caching_workers); |
2561 | ret |= btrfs_start_workers(&fs_info->readahead_workers); | 2545 | ret |= btrfs_start_workers(&fs_info->readahead_workers); |
@@ -2565,7 +2549,11 @@ int open_ctree(struct super_block *sb, | |||
2565 | goto fail_sb_buffer; | 2549 | goto fail_sb_buffer; |
2566 | } | 2550 | } |
2567 | if (!(fs_info->workers && fs_info->delalloc_workers && | 2551 | if (!(fs_info->workers && fs_info->delalloc_workers && |
2568 | fs_info->submit_workers && fs_info->flush_workers)) { | 2552 | fs_info->submit_workers && fs_info->flush_workers && |
2553 | fs_info->endio_workers && fs_info->endio_meta_workers && | ||
2554 | fs_info->endio_meta_write_workers && | ||
2555 | fs_info->endio_write_workers && fs_info->endio_raid56_workers && | ||
2556 | fs_info->endio_freespace_worker)) { | ||
2569 | err = -ENOMEM; | 2557 | err = -ENOMEM; |
2570 | goto fail_sb_buffer; | 2558 | goto fail_sb_buffer; |
2571 | } | 2559 | } |
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 6c043bed0c32..ce3f73046605 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
@@ -2750,7 +2750,7 @@ out: | |||
2750 | return ret; | 2750 | return ret; |
2751 | } | 2751 | } |
2752 | 2752 | ||
2753 | static void finish_ordered_fn(struct btrfs_work *work) | 2753 | static void finish_ordered_fn(struct btrfs_work_struct *work) |
2754 | { | 2754 | { |
2755 | struct btrfs_ordered_extent *ordered_extent; | 2755 | struct btrfs_ordered_extent *ordered_extent; |
2756 | ordered_extent = container_of(work, struct btrfs_ordered_extent, work); | 2756 | ordered_extent = container_of(work, struct btrfs_ordered_extent, work); |
@@ -2763,7 +2763,7 @@ static int btrfs_writepage_end_io_hook(struct page *page, u64 start, u64 end, | |||
2763 | struct inode *inode = page->mapping->host; | 2763 | struct inode *inode = page->mapping->host; |
2764 | struct btrfs_root *root = BTRFS_I(inode)->root; | 2764 | struct btrfs_root *root = BTRFS_I(inode)->root; |
2765 | struct btrfs_ordered_extent *ordered_extent = NULL; | 2765 | struct btrfs_ordered_extent *ordered_extent = NULL; |
2766 | struct btrfs_workers *workers; | 2766 | struct btrfs_workqueue_struct *workers; |
2767 | 2767 | ||
2768 | trace_btrfs_writepage_end_io_hook(page, start, end, uptodate); | 2768 | trace_btrfs_writepage_end_io_hook(page, start, end, uptodate); |
2769 | 2769 | ||
@@ -2772,14 +2772,13 @@ static int btrfs_writepage_end_io_hook(struct page *page, u64 start, u64 end, | |||
2772 | end - start + 1, uptodate)) | 2772 | end - start + 1, uptodate)) |
2773 | return 0; | 2773 | return 0; |
2774 | 2774 | ||
2775 | ordered_extent->work.func = finish_ordered_fn; | 2775 | btrfs_init_work(&ordered_extent->work, finish_ordered_fn, NULL, NULL); |
2776 | ordered_extent->work.flags = 0; | ||
2777 | 2776 | ||
2778 | if (btrfs_is_free_space_inode(inode)) | 2777 | if (btrfs_is_free_space_inode(inode)) |
2779 | workers = &root->fs_info->endio_freespace_worker; | 2778 | workers = root->fs_info->endio_freespace_worker; |
2780 | else | 2779 | else |
2781 | workers = &root->fs_info->endio_write_workers; | 2780 | workers = root->fs_info->endio_write_workers; |
2782 | btrfs_queue_worker(workers, &ordered_extent->work); | 2781 | btrfs_queue_work(workers, &ordered_extent->work); |
2783 | 2782 | ||
2784 | return 0; | 2783 | return 0; |
2785 | } | 2784 | } |
@@ -7046,10 +7045,9 @@ again: | |||
7046 | if (!ret) | 7045 | if (!ret) |
7047 | goto out_test; | 7046 | goto out_test; |
7048 | 7047 | ||
7049 | ordered->work.func = finish_ordered_fn; | 7048 | btrfs_init_work(&ordered->work, finish_ordered_fn, NULL, NULL); |
7050 | ordered->work.flags = 0; | 7049 | btrfs_queue_work(root->fs_info->endio_write_workers, |
7051 | btrfs_queue_worker(&root->fs_info->endio_write_workers, | 7050 | &ordered->work); |
7052 | &ordered->work); | ||
7053 | out_test: | 7051 | out_test: |
7054 | /* | 7052 | /* |
7055 | * our bio might span multiple ordered extents. If we haven't | 7053 | * our bio might span multiple ordered extents. If we haven't |
diff --git a/fs/btrfs/ordered-data.h b/fs/btrfs/ordered-data.h index fe9f4dbab09c..84bb236119fe 100644 --- a/fs/btrfs/ordered-data.h +++ b/fs/btrfs/ordered-data.h | |||
@@ -130,7 +130,7 @@ struct btrfs_ordered_extent { | |||
130 | /* a per root list of all the pending ordered extents */ | 130 | /* a per root list of all the pending ordered extents */ |
131 | struct list_head root_extent_list; | 131 | struct list_head root_extent_list; |
132 | 132 | ||
133 | struct btrfs_work work; | 133 | struct btrfs_work_struct work; |
134 | 134 | ||
135 | struct completion completion; | 135 | struct completion completion; |
136 | struct btrfs_work_struct flush_work; | 136 | struct btrfs_work_struct flush_work; |
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c index 9ed559ebe914..d95d98d3e72c 100644 --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c | |||
@@ -1329,11 +1329,12 @@ static void btrfs_resize_thread_pool(struct btrfs_fs_info *fs_info, | |||
1329 | btrfs_workqueue_set_max(fs_info->submit_workers, new_pool_size); | 1329 | btrfs_workqueue_set_max(fs_info->submit_workers, new_pool_size); |
1330 | btrfs_set_max_workers(&fs_info->caching_workers, new_pool_size); | 1330 | btrfs_set_max_workers(&fs_info->caching_workers, new_pool_size); |
1331 | btrfs_set_max_workers(&fs_info->fixup_workers, new_pool_size); | 1331 | btrfs_set_max_workers(&fs_info->fixup_workers, new_pool_size); |
1332 | btrfs_set_max_workers(&fs_info->endio_workers, new_pool_size); | 1332 | btrfs_workqueue_set_max(fs_info->endio_workers, new_pool_size); |
1333 | btrfs_set_max_workers(&fs_info->endio_meta_workers, new_pool_size); | 1333 | btrfs_workqueue_set_max(fs_info->endio_meta_workers, new_pool_size); |
1334 | btrfs_set_max_workers(&fs_info->endio_meta_write_workers, new_pool_size); | 1334 | btrfs_workqueue_set_max(fs_info->endio_meta_write_workers, |
1335 | btrfs_set_max_workers(&fs_info->endio_write_workers, new_pool_size); | 1335 | new_pool_size); |
1336 | btrfs_set_max_workers(&fs_info->endio_freespace_worker, new_pool_size); | 1336 | btrfs_workqueue_set_max(fs_info->endio_write_workers, new_pool_size); |
1337 | btrfs_workqueue_set_max(fs_info->endio_freespace_worker, new_pool_size); | ||
1337 | btrfs_set_max_workers(&fs_info->delayed_workers, new_pool_size); | 1338 | btrfs_set_max_workers(&fs_info->delayed_workers, new_pool_size); |
1338 | btrfs_set_max_workers(&fs_info->readahead_workers, new_pool_size); | 1339 | btrfs_set_max_workers(&fs_info->readahead_workers, new_pool_size); |
1339 | btrfs_set_max_workers(&fs_info->scrub_wr_completion_workers, | 1340 | btrfs_set_max_workers(&fs_info->scrub_wr_completion_workers, |