Merge patch series "replace old wq(s), added WQ_PERCPU to alloc_workqueue"

Marco Crivellari <marco.crivellari@suse.com> says:

Hi,

=== Current situation: problems ===

Let's consider a nohz_full system with isolated CPUs: wq_unbound_cpumask is
set to the housekeeping CPUs, for !WQ_UNBOUND the local CPU is selected.

This leads to different scenarios if a work item is scheduled on an
isolated CPU where "delay" value is 0 or greater then 0:
        schedule_delayed_work(, 0);

This will be handled by __queue_work() that will queue the work item on the
current local (isolated) CPU, while:

        schedule_delayed_work(, 1);

Will move the timer on an housekeeping CPU, and schedule the work there.

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 consistency cannot be addressed without refactoring the API.

=== Recent changes to the WQ API ===

The following, address the recent changes in the Workqueue API:

- commit 128ea9f6cc ("workqueue: Add system_percpu_wq and system_dfl_wq")
- commit 930c2ea566 ("workqueue: Add new WQ_PERCPU flag")

The old workqueues will be removed in a future release cycle.

=== Introduced Changes by this series ===

1) [P 1]  Replace uses of system_wq and system_unbound_wq

    system_unbound_wq is to be used when locality is not required.

    Because of that, system_unbound_wq has been replaced with
	system_dfl_wq, to make clear it should be used when locality
	is not required.

2) [P 2-3-4] WQ_PERCPU added to alloc_workqueue()

    This change adds a new WQ_PERCPU flag to explicitly request
    alloc_workqueue() to be per-cpu when WQ_UNBOUND has not been specified.

Thanks!

Link: https://patch.msgid.link/20251031095643.74246-1-marco.crivellari@suse.com
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
This commit is contained in:
Martin K. Petersen
2025-11-12 21:30:23 -05:00
16 changed files with 38 additions and 27 deletions

View File

