@@ -4,6 +4,7 @@ config BTRFS_FS
select LIBCRC32C
select ZLIB_INFLATE
select ZLIB_DEFLATE
+ select BTRQ
help
Btrfs is a new filesystem with extents, writable snapshotting,
support for multiple devices and many more features.
@@ -5,6 +5,6 @@ btrfs-y += super.o ctree.o extent-tree.o print-tree.o root-tree.o dir-item.o \
file-item.o inode-item.o inode-map.o disk-io.o \
transaction.o inode.o file.o tree-defrag.o \
extent_map.o sysfs.o struct-funcs.o xattr.o ordered-data.o \
- extent_io.o volumes.o async-thread.o ioctl.o locking.o orphan.o \
+ extent_io.o volumes.o ioctl.o locking.o orphan.o \
export.o tree-log.o acl.o free-space-cache.o zlib.o \
compression.o delayed-ref.o relocation.o
@@ -26,10 +26,10 @@
#include <linux/completion.h>
#include <linux/backing-dev.h>
#include <linux/wait.h>
+#include <linux/btrqueue.h>
#include <asm/kmap_types.h>
#include "extent_io.h"
#include "extent_map.h"
-#include "async-thread.h"
struct btrfs_trans_handle;
struct btrfs_transaction;
@@ -910,21 +910,21 @@ struct btrfs_fs_info {
* A third pool does submit_bio to avoid deadlocking with the other
* two
*/
- struct btrfs_workers generic_worker;
- struct btrfs_workers workers;
- struct btrfs_workers delalloc_workers;
- struct btrfs_workers endio_workers;
- struct btrfs_workers endio_meta_workers;
- struct btrfs_workers endio_meta_write_workers;
- struct btrfs_workers endio_write_workers;
- struct btrfs_workers submit_workers;
- struct btrfs_workers enospc_workers;
+ struct btrq_workers generic_worker;
+ struct btrq_workers workers;
+ struct btrq_workers delalloc_workers;
+ struct btrq_workers endio_workers;
+ struct btrq_workers endio_meta_workers;
+ struct btrq_workers endio_meta_write_workers;
+ struct btrq_workers endio_write_workers;
+ struct btrq_workers submit_workers;
+ struct btrq_workers enospc_workers;
/*
* fixup workers take dirty pages that didn't properly go through
* the cow mechanism and make them safe to write. It happens
* for the sys_munmap function call path
*/
- struct btrfs_workers fixup_workers;
+ struct btrq_workers fixup_workers;
struct task_struct *transaction_kthread;
struct task_struct *cleaner_kthread;
int thread_pool_size;
@@ -27,6 +27,7 @@
#include <linux/kthread.h>
#include <linux/freezer.h>
#include <linux/crc32c.h>
+#include <linux/btrqueue.h>
#include "compat.h"
#include "ctree.h"
#include "disk-io.h"
@@ -34,13 +35,12 @@
#include "btrfs_inode.h"
#include "volumes.h"
#include "print-tree.h"
-#include "async-thread.h"
#include "locking.h"
#include "tree-log.h"
#include "free-space-cache.h"
static struct extent_io_ops btree_extent_io_ops;
-static void end_workqueue_fn(struct btrfs_work *work);
+static void end_workqueue_fn(struct btrq_work *work);
static void free_fs_root(struct btrfs_root *root);
static atomic_t btrfs_bdi_num = ATOMIC_INIT(0);
@@ -58,7 +58,7 @@ struct end_io_wq {
int error;
int metadata;
struct list_head list;
- struct btrfs_work work;
+ struct btrq_work work;
};
/*
@@ -75,7 +75,7 @@ struct async_submit_bio {
int rw;
int mirror_num;
unsigned long bio_flags;
- struct btrfs_work work;
+ struct btrq_work work;
};
/* These are used to set the lockdep class on the extent buffer locks.
@@ -476,18 +476,18 @@ static void end_workqueue_bio(struct bio *bio, int err)
if (bio->bi_rw & (1 << BIO_RW)) {
if (end_io_wq->metadata)
- btrfs_queue_worker(&fs_info->endio_meta_write_workers,
- &end_io_wq->work);
+ btrq_queue_worker(&fs_info->endio_meta_write_workers,
+ &end_io_wq->work);
else
- btrfs_queue_worker(&fs_info->endio_write_workers,
- &end_io_wq->work);
+ btrq_queue_worker(&fs_info->endio_write_workers,
+ &end_io_wq->work);
} else {
if (end_io_wq->metadata)
- btrfs_queue_worker(&fs_info->endio_meta_workers,
- &end_io_wq->work);
+ btrq_queue_worker(&fs_info->endio_meta_workers,
+ &end_io_wq->work);
else
- btrfs_queue_worker(&fs_info->endio_workers,
- &end_io_wq->work);
+ btrq_queue_worker(&fs_info->endio_workers,
+ &end_io_wq->work);
}
}
@@ -525,7 +525,7 @@ int btrfs_congested_async(struct btrfs_fs_info *info, int iodone)
btrfs_async_submit_limit(info);
}
-static void run_one_async_start(struct btrfs_work *work)
+static void run_one_async_start(struct btrq_work *work)
{
struct btrfs_fs_info *fs_info;
struct async_submit_bio *async;
@@ -536,7 +536,7 @@ static void run_one_async_start(struct btrfs_work *work)
async->mirror_num, async->bio_flags);
}
-static void run_one_async_done(struct btrfs_work *work)
+static void run_one_async_done(struct btrq_work *work)
{
struct btrfs_fs_info *fs_info;
struct async_submit_bio *async;
@@ -558,7 +558,7 @@ static void run_one_async_done(struct btrfs_work *work)
async->mirror_num, async->bio_flags);
}
-static void run_one_async_free(struct btrfs_work *work)
+static void run_one_async_free(struct btrq_work *work)
{
struct async_submit_bio *async;
@@ -595,9 +595,9 @@ int btrfs_wq_submit_bio(struct btrfs_fs_info *fs_info, struct inode *inode,
atomic_inc(&fs_info->nr_async_submits);
if (rw & (1 << BIO_RW_SYNCIO))
- btrfs_set_work_high_prio(&async->work);
+ btrq_set_work_high_prio(&async->work);
- btrfs_queue_worker(&fs_info->workers, &async->work);
+ btrq_queue_worker(&fs_info->workers, &async->work);
while (atomic_read(&fs_info->async_submit_draining) &&
atomic_read(&fs_info->nr_async_submits)) {
@@ -1435,7 +1435,7 @@ static int bio_ready_for_csum(struct bio *bio)
* called by the kthread helper functions to finally call the bio end_io
* functions. This is where read checksum verification actually happens
*/
-static void end_workqueue_fn(struct btrfs_work *work)
+static void end_workqueue_fn(struct btrq_work *work)
{
struct bio *bio;
struct end_io_wq *end_io_wq;
@@ -1453,8 +1453,8 @@ static void end_workqueue_fn(struct btrfs_work *work)
*/
if (!(bio->bi_rw & (1 << BIO_RW)) && end_io_wq->metadata &&
!bio_ready_for_csum(bio)) {
- btrfs_queue_worker(&fs_info->endio_meta_workers,
- &end_io_wq->work);
+ btrq_queue_worker(&fs_info->endio_meta_workers,
+ &end_io_wq->work);
return;
}
error = end_io_wq->error;
@@ -1749,24 +1749,23 @@ struct btrfs_root *open_ctree(struct super_block *sb,
goto fail_iput;
}
- btrfs_init_workers(&fs_info->generic_worker,
- "genwork", 1, NULL);
+ btrq_init_workers(&fs_info->generic_worker, "btrfs-genwork", 1, NULL);
- btrfs_init_workers(&fs_info->workers, "worker",
- fs_info->thread_pool_size,
- &fs_info->generic_worker);
+ btrq_init_workers(&fs_info->workers, "btrfs-worker",
+ fs_info->thread_pool_size,
+ &fs_info->generic_worker);
- btrfs_init_workers(&fs_info->delalloc_workers, "delalloc",
- fs_info->thread_pool_size,
- &fs_info->generic_worker);
+ btrq_init_workers(&fs_info->delalloc_workers, "btrfs-delalloc",
+ fs_info->thread_pool_size,
+ &fs_info->generic_worker);
- btrfs_init_workers(&fs_info->submit_workers, "submit",
- min_t(u64, fs_devices->num_devices,
- fs_info->thread_pool_size),
- &fs_info->generic_worker);
- btrfs_init_workers(&fs_info->enospc_workers, "enospc",
- fs_info->thread_pool_size,
- &fs_info->generic_worker);
+ btrq_init_workers(&fs_info->submit_workers, "btrfs-submit",
+ min_t(u64, fs_devices->num_devices,
+ fs_info->thread_pool_size),
+ &fs_info->generic_worker);
+ btrq_init_workers(&fs_info->enospc_workers, "btrfs-enospc",
+ fs_info->thread_pool_size,
+ &fs_info->generic_worker);
/* a higher idle thresh on the submit workers makes it much more
* likely that bios will be send down in a sane order to the
@@ -1780,20 +1779,20 @@ struct btrfs_root *open_ctree(struct super_block *sb,
fs_info->delalloc_workers.idle_thresh = 2;
fs_info->delalloc_workers.ordered = 1;
- btrfs_init_workers(&fs_info->fixup_workers, "fixup", 1,
- &fs_info->generic_worker);
- btrfs_init_workers(&fs_info->endio_workers, "endio",
- fs_info->thread_pool_size,
- &fs_info->generic_worker);
- btrfs_init_workers(&fs_info->endio_meta_workers, "endio-meta",
- fs_info->thread_pool_size,
- &fs_info->generic_worker);
- btrfs_init_workers(&fs_info->endio_meta_write_workers,
- "endio-meta-write", fs_info->thread_pool_size,
- &fs_info->generic_worker);
- btrfs_init_workers(&fs_info->endio_write_workers, "endio-write",
- fs_info->thread_pool_size,
- &fs_info->generic_worker);
+ btrq_init_workers(&fs_info->fixup_workers, "btrfs-fixup", 1,
+ &fs_info->generic_worker);
+ btrq_init_workers(&fs_info->endio_workers, "btrfs-endio",
+ fs_info->thread_pool_size,
+ &fs_info->generic_worker);
+ btrq_init_workers(&fs_info->endio_meta_workers, "btrfs-endio-meta",
+ fs_info->thread_pool_size,
+ &fs_info->generic_worker);
+ btrq_init_workers(&fs_info->endio_meta_write_workers,
+ "btrfs-endio-meta-write", fs_info->thread_pool_size,
+ &fs_info->generic_worker);
+ btrq_init_workers(&fs_info->endio_write_workers, "btrfs-endio-write",
+ fs_info->thread_pool_size,
+ &fs_info->generic_worker);
/*
* endios are largely parallel and should have a very
@@ -1805,16 +1804,16 @@ struct btrfs_root *open_ctree(struct super_block *sb,
fs_info->endio_write_workers.idle_thresh = 2;
fs_info->endio_meta_write_workers.idle_thresh = 2;
- btrfs_start_workers(&fs_info->workers, 1);
- btrfs_start_workers(&fs_info->generic_worker, 1);
- btrfs_start_workers(&fs_info->submit_workers, 1);
- btrfs_start_workers(&fs_info->delalloc_workers, 1);
- btrfs_start_workers(&fs_info->fixup_workers, 1);
- btrfs_start_workers(&fs_info->endio_workers, 1);
- btrfs_start_workers(&fs_info->endio_meta_workers, 1);
- btrfs_start_workers(&fs_info->endio_meta_write_workers, 1);
- btrfs_start_workers(&fs_info->endio_write_workers, 1);
- btrfs_start_workers(&fs_info->enospc_workers, 1);
+ btrq_start_workers(&fs_info->workers, 1);
+ btrq_start_workers(&fs_info->generic_worker, 1);
+ btrq_start_workers(&fs_info->submit_workers, 1);
+ btrq_start_workers(&fs_info->delalloc_workers, 1);
+ btrq_start_workers(&fs_info->fixup_workers, 1);
+ btrq_start_workers(&fs_info->endio_workers, 1);
+ btrq_start_workers(&fs_info->endio_meta_workers, 1);
+ btrq_start_workers(&fs_info->endio_meta_write_workers, 1);
+ btrq_start_workers(&fs_info->endio_write_workers, 1);
+ btrq_start_workers(&fs_info->enospc_workers, 1);
fs_info->bdi.ra_pages *= btrfs_super_num_devices(disk_super);
fs_info->bdi.ra_pages = max(fs_info->bdi.ra_pages,
@@ -2020,16 +2019,16 @@ fail_chunk_root:
free_extent_buffer(chunk_root->node);
free_extent_buffer(chunk_root->commit_root);
fail_sb_buffer:
- btrfs_stop_workers(&fs_info->generic_worker);
- btrfs_stop_workers(&fs_info->fixup_workers);
- btrfs_stop_workers(&fs_info->delalloc_workers);
- btrfs_stop_workers(&fs_info->workers);
- btrfs_stop_workers(&fs_info->endio_workers);
- btrfs_stop_workers(&fs_info->endio_meta_workers);
- btrfs_stop_workers(&fs_info->endio_meta_write_workers);
- btrfs_stop_workers(&fs_info->endio_write_workers);
- btrfs_stop_workers(&fs_info->submit_workers);
- btrfs_stop_workers(&fs_info->enospc_workers);
+ btrq_stop_workers(&fs_info->generic_worker);
+ btrq_stop_workers(&fs_info->fixup_workers);
+ btrq_stop_workers(&fs_info->delalloc_workers);
+ btrq_stop_workers(&fs_info->workers);
+ btrq_stop_workers(&fs_info->endio_workers);
+ btrq_stop_workers(&fs_info->endio_meta_workers);
+ btrq_stop_workers(&fs_info->endio_meta_write_workers);
+ btrq_stop_workers(&fs_info->endio_write_workers);
+ btrq_stop_workers(&fs_info->submit_workers);
+ btrq_stop_workers(&fs_info->enospc_workers);
fail_iput:
invalidate_inode_pages2(fs_info->btree_inode->i_mapping);
iput(fs_info->btree_inode);
@@ -2447,16 +2446,16 @@ int close_ctree(struct btrfs_root *root)
iput(fs_info->btree_inode);
- btrfs_stop_workers(&fs_info->generic_worker);
- btrfs_stop_workers(&fs_info->fixup_workers);
- btrfs_stop_workers(&fs_info->delalloc_workers);
- btrfs_stop_workers(&fs_info->workers);
- btrfs_stop_workers(&fs_info->endio_workers);
- btrfs_stop_workers(&fs_info->endio_meta_workers);
- btrfs_stop_workers(&fs_info->endio_meta_write_workers);
- btrfs_stop_workers(&fs_info->endio_write_workers);
- btrfs_stop_workers(&fs_info->submit_workers);
- btrfs_stop_workers(&fs_info->enospc_workers);
+ btrq_stop_workers(&fs_info->generic_worker);
+ btrq_stop_workers(&fs_info->fixup_workers);
+ btrq_stop_workers(&fs_info->delalloc_workers);
+ btrq_stop_workers(&fs_info->workers);
+ btrq_stop_workers(&fs_info->endio_workers);
+ btrq_stop_workers(&fs_info->endio_meta_workers);
+ btrq_stop_workers(&fs_info->endio_meta_write_workers);
+ btrq_stop_workers(&fs_info->endio_write_workers);
+ btrq_stop_workers(&fs_info->submit_workers);
+ btrq_stop_workers(&fs_info->enospc_workers);
btrfs_close_devices(fs_info->fs_devices);
btrfs_mapping_tree_free(&fs_info->mapping_tree);
@@ -2867,10 +2867,10 @@ static void check_force_delalloc(struct btrfs_space_info *meta_sinfo)
struct async_flush {
struct btrfs_root *root;
struct btrfs_space_info *info;
- struct btrfs_work work;
+ struct btrq_work work;
};
-static noinline void flush_delalloc_async(struct btrfs_work *work)
+static noinline void flush_delalloc_async(struct btrq_work *work)
{
struct async_flush *async;
struct btrfs_root *root;
@@ -2950,8 +2950,7 @@ static void flush_delalloc(struct btrfs_root *root,
async->info = info;
async->work.func = flush_delalloc_async;
- btrfs_queue_worker(&root->fs_info->enospc_workers,
- &async->work);
+ btrq_queue_worker(&root->fs_info->enospc_workers, &async->work);
wait_on_flush(info);
return;
@@ -261,7 +261,7 @@ struct async_cow {
u64 start;
u64 end;
struct list_head extents;
- struct btrfs_work work;
+ struct btrq_work work;
};
static noinline int add_async_extent(struct async_cow *cow,
@@ -854,7 +854,7 @@ out:
/*
* work queue call back to started compression on a file and pages
*/
-static noinline void async_cow_start(struct btrfs_work *work)
+static noinline void async_cow_start(struct btrq_work *work)
{
struct async_cow *async_cow;
int num_added = 0;
@@ -870,7 +870,7 @@ static noinline void async_cow_start(struct btrfs_work *work)
/*
* work queue call back to submit previously compressed pages
*/
-static noinline void async_cow_submit(struct btrfs_work *work)
+static noinline void async_cow_submit(struct btrq_work *work)
{
struct async_cow *async_cow;
struct btrfs_root *root;
@@ -893,7 +893,7 @@ static noinline void async_cow_submit(struct btrfs_work *work)
submit_compressed_extents(async_cow->inode, async_cow);
}
-static noinline void async_cow_free(struct btrfs_work *work)
+static noinline void async_cow_free(struct btrq_work *work)
{
struct async_cow *async_cow;
async_cow = container_of(work, struct async_cow, work);
@@ -936,8 +936,8 @@ static int cow_file_range_async(struct inode *inode, struct page *locked_page,
PAGE_CACHE_SHIFT;
atomic_add(nr_pages, &root->fs_info->async_delalloc_pages);
- btrfs_queue_worker(&root->fs_info->delalloc_workers,
- &async_cow->work);
+ btrq_queue_worker(&root->fs_info->delalloc_workers,
+ &async_cow->work);
if (atomic_read(&root->fs_info->async_delalloc_pages) > limit) {
wait_event(root->fs_info->async_submit_wait,
@@ -1507,10 +1507,10 @@ int btrfs_set_extent_delalloc(struct inode *inode, u64 start, u64 end)
/* see btrfs_writepage_start_hook for details on why this is required */
struct btrfs_writepage_fixup {
struct page *page;
- struct btrfs_work work;
+ struct btrq_work work;
};
-static void btrfs_writepage_fixup_worker(struct btrfs_work *work)
+static void btrfs_writepage_fixup_worker(struct btrq_work *work)
{
struct btrfs_writepage_fixup *fixup;
struct btrfs_ordered_extent *ordered;
@@ -1588,7 +1588,7 @@ static int btrfs_writepage_start_hook(struct page *page, u64 start, u64 end)
page_cache_get(page);
fixup->work.func = btrfs_writepage_fixup_worker;
fixup->page = page;
- btrfs_queue_worker(&root->fs_info->fixup_workers, &fixup->work);
+ btrq_queue_worker(&root->fs_info->fixup_workers, &fixup->work);
return -EAGAIN;
}
@@ -21,13 +21,13 @@
#include <linux/writeback.h>
#include <linux/blkdev.h>
#include <linux/rbtree.h>
+#include <linux/btrqueue.h>
#include "ctree.h"
#include "disk-io.h"
#include "transaction.h"
#include "volumes.h"
#include "locking.h"
#include "btrfs_inode.h"
-#include "async-thread.h"
/*
* backref_node, mapping_node and tree_block start with this
@@ -137,7 +137,7 @@ struct reloc_control {
struct btrfs_root *extent_root;
/* inode for moving data */
struct inode *data_inode;
- struct btrfs_workers workers;
+ struct btrq_workers workers;
/* tree blocks have been processed */
struct extent_io_tree processed_blocks;
/* map start of tree root to corresponding reloc tree */
@@ -161,7 +161,7 @@ struct reloc_control {
* merge reloc tree to corresponding fs tree in worker threads
*/
struct async_merge {
- struct btrfs_work work;
+ struct btrq_work work;
struct reloc_control *rc;
struct btrfs_root *root;
struct completion *done;
@@ -1777,7 +1777,7 @@ out:
* this function merges reloc tree with corresponding fs tree,
* and then drops the reloc tree.
*/
-static void merge_func(struct btrfs_work *work)
+static void merge_func(struct btrq_work *work)
{
struct btrfs_trans_handle *trans;
struct btrfs_root *root;
@@ -1832,7 +1832,7 @@ static int merge_reloc_roots(struct reloc_control *rc)
async->done = &done;
async->num_pending = &num_pending;
atomic_inc(&num_pending);
- btrfs_queue_worker(&rc->workers, &async->work);
+ btrq_queue_worker(&rc->workers, &async->work);
}
if (!atomic_dec_and_test(&num_pending))
@@ -3517,8 +3517,8 @@ int btrfs_relocate_block_group(struct btrfs_root *extent_root, u64 group_start)
rc->block_group = btrfs_lookup_block_group(fs_info, group_start);
BUG_ON(!rc->block_group);
- btrfs_init_workers(&rc->workers, "relocate",
- fs_info->thread_pool_size, NULL);
+ btrq_init_workers(&rc->workers, "btrfs-relocate",
+ fs_info->thread_pool_size, NULL);
rc->extent_root = extent_root;
btrfs_prepare_block_group_relocation(extent_root, rc->block_group);
@@ -3588,7 +3588,7 @@ int btrfs_relocate_block_group(struct btrfs_root *extent_root, u64 group_start)
WARN_ON(btrfs_block_group_used(&rc->block_group->item) > 0);
out:
iput(rc->data_inode);
- btrfs_stop_workers(&rc->workers);
+ btrq_stop_workers(&rc->workers);
btrfs_put_block_group(rc->block_group);
kfree(rc);
return err;
@@ -3700,8 +3700,8 @@ int btrfs_recover_relocation(struct btrfs_root *root)
mapping_tree_init(&rc->reloc_root_tree);
INIT_LIST_HEAD(&rc->reloc_roots);
- btrfs_init_workers(&rc->workers, "relocate",
- root->fs_info->thread_pool_size, NULL);
+ btrq_init_workers(&rc->workers, "btrfs-relocate",
+ root->fs_info->thread_pool_size, NULL);
rc->extent_root = root->fs_info->extent_root;
set_reloc_control(rc);
@@ -3736,7 +3736,7 @@ int btrfs_recover_relocation(struct btrfs_root *root)
btrfs_commit_transaction(trans, rc->extent_root);
out:
if (rc) {
- btrfs_stop_workers(&rc->workers);
+ btrq_stop_workers(&rc->workers);
kfree(rc);
}
while (!list_empty(&reloc_roots)) {
@@ -21,6 +21,7 @@
#include <linux/blkdev.h>
#include <linux/random.h>
#include <linux/iocontext.h>
+#include <linux/btrqueue.h>
#include <asm/div64.h>
#include "compat.h"
#include "ctree.h"
@@ -29,7 +30,6 @@
#include "transaction.h"
#include "print-tree.h"
#include "volumes.h"
-#include "async-thread.h"
struct map_lookup {
u64 type;
@@ -316,7 +316,7 @@ loop_lock:
device->running_pending = 1;
spin_unlock(&device->io_lock);
- btrfs_requeue_work(&device->work);
+ btrq_requeue_work(&device->work);
goto done;
}
}
@@ -350,7 +350,7 @@ done:
return 0;
}
-static void pending_bios_fn(struct btrfs_work *work)
+static void pending_bios_fn(struct btrq_work *work)
{
struct btrfs_device *device;
@@ -2907,7 +2907,7 @@ struct async_sched {
struct bio *bio;
int rw;
struct btrfs_fs_info *info;
- struct btrfs_work work;
+ struct btrq_work work;
};
/*
@@ -2961,8 +2961,8 @@ static noinline int schedule_bio(struct btrfs_root *root,
spin_unlock(&device->io_lock);
if (should_queue)
- btrfs_queue_worker(&root->fs_info->submit_workers,
- &device->work);
+ btrq_queue_worker(&root->fs_info->submit_workers,
+ &device->work);
return 0;
}
@@ -20,7 +20,7 @@
#define __BTRFS_VOLUMES_
#include <linux/bio.h>
-#include "async-thread.h"
+#include <linux/btrqueue.h>
struct buffer_head;
struct btrfs_pending_bios {
@@ -82,7 +82,7 @@ struct btrfs_device {
/* physical drive uuid (or lvm uuid) */
u8 uuid[BTRFS_UUID_SIZE];
- struct btrfs_work work;
+ struct btrq_work work;
};
struct btrfs_fs_devices {
similarity index 76%
rename from fs/btrfs/async-thread.h
rename to include/linux/btrqueue.h
@@ -19,7 +19,7 @@
#ifndef __BTRFS_ASYNC_THREAD_
#define __BTRFS_ASYNC_THREAD_
-struct btrfs_worker_thread;
+struct btrq_worker_thread;
/*
* This is similar to a workqueue, but it is meant to spread the operations
@@ -28,14 +28,14 @@ struct btrfs_worker_thread;
* cut down on context switches.
*
* By default threads are added on demand up to 2 * the number of cpus.
- * Changing struct btrfs_workers->max_workers is one way to prevent
+ * Changing struct btrq_workers->max_workers is one way to prevent
* demand creation of kthreads.
*
- * the basic model of these worker threads is to embed a btrfs_work
+ * the basic model of these worker threads is to embed a btrq_work
* structure in your own data struct, and use container_of in a
* work function to get back to your data struct.
*/
-struct btrfs_work {
+struct btrq_work {
/*
* func should be set to the function you want called
* your work struct is passed as the only arg
@@ -44,9 +44,9 @@ struct btrfs_work {
* and it is called to complete a given work item in the same
* order they were sent to the queue.
*/
- void (*func)(struct btrfs_work *work);
- void (*ordered_func)(struct btrfs_work *work);
- void (*ordered_free)(struct btrfs_work *work);
+ void (*func)(struct btrq_work *work);
+ void (*ordered_func)(struct btrq_work *work);
+ void (*ordered_free)(struct btrq_work *work);
/*
* flags should be set to zero. It is used to make sure the
@@ -55,18 +55,18 @@ struct btrfs_work {
unsigned long flags;
/* don't touch these */
- struct btrfs_worker_thread *worker;
+ struct btrq_worker_thread *worker;
struct list_head list;
struct list_head order_list;
};
-struct btrfs_workers {
+struct btrq_workers {
/* current number of running workers */
int num_workers;
int num_workers_starting;
- /* max number of workers allowed. changed by btrfs_start_workers */
+ /* max number of workers allowed. changed by btrq_start_workers */
int max_workers;
/* once a worker has this many requests or fewer, it is idle */
@@ -83,7 +83,7 @@ struct btrfs_workers {
* to start them at a later time? If we can't sleep, this indicates
* which queue we need to use to schedule thread creation.
*/
- struct btrfs_workers *atomic_worker_start;
+ struct btrq_workers *atomic_worker_start;
/* list with all the work threads. The workers on the idle thread
* may be actively servicing jobs, but they haven't yet hit the
@@ -109,11 +109,11 @@ struct btrfs_workers {
char *name;
};
-int btrfs_queue_worker(struct btrfs_workers *workers, struct btrfs_work *work);
-int btrfs_start_workers(struct btrfs_workers *workers, int num_workers);
-int btrfs_stop_workers(struct btrfs_workers *workers);
-void btrfs_init_workers(struct btrfs_workers *workers, char *name, int max,
- struct btrfs_workers *async_starter);
-int btrfs_requeue_work(struct btrfs_work *work);
-void btrfs_set_work_high_prio(struct btrfs_work *work);
+int btrq_queue_worker(struct btrq_workers *workers, struct btrq_work *work);
+int btrq_start_workers(struct btrq_workers *workers, int num_workers);
+int btrq_stop_workers(struct btrq_workers *workers);
+void btrq_init_workers(struct btrq_workers *workers, char *name, int max,
+ struct btrq_workers *async_starter);
+int btrq_requeue_work(struct btrq_work *work);
+void btrq_set_work_high_prio(struct btrq_work *work);
#endif
@@ -118,6 +118,12 @@ config DECOMPRESS_LZMA
tristate
#
+# "Butter" workqueue for load balanced work
+#
+config BTRQ
+ tristate
+
+#
# Generic allocator support is selected if needed
#
config GENERIC_ALLOCATOR
@@ -70,6 +70,8 @@ lib-$(CONFIG_DECOMPRESS_GZIP) += decompress_inflate.o
lib-$(CONFIG_DECOMPRESS_BZIP2) += decompress_bunzip2.o
lib-$(CONFIG_DECOMPRESS_LZMA) += decompress_unlzma.o
+obj-$(CONFIG_BTRQ) += btrqueue.o
+
obj-$(CONFIG_TEXTSEARCH) += textsearch.o
obj-$(CONFIG_TEXTSEARCH_KMP) += ts_kmp.o
obj-$(CONFIG_TEXTSEARCH_BM) += ts_bm.o
similarity index 82%
rename from fs/btrfs/async-thread.c
rename to lib/btrqueue.c
@@ -20,7 +20,8 @@
#include <linux/list.h>
#include <linux/spinlock.h>
#include <linux/freezer.h>
-#include "async-thread.h"
+#include <linux/btrqueue.h>
+#include <linux/module.h>
#define WORK_QUEUED_BIT 0
#define WORK_DONE_BIT 1
@@ -31,15 +32,15 @@
* container for the kthread task pointer and the list of pending work
* One of these is allocated per thread.
*/
-struct btrfs_worker_thread {
+struct btrq_worker_thread {
/* pool we belong to */
- struct btrfs_workers *workers;
+ struct btrq_workers *workers;
- /* list of struct btrfs_work that are waiting for service */
+ /* list of struct btrq_work that are waiting for service */
struct list_head pending;
struct list_head prio_pending;
- /* list of worker threads from struct btrfs_workers */
+ /* list of worker threads from struct btrq_workers */
struct list_head worker_list;
/* kthread */
@@ -64,12 +65,12 @@ struct btrfs_worker_thread {
};
/*
- * btrfs_start_workers uses kthread_run, which can block waiting for memory
+ * btrq_start_workers uses kthread_run, which can block waiting for memory
* for a very long time. It will actually throttle on page writeback,
- * and so it may not make progress until after our btrfs worker threads
+ * and so it may not make progress until after our btrq worker threads
* process all of the pending work structs in their queue
*
- * This means we can't use btrfs_start_workers from inside a btrfs worker
+ * This means we can't use btrq_start_workers from inside a btrq worker
* thread that is used as part of cleaning dirty memory, which pretty much
* involves all of the worker threads.
*
@@ -79,19 +80,19 @@ struct btrfs_worker_thread {
* another worker.
*/
struct worker_start {
- struct btrfs_work work;
- struct btrfs_workers *queue;
+ struct btrq_work work;
+ struct btrq_workers *queue;
};
-static void start_new_worker_func(struct btrfs_work *work)
+static void start_new_worker_func(struct btrq_work *work)
{
struct worker_start *start;
start = container_of(work, struct worker_start, work);
- btrfs_start_workers(start->queue, 1);
+ btrq_start_workers(start->queue, 1);
kfree(start);
}
-static int start_new_worker(struct btrfs_workers *queue)
+static int start_new_worker(struct btrq_workers *queue)
{
struct worker_start *start;
int ret;
@@ -102,7 +103,7 @@ static int start_new_worker(struct btrfs_workers *queue)
start->work.func = start_new_worker_func;
start->queue = queue;
- ret = btrfs_queue_worker(queue->atomic_worker_start, &start->work);
+ ret = btrq_queue_worker(queue->atomic_worker_start, &start->work);
if (ret)
kfree(start);
return ret;
@@ -112,7 +113,7 @@ static int start_new_worker(struct btrfs_workers *queue)
* helper function to move a thread onto the idle list after it
* has finished some requests.
*/
-static void check_idle_worker(struct btrfs_worker_thread *worker)
+static void check_idle_worker(struct btrq_worker_thread *worker)
{
if (!worker->idle && atomic_read(&worker->num_pending) <
worker->workers->idle_thresh / 2) {
@@ -133,7 +134,7 @@ static void check_idle_worker(struct btrfs_worker_thread *worker)
* helper function to move a thread off the idle list after new
* pending work is added.
*/
-static void check_busy_worker(struct btrfs_worker_thread *worker)
+static void check_busy_worker(struct btrq_worker_thread *worker)
{
if (worker->idle && atomic_read(&worker->num_pending) >=
worker->workers->idle_thresh) {
@@ -149,9 +150,9 @@ static void check_busy_worker(struct btrfs_worker_thread *worker)
}
}
-static void check_pending_worker_creates(struct btrfs_worker_thread *worker)
+static void check_pending_worker_creates(struct btrq_worker_thread *worker)
{
- struct btrfs_workers *workers = worker->workers;
+ struct btrq_workers *workers = worker->workers;
unsigned long flags;
rmb();
@@ -176,8 +177,8 @@ out:
spin_unlock_irqrestore(&workers->lock, flags);
}
-static noinline int run_ordered_completions(struct btrfs_workers *workers,
- struct btrfs_work *work)
+static noinline int run_ordered_completions(struct btrq_workers *workers,
+ struct btrq_work *work)
{
if (!workers->ordered)
return 0;
@@ -189,10 +190,10 @@ static noinline int run_ordered_completions(struct btrfs_workers *workers,
while (1) {
if (!list_empty(&workers->prio_order_list)) {
work = list_entry(workers->prio_order_list.next,
- struct btrfs_work, order_list);
+ struct btrq_work, order_list);
} else if (!list_empty(&workers->order_list)) {
work = list_entry(workers->order_list.next,
- struct btrfs_work, order_list);
+ struct btrq_work, order_list);
} else {
break;
}
@@ -221,13 +222,13 @@ static noinline int run_ordered_completions(struct btrfs_workers *workers,
return 0;
}
-static void put_worker(struct btrfs_worker_thread *worker)
+static void put_worker(struct btrq_worker_thread *worker)
{
if (atomic_dec_and_test(&worker->refs))
kfree(worker);
}
-static int try_worker_shutdown(struct btrfs_worker_thread *worker)
+static int try_worker_shutdown(struct btrq_worker_thread *worker)
{
int freeit = 0;
@@ -252,11 +253,11 @@ static int try_worker_shutdown(struct btrfs_worker_thread *worker)
return freeit;
}
-static struct btrfs_work *get_next_work(struct btrfs_worker_thread *worker,
+static struct btrq_work *get_next_work(struct btrq_worker_thread *worker,
struct list_head *prio_head,
struct list_head *head)
{
- struct btrfs_work *work = NULL;
+ struct btrq_work *work = NULL;
struct list_head *cur = NULL;
if(!list_empty(prio_head))
@@ -287,7 +288,7 @@ refill:
goto out_fail;
out:
- work = list_entry(cur, struct btrfs_work, list);
+ work = list_entry(cur, struct btrq_work, list);
out_fail:
return work;
@@ -298,10 +299,10 @@ out_fail:
*/
static int worker_loop(void *arg)
{
- struct btrfs_worker_thread *worker = arg;
+ struct btrq_worker_thread *worker = arg;
struct list_head head;
struct list_head prio_head;
- struct btrfs_work *work;
+ struct btrq_work *work;
INIT_LIST_HEAD(&head);
INIT_LIST_HEAD(&prio_head);
@@ -403,17 +404,17 @@ again:
/*
* this will wait for all the worker threads to shutdown
*/
-int btrfs_stop_workers(struct btrfs_workers *workers)
+int btrq_stop_workers(struct btrq_workers *workers)
{
struct list_head *cur;
- struct btrfs_worker_thread *worker;
+ struct btrq_worker_thread *worker;
int can_stop;
spin_lock_irq(&workers->lock);
list_splice_init(&workers->idle_list, &workers->worker_list);
while (!list_empty(&workers->worker_list)) {
cur = workers->worker_list.next;
- worker = list_entry(cur, struct btrfs_worker_thread,
+ worker = list_entry(cur, struct btrq_worker_thread,
worker_list);
atomic_inc(&worker->refs);
@@ -433,12 +434,13 @@ int btrfs_stop_workers(struct btrfs_workers *workers)
spin_unlock_irq(&workers->lock);
return 0;
}
+EXPORT_SYMBOL_GPL(btrq_stop_workers);
/*
- * simple init on struct btrfs_workers
+ * simple init on struct btrq_workers
*/
-void btrfs_init_workers(struct btrfs_workers *workers, char *name, int max,
- struct btrfs_workers *async_helper)
+void btrq_init_workers(struct btrq_workers *workers, char *name, int max,
+ struct btrq_workers *async_helper)
{
workers->num_workers = 0;
workers->num_workers_starting = 0;
@@ -455,15 +457,16 @@ void btrfs_init_workers(struct btrfs_workers *workers, char *name, int max,
workers->atomic_start_pending = 0;
workers->atomic_worker_start = async_helper;
}
+EXPORT_SYMBOL_GPL(btrq_init_workers);
/*
* starts new worker threads. This does not enforce the max worker
* count in case you need to temporarily go past it.
*/
-static int __btrfs_start_workers(struct btrfs_workers *workers,
+static int __btrq_start_workers(struct btrq_workers *workers,
int num_workers)
{
- struct btrfs_worker_thread *worker;
+ struct btrq_worker_thread *worker;
int ret = 0;
int i;
@@ -483,7 +486,7 @@ static int __btrfs_start_workers(struct btrfs_workers *workers,
atomic_set(&worker->refs, 1);
worker->workers = workers;
worker->task = kthread_run(worker_loop, worker,
- "btrfs-%s-%d", workers->name,
+ "%s/%d", workers->name,
workers->num_workers + i);
if (IS_ERR(worker->task)) {
ret = PTR_ERR(worker->task);
@@ -500,26 +503,27 @@ static int __btrfs_start_workers(struct btrfs_workers *workers,
}
return 0;
fail:
- btrfs_stop_workers(workers);
+ btrq_stop_workers(workers);
return ret;
}
-int btrfs_start_workers(struct btrfs_workers *workers, int num_workers)
+int btrq_start_workers(struct btrq_workers *workers, int num_workers)
{
spin_lock_irq(&workers->lock);
workers->num_workers_starting += num_workers;
spin_unlock_irq(&workers->lock);
- return __btrfs_start_workers(workers, num_workers);
+ return __btrq_start_workers(workers, num_workers);
}
+EXPORT_SYMBOL_GPL(btrq_start_workers);
/*
* run through the list and find a worker thread that doesn't have a lot
* to do right now. This can return null if we aren't yet at the thread
* count limit and all of the threads are busy.
*/
-static struct btrfs_worker_thread *next_worker(struct btrfs_workers *workers)
+static struct btrq_worker_thread *next_worker(struct btrq_workers *workers)
{
- struct btrfs_worker_thread *worker;
+ struct btrq_worker_thread *worker;
struct list_head *next;
int enforce_min;
@@ -534,7 +538,7 @@ static struct btrfs_worker_thread *next_worker(struct btrfs_workers *workers)
*/
if (!list_empty(&workers->idle_list)) {
next = workers->idle_list.next;
- worker = list_entry(next, struct btrfs_worker_thread,
+ worker = list_entry(next, struct btrq_worker_thread,
worker_list);
return worker;
}
@@ -548,7 +552,7 @@ static struct btrfs_worker_thread *next_worker(struct btrfs_workers *workers)
* requests submitted at roughly the same time onto the same worker.
*/
next = workers->worker_list.next;
- worker = list_entry(next, struct btrfs_worker_thread, worker_list);
+ worker = list_entry(next, struct btrq_worker_thread, worker_list);
worker->sequence++;
if (worker->sequence % workers->idle_thresh == 0)
@@ -561,9 +565,9 @@ static struct btrfs_worker_thread *next_worker(struct btrfs_workers *workers)
* an idle worker, start a new worker up to the max count, or just return
* one of the existing busy workers.
*/
-static struct btrfs_worker_thread *find_worker(struct btrfs_workers *workers)
+static struct btrq_worker_thread *find_worker(struct btrq_workers *workers)
{
- struct btrfs_worker_thread *worker;
+ struct btrq_worker_thread *worker;
unsigned long flags;
struct list_head *fallback;
@@ -582,7 +586,7 @@ again:
workers->num_workers_starting++;
spin_unlock_irqrestore(&workers->lock, flags);
/* we're below the limit, start another worker */
- __btrfs_start_workers(workers, 1);
+ __btrq_start_workers(workers, 1);
goto again;
}
}
@@ -600,7 +604,7 @@ fallback:
fallback = workers->idle_list.next;
BUG_ON(!fallback);
worker = list_entry(fallback,
- struct btrfs_worker_thread, worker_list);
+ struct btrq_worker_thread, worker_list);
found:
/*
* this makes sure the worker doesn't exit before it is placed
@@ -612,13 +616,13 @@ found:
}
/*
- * btrfs_requeue_work just puts the work item back on the tail of the list
+ * btrq_requeue_work just puts the work item back on the tail of the list
* it was taken from. It is intended for use with long running work functions
* that make some progress and want to give the cpu up for others.
*/
-int btrfs_requeue_work(struct btrfs_work *work)
+int btrq_requeue_work(struct btrq_work *work)
{
- struct btrfs_worker_thread *worker = work->worker;
+ struct btrq_worker_thread *worker = work->worker;
unsigned long flags;
int wake = 0;
@@ -654,18 +658,20 @@ out:
return 0;
}
+EXPORT_SYMBOL_GPL(btrq_requeue_work);
-void btrfs_set_work_high_prio(struct btrfs_work *work)
+void btrq_set_work_high_prio(struct btrq_work *work)
{
set_bit(WORK_HIGH_PRIO_BIT, &work->flags);
}
+EXPORT_SYMBOL_GPL(btrq_set_work_high_prio);
/*
- * places a struct btrfs_work into the pending queue of one of the kthreads
+ * places a struct btrq_work into the pending queue of one of the kthreads
*/
-int btrfs_queue_worker(struct btrfs_workers *workers, struct btrfs_work *work)
+int btrq_queue_worker(struct btrq_workers *workers, struct btrq_work *work)
{
- struct btrfs_worker_thread *worker;
+ struct btrq_worker_thread *worker;
unsigned long flags;
int wake = 0;
@@ -714,3 +720,4 @@ int btrfs_queue_worker(struct btrfs_workers *workers, struct btrfs_work *work)
out:
return 0;
}
+EXPORT_SYMBOL_GPL(btrq_queue_worker);