Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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 128ea9f6ccfb ("workqueue: Add system_percpu_wq and system_dfl_wq")
- commit 930c2ea566af ("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>

+38 -27
+5 -2
drivers/message/fusion/mptbase.c
··· 1857 1857 INIT_DELAYED_WORK(&ioc->fault_reset_work, mpt_fault_reset_work); 1858 1858 1859 1859 ioc->reset_work_q = 1860 - alloc_workqueue("mpt_poll_%d", WQ_MEM_RECLAIM, 0, ioc->id); 1860 + alloc_workqueue("mpt_poll_%d", WQ_MEM_RECLAIM | WQ_PERCPU, 0, 1861 + ioc->id); 1861 1862 if (!ioc->reset_work_q) { 1862 1863 printk(MYIOC_s_ERR_FMT "Insufficient memory to add adapter!\n", 1863 1864 ioc->name); ··· 1985 1984 1986 1985 INIT_LIST_HEAD(&ioc->fw_event_list); 1987 1986 spin_lock_init(&ioc->fw_event_lock); 1988 - ioc->fw_event_q = alloc_workqueue("mpt/%d", WQ_MEM_RECLAIM, 0, ioc->id); 1987 + ioc->fw_event_q = alloc_workqueue("mpt/%d", 1988 + WQ_MEM_RECLAIM | WQ_PERCPU, 0, 1989 + ioc->id); 1989 1990 if (!ioc->fw_event_q) { 1990 1991 printk(MYIOC_s_ERR_FMT "Insufficient memory to add adapter!\n", 1991 1992 ioc->name);
+2 -1
drivers/scsi/be2iscsi/be_main.c
··· 5633 5633 5634 5634 phba->ctrl.mcc_alloc_index = phba->ctrl.mcc_free_index = 0; 5635 5635 5636 - phba->wq = alloc_workqueue("beiscsi_%02x_wq", WQ_MEM_RECLAIM, 1, 5636 + phba->wq = alloc_workqueue("beiscsi_%02x_wq", 5637 + WQ_MEM_RECLAIM | WQ_PERCPU, 1, 5637 5638 phba->shost->host_no); 5638 5639 if (!phba->wq) { 5639 5640 beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT,
+1 -1
drivers/scsi/bnx2fc/bnx2fc_fcoe.c
··· 2695 2695 if (rc) 2696 2696 goto detach_ft; 2697 2697 2698 - bnx2fc_wq = alloc_workqueue("bnx2fc", 0, 0); 2698 + bnx2fc_wq = alloc_workqueue("bnx2fc", WQ_PERCPU, 0); 2699 2699 if (!bnx2fc_wq) { 2700 2700 rc = -ENOMEM; 2701 2701 goto release_bt;
+1 -1
drivers/scsi/device_handler/scsi_dh_alua.c
··· 1300 1300 { 1301 1301 int r; 1302 1302 1303 - kaluad_wq = alloc_workqueue("kaluad", WQ_MEM_RECLAIM, 0); 1303 + kaluad_wq = alloc_workqueue("kaluad", WQ_MEM_RECLAIM | WQ_PERCPU, 0); 1304 1304 if (!kaluad_wq) 1305 1305 return -ENOMEM; 1306 1306
+2 -1
drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c
··· 3533 3533 init_completion(&vscsi->wait_idle); 3534 3534 init_completion(&vscsi->unconfig); 3535 3535 3536 - vscsi->work_q = alloc_workqueue("ibmvscsis%s", WQ_MEM_RECLAIM, 1, 3536 + vscsi->work_q = alloc_workqueue("ibmvscsis%s", 3537 + WQ_MEM_RECLAIM | WQ_PERCPU, 1, 3537 3538 dev_name(&vdev->dev)); 3538 3539 if (!vscsi->work_q) { 3539 3540 rc = -ENOMEM;
+1 -1
drivers/scsi/lpfc/lpfc_init.c
··· 7944 7944 /* Allocate all driver workqueues here */ 7945 7945 7946 7946 /* The lpfc_wq workqueue for deferred irq use */ 7947 - phba->wq = alloc_workqueue("lpfc_wq", WQ_MEM_RECLAIM, 0); 7947 + phba->wq = alloc_workqueue("lpfc_wq", WQ_MEM_RECLAIM | WQ_PERCPU, 0); 7948 7948 if (!phba->wq) 7949 7949 return -ENOMEM; 7950 7950
+1 -1
drivers/scsi/pm8001/pm8001_init.c
··· 1534 1534 if (pm8001_use_tasklet && !pm8001_use_msix) 1535 1535 pm8001_use_tasklet = false; 1536 1536 1537 - pm8001_wq = alloc_workqueue("pm80xx", 0, 0); 1537 + pm8001_wq = alloc_workqueue("pm80xx", WQ_PERCPU, 0); 1538 1538 if (!pm8001_wq) 1539 1539 goto err; 1540 1540
+10 -5
drivers/scsi/qedf/qedf_main.c
··· 3374 3374 QEDF_INFO(&(qedf->dbg_ctx), QEDF_LOG_INFO, "qedf->io_mempool=%p.\n", 3375 3375 qedf->io_mempool); 3376 3376 3377 - qedf->link_update_wq = alloc_workqueue("qedf_%u_link", WQ_MEM_RECLAIM, 3377 + qedf->link_update_wq = alloc_workqueue("qedf_%u_link", 3378 + WQ_MEM_RECLAIM | WQ_PERCPU, 3378 3379 1, qedf->lport->host->host_no); 3379 3380 INIT_DELAYED_WORK(&qedf->link_update, qedf_handle_link_update); 3380 3381 INIT_DELAYED_WORK(&qedf->link_recovery, qedf_link_recovery); ··· 3586 3585 ether_addr_copy(params.ll2_mac_address, qedf->mac); 3587 3586 3588 3587 /* Start LL2 processing thread */ 3589 - qedf->ll2_recv_wq = alloc_workqueue("qedf_%d_ll2", WQ_MEM_RECLAIM, 1, 3588 + qedf->ll2_recv_wq = alloc_workqueue("qedf_%d_ll2", 3589 + WQ_MEM_RECLAIM | WQ_PERCPU, 1, 3590 3590 host->host_no); 3591 3591 if (!qedf->ll2_recv_wq) { 3592 3592 QEDF_ERR(&(qedf->dbg_ctx), "Failed to LL2 workqueue.\n"); ··· 3630 3628 } 3631 3629 3632 3630 qedf->timer_work_queue = alloc_workqueue("qedf_%u_timer", 3633 - WQ_MEM_RECLAIM, 1, qedf->lport->host->host_no); 3631 + WQ_MEM_RECLAIM | WQ_PERCPU, 1, 3632 + qedf->lport->host->host_no); 3634 3633 if (!qedf->timer_work_queue) { 3635 3634 QEDF_ERR(&(qedf->dbg_ctx), "Failed to start timer " 3636 3635 "workqueue.\n"); ··· 3644 3641 sprintf(host_buf, "qedf_%u_dpc", 3645 3642 qedf->lport->host->host_no); 3646 3643 qedf->dpc_wq = 3647 - alloc_workqueue("%s", WQ_MEM_RECLAIM, 1, host_buf); 3644 + alloc_workqueue("%s", WQ_MEM_RECLAIM | WQ_PERCPU, 1, 3645 + host_buf); 3648 3646 } 3649 3647 INIT_DELAYED_WORK(&qedf->recovery_work, qedf_recovery_handler); 3650 3648 ··· 4181 4177 goto err3; 4182 4178 } 4183 4179 4184 - qedf_io_wq = alloc_workqueue("%s", WQ_MEM_RECLAIM, 1, "qedf_io_wq"); 4180 + qedf_io_wq = alloc_workqueue("%s", WQ_MEM_RECLAIM | WQ_PERCPU, 1, 4181 + "qedf_io_wq"); 4185 4182 if (!qedf_io_wq) { 4186 4183 QEDF_ERR(NULL, "Could not create qedf_io_wq.\n"); 4187 4184 goto err4;
+1 -1
drivers/scsi/qedi/qedi_main.c
··· 2768 2768 } 2769 2769 2770 2770 qedi->offload_thread = alloc_workqueue("qedi_ofld%d", 2771 - WQ_MEM_RECLAIM, 2771 + WQ_MEM_RECLAIM | WQ_PERCPU, 2772 2772 1, qedi->shost->host_no); 2773 2773 if (!qedi->offload_thread) { 2774 2774 QEDI_ERR(&qedi->dbg_ctx,
+2 -2
drivers/scsi/qla2xxx/qla_os.c
··· 3407 3407 "req->req_q_in=%p req->req_q_out=%p rsp->rsp_q_in=%p rsp->rsp_q_out=%p.\n", 3408 3408 req->req_q_in, req->req_q_out, rsp->rsp_q_in, rsp->rsp_q_out); 3409 3409 3410 - ha->wq = alloc_workqueue("qla2xxx_wq", WQ_MEM_RECLAIM, 0); 3410 + ha->wq = alloc_workqueue("qla2xxx_wq", WQ_MEM_RECLAIM | WQ_PERCPU, 0); 3411 3411 if (unlikely(!ha->wq)) { 3412 3412 ret = -ENOMEM; 3413 3413 goto probe_failed; ··· 5284 5284 qla2x00_set_fcport_disc_state(fcport, DSC_UPD_FCPORT); 5285 5285 spin_unlock_irqrestore(&fcport->vha->work_lock, flags); 5286 5286 5287 - queue_work(system_unbound_wq, &fcport->reg_work); 5287 + queue_work(system_dfl_wq, &fcport->reg_work); 5288 5288 } 5289 5289 5290 5290 static
+3 -2
drivers/scsi/scsi_transport_fc.c
··· 441 441 fc_host->next_vport_number = 0; 442 442 fc_host->npiv_vports_inuse = 0; 443 443 444 - fc_host->work_q = alloc_workqueue("fc_wq_%d", 0, 0, shost->host_no); 444 + fc_host->work_q = alloc_workqueue("fc_wq_%d", WQ_PERCPU, 0, 445 + shost->host_no); 445 446 if (!fc_host->work_q) 446 447 return -ENOMEM; 447 448 ··· 3089 3088 3090 3089 spin_unlock_irqrestore(shost->host_lock, flags); 3091 3090 3092 - rport->devloss_work_q = alloc_workqueue("fc_dl_%d_%d", 0, 0, 3091 + rport->devloss_work_q = alloc_workqueue("fc_dl_%d_%d", WQ_PERCPU, 0, 3093 3092 shost->host_no, rport->number); 3094 3093 if (!rport->devloss_work_q) { 3095 3094 printk(KERN_ERR "FC Remote Port alloc_workqueue failed\n");
+1 -1
drivers/scsi/scsi_transport_iscsi.c
··· 3961 3961 list_del_init(&session->sess_list); 3962 3962 spin_unlock_irqrestore(&sesslock, flags); 3963 3963 3964 - queue_work(system_unbound_wq, &session->destroy_work); 3964 + queue_work(system_dfl_wq, &session->destroy_work); 3965 3965 } 3966 3966 break; 3967 3967 case ISCSI_UEVENT_UNBIND_SESSION:
+4 -4
drivers/target/sbp/sbp_target.c
··· 730 730 pr_debug("tgt_agent ORB_POINTER write: 0x%llx\n", 731 731 agent->orb_pointer); 732 732 733 - queue_work(system_unbound_wq, &agent->work); 733 + queue_work(system_dfl_wq, &agent->work); 734 734 735 735 return RCODE_COMPLETE; 736 736 ··· 764 764 765 765 pr_debug("tgt_agent DOORBELL\n"); 766 766 767 - queue_work(system_unbound_wq, &agent->work); 767 + queue_work(system_dfl_wq, &agent->work); 768 768 769 769 return RCODE_COMPLETE; 770 770 ··· 990 990 991 991 if (tgt_agent_check_active(agent) && !doorbell) { 992 992 INIT_WORK(&req->work, tgt_agent_process_work); 993 - queue_work(system_unbound_wq, &req->work); 993 + queue_work(system_dfl_wq, &req->work); 994 994 } else { 995 995 /* don't process this request, just check next_ORB */ 996 996 sbp_free_request(req); ··· 1618 1618 agent->orb_offset = sbp2_pointer_to_addr(ptr); 1619 1619 agent->request = req; 1620 1620 1621 - queue_work(system_unbound_wq, &agent->work); 1621 + queue_work(system_dfl_wq, &agent->work); 1622 1622 rcode = RCODE_COMPLETE; 1623 1623 } else if (tcode == TCODE_READ_BLOCK_REQUEST) { 1624 1624 addr_to_sbp2_pointer(agent->orb_offset, ptr);
+2 -2
drivers/target/target_core_transport.c
··· 126 126 } 127 127 128 128 target_completion_wq = alloc_workqueue("target_completion", 129 - WQ_MEM_RECLAIM, 0); 129 + WQ_MEM_RECLAIM | WQ_PERCPU, 0); 130 130 if (!target_completion_wq) 131 131 goto out_free_lba_map_mem_cache; 132 132 133 133 target_submission_wq = alloc_workqueue("target_submission", 134 - WQ_MEM_RECLAIM, 0); 134 + WQ_MEM_RECLAIM | WQ_PERCPU, 0); 135 135 if (!target_submission_wq) 136 136 goto out_free_completion_wq; 137 137
+1 -1
drivers/target/target_core_xcopy.c
··· 462 462 463 463 int target_xcopy_setup_pt(void) 464 464 { 465 - xcopy_wq = alloc_workqueue("xcopy_wq", WQ_MEM_RECLAIM, 0); 465 + xcopy_wq = alloc_workqueue("xcopy_wq", WQ_MEM_RECLAIM | WQ_PERCPU, 0); 466 466 if (!xcopy_wq) { 467 467 pr_err("Unable to allocate xcopy_wq\n"); 468 468 return -ENOMEM;
+1 -1
drivers/target/tcm_fc/tfc_conf.c
··· 250 250 tpg->lport_wwn = ft_wwn; 251 251 INIT_LIST_HEAD(&tpg->lun_list); 252 252 253 - wq = alloc_workqueue("tcm_fc", 0, 1); 253 + wq = alloc_workqueue("tcm_fc", WQ_PERCPU, 1); 254 254 if (!wq) { 255 255 kfree(tpg); 256 256 return NULL;