From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from relay.hostedemail.com (smtprelay0011.hostedemail.com [216.40.44.11]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 0C69E3BB669 for ; Thu, 4 Jun 2026 05:08:48 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=216.40.44.11 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780549730; cv=none; b=O2Q017XNioZzvk93pQ4sgNUrT7+vbM6A/bAEfNWPTTxcN3Tuo1e4GpXn5f4Y432XqqtQ60+5BjHF1Wi2JU3b7AkEY0rkoTwfY+CAi4CkxU9BIvIVlpUwcKNuUqe34DR91PFB/0ZgPW9qZl4EvGRfDWGGdzaBHScMXzTCyH+9r+Q= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780549730; c=relaxed/simple; bh=G+D/p1Pt8pTo4Lp4utWV/5yliHffvfrHlI8diRylOj0=; h=Message-ID:Subject:From:To:Cc:Date:In-Reply-To:References: Content-Type:MIME-Version; b=JR9hhnsS2iEkW9ih2Wflkj9dS81/f1zjz3Geq27uZy1sfMT5IjQAoOvPRkPdM+syXLz0mh8VIEqis7Z9de5gUJ4NdDcF1aZge8tJXzM6tBJPSgFbvHFUzyvWFFzsZmQLCavIJ9PDgBWtb2Y/29U2dTwPIxlYXMfNKJzWzgvipGA= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=perches.com; spf=pass smtp.mailfrom=perches.com; arc=none smtp.client-ip=216.40.44.11 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=perches.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=perches.com Received: from omf19.hostedemail.com (lb01a-stub [10.200.18.249]) by unirelay07.hostedemail.com (Postfix) with ESMTP id 79487163386; Thu, 4 Jun 2026 05:08:47 +0000 (UTC) Received: from [HIDDEN] (Authenticated sender: joe@perches.com) by omf19.hostedemail.com (Postfix) with ESMTPA id E02E320025; Thu, 4 Jun 2026 05:08:44 +0000 (UTC) Message-ID: <8add4f780ec4861fba4e6bd77d50b384d32a642b.camel@perches.com> Subject: Re: [PATCH] checkpatch: Check WQ_PERCPU or WQ_UNBOUND presence in alloc_workqueue() users From: Joe Perches To: Marco Crivellari , linux-kernel@vger.kernel.org Cc: Andy Whitcroft , Dwaipayan Ray , Lukas Bulwahn , Tejun Heo , Frederic Weisbecker , Michal Hocko , Breno Leitao Date: Wed, 03 Jun 2026 22:08:43 -0700 In-Reply-To: <20260603140941.320063-1-marco.crivellari@suse.com> References: <20260603140941.320063-1-marco.crivellari@suse.com> Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable User-Agent: Evolution 3.58.3 (3.58.3-1.fc43) Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Stat-Signature: nopbmggpx7fngngdxz8omrzw3f75165a X-Rspamd-Server: rspamout08 X-Rspamd-Queue-Id: E02E320025 X-Session-Marker: 6A6F6540706572636865732E636F6D X-Session-ID: U2FsdGVkX1921NZOipwPfTZveZrFu/FsSY7rtSnldDk= X-HE-Tag: 1780549724-810189 X-HE-Meta: U2FsdGVkX1/TjDUJfFmaUzTfZj0W9ocerJSZPq2Yqxs/WU9TVum/WfNfImJM38Ntr1aWJCFmPkU2mXMasefdHpg9e7DgTDAL7M2VGeREuExVFkjVHmlA/Vpl4ssND52D2lQ9UpwP+BfdpUF8vQIpRMPgrzPbAibFZnr/ISVMPyCXkER+3ZCwrF8TE+Ak5SBAKyDt4NMWfgKjSO00acRo9EywAHwV6lozhVWsKuSmxffl39f241PDfvWyj2hGoc4eL9KmIUuHMm2hxV031Mk9BMwXeTjeAK2z3AeWJCsbrsbqmC00I3rTncy1KrVchoxh On Wed, 2026-06-03 at 16:09 +0200, Marco Crivellari wrote: > The workqueue API introduced a new flag, WQ_PERCPU, that has to be used w= hen > WQ_UNBOUND is not present. One of these flags must be present, but not > both of them. >=20 > To limit usage mistakes, emit an ERROR if one of the below condition is m= et: > - alloc_workqueue() is called without WQ_PERCPU nor WQ_UNBOUND > - alloc_workqueue() is called with both WQ_PERCPU and WQ_UNBOUND [] > diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl [] > @@ -7804,6 +7804,22 @@ sub process { > ERROR("UNINITIALIZED_PTR_WITH_FREE", > "pointer '$1' with __free attribute should be initialized\n" . = $herecurr); > } > + > +# check alloc_workqueue() flags parameter (2nd argument) for WQ_PERCPU, = WQ_UNBOUND presence > + if ($line =3D~ /\balloc_workqueue\s*\(/ && > + $stat =3D~ /\balloc_workqueue\s*\(\s*[^,]+\s*,\s*([^,]+)/s) { > + my $flags =3D $1; > + my $has_percpu =3D $flags =3D~ /\bWQ_PERCPU\b/; > + my $has_unbound =3D $flags =3D~ /\bWQ_UNBOUND\b/; > + > + if ($has_percpu && $has_unbound) { > + ERROR("ALLOC_WORKQUEUE_FLAGS", > + "alloc_workqueue() second parameter should not contain both WQ= _PERCPU and WQ_UNBOUND\n" . $herecurr); > + } elsif (!$has_percpu && !$has_unbound) { > + ERROR("ALLOC_WORKQUEUE_FLAGS", > + "alloc_workqueue() second parameter should specify either WQ_P= ERCPU or WQ_UNBOUND\n" . $herecurr); > + } > + } > } OK but a couple comments: Add devm_alloc_workqueue as well? Avoid using $line here as $stat isn't populated on multi-line uses of alloc_workqueue. Just test $stat Using the patch below gives a few matches treewide with a few false positives as the flags are stored in a variable in drivers/nvme/host/... and fs/btrfs/... ----------------- block/blk-zoned.c ----------------- ERROR: alloc_workqueue() must specify either WQ_PERCPU or WQ_UNBOUND #1926: FILE: block/blk-zoned.c:1926: + disk->zone_wplugs_wq =3D + alloc_workqueue("%s_zwplugs", WQ_MEM_RECLAIM | WQ_HIGHPRI, + pool_size, disk->disk_name); ----------------------------------------- drivers/gpu/drm/bridge/analogix/anx7625.c ----------------------------------------- ERROR: alloc_workqueue() must specify either WQ_PERCPU or WQ_UNBOUND #2851: FILE: drivers/gpu/drm/bridge/analogix/anx7625.c:2851: + platform->workqueue =3D alloc_workqueue("anx7625_work", + WQ_FREEZABLE | WQ_MEM_RECLAIM, 1); ------------------------------------- drivers/gpu/drm/nouveau/nouveau_drm.c ------------------------------------- ERROR: alloc_workqueue() must specify either WQ_PERCPU or WQ_UNBOUND #635: FILE: drivers/gpu/drm/nouveau/nouveau_drm.c:635: + drm->sched_wq =3D alloc_workqueue("nouveau_sched_wq_shared", 0, + WQ_MAX_ACTIVE); --------------------------------------- drivers/gpu/drm/nouveau/nouveau_sched.c --------------------------------------- ERROR: alloc_workqueue() must specify either WQ_PERCPU or WQ_UNBOUND #417: FILE: drivers/gpu/drm/nouveau/nouveau_sched.c:417: + wq =3D alloc_workqueue("nouveau_sched_wq_%d", 0, WQ_MAX_ACTIVE, + current->pid); ------------------------------------------ drivers/media/pci/ddbridge/ddbridge-core.c ------------------------------------------ ERROR: alloc_workqueue() must specify either WQ_PERCPU or WQ_UNBOUND #3433: FILE: drivers/media/pci/ddbridge/ddbridge-core.c:3433: + ddb_wq =3D alloc_workqueue("ddbridge", 0, 0); ------------------------------------- drivers/net/wireless/ath/ath6kl/usb.c ------------------------------------- ERROR: alloc_workqueue() must specify either WQ_PERCPU or WQ_UNBOUND #639: FILE: drivers/net/wireless/ath/ath6kl/usb.c:639: + ar_usb->wq =3D alloc_workqueue("ath6kl_wq", 0, 0); ------------------------ drivers/nvme/host/core.c ------------------------ ERROR: alloc_workqueue() must specify either WQ_PERCPU or WQ_UNBOUND #5410: FILE: drivers/nvme/host/core.c:5410: + nvme_wq =3D alloc_workqueue("nvme-wq", wq_flags, 0); ERROR: alloc_workqueue() must specify either WQ_PERCPU or WQ_UNBOUND #5414: FILE: drivers/nvme/host/core.c:5414: + nvme_reset_wq =3D alloc_workqueue("nvme-reset-wq", wq_flags, 0); ERROR: alloc_workqueue() must specify either WQ_PERCPU or WQ_UNBOUND #5418: FILE: drivers/nvme/host/core.c:5418: + nvme_delete_wq =3D alloc_workqueue("nvme-delete-wq", wq_flags, 0); --------------------- drivers/rapidio/rio.c --------------------- ERROR: alloc_workqueue() must specify either WQ_PERCPU or WQ_UNBOUND #1997: FILE: drivers/rapidio/rio.c:1997: + rio_wq =3D alloc_workqueue("riodisc", 0, 0); ------------------------------ drivers/thermal/thermal_core.c ------------------------------ ERROR: alloc_workqueue() must specify either WQ_PERCPU or WQ_UNBOUND #1892: FILE: drivers/thermal/thermal_core.c:1892: + thermal_wq =3D alloc_workqueue("thermal_events", WQ_POWER_EFFICIENT, 0); ------------------------- drivers/virt/acrn/irqfd.c ------------------------- ERROR: alloc_workqueue() must specify either WQ_PERCPU or WQ_UNBOUND #209: FILE: drivers/virt/acrn/irqfd.c:209: + vm->irqfd_wq =3D alloc_workqueue("acrn_irqfd-%u", 0, 0, vm->vmid); ------------------ fs/btrfs/disk-io.c ------------------ ERROR: alloc_workqueue() must specify either WQ_PERCPU or WQ_UNBOUND #1950: FILE: fs/btrfs/disk-io.c:1950: + fs_info->endio_workers =3D + alloc_workqueue("btrfs-endio", flags, max_active); ERROR: alloc_workqueue() must specify either WQ_PERCPU or WQ_UNBOUND #1952: FILE: fs/btrfs/disk-io.c:1952: + fs_info->endio_meta_workers =3D + alloc_workqueue("btrfs-endio-meta", flags, max_active); ERROR: alloc_workqueue() must specify either WQ_PERCPU or WQ_UNBOUND #1954: FILE: fs/btrfs/disk-io.c:1954: + fs_info->rmw_workers =3D alloc_workqueue("btrfs-rmw", flags, max_active); ---------------- fs/btrfs/scrub.c ---------------- ERROR: alloc_workqueue() must specify either WQ_PERCPU or WQ_UNBOUND #3050: FILE: fs/btrfs/scrub.c:3050: + scrub_workers =3D alloc_workqueue("btrfs-scrub", flags, max_active); --------------- fs/ntfs/super.c --------------- ERROR: alloc_workqueue() must specify either WQ_PERCPU or WQ_UNBOUND #2652: FILE: fs/ntfs/super.c:2652: + ntfs_wq =3D alloc_workqueue("ntfs-bg-io", 0, 0); --- scripts/checkpatch.pl | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index 0492d6afc9a1..aed83ce4b552 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -7804,6 +7804,31 @@ sub process { ERROR("UNINITIALIZED_PTR_WITH_FREE", "pointer '$1' with __free attribute should be initialized\n" . $h= erecurr); } + +# check alloc_workqueue() and devm_alloc_workqueue parameters for +# WQ_PERCPU and WQ_UNBOUND uses + if (defined($stat) && + $stat =3D~ /^[ \+]\s*(?:$Lval\s*=3D\s*)?((?:devm_)?alloc_workqueue)\= s*($balanced_parens)/) { + my $func =3D $1; + my $args =3D $2; + my $has_percpu =3D $args =3D~ /\bWQ_PERCPU\b/; + my $has_unbound =3D $args =3D~ /\bWQ_UNBOUND\b/; + my $error_msg; + + if ($has_percpu && $has_unbound) { + $error_msg =3D "$func() should not contain both WQ_PERCPU and WQ_UNBOU= ND\n"; + } elsif (!$has_percpu && !$has_unbound) { + $error_msg =3D "$func() must specify either WQ_PERCPU or WQ_UNBOUND\n"= ; + } + + if (defined($error_msg)) { + my $stmt_cnt =3D statement_rawlines($stat); + my $herectx =3D get_stat_here($linenr, $stmt_cnt, $here); + ERROR("ALLOC_WORKQUEUE_FLAGS", + $error_msg . $herectx); + } + + } } =20 # If we have no input at all, then there is nothing to report on