@@ -1857,7 +1857,8 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id)
INIT_DELAYED_WORK(&ioc->fault_reset_work, mpt_fault_reset_work); INIT_DELAYED_WORK(&ioc->fault_reset_work, mpt_fault_reset_work);
ioc->reset_work_q = ioc->reset_work_q =
alloc_workqueue("mpt_poll_%d", WQ_MEM_RECLAIM, 0, ioc->id); alloc_workqueue("mpt_poll_%d", WQ_MEM_RECLAIM | WQ_PERCPU, 0,
ioc->id);
if (!ioc->reset_work_q) { if (!ioc->reset_work_q) {
printk(MYIOC_s_ERR_FMT "Insufficient memory to add adapter!\n", printk(MYIOC_s_ERR_FMT "Insufficient memory to add adapter!\n",
ioc->name); ioc->name);
@@ -1984,7 +1985,9 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id)
INIT_LIST_HEAD(&ioc->fw_event_list); INIT_LIST_HEAD(&ioc->fw_event_list);
spin_lock_init(&ioc->fw_event_lock); spin_lock_init(&ioc->fw_event_lock);
ioc->fw_event_q = alloc_workqueue("mpt/%d", WQ_MEM_RECLAIM, 0, ioc->id); ioc->fw_event_q = alloc_workqueue("mpt/%d",
WQ_MEM_RECLAIM | WQ_PERCPU, 0,
ioc->id);
if (!ioc->fw_event_q) { if (!ioc->fw_event_q) {
printk(MYIOC_s_ERR_FMT "Insufficient memory to add adapter!\n", printk(MYIOC_s_ERR_FMT "Insufficient memory to add adapter!\n",
ioc->name); ioc->name);

View File

@@ -5633,7 +5633,8 @@ static int beiscsi_dev_probe(struct pci_dev *pcidev,
phba->ctrl.mcc_alloc_index = phba->ctrl.mcc_free_index = 0; phba->ctrl.mcc_alloc_index = phba->ctrl.mcc_free_index = 0;
phba->wq = alloc_workqueue("beiscsi_%02x_wq", WQ_MEM_RECLAIM, 1, phba->wq = alloc_workqueue("beiscsi_%02x_wq",
WQ_MEM_RECLAIM | WQ_PERCPU, 1,
phba->shost->host_no); phba->shost->host_no);
if (!phba->wq) { if (!phba->wq) {
beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT,

View File

@@ -2695,7 +2695,7 @@ static int __init bnx2fc_mod_init(void)
if (rc) if (rc)
goto detach_ft; goto detach_ft;
bnx2fc_wq = alloc_workqueue("bnx2fc", 0, 0); bnx2fc_wq = alloc_workqueue("bnx2fc", WQ_PERCPU, 0);
if (!bnx2fc_wq) { if (!bnx2fc_wq) {
rc = -ENOMEM; rc = -ENOMEM;
goto release_bt; goto release_bt;

View File

@@ -1300,7 +1300,7 @@ static int __init alua_init(void)
{ {
int r; int r;
kaluad_wq = alloc_workqueue("kaluad", WQ_MEM_RECLAIM, 0); kaluad_wq = alloc_workqueue("kaluad", WQ_MEM_RECLAIM | WQ_PERCPU, 0);
if (!kaluad_wq) if (!kaluad_wq)
return -ENOMEM; return -ENOMEM;

View File

@@ -3533,7 +3533,8 @@ static int ibmvscsis_probe(struct vio_dev *vdev,
init_completion(&vscsi->wait_idle); init_completion(&vscsi->wait_idle);
init_completion(&vscsi->unconfig); init_completion(&vscsi->unconfig);
vscsi->work_q = alloc_workqueue("ibmvscsis%s", WQ_MEM_RECLAIM, 1, vscsi->work_q = alloc_workqueue("ibmvscsis%s",
WQ_MEM_RECLAIM | WQ_PERCPU, 1,
dev_name(&vdev->dev)); dev_name(&vdev->dev));
if (!vscsi->work_q) { if (!vscsi->work_q) {
rc = -ENOMEM; rc = -ENOMEM;

View File

@@ -7944,7 +7944,7 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba)
/* Allocate all driver workqueues here */ /* Allocate all driver workqueues here */
/* The lpfc_wq workqueue for deferred irq use */ /* The lpfc_wq workqueue for deferred irq use */
phba->wq = alloc_workqueue("lpfc_wq", WQ_MEM_RECLAIM, 0); phba->wq = alloc_workqueue("lpfc_wq", WQ_MEM_RECLAIM | WQ_PERCPU, 0);
if (!phba->wq) if (!phba->wq)
return -ENOMEM; return -ENOMEM;

View File

@@ -1534,7 +1534,7 @@ static int __init pm8001_init(void)
if (pm8001_use_tasklet && !pm8001_use_msix) if (pm8001_use_tasklet && !pm8001_use_msix)
pm8001_use_tasklet = false; pm8001_use_tasklet = false;
pm8001_wq = alloc_workqueue("pm80xx", 0, 0); pm8001_wq = alloc_workqueue("pm80xx", WQ_PERCPU, 0);
if (!pm8001_wq) if (!pm8001_wq)
goto err; goto err;

View File

@@ -3374,7 +3374,8 @@ retry_probe:
QEDF_INFO(&(qedf->dbg_ctx), QEDF_LOG_INFO, "qedf->io_mempool=%p.\n", QEDF_INFO(&(qedf->dbg_ctx), QEDF_LOG_INFO, "qedf->io_mempool=%p.\n",
qedf->io_mempool); qedf->io_mempool);
qedf->link_update_wq = alloc_workqueue("qedf_%u_link", WQ_MEM_RECLAIM, qedf->link_update_wq = alloc_workqueue("qedf_%u_link",
WQ_MEM_RECLAIM | WQ_PERCPU,
1, qedf->lport->host->host_no); 1, qedf->lport->host->host_no);
INIT_DELAYED_WORK(&qedf->link_update, qedf_handle_link_update); INIT_DELAYED_WORK(&qedf->link_update, qedf_handle_link_update);
INIT_DELAYED_WORK(&qedf->link_recovery, qedf_link_recovery); INIT_DELAYED_WORK(&qedf->link_recovery, qedf_link_recovery);
@@ -3585,7 +3586,8 @@ retry_probe:
ether_addr_copy(params.ll2_mac_address, qedf->mac); ether_addr_copy(params.ll2_mac_address, qedf->mac);
/* Start LL2 processing thread */ /* Start LL2 processing thread */
qedf->ll2_recv_wq = alloc_workqueue("qedf_%d_ll2", WQ_MEM_RECLAIM, 1, qedf->ll2_recv_wq = alloc_workqueue("qedf_%d_ll2",
WQ_MEM_RECLAIM | WQ_PERCPU, 1,
host->host_no); host->host_no);
if (!qedf->ll2_recv_wq) { if (!qedf->ll2_recv_wq) {
QEDF_ERR(&(qedf->dbg_ctx), "Failed to LL2 workqueue.\n"); QEDF_ERR(&(qedf->dbg_ctx), "Failed to LL2 workqueue.\n");
@@ -3628,7 +3630,8 @@ retry_probe:
} }
qedf->timer_work_queue = alloc_workqueue("qedf_%u_timer", qedf->timer_work_queue = alloc_workqueue("qedf_%u_timer",
WQ_MEM_RECLAIM, 1, qedf->lport->host->host_no); WQ_MEM_RECLAIM | WQ_PERCPU, 1,
qedf->lport->host->host_no);
if (!qedf->timer_work_queue) { if (!qedf->timer_work_queue) {
QEDF_ERR(&(qedf->dbg_ctx), "Failed to start timer " QEDF_ERR(&(qedf->dbg_ctx), "Failed to start timer "
"workqueue.\n"); "workqueue.\n");
@@ -3641,7 +3644,8 @@ retry_probe:
sprintf(host_buf, "qedf_%u_dpc", sprintf(host_buf, "qedf_%u_dpc",
qedf->lport->host->host_no); qedf->lport->host->host_no);
qedf->dpc_wq = qedf->dpc_wq =
alloc_workqueue("%s", WQ_MEM_RECLAIM, 1, host_buf); alloc_workqueue("%s", WQ_MEM_RECLAIM | WQ_PERCPU, 1,
host_buf);
} }
INIT_DELAYED_WORK(&qedf->recovery_work, qedf_recovery_handler); INIT_DELAYED_WORK(&qedf->recovery_work, qedf_recovery_handler);
@@ -4177,7 +4181,8 @@ static int __init qedf_init(void)
goto err3; goto err3;
} }
qedf_io_wq = alloc_workqueue("%s", WQ_MEM_RECLAIM, 1, "qedf_io_wq"); qedf_io_wq = alloc_workqueue("%s", WQ_MEM_RECLAIM | WQ_PERCPU, 1,
"qedf_io_wq");
if (!qedf_io_wq) { if (!qedf_io_wq) {
QEDF_ERR(NULL, "Could not create qedf_io_wq.\n"); QEDF_ERR(NULL, "Could not create qedf_io_wq.\n");
goto err4; goto err4;

View File

@@ -2768,7 +2768,7 @@ retry_probe:
} }
qedi->offload_thread = alloc_workqueue("qedi_ofld%d", qedi->offload_thread = alloc_workqueue("qedi_ofld%d",
WQ_MEM_RECLAIM, WQ_MEM_RECLAIM | WQ_PERCPU,
1, qedi->shost->host_no); 1, qedi->shost->host_no);
if (!qedi->offload_thread) { if (!qedi->offload_thread) {
QEDI_ERR(&qedi->dbg_ctx, QEDI_ERR(&qedi->dbg_ctx,

View File

@@ -3407,7 +3407,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
"req->req_q_in=%p req->req_q_out=%p rsp->rsp_q_in=%p rsp->rsp_q_out=%p.\n", "req->req_q_in=%p req->req_q_out=%p rsp->rsp_q_in=%p rsp->rsp_q_out=%p.\n",
req->req_q_in, req->req_q_out, rsp->rsp_q_in, rsp->rsp_q_out); req->req_q_in, req->req_q_out, rsp->rsp_q_in, rsp->rsp_q_out);
ha->wq = alloc_workqueue("qla2xxx_wq", WQ_MEM_RECLAIM, 0); ha->wq = alloc_workqueue("qla2xxx_wq", WQ_MEM_RECLAIM | WQ_PERCPU, 0);
if (unlikely(!ha->wq)) { if (unlikely(!ha->wq)) {
ret = -ENOMEM; ret = -ENOMEM;
goto probe_failed; goto probe_failed;
@@ -5284,7 +5284,7 @@ void qla24xx_sched_upd_fcport(fc_port_t *fcport)
qla2x00_set_fcport_disc_state(fcport, DSC_UPD_FCPORT); qla2x00_set_fcport_disc_state(fcport, DSC_UPD_FCPORT);
spin_unlock_irqrestore(&fcport->vha->work_lock, flags); spin_unlock_irqrestore(&fcport->vha->work_lock, flags);
queue_work(system_unbound_wq, &fcport->reg_work); queue_work(system_dfl_wq, &fcport->reg_work);
} }
static static

View File

@@ -441,7 +441,8 @@ static int fc_host_setup(struct transport_container *tc, struct device *dev,
fc_host->next_vport_number = 0; fc_host->next_vport_number = 0;
fc_host->npiv_vports_inuse = 0; fc_host->npiv_vports_inuse = 0;
fc_host->work_q = alloc_workqueue("fc_wq_%d", 0, 0, shost->host_no); fc_host->work_q = alloc_workqueue("fc_wq_%d", WQ_PERCPU, 0,
shost->host_no);
if (!fc_host->work_q) if (!fc_host->work_q)
return -ENOMEM; return -ENOMEM;
@@ -3088,7 +3089,7 @@ fc_remote_port_create(struct Scsi_Host *shost, int channel,
spin_unlock_irqrestore(shost->host_lock, flags); spin_unlock_irqrestore(shost->host_lock, flags);
rport->devloss_work_q = alloc_workqueue("fc_dl_%d_%d", 0, 0, rport->devloss_work_q = alloc_workqueue("fc_dl_%d_%d", WQ_PERCPU, 0,
shost->host_no, rport->number); shost->host_no, rport->number);
if (!rport->devloss_work_q) { if (!rport->devloss_work_q) {
printk(KERN_ERR "FC Remote Port alloc_workqueue failed\n"); printk(KERN_ERR "FC Remote Port alloc_workqueue failed\n");

View File

@@ -3961,7 +3961,7 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, uint32_t *group)
list_del_init(&session->sess_list); list_del_init(&session->sess_list);
spin_unlock_irqrestore(&sesslock, flags); spin_unlock_irqrestore(&sesslock, flags);
queue_work(system_unbound_wq, &session->destroy_work); queue_work(system_dfl_wq, &session->destroy_work);
} }
break; break;
case ISCSI_UEVENT_UNBIND_SESSION: case ISCSI_UEVENT_UNBIND_SESSION:

View File

@@ -730,7 +730,7 @@ static int tgt_agent_rw_orb_pointer(struct fw_card *card, int tcode, void *data,
pr_debug("tgt_agent ORB_POINTER write: 0x%llx\n", pr_debug("tgt_agent ORB_POINTER write: 0x%llx\n",
agent->orb_pointer); agent->orb_pointer);
queue_work(system_unbound_wq, &agent->work); queue_work(system_dfl_wq, &agent->work);
return RCODE_COMPLETE; return RCODE_COMPLETE;
@@ -764,7 +764,7 @@ static int tgt_agent_rw_doorbell(struct fw_card *card, int tcode, void *data,
pr_debug("tgt_agent DOORBELL\n"); pr_debug("tgt_agent DOORBELL\n");
queue_work(system_unbound_wq, &agent->work); queue_work(system_dfl_wq, &agent->work);
return RCODE_COMPLETE; return RCODE_COMPLETE;
@@ -990,7 +990,7 @@ static void tgt_agent_fetch_work(struct work_struct *work)
if (tgt_agent_check_active(agent) && !doorbell) { if (tgt_agent_check_active(agent) && !doorbell) {
INIT_WORK(&req->work, tgt_agent_process_work); INIT_WORK(&req->work, tgt_agent_process_work);
queue_work(system_unbound_wq, &req->work); queue_work(system_dfl_wq, &req->work);
} else { } else {
/* don't process this request, just check next_ORB */ /* don't process this request, just check next_ORB */
sbp_free_request(req); sbp_free_request(req);
@@ -1618,7 +1618,7 @@ static void sbp_mgt_agent_rw(struct fw_card *card,
agent->orb_offset = sbp2_pointer_to_addr(ptr); agent->orb_offset = sbp2_pointer_to_addr(ptr);
agent->request = req; agent->request = req;
queue_work(system_unbound_wq, &agent->work); queue_work(system_dfl_wq, &agent->work);
rcode = RCODE_COMPLETE; rcode = RCODE_COMPLETE;
} else if (tcode == TCODE_READ_BLOCK_REQUEST) { } else if (tcode == TCODE_READ_BLOCK_REQUEST) {
addr_to_sbp2_pointer(agent->orb_offset, ptr); addr_to_sbp2_pointer(agent->orb_offset, ptr);

View File

@@ -126,12 +126,12 @@ int init_se_kmem_caches(void)
} }
target_completion_wq = alloc_workqueue("target_completion", target_completion_wq = alloc_workqueue("target_completion",
WQ_MEM_RECLAIM, 0); WQ_MEM_RECLAIM | WQ_PERCPU, 0);
if (!target_completion_wq) if (!target_completion_wq)
goto out_free_lba_map_mem_cache; goto out_free_lba_map_mem_cache;
target_submission_wq = alloc_workqueue("target_submission", target_submission_wq = alloc_workqueue("target_submission",
WQ_MEM_RECLAIM, 0); WQ_MEM_RECLAIM | WQ_PERCPU, 0);
if (!target_submission_wq) if (!target_submission_wq)
goto out_free_completion_wq; goto out_free_completion_wq;

View File

@@ -462,7 +462,7 @@ static const struct target_core_fabric_ops xcopy_pt_tfo = {
int target_xcopy_setup_pt(void) int target_xcopy_setup_pt(void)
{ {
xcopy_wq = alloc_workqueue("xcopy_wq", WQ_MEM_RECLAIM, 0); xcopy_wq = alloc_workqueue("xcopy_wq", WQ_MEM_RECLAIM | WQ_PERCPU, 0);
if (!xcopy_wq) { if (!xcopy_wq) {
pr_err("Unable to allocate xcopy_wq\n"); pr_err("Unable to allocate xcopy_wq\n");
return -ENOMEM; return -ENOMEM;

View File

@@ -250,7 +250,7 @@ static struct se_portal_group *ft_add_tpg(struct se_wwn *wwn, const char *name)
tpg->lport_wwn = ft_wwn; tpg->lport_wwn = ft_wwn;
INIT_LIST_HEAD(&tpg->lun_list); INIT_LIST_HEAD(&tpg->lun_list);
wq = alloc_workqueue("tcm_fc", 0, 1); wq = alloc_workqueue("tcm_fc", WQ_PERCPU, 1);
if (!wq) { if (!wq) {
kfree(tpg); kfree(tpg);
return NULL; return NULL;