From nobody Tue Apr 7 18:00:32 2026 Received: from mail-ed1-f73.google.com (mail-ed1-f73.google.com [209.85.208.73]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 8E94138B135 for ; Thu, 12 Mar 2026 09:23:17 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.208.73 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773307399; cv=none; b=mpT5IwiVLhaF7f1p/SXynZXPANfoNBq5d/lKnlqI4mlvmI3zD0OBByhMivAcUgNSSvMGcBxD0J7rAS3S2KoRCQ1CABYKEMoStklCp4oRTliw5ajmeSozS5DuKq56uDcywNcjB9RwAOej49naFuyWciKpZjrthRpvVFXkKJvtcZQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773307399; c=relaxed/simple; bh=HGRaRGYIp/2I1VCTP2/AvId3YATUkkj6n4gXWOYzK4A=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=PgIKHxWcTHPmg02BCWH3QolkYW80+VvtHf7FnCxPd2z725PcS9Blwtur1BmOWYfEQRlTCCN3y6SZN+Jzywa8K3LLajNF1ri7AUDjftrxhD8lovwhCVu3Gs8ibIzxiTlqSdIWx2zeS/k9Ds1zGU4zQ0AKQ7kdRVqeEx+eOoNbZ2s= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--aliceryhl.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=eniJemST; arc=none smtp.client-ip=209.85.208.73 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--aliceryhl.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="eniJemST" Received: by mail-ed1-f73.google.com with SMTP id 4fb4d7f45d1cf-661cd3c9c0eso832535a12.0 for ; Thu, 12 Mar 2026 02:23:17 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1773307396; x=1773912196; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=g0tQd8FbPi346llSLS3fx1+p0t2zeeyNV0n8zJlO0zs=; b=eniJemST2Gsmooqqc7041e53b5huuLXPL4hpRcrysLW4+f/fgI17dgx0srlWkfkmrd wzI3M8ZuzyhZCcgNbup4rzfL1nb6nO+kolYYvVTWD0QWHestWSf16ga9BQWKdp0x7REO TdyfbiYe+c0KrPH7kKgOMssRO5Ajft3b4yVZM9NpLvyPnNPUfVwMR+VgT4UpbMasMXa6 F48lIHbYhltj+GZSliY+XAU2Yer5Op6Hz5UsksQeigu2c4kQPDDK871q+PwscJAyVgHB Niv3QUvS/1V0hXFn5Cj9cmkp3efTR/TPywnFlozOlH8EJgAceOETSDwssnCWe5hzNcH5 daJA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1773307396; x=1773912196; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=g0tQd8FbPi346llSLS3fx1+p0t2zeeyNV0n8zJlO0zs=; b=cvAwgd0YaW9inrVPOzVOsnHdr4qqCMvBorfDb3RJ74ShO4htcqghzH/4F/TPVMHZtY 2lhcRT7W/DvbMaKWHm5rRzSY3OJ0yBNMqIzZjxEJOcztCft1kV3nKPCwycl1IwbchOLQ IGZCaSjpUDVwtgt3ClwV7/1prat+62G7NORXtASRsvPaI7DtfQC/igIYTvHzn6gCZTT6 ogbHKa7JhzN1lpQEKu0NzBUQ+ftrO5tWhMbI1MH9SaeT927gzyL+W+ro09/tK/FwZCTY oeA0QpaFZ6W8xsB/rdCKmAFubfvpTgpW6cVpkMsWhTjuc+ASR1ZhmmW1bRAfs9crfk6X WjmA== X-Forwarded-Encrypted: i=1; AJvYcCWNpI7YXJB94urznUUOE0zsxWCBaLVjRI6Ly/o2BqVVXHUnneRVPpPSWcrQjAe2J98yuBz6TMRPXqi2XxU=@vger.kernel.org X-Gm-Message-State: AOJu0YyubpobJDnV7hl9bdlHTpZRa/TAuCwJfda1Dx7m4SyZj+t9Aj/y lyJ7t3GYPN9S5uhRFRSJcluxvVDa3af0ZrTZU4fJKdZO5to2M2zJD3rGgtEr/pYOXGya0a1+ZdO V6pYl/vlXZaW/ramagg== X-Received: from edsr1.prod.google.com ([2002:aa7:da01:0:b0:660:a402:c93b]) (user=aliceryhl job=prod-delivery.src-stubby-dispatcher) by 2002:a05:6402:3552:b0:662:ac65:19e1 with SMTP id 4fb4d7f45d1cf-66319bc7dc5mr3072407a12.12.1773307395717; Thu, 12 Mar 2026 02:23:15 -0700 (PDT) Date: Thu, 12 Mar 2026 09:23:02 +0000 In-Reply-To: <20260312-create-workqueue-v4-0-ea39c351c38f@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20260312-create-workqueue-v4-0-ea39c351c38f@google.com> X-Developer-Key: i=aliceryhl@google.com; a=openpgp; fpr=49F6C1FAA74960F43A5B86A1EE7A392FDE96209F X-Developer-Signature: v=1; a=openpgp-sha256; l=1759; i=aliceryhl@google.com; h=from:subject:message-id; bh=HGRaRGYIp/2I1VCTP2/AvId3YATUkkj6n4gXWOYzK4A=; b=owEBbQKS/ZANAwAKAQRYvu5YxjlGAcsmYgBpsoYA0cmDxCYMoHbbLy2sfHV5bUhhXB6n5BYTs mh0uOrhrLmJAjMEAAEKAB0WIQSDkqKUTWQHCvFIvbIEWL7uWMY5RgUCabKGAAAKCRAEWL7uWMY5 RjrsEACqk+IzvK1DPpswLCFP86Y69YbF8A/IaxxZ1r/SHlssFKn6BWjIO1fkaSbN63iqosgZsLd DHrmnuRegh1mEFjpQV4rL1GwUGtjja2A1+dZwbFrQLIAqfD95ZbDsCktBFRKlZFX8+qYObi+sjq wMgxpSad4Y9S4zInE76l0FMTkpLLB0oVYms3nysnpeALtcmfNwfy2FfcYVXUcwVX7/R7Tc/S8jf DHwG9ivrVB/UNwSa+alahlMhfdhy8HcJ1DgstbV94+ktLB5rdHjuZPhGPvjbNJStfyX1IzHt+u9 0Cc+beAZ+UPQG6i5c862V6KrtnNZo+Vw0VhU+vnH0EUPc4FELdZHXSYlxg116BWLa3sC6GCGEAf TW8uFtcIr3/RI/kCqxzQDwY8V1f+A83PVMxdJNCGZg+T/JAOLxvEjXyCJnfncd5b7yLeu2DWb2z 3fcTX2FH9xAgJcjF92vXN/zbbMVtY0MpQW2hp3NBD0wHfQLu2zWw/1LA1E50a+2w1pGZdMB+U3n k1liSerLDb1+dv7BtqxNqxqMRy/+h4aChYHn+3Ci2FnDBZrixrdL6U5TiIMIf+RBwMlZx7n1i8I 16Xw+2q13GpvS6VQe1tK0CzyvKcz5AV1toUtw6f1yO2uMvEQysreXRQriGqhygnvSq9Npi6T1zQ g6IXLDMPrNHjPSw== X-Mailer: b4 0.14.3 Message-ID: <20260312-create-workqueue-v4-1-ea39c351c38f@google.com> Subject: [PATCH v4 1/3] rust: workqueue: restrict delayed work to global wqs From: Alice Ryhl To: Tejun Heo , Miguel Ojeda Cc: Lai Jiangshan , Gary Guo , "=?utf-8?q?Bj=C3=B6rn_Roy_Baron?=" , Andreas Hindborg , Trevor Gross , Danilo Krummrich , Daniel Almeida , John Hubbard , Philipp Stanner , rust-for-linux@vger.kernel.org, linux-kernel@vger.kernel.org, Alice Ryhl , Boqun Feng , Benno Lossin , Tamir Duberstein , stable@vger.kernel.org Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable When a workqueue is shut down, delayed work that is pending but not scheduled does not get properly cleaned up, so it's not safe to use `enqueue_delayed` on a workqueue that might be destroyed. To fix this, restricted `enqueue_delayed` to static queues. This may be fixed in the future by an approach along the lines of [1]. Cc: stable@vger.kernel.org Fixes: 7c098cd5eaae ("workqueue: rust: add delayed work items") Reviewed-by: John Hubbard Reviewed-by: Danilo Krummrich Reviewed-by: Gary Guo Link: https://lore.kernel.org/r/20250423-destroy-workqueue-flush-v1-1-3d748= 20780a5@google.com [1] Signed-off-by: Alice Ryhl Reviewed-by: Andreas Hindborg --- rust/kernel/workqueue.rs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/rust/kernel/workqueue.rs b/rust/kernel/workqueue.rs index 706e833e9702..1acd113c04ee 100644 --- a/rust/kernel/workqueue.rs +++ b/rust/kernel/workqueue.rs @@ -296,8 +296,15 @@ pub fn enqueue(&self, w: W) -> W::En= queueOutput /// /// This may fail if the work item is already enqueued in a workqueue. /// + /// This is only valid for global workqueues (with static lifetimes) b= ecause those are the only + /// ones that outlive all possible delayed work items. + /// /// The work item will be submitted using `WORK_CPU_UNBOUND`. - pub fn enqueue_delayed(&self, w: W, delay: Jiffies) = -> W::EnqueueOutput + pub fn enqueue_delayed( + &'static self, + w: W, + delay: Jiffies, + ) -> W::EnqueueOutput where W: RawDelayedWorkItem + Send + 'static, { --=20 2.53.0.473.g4a7958ca14-goog From nobody Tue Apr 7 18:00:32 2026 Received: from mail-wr1-f74.google.com (mail-wr1-f74.google.com [209.85.221.74]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 623EE3B4EB5 for ; Thu, 12 Mar 2026 09:23:19 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.221.74 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773307400; cv=none; b=k1pcjHGGRSyJX93Q0dua4zsiudkjj+l/z2BKTVUfZFDSdjg/1RERFwDAKrjLHCydd420B9o2zWeB53ezfnam1i625rA2z7a0zxYN0cNqd5kxL2ETLeVKjsJ8BtD1uSMzshck9T5+/0o1KFUxiGTfgFDZvyf2IB+rSZ22qpMr/Is= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773307400; c=relaxed/simple; bh=Tr9+4ArZOZk2AagcvOQLIT+XXEMjOCbqhU+kgWpUMbQ=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=OleHOKUGKoBMqiYWKmhz9s4BBdtn7evdcUV4oh6x2YszouNcCrojdRhf792KAFRRQvZxpHqP2U8AKTpGAFd7VT5yMajI09k4o4lWVnT82/JikyYalD3PTlmiQIDIBB0PkbNWLtkkWYh6dPs5icgN39NCmPsu6m3p+L6v23XQ8Mo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--aliceryhl.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=M62tqwRN; arc=none smtp.client-ip=209.85.221.74 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--aliceryhl.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="M62tqwRN" Received: by mail-wr1-f74.google.com with SMTP id ffacd0b85a97d-439b8bc43aeso631761f8f.1 for ; Thu, 12 Mar 2026 02:23:19 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1773307398; x=1773912198; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=UBg/zFi7SrjD963r+qA/oZ5mO1M8DDxmkcgZtBd+URk=; b=M62tqwRNUZx0XvNogaSicSXfoIqSmt7peoV6w9oQowqwNZpoAVx9ExTTFAHTMVecSe 84gSY7hoin/1HZcg4U2eYkcGNK2cTnx1wei2j/cphcdTF8QZ3lKgKYNtxhKltYHvvAyr oV2VJ5s1wIK+WOGA4OJZQG/5ZkKbwIza0ygteYBicULCAteYzFbcDRZNEABnKmEwHc2b Vp/5C0h4Gxj3nsHs3orHBJ9NGK8AYuj6tQeNnmlPMkUiy2XPEjIsI6bKFMoYLrfyCDz2 d6IIxJ3TqtMBqy5rZdFrLOg/7aTEH8r3RS1/gvABjB8WgkXjOI8qyjV7MvEjC0lGBrSx PSKg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1773307398; x=1773912198; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=UBg/zFi7SrjD963r+qA/oZ5mO1M8DDxmkcgZtBd+URk=; b=EUvFfMkFd4oQaO+7CnhyNnzYBh3wjki/tXer7Aou3so4sogzFNy9Pce8fGU9oBD0QT b2aQ7Sgo4D0FtGyqkAwdKBQ5kaT5fxdaK/x+mr8i+HFz48Q0Vm+Weza1feih36omgrAe E5hnHVmU5uxkmQGz231jp/o2XlsgBZg+uwDZWTMGNaLJ16d4khznLdFm5Cg4LQKIzjTS HuTMuEUvZpJmfhxJlMOyyv1qbnju28its33TEzBZbgbbSPnGPHtNHJcHviTOib8x3uuH wZUU+60Et/ne7ni10fYoDzMlJKrCCu8B3Seuaz5zFD21RulS/inbkAwjhs+qHZmpmlYz dc+Q== X-Forwarded-Encrypted: i=1; AJvYcCWsZ71B5GY+Yvns0C66m1Qhsykw6rjqKWV7PDwgodhYHQXSwSmr8X3OpiA1RJLAU4TM9nurBFkctRvcluQ=@vger.kernel.org X-Gm-Message-State: AOJu0YxcASqUFaL9juP2zsNwRX7CqqKxWkje53bK7MXI2uXaAl8HQnk8 2473H1PzwuqePt85gCwtzeqi/o2Vqpx4fk62yvVDBLZVoF2rew1a+mW/Go6LY0nCozWZPF4btEj eOP+pVJ7abJ1DS9n2LA== X-Received: from wrbfy5.prod.google.com ([2002:a05:6000:2d85:b0:437:7338:c338]) (user=aliceryhl job=prod-delivery.src-stubby-dispatcher) by 2002:a05:6000:3112:b0:439:b744:c606 with SMTP id ffacd0b85a97d-439f8222e03mr10338047f8f.40.1773307397557; Thu, 12 Mar 2026 02:23:17 -0700 (PDT) Date: Thu, 12 Mar 2026 09:23:03 +0000 In-Reply-To: <20260312-create-workqueue-v4-0-ea39c351c38f@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20260312-create-workqueue-v4-0-ea39c351c38f@google.com> X-Developer-Key: i=aliceryhl@google.com; a=openpgp; fpr=49F6C1FAA74960F43A5B86A1EE7A392FDE96209F X-Developer-Signature: v=1; a=openpgp-sha256; l=947; i=aliceryhl@google.com; h=from:subject:message-id; bh=Tr9+4ArZOZk2AagcvOQLIT+XXEMjOCbqhU+kgWpUMbQ=; b=owEBbQKS/ZANAwAKAQRYvu5YxjlGAcsmYgBpsoYA9HEb7ZfNFFbmLOOPVm4+/zt0+YzwFUDuU hiDeNdGu7mJAjMEAAEKAB0WIQSDkqKUTWQHCvFIvbIEWL7uWMY5RgUCabKGAAAKCRAEWL7uWMY5 Rv34EACJndARE/ruUcol5qzH+F8IpKEVped6mowz8jgFU61HotTB+NXlc/ayxK6RosgrrG2bpLp j3fmi5jjl8c0REYgwi4G6dCsyUBo3kn4RRG8xIjxkeHbjPFbPP+1GIVUG4SmwkDs0XIADqTGgUb 7xt1pooJv/Rt7oa4/UChKtDs+OtAAT510wx7yDLKOHEFzwfkw2EXBTR514eEcffP8c8VYoVngSP ZI8FnxMHpS5npaJzMfcNWy51AWpGw4eouElv+O5EBbm4UOR8hwOpyuBwp6/j2RZ6+IS/g55OgqI lW44PJu88nposC2FaLkQUMPnzTGPefsGAArvAPzDB6/afWwwzHPnTP1cn/piley4gGaYlLGMF8k eDVCU8buWs4LOpHEeuzj+qUWtQPsrR5fOq3XAAbqWjYPRyNB6yVVbXwjR9Syf1oxUOZ9fJlSPBo 4Q3zOywwdLsBHh94kJS/oj+rRVJ8W0OPQtymcvZgSj4vea5GiParLomoCe/dmjO/YtmtMgReKoA mO5YW3plDDfHcbkasAFU1ADSG7MzPptxr2YZL2NqMzhaJEXb1vKscbi5kp/eG4d/yyc8ECLjH5c GlAdSa/TCbJ5oLpd+8LNA6FdSKnRwrQigvKKkL0WaKKtTkK5ofoFy9y5rmZlWEufGBzQFsPEnoC DOhFFOHQtVW5FZg== X-Mailer: b4 0.14.3 Message-ID: <20260312-create-workqueue-v4-2-ea39c351c38f@google.com> Subject: [PATCH v4 2/3] rust: workqueue: create workqueue subdirectory From: Alice Ryhl To: Tejun Heo , Miguel Ojeda Cc: Lai Jiangshan , Gary Guo , "=?utf-8?q?Bj=C3=B6rn_Roy_Baron?=" , Andreas Hindborg , Trevor Gross , Danilo Krummrich , Daniel Almeida , John Hubbard , Philipp Stanner , rust-for-linux@vger.kernel.org, linux-kernel@vger.kernel.org, Alice Ryhl , Boqun Feng , Benno Lossin , Tamir Duberstein Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable The following patch will implement a workqueue builder in a separate file. To prepare for that, create a rust/kernel/workqueue subdirectory and move the existing file. Signed-off-by: Alice Ryhl --- MAINTAINERS | 1 + rust/kernel/{workqueue.rs =3D> workqueue/mod.rs} | 0 2 files changed, 1 insertion(+) diff --git a/MAINTAINERS b/MAINTAINERS index 8fb7b70dfb47..8a12db6bd127 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -28511,6 +28511,7 @@ F: Documentation/core-api/workqueue.rst F: include/linux/workqueue.h F: kernel/workqueue.c F: kernel/workqueue_internal.h +F: rust/kernel/workqueue/ =20 WWAN DRIVERS M: Loic Poulain diff --git a/rust/kernel/workqueue.rs b/rust/kernel/workqueue/mod.rs similarity index 100% rename from rust/kernel/workqueue.rs rename to rust/kernel/workqueue/mod.rs --=20 2.53.0.473.g4a7958ca14-goog From nobody Tue Apr 7 18:00:32 2026 Received: from mail-wm1-f73.google.com (mail-wm1-f73.google.com [209.85.128.73]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 764573B7747 for ; Thu, 12 Mar 2026 09:23:20 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.73 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773307407; cv=none; b=mt1M3AI/LLpe1v7BM4z9NMolBL3IQ8ZvOrzQCJ1gL9ZvVzF53yYVARlCmTsoOuD2gwcbdi3+D24RZN8LxHfvoEhlaWKys+Y9X2nmT8TU2GpGMirZ/qVxmOIliebcAt82umYlT+PYoQQS4uXWpwtn+Cjyv71+LDMrkJlknZQyF0A= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773307407; c=relaxed/simple; bh=Njh07MuB7ze5MMilDqkmBUk983qNAK80TxHIdtvMZzY=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=XyBQB9gIRqiKXBUfjp5RfOV55KFcscTPDf4JKp1D5cY4aAIQmsows7n5puqGifmmhk5vIlhQ2jSiT5JpC/5pkzc93US0q/FT0h3TbKqOTBTjQxmnT7xMb64Q6qvixdaJ6kFiNLImst8FUSV1YTj3PKqONbtaqyID5cx3GcTA4Do= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--aliceryhl.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=xmHFVWp1; arc=none smtp.client-ip=209.85.128.73 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--aliceryhl.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="xmHFVWp1" Received: by mail-wm1-f73.google.com with SMTP id 5b1f17b1804b1-48532df52c5so6701495e9.1 for ; Thu, 12 Mar 2026 02:23:20 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1773307399; x=1773912199; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=BFJzMRfY/myRGsRdPPcQhPG3SwxOpi1cJEeNl8rz5ZY=; b=xmHFVWp191Wb0BxhA77LDrw5r4Y3V1O+mI3fEZNTeHlHlSSSusKEuJQSZasfzG70JK 1ToMp/fscCgo9gDNISOyuK8Rn7ji5A5q96DzxmW1TN81W8afdlFAzBTS7BmS6g9QGloL rqgRtNXTEzMxln1GBFZB8OFAYAuXaXzMSc55vJHn3oXi3ci18fRqtzA/zgcfiXuxGEr/ aeUpTz4i5UiYqXUydyDtFLDUktbyN1PsXSFE0MGOQ5lOhdGdru8ASPut1btn9/4llY/p e5Yf5cDg9NLQVAsr57YMy+FEESyFaWazZaQhrsclAIHgKJroqTD+gDgngscdOoTIzvE1 IWpA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1773307399; x=1773912199; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=BFJzMRfY/myRGsRdPPcQhPG3SwxOpi1cJEeNl8rz5ZY=; b=eg73j62Z//zOzywcp9HqGPQlo7sXWd5Y2NJSqw3ofz+nxwXQq+4pBRbz0nOyYdVuol 5EEdFILb9A1nkge3md8s9qyt24G/IVxO3KpRAo2OFXrDUXyZruxRqCvsYvDrE2KARpH1 ItFHYUvJ3aOXlBMz9XzRzgqV0wCdPhHucozxwcQpzkSo45ISYXEofiSqJPSmPvxwF0SJ RqCw9MBK/Adh/wzGlS8HLqWrw7o+ndpGxmm+Sgi5fy6IF8Hck2wQMurBIvenLR3VyPoA 8Z+tSJCqzcoRajuA9hnVTH4NfecsL/tKOLPOPWmHsOkjntLdE50sg2zTTjiIwuaS08EO 6sbg== X-Forwarded-Encrypted: i=1; AJvYcCWNMp/VmDr5LyIIZECusOj1DRovKJhxe5JIw0q5VhEuRFKXAjZVnzjFfbmfQP2scOy33eMB0bSdapXtMYc=@vger.kernel.org X-Gm-Message-State: AOJu0YwZx+YHYgsYmN+VUdzGCcm5Fpg053yBFnocApK1T4RKzkfzsi09 bGhR+S+4xA4NeIjaxY4+d7JDkMHsiWYrDylcLeBxWStBjHG6yHuDqnb+gXK9XEEhwSfx/RndPBx rh9qcVJsDSd82QZnz1Q== X-Received: from wmer1.prod.google.com ([2002:a05:600c:4341:b0:47f:c96e:8381]) (user=aliceryhl job=prod-delivery.src-stubby-dispatcher) by 2002:a05:600d:8488:10b0:485:4eaf:eb14 with SMTP id 5b1f17b1804b1-4854eafefa3mr45517535e9.21.1773307398868; Thu, 12 Mar 2026 02:23:18 -0700 (PDT) Date: Thu, 12 Mar 2026 09:23:04 +0000 In-Reply-To: <20260312-create-workqueue-v4-0-ea39c351c38f@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20260312-create-workqueue-v4-0-ea39c351c38f@google.com> X-Developer-Key: i=aliceryhl@google.com; a=openpgp; fpr=49F6C1FAA74960F43A5B86A1EE7A392FDE96209F X-Developer-Signature: v=1; a=openpgp-sha256; l=15283; i=aliceryhl@google.com; h=from:subject:message-id; bh=Njh07MuB7ze5MMilDqkmBUk983qNAK80TxHIdtvMZzY=; b=owEBbQKS/ZANAwAKAQRYvu5YxjlGAcsmYgBpsoYABjmTiX6dqsf5aOh4gdcYabBFgSwDXUAdz H1B/2oMh/KJAjMEAAEKAB0WIQSDkqKUTWQHCvFIvbIEWL7uWMY5RgUCabKGAAAKCRAEWL7uWMY5 Rmo9D/4rRb9dAzb/vfrw0PsGYp3Frf0ITwCbN6ndS7WH3gLoyehhIQMwo0aWVWBaSeBFEqFoKwU figbumYmYclb/NNzdNu65ybUqtYPjX/bzm5yXOaSa0UcDKz2emfjqX+N1Ez9AMf/wGsgO+E+Enb hPPlroHzWInEInrS0WoGUB8xtDy900XFK1rWV/2icG9AFvAOvyZHowSIJLpDRdheLQZrAxaEuXH 1in2S8S4tmYBXR38KuEvy5cPChH6Zlxd7WOSSAaQBkoJ0OM9+wVuk7jAmrgcA0KJYhiriAn3xzA IVWrDLGc8PhLRzbWlK7DUr/iijbL5HplqTJxKQoN5HmnhU3PSp8dKCqQaK2sput56bdVABKjBw5 dL5KFmN4nJfktAnXw0ARLqLX1WP0TPNsCRphk3EuD8OpwF8UhCR1KpuIOuqHUs3vyzqI8uCqSvs InAuHux4gGGeprGGsdMxHMtzDYlbO7zAfWsa4J9MQUfkP+B90RKo2zPNGjWjpbc1MZSh9HVR/xQ f3bAKxaMbHyO0EPqPT8diQ6+AXUQadIY12sMxBllHZVZ6Qp2weRNzN/d8WYPd/uONvLk83S6d3G Ml7AH8epmNDbZjGGqEFtAj++kAXtSuK/Q7IL7OPekual7rdYAIJ/2yR0mtun1k7i8yVIIguUgyu HUx0J+uvuVmZNBg== X-Mailer: b4 0.14.3 Message-ID: <20260312-create-workqueue-v4-3-ea39c351c38f@google.com> Subject: [PATCH v4 3/3] rust: workqueue: add creation of workqueues From: Alice Ryhl To: Tejun Heo , Miguel Ojeda Cc: Lai Jiangshan , Gary Guo , "=?utf-8?q?Bj=C3=B6rn_Roy_Baron?=" , Andreas Hindborg , Trevor Gross , Danilo Krummrich , Daniel Almeida , John Hubbard , Philipp Stanner , rust-for-linux@vger.kernel.org, linux-kernel@vger.kernel.org, Alice Ryhl , Boqun Feng , Benno Lossin , Tamir Duberstein Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Creating workqueues is needed by various GPU drivers. Not only does it give you better control over execution, it also allows devices to ensure that all tasks have exited before the device is unbound (or similar) by running the workqueue destructor. Signed-off-by: Alice Ryhl Reviewed-by: Andreas Hindborg --- rust/helpers/workqueue.c | 7 + rust/kernel/workqueue/builder.rs | 380 +++++++++++++++++++++++++++++++++++= ++++ rust/kernel/workqueue/mod.rs | 44 ++++- 3 files changed, 428 insertions(+), 3 deletions(-) diff --git a/rust/helpers/workqueue.c b/rust/helpers/workqueue.c index ce1c3a5b2150..e4b9d1b3d6bf 100644 --- a/rust/helpers/workqueue.c +++ b/rust/helpers/workqueue.c @@ -14,3 +14,10 @@ __rust_helper void rust_helper_init_work_with_key(struct= work_struct *work, INIT_LIST_HEAD(&work->entry); work->func =3D func; } + +__rust_helper +struct workqueue_struct *rust_helper_alloc_workqueue(const char *fmt, unsi= gned int flags, + int max_active, const void *data) +{ + return alloc_workqueue(fmt, flags, max_active, data); +} diff --git a/rust/kernel/workqueue/builder.rs b/rust/kernel/workqueue/build= er.rs new file mode 100644 index 000000000000..d4d77b96f9c4 --- /dev/null +++ b/rust/kernel/workqueue/builder.rs @@ -0,0 +1,380 @@ +// SPDX-License-Identifier: GPL-2.0 + +//! Workqueue builders. + +use kernel::{ + alloc::AllocError, + prelude::*, + workqueue::{ + OwnedQueue, // + Queue, + }, // +}; + +use core::{ + marker::PhantomData, // + ptr::{self, NonNull}, +}; + +/// Workqueue builder. +/// +/// A valid combination of workqueue flags contains one of the base flags = (`WQ_UNBOUND`, `WQ_BH`, +/// or `WQ_PERCPU`) and a combination of modifier flags that are compatibl= e with the selected base +/// flag. +/// +/// For details, please refer to `Documentation/core-api/workqueue.rst`. +pub struct Builder { + flags: bindings::wq_flags, + max_active: i32, + _type: PhantomData, +} + +pub enum TypeUnbound {} +pub enum TypePercpu {} +pub enum TypePowerEfficient {} +pub enum TypeBH {} +pub enum TypeOrdered {} + +/// Entry-points to the builder API. +impl Queue { + /// Build a workqueue whose work may execute on any cpu. + /// + /// # Examples + /// + /// ``` + /// use kernel::workqueue::Queue; + /// + /// let wq =3D Queue::new_unbound().build(c"my-wq")?; + /// wq.try_spawn(GFP_KERNEL, || pr_info!("Hello from unbound wq"))?; + /// # Ok::<(), Error>(()) + /// ``` + #[inline] + #[doc(alias =3D "WQ_UNBOUND")] + pub fn new_unbound() -> Builder { + Builder { + flags: bindings::wq_flags_WQ_UNBOUND, + max_active: 0, + _type: PhantomData, + } + } + + /// Build a workqueue whose work is bound to a specific cpu. + /// + /// # Examples + /// + /// ``` + /// use kernel::workqueue::Queue; + /// + /// let wq =3D Queue::new_percpu().build(c"my-wq")?; + /// wq.try_spawn(GFP_KERNEL, || pr_info!("Hello from percpu wq"))?; + /// # Ok::<(), Error>(()) + /// ``` + #[inline] + #[doc(alias =3D "WQ_PERCPU")] + pub fn new_percpu() -> Builder { + Builder { + flags: bindings::wq_flags_WQ_PERCPU, + max_active: 0, + _type: PhantomData, + } + } + + /// Build a power-efficient workqueue. + /// + /// # Examples + /// + /// ``` + /// use kernel::workqueue::Queue; + /// + /// let wq =3D Queue::new_power_efficient().build(c"my-wq")?; + /// wq.try_spawn(GFP_KERNEL, || pr_info!("Hello from power-efficient w= q"))?; + /// # Ok::<(), Error>(()) + /// ``` + #[inline] + #[doc(alias =3D "WQ_POWER_EFFICIENT")] + pub fn new_power_efficient() -> Builder { + Builder { + flags: bindings::wq_flags_WQ_POWER_EFFICIENT, + max_active: 0, + _type: PhantomData, + } + } + + /// Build a single-threaded workqueue that executes jobs in order. + /// + /// # Examples + /// + /// ``` + /// use kernel::workqueue::Queue; + /// + /// let wq =3D Queue::new_ordered().build(c"my-wq")?; + /// wq.try_spawn(GFP_KERNEL, || pr_info!("Hello from ordered wq"))?; + /// # Ok::<(), Error>(()) + /// ``` + #[inline] + #[doc(alias =3D "alloc_ordered_workqueue")] + #[doc(alias =3D "__WQ_ORDERED")] + pub fn new_ordered() -> Builder { + Builder { + flags: bindings::wq_flags_WQ_UNBOUND | bindings::wq_flags___WQ= _ORDERED, + max_active: 0, + _type: PhantomData, + } + } + + /// Build a workqueue that executes in bottom-half (softirq) context. + /// + /// # Examples + /// + /// ``` + /// use kernel::workqueue::Queue; + /// + /// let wq =3D Queue::new_bh().build(c"my-wq")?; + /// wq.try_spawn(GFP_KERNEL, || pr_info!("Hello from BH wq"))?; + /// # Ok::<(), Error>(()) + /// ``` + #[inline] + #[doc(alias =3D "WQ_BH")] + pub fn new_bh() -> Builder { + Builder { + flags: bindings::wq_flags_WQ_BH, + max_active: 0, + _type: PhantomData, + } + } +} + +/// Options that may be used with all workqueue types. +impl Builder { + /// Mark this workqueue high priority. + /// + /// # Examples + /// + /// ``` + /// use kernel::workqueue::Queue; + /// + /// let wq =3D Queue::new_unbound().highpri().build(c"my-wq")?; + /// wq.try_spawn(GFP_KERNEL, || pr_info!("Hello from highpri wq"))?; + /// # Ok::<(), Error>(()) + /// ``` + #[inline] + #[doc(alias =3D "WQ_HIGHPRI")] + pub fn highpri(mut self) -> Self { + self.flags |=3D bindings::wq_flags_WQ_HIGHPRI; + self + } + + /// Creates the workqueue. + /// + /// The provided name is used verbatim as the workqueue name. + /// + /// # Examples + /// + /// ``` + /// use kernel::workqueue::Queue; + /// + /// // create an unbound workqueue registered with sysfs + /// let wq =3D Queue::new_unbound().sysfs().build(c"my-wq")?; + /// + /// // spawn a work item on it + /// wq.try_spawn( + /// GFP_KERNEL, + /// || pr_warn!("Printing from my-wq"), + /// )?; + /// # Ok::<(), Error>(()) + /// ``` + #[inline] + #[doc(alias =3D "alloc_workqueue")] + pub fn build(self, name: &CStr) -> Result { + // SAFETY: + // * c"%s" is compatible with passing the name as a c-string. + // * the builder only permits valid flag combinations + let ptr =3D unsafe { + bindings::alloc_workqueue( + c"%s".as_char_ptr(), + self.flags, + self.max_active, + name.as_char_ptr().cast::(), + ) + }; + + // INVARIANT: We successfully created the workqueue, so we can ret= urn ownership to the + // caller. + Ok(OwnedQueue { + queue: NonNull::new(ptr).ok_or(AllocError)?.cast(), + }) + } + + /// Creates the workqueue. + /// + /// # Examples + /// + /// This example shows how to pass a Rust string formatter to the work= queue name, creating + /// workqueues with names such as `my-wq-1` and `my-wq-2`. + /// + /// ``` + /// use kernel::workqueue::{Queue, OwnedQueue}; + /// + /// fn my_wq(num: u32) -> Result { + /// // create a percpu workqueue called my-wq-{num} + /// let wq =3D Queue::new_percpu().build_fmt(fmt!("my-wq-{num}"))?; + /// Ok(wq) + /// } + /// ``` + #[inline] + pub fn build_fmt(self, name: kernel::fmt::Arguments<'_>) -> Result { + // SAFETY: + // * c"%pA" is compatible with passing an `Arguments` pointer. + // * the builder only permits valid flag combinations + let ptr =3D unsafe { + bindings::alloc_workqueue( + c"%pA".as_char_ptr(), + self.flags, + self.max_active, + ptr::from_ref(&name).cast::(), + ) + }; + + // INVARIANT: We successfully created the workqueue, so we can ret= urn ownership to the + // caller. + Ok(OwnedQueue { + queue: NonNull::new(ptr).ok_or(AllocError)?.cast(), + }) + } +} + +/// Indicates that this workqueue is threaded. +pub trait TypeThreaded {} +impl TypeThreaded for TypeUnbound {} +impl TypeThreaded for TypePercpu {} +impl TypeThreaded for TypePowerEfficient {} + +/// Options that are not available on BH or ordered workqueues. +impl Builder { + /// Set the maximum number of active cpus. + /// + /// If not set, a default value of `WQ_DFL_ACTIVE` is used. The maximu= m value is + /// `WQ_MAX_ACTIVE`. + /// + /// # Examples + /// + /// ``` + /// use kernel::workqueue::Queue; + /// + /// let wq =3D Queue::new_unbound().max_active(16).build(c"my-wq")?; + /// wq.try_spawn(GFP_KERNEL, || pr_info!("Hello from wq with max_activ= e=3D16"))?; + /// # Ok::<(), Error>(()) + /// ``` + #[inline] + pub fn max_active(mut self, max_active: u32) -> Self { + // If provided `max_active` is greater than `i32::MAX`, then we ne= ed to trigger the C-side + // comparison with `WQ_MAX_ACTIVE`, which we can do by clamping to= `i32::MAX`. + self.max_active =3D i32::try_from(max_active).unwrap_or(i32::MAX); + self + } + + /// Mark this workqueue as cpu intensive. + /// + /// # Examples + /// + /// ``` + /// use kernel::workqueue::Queue; + /// + /// let wq =3D Queue::new_unbound().cpu_intensive().build(c"my-wq")?; + /// wq.try_spawn(GFP_KERNEL, || pr_info!("Hello from cpu-intensive wq"= ))?; + /// # Ok::<(), Error>(()) + /// ``` + #[inline] + #[doc(alias =3D "WQ_CPU_INTENSIVE")] + pub fn cpu_intensive(mut self) -> Self { + self.flags |=3D bindings::wq_flags_WQ_CPU_INTENSIVE; + self + } + + /// Make this workqueue visible in sysfs. + /// + /// # Examples + /// + /// ``` + /// use kernel::workqueue::Queue; + /// + /// let wq =3D Queue::new_unbound().sysfs().build(c"my-wq")?; + /// wq.try_spawn(GFP_KERNEL, || pr_info!("Hello from sysfs wq"))?; + /// # Ok::<(), Error>(()) + /// ``` + #[inline] + #[doc(alias =3D "WQ_SYSFS")] + pub fn sysfs(mut self) -> Self { + self.flags |=3D bindings::wq_flags_WQ_SYSFS; + self + } +} + +/// Indicates that this workqueue runs in a normal context (as opposed to = softirq context). +pub trait TypeNormal {} +impl TypeNormal for TypeUnbound {} +impl TypeNormal for TypePercpu {} +impl TypeNormal for TypePowerEfficient {} +impl TypeNormal for TypeOrdered {} + +/// Options that are not available on BH workqueues. +impl Builder { + /// Allow this workqueue to be frozen during suspend. + /// + /// # Examples + /// + /// ``` + /// use kernel::workqueue::Queue; + /// + /// let wq =3D Queue::new_unbound().freezable().build(c"my-wq")?; + /// wq.try_spawn(GFP_KERNEL, || pr_info!("Hello from freezable wq"))?; + /// # Ok::<(), Error>(()) + /// ``` + #[inline] + #[doc(alias =3D "WQ_FREEZABLE")] + pub fn freezable(mut self) -> Self { + self.flags |=3D bindings::wq_flags_WQ_FREEZABLE; + self + } + + /// This workqueue may be used during memory reclaim. + /// + /// # Examples + /// + /// ``` + /// use kernel::workqueue::Queue; + /// + /// let wq =3D Queue::new_unbound().mem_reclaim().build(c"my-wq")?; + /// wq.try_spawn(GFP_KERNEL, || pr_info!("Hello from mem_reclaim wq"))= ?; + /// # Ok::<(), Error>(()) + /// ``` + #[inline] + #[doc(alias =3D "WQ_MEM_RECLAIM")] + pub fn mem_reclaim(mut self) -> Self { + self.flags |=3D bindings::wq_flags_WQ_MEM_RECLAIM; + self + } +} + +/// Options only available on a BH workqueue. +impl Builder { + /// Configure this BH workqueue to be percpu. + /// + /// To configure a non-BH percpu workqueue, use [`Queue::new_percpu`] = instead. + /// + /// # Examples + /// + /// ``` + /// use kernel::workqueue::Queue; + /// + /// let wq =3D Queue::new_bh().percpu().build(c"my-wq")?; + /// wq.try_spawn(GFP_KERNEL, || pr_info!("Hello from percpu BH wq"))?; + /// # Ok::<(), Error>(()) + /// ``` + #[inline] + #[doc(alias =3D "WQ_PERCPU")] + pub fn percpu(mut self) -> Self { + self.flags |=3D bindings::wq_flags_WQ_PERCPU; + self + } +} diff --git a/rust/kernel/workqueue/mod.rs b/rust/kernel/workqueue/mod.rs index 1acd113c04ee..6049c0e8e4b6 100644 --- a/rust/kernel/workqueue/mod.rs +++ b/rust/kernel/workqueue/mod.rs @@ -186,7 +186,10 @@ //! C header: [`include/linux/workqueue.h`](srctree/include/linux/workqueu= e.h) =20 use crate::{ - alloc::{AllocError, Flags}, + alloc::{ + self, + AllocError, // + }, container_of, prelude::*, sync::Arc, @@ -194,7 +197,14 @@ time::Jiffies, types::Opaque, }; -use core::marker::PhantomData; +use core::{ + marker::PhantomData, + ops::Deref, + ptr::NonNull, // +}; + +mod builder; +pub use self::builder::Builder; =20 /// Creates a [`Work`] initialiser with the given name and a newly-created= lock class. #[macro_export] @@ -340,7 +350,7 @@ pub fn enqueue_delayed( /// This method can fail because it allocates memory to store the work= item. pub fn try_spawn( &self, - flags: Flags, + flags: alloc::Flags, func: T, ) -> Result<(), AllocError> { let init =3D pin_init!(ClosureWork { @@ -353,6 +363,34 @@ pub fn try_spawn( } } =20 +/// An owned kernel work queue. +/// +/// Dropping a workqueue blocks on all pending work. +/// +/// # Invariants +/// +/// `queue` points at a valid workqueue that is owned by this `OwnedQueue`. +pub struct OwnedQueue { + queue: NonNull, +} + +impl Deref for OwnedQueue { + type Target =3D Queue; + fn deref(&self) -> &Queue { + // SAFETY: By the type invariants, this pointer references a valid= queue. + unsafe { &*self.queue.as_ptr() } + } +} + +impl Drop for OwnedQueue { + fn drop(&mut self) { + // SAFETY: This `OwnedQueue` owns a valid workqueue, so we can des= troy it. There is no + // delayed work scheduled on this queue that may attempt to use it= after this call, as + // scheduling delayed work requires a 'static reference. + unsafe { bindings::destroy_workqueue(self.queue.as_ptr().cast()) } + } +} + /// A helper type used in [`try_spawn`]. /// /// [`try_spawn`]: Queue::try_spawn --=20 2.53.0.473.g4a7958ca14-goog