Unverified Commit 69635d7f authored by Marco Crivellari's avatar Marco Crivellari Committed by Christian Brauner
Browse files

fs: WQ_PERCPU added to alloc_workqueue users



Currently if a user enqueue a work item using schedule_delayed_work() the
used wq is "system_wq" (per-cpu wq) while queue_delayed_work() use
WORK_CPU_UNBOUND (used when a cpu is not specified). The same applies to
schedule_work() that is using system_wq and queue_work(), that makes use
again of WORK_CPU_UNBOUND.
This lack of consistentcy cannot be addressed without refactoring the API.

alloc_workqueue() treats all queues as per-CPU by default, while unbound
workqueues must opt-in via WQ_UNBOUND.

This default is suboptimal: most workloads benefit from unbound queues,
allowing the scheduler to place worker threads where they’re needed and
reducing noise when CPUs are isolated.

This patch adds a new WQ_PERCPU flag to all the fs subsystem users to
explicitly request the use of the per-CPU behavior. Both flags coexist
for one release cycle to allow callers to transition their calls.

Once migration is complete, WQ_UNBOUND can be removed and unbound will
become the implicit default.

With the introduction of the WQ_PERCPU flag (equivalent to !WQ_UNBOUND),
any alloc_workqueue() caller that doesn’t explicitly specify WQ_UNBOUND
must now use WQ_PERCPU.

All existing users have been updated accordingly.

Suggested-by: default avatarTejun Heo <tj@kernel.org>
Signed-off-by: default avatarMarco Crivellari <marco.crivellari@suse.com>
Link: https://lore.kernel.org/20250916082906.77439-4-marco.crivellari@suse.com


Signed-off-by: default avatarChristian Brauner <brauner@kernel.org>
parent 4ef64db0
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -169,13 +169,13 @@ static int __init afs_init(void)

	printk(KERN_INFO "kAFS: Red Hat AFS client v0.1 registering.\n");

	afs_wq = alloc_workqueue("afs", 0, 0);
	afs_wq = alloc_workqueue("afs", WQ_PERCPU, 0);
	if (!afs_wq)
		goto error_afs_wq;
	afs_async_calls = alloc_workqueue("kafsd", WQ_MEM_RECLAIM | WQ_UNBOUND, 0);
	if (!afs_async_calls)
		goto error_async;
	afs_lock_manager = alloc_workqueue("kafs_lockd", WQ_MEM_RECLAIM, 0);
	afs_lock_manager = alloc_workqueue("kafs_lockd", WQ_MEM_RECLAIM | WQ_PERCPU, 0);
	if (!afs_lock_manager)
		goto error_lockmgr;

+5 −5
Original line number Diff line number Diff line
@@ -801,13 +801,13 @@ int bch2_fs_init_rw(struct bch_fs *c)
	if (!(c->btree_update_wq = alloc_workqueue("bcachefs",
				WQ_HIGHPRI|WQ_FREEZABLE|WQ_MEM_RECLAIM|WQ_UNBOUND, 512)) ||
	    !(c->btree_write_complete_wq = alloc_workqueue("bcachefs_btree_write_complete",
				WQ_HIGHPRI|WQ_FREEZABLE|WQ_MEM_RECLAIM, 1)) ||
				WQ_HIGHPRI|WQ_FREEZABLE|WQ_MEM_RECLAIM|WQ_PERCPU, 1)) ||
	    !(c->copygc_wq = alloc_workqueue("bcachefs_copygc",
				WQ_HIGHPRI|WQ_FREEZABLE|WQ_MEM_RECLAIM|WQ_CPU_INTENSIVE, 1)) ||
				WQ_HIGHPRI|WQ_FREEZABLE|WQ_MEM_RECLAIM|WQ_CPU_INTENSIVE|WQ_PERCPU, 1)) ||
	    !(c->btree_write_submit_wq = alloc_workqueue("bcachefs_btree_write_sumit",
				WQ_HIGHPRI|WQ_FREEZABLE|WQ_MEM_RECLAIM, 1)) ||
				WQ_HIGHPRI|WQ_FREEZABLE|WQ_MEM_RECLAIM|WQ_PERCPU, 1)) ||
	    !(c->write_ref_wq = alloc_workqueue("bcachefs_write_ref",
				WQ_FREEZABLE, 0)))
				WQ_FREEZABLE|WQ_PERCPU, 0)))
		return bch_err_throw(c, ENOMEM_fs_other_alloc);

	int ret = bch2_fs_btree_interior_update_init(c) ?:
@@ -975,7 +975,7 @@ static struct bch_fs *bch2_fs_alloc(struct bch_sb *sb, struct bch_opts *opts,
		sizeof(struct sort_iter_set);

	if (!(c->btree_read_complete_wq = alloc_workqueue("bcachefs_btree_read_complete",
				WQ_HIGHPRI|WQ_FREEZABLE|WQ_MEM_RECLAIM, 512)) ||
				WQ_HIGHPRI|WQ_FREEZABLE|WQ_MEM_RECLAIM|WQ_PERCPU, 512)) ||
	    enumerated_ref_init(&c->writes, BCH_WRITE_REF_NR,
				bch2_writes_disabled) ||
	    mempool_init_kmalloc_pool(&c->fill_iter, 1, iter_size) ||
+1 −1
Original line number Diff line number Diff line
@@ -1958,7 +1958,7 @@ static int btrfs_init_workqueues(struct btrfs_fs_info *fs_info)
{
	u32 max_active = fs_info->thread_pool_size;
	unsigned int flags = WQ_MEM_RECLAIM | WQ_FREEZABLE | WQ_UNBOUND;
	unsigned int ordered_flags = WQ_MEM_RECLAIM | WQ_FREEZABLE;
	unsigned int ordered_flags = WQ_MEM_RECLAIM | WQ_FREEZABLE | WQ_PERCPU;

	fs_info->workers =
		btrfs_alloc_workqueue(fs_info, "worker", flags, max_active, 16);
+1 −1
Original line number Diff line number Diff line
@@ -862,7 +862,7 @@ static struct ceph_fs_client *create_fs_client(struct ceph_mount_options *fsopt,
	fsc->inode_wq = alloc_workqueue("ceph-inode", WQ_UNBOUND, 0);
	if (!fsc->inode_wq)
		goto fail_client;
	fsc->cap_wq = alloc_workqueue("ceph-cap", 0, 1);
	fsc->cap_wq = alloc_workqueue("ceph-cap", WQ_PERCPU, 1);
	if (!fsc->cap_wq)
		goto fail_inode_wq;

+1 −1
Original line number Diff line number Diff line
@@ -1703,7 +1703,7 @@ static int work_start(void)
		return -ENOMEM;
	}

	process_workqueue = alloc_workqueue("dlm_process", WQ_HIGHPRI | WQ_BH, 0);
	process_workqueue = alloc_workqueue("dlm_process", WQ_HIGHPRI | WQ_BH | WQ_PERCPU, 0);
	if (!process_workqueue) {
		log_print("can't start dlm_process");
		destroy_workqueue(io_workqueue);
Loading