From nobody Mon Jun 15 06:30:21 2026 Received: from mail-pj1-f54.google.com (mail-pj1-f54.google.com [209.85.216.54]) (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 7E44D3D1CD1 for ; Wed, 8 Apr 2026 14:00:45 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.216.54 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1775656846; cv=none; b=C3+vPFh9Up8XjtissXFZ5Ce30eAa03QulWbH9ab3cElVZ4mL8L0yvCl4z3dBoAAq+VW89EjsEy4+9ZTdhkuEAR/6h5PPu92sIIN0EKKT0I1j6t8uYObh/rFXJaC5eieSFo/ThfMG96yjsIo3YcIcv946K7kx7fl+tRc54qNhX6o= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1775656846; c=relaxed/simple; bh=Ajh1kH0EH04xoJ5hb4yQC9k86L0NK6LiOGqekq+uiwY=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=D6YKZvwy/3M4G/wSkSgG8Oy3lm1xdzrFDrBFQhHPHysrhWIQTgcJihAPtcmW5L+qJ+aTL1pog3ya9ykWGapJ7g57zdfxnPZUeP312+ZbFoP8e+C9H1RJWQkaFrqOObm9NyG4jtKitlmkA3eJIQs8QNB+RmbMOmqNzUCvn+fYMOc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=furiosa.ai; spf=none smtp.mailfrom=furiosa.ai; dkim=pass (1024-bit key) header.d=furiosa.ai header.i=@furiosa.ai header.b=jTmfBXcp; arc=none smtp.client-ip=209.85.216.54 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=furiosa.ai Authentication-Results: smtp.subspace.kernel.org; spf=none smtp.mailfrom=furiosa.ai Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=furiosa.ai header.i=@furiosa.ai header.b="jTmfBXcp" Received: by mail-pj1-f54.google.com with SMTP id 98e67ed59e1d1-35d971fb6f1so5451151a91.0 for ; Wed, 08 Apr 2026 07:00:45 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=furiosa.ai; s=google; t=1775656845; x=1776261645; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=vErTInlxRjeWcngKnHXzSGF2rVJW9g4tJWcacgmMs4Q=; b=jTmfBXcpDpNuL1stKo2hJ3wVIm9/QCK9P9WSujueIn5z5NCxESIt13qTKp3iB2cPbP oD15rHnkkDux6JxGXdDnL9gkA8Y8/+ZhA0KCDWEPB28H5Clf+gpo4+y05LKKLbbHdfOG Pe7ttJzJgkmeW2T3W3DLH2Mw6ex7zmbA8VQyc= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1775656845; x=1776261645; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=vErTInlxRjeWcngKnHXzSGF2rVJW9g4tJWcacgmMs4Q=; b=d0DA+APE4nhBIdY668X5keGjjnvpbGd8RFh7TO1uj115opnmU0yMCfxrPSosECSR7r TFNgXsKCr8SRAwv5Ps6WB604lA+xswWHnCuJeRmZNAd+pAAxa3TBXWLW8UH35fmC4vU6 WEFfPn0YQIp0yG/CGPQpUoBA35zn80cDY/7ODLbijjYArRqdwB7OA3WvwYnMevqs+7L4 2gDCJfdMOTSYzolbZIQIAKDydVxrujEkH1VDfCNUgt93KX/CXFE9f0IfWWie1RkcpKqH h+4TJE5I2sDTeNjnMhkeGLnucLdWIkSEq4sK9469mHux4DVvkfWRqjNbS+dJ++j8LdCZ OP2w== X-Forwarded-Encrypted: i=1; AJvYcCUuKxM+OYeQ6cZjbgkWH1jO6rNAbPaiyYPNx3kheA9cuDYXjb2T7xfGAMLrwYUMy7EQnY/bp4GMEx/Bls4=@vger.kernel.org X-Gm-Message-State: AOJu0Yx9tKs38IENN3lOStzYNSPTph/FppwGpKq1lpiWvkxY8zVfbDx9 3Z2TNTRMxDmUEP0e0FKqhR6O8Md8irWGZh3L1ErlckIb2ioYtQgupLhfC5VnbEctE4Y= X-Gm-Gg: AeBDievg5alKiiW/bi2qKBQZV3pk5x3/FA42fGS9NRx+B20V9JXDb3mQRj1Gqnz5/RN IkYzNHCp/ZMBtwABScZmSTJ01tF/vWsxLm7myU8WJne9OYcCUR7xsE1J5O9p7Vk1wnyswJZiRdI GJKTKtAOjHwkEVwXFgb0kY5RC7dYjayKZT+f2GfFJvH/QWO7PEl9xckuwhH2qZsCfrUe+JekWMG XIp4zN8Yk9Ahvf0lSG+CEkEkmYUkCS0MAlwD/Ehu7dAOtRx/MXxNTt7c1koXmd8FyVKdOz077LP xUxUWZUA9pLAE7IRh0c8UahyXBch9BuYKG3OwEbrvEmNqr4kEdLSkKWMTSQuJfpnGYq31I9w4e8 aYGpEp7jz+QK+g4HzKIUBlOUbJ/0Kd4QFMSugDdxi3wi6BBY0LBKw70zOx6spKwuhs4bB0U0Foj FgSahcj93lq5zHBNjYUKU0EH/wWwn6Z9w2AEV7pOUdnNgXhbedFAeoGaspKqA= X-Received: by 2002:a17:902:d2c8:b0:2b2:523f:50d with SMTP id d9443c01a7336-2b281802cacmr224321255ad.29.1775656844749; Wed, 08 Apr 2026 07:00:44 -0700 (PDT) Received: from sidong.sidong.yang.office.furiosa.vpn ([61.83.209.48]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-2b2747612b7sm204465145ad.23.2026.04.08.07.00.42 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 08 Apr 2026 07:00:44 -0700 (PDT) From: Sidong Yang To: Jens Axboe , Daniel Almeida , Caleb Sander Mateos , Benno Lossin Cc: Miguel Ojeda , Arnd Bergmann , Greg Kroah-Hartman , rust-for-linux@vger.kernel.org, linux-kernel@vger.kernel.org, io-uring@vger.kernel.org, Sidong Yang Subject: [PATCH v4 1/5] rust: bindings: add io_uring headers in bindings_helper.h Date: Wed, 8 Apr 2026 13:59:58 +0000 Message-ID: <20260408140007.8401-2-sidong.yang@furiosa.ai> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260408140007.8401-1-sidong.yang@furiosa.ai> References: <20260408140007.8401-1-sidong.yang@furiosa.ai> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" This patch adds two headers io_uring.h io_uring/cmd.h in bindings_helper for implementing rust io_uring abstraction. Signed-off-by: Sidong Yang --- rust/bindings/bindings_helper.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/rust/bindings/bindings_helper.h b/rust/bindings/bindings_helpe= r.h index faf3ee634ced..01f2c6044ae5 100644 --- a/rust/bindings/bindings_helper.h +++ b/rust/bindings/bindings_helper.h @@ -88,6 +88,8 @@ #include #include #include +#include +#include #include =20 /* --=20 2.43.0 From nobody Mon Jun 15 06:30:21 2026 Received: from mail-pl1-f179.google.com (mail-pl1-f179.google.com [209.85.214.179]) (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 67E1E3D3326 for ; Wed, 8 Apr 2026 14:00:48 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.179 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1775656849; cv=none; b=MTpeShRRvree2jTbcEZaVZLw1QTiL5C8mn5eJzVGLG+72q8lBpwvm1sgOjEFwaXO8KZh2t0Xz8AJE4ZDmiJo5v0q529L+iB6nIgRdJS66QfZd5IQhSqvueQHJDfY61EA31SHrBM4Ob0XHsxt1XYrDgaAAzQYsmKB7BwgZdeyzik= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1775656849; c=relaxed/simple; bh=9tIRZ7wtaK7vVXlVitnVin2aqh2a4oFAewRMzOPu3io=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=mHzXUXNM6juY9TWb0vL4ilPIH308gqkqChJbH6Dd4UGi70RDGlh76xRjXvfgUUrLNmHVaa0bfGxHsh3+s25o2JsrBfVOnZOzjWhDADxf36CwqUGbxHhSD2nFlB6mV6EB2+hAV+8OmRfB+YZ4y8t6lPcv6ZSG39rVU3p5idal+h4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=furiosa.ai; spf=none smtp.mailfrom=furiosa.ai; dkim=pass (1024-bit key) header.d=furiosa.ai header.i=@furiosa.ai header.b=BLapcAMZ; arc=none smtp.client-ip=209.85.214.179 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=furiosa.ai Authentication-Results: smtp.subspace.kernel.org; spf=none smtp.mailfrom=furiosa.ai Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=furiosa.ai header.i=@furiosa.ai header.b="BLapcAMZ" Received: by mail-pl1-f179.google.com with SMTP id d9443c01a7336-2ab232cc803so28698345ad.3 for ; Wed, 08 Apr 2026 07:00:48 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=furiosa.ai; s=google; t=1775656848; x=1776261648; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=Z26SDW5ZIR+r/lzeAq39TL8dqU+dlFU+cqs8ZAl7ag4=; b=BLapcAMZd/6hlxtqClOfZnV9LMlU2G2gvv2UC8HuQWQ6BVk5aBVKpzHLaQ56+s/Xvs ERK8jN4PQhHc1GKcJHdRGeGma9D4Zesd0CVOwc2q69SSvIOA+PTSWdjOArd+5vW9dH5Y l/wQLO4R7ejwPWGO5HOqbycAX8wPMKKcJ5xjs= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1775656848; x=1776261648; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=Z26SDW5ZIR+r/lzeAq39TL8dqU+dlFU+cqs8ZAl7ag4=; b=QsBu6ksK2y2Z1I8/7fHqVRCkIT/FeA4Eh/rpodsaWUy7JjWoYkvnzkDqYE3ROwU6xw ZRIvrr5yF8ghYVC350D7+1CIHv9j25i23Eq/8xckKFzfZ5XiUzrmsTm40bjKWJ7vXmzm 1WbTRvTsLIUlaaUDgFfeJUCYhcgwdyuxtEv6ylNrpUT/t2lTDmst1yuRKnWAAAY/fvEM 4vaQ6kSOZX7wfTscosiRGwmw1k5wW/h1eppRzH6B/IhyBGL5ypqAGZ4dcNgHJsg0ufTD MaJBAHJmfPYAVYcwUNT1WBvxctE9h0XM+x3TM7/HWSE2t9qiv2ErVMY+PkMMVqCDo43i 4Wsw== X-Forwarded-Encrypted: i=1; AJvYcCWDpNvvFM+1rqTqJNh6FYXoKPJZSfQwMeOquIieSRfssIaq1GWpXDgdZq5YKU1/omkMTTkIt7ZmgOpy4Oo=@vger.kernel.org X-Gm-Message-State: AOJu0Ywny8xJXyFtE2zRJNsOMV52xVncMLnBNI30q0xrF6SxEz+dpErl WKk5phtsJkJi+VUynEW+vui0tpNGjLcG4s++5qL7D8rVGe/rfqAkvZDm3GEbWzRha8s= X-Gm-Gg: AeBDietqnje1qKeJgfg04qtZXUD3ODDOKL0ngx6iKnNu39LtFNraNrRrzezKFYGGz+S wfwghzOggBDi+2T185b3yqG7KzGq932LZwRSa6kXne3RELyt1BYqfqymAGhq6JL0yEiDjQYpbAA +SmQ4Q1UoEStJHG1+BbKyaGAeZDao2Rn3sVOyv/9oSofvIvsNa/g0JqQsDrGv7PjEy4W/XM6m8+ k1H09OkKEVpb6sDXTMu3jAHzuZLfuwI+p4s1+IBlNET9gcdkjsR1MeFfI2S00yGs0J0XUA14jM/ dCne3s4fcVECGTYjLnNmrx/4tUVKusQqQvQ30ulQHh9RMZ3oIlvV044VufmPB/dKKacDJViFAVA yyrv2RqefPbxt4t8F5IBumM8XCeBvI3ShiEUDCWPDm6bNh5fMaAoCW/JV3WwYWamPjr15Wctwfo m9x5JhBJPGsGc8yT+LCUAxBZcu3kF5kjfd0uJlsuA9HK+Y85oyR/ICfXgbxozhS00nCnd73Q== X-Received: by 2002:a17:903:2c0d:b0:2b2:6cab:313c with SMTP id d9443c01a7336-2b281831e94mr231509005ad.20.1775656847482; Wed, 08 Apr 2026 07:00:47 -0700 (PDT) Received: from sidong.sidong.yang.office.furiosa.vpn ([61.83.209.48]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-2b2747612b7sm204465145ad.23.2026.04.08.07.00.45 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 08 Apr 2026 07:00:46 -0700 (PDT) From: Sidong Yang To: Jens Axboe , Daniel Almeida , Caleb Sander Mateos , Benno Lossin Cc: Miguel Ojeda , Arnd Bergmann , Greg Kroah-Hartman , rust-for-linux@vger.kernel.org, linux-kernel@vger.kernel.org, io-uring@vger.kernel.org, Sidong Yang Subject: [PATCH v4 2/5] io_uring/cmd: zero-init pdu in io_uring_cmd_prep() to avoid UB Date: Wed, 8 Apr 2026 13:59:59 +0000 Message-ID: <20260408140007.8401-3-sidong.yang@furiosa.ai> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260408140007.8401-1-sidong.yang@furiosa.ai> References: <20260408140007.8401-1-sidong.yang@furiosa.ai> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" The pdu field in io_uring_cmd may contain stale data when a request object is recycled from the slab cache. Accessing uninitialized or garbage memory can lead to undefined behavior in users of the pdu. Ensure the pdu buffer is cleared during io_uring_cmd_prep() so that each command starts from a well-defined state. This avoids exposing uninitialized memory and prevents potential misinterpretation of data from previous requests. No functional change is intended other than guaranteeing that pdu is always zero-initialized before use. Signed-off-by: Sidong Yang --- io_uring/uring_cmd.c | 1 + 1 file changed, 1 insertion(+) diff --git a/io_uring/uring_cmd.c b/io_uring/uring_cmd.c index ee7b49f47cb5..fa3a6f832460 100644 --- a/io_uring/uring_cmd.c +++ b/io_uring/uring_cmd.c @@ -209,6 +209,7 @@ int io_uring_cmd_prep(struct io_kiocb *req, const struc= t io_uring_sqe *sqe) if (!ac) return -ENOMEM; ioucmd->sqe =3D sqe; + memset(&ioucmd->pdu, 0, sizeof(ioucmd->pdu)); return 0; } =20 --=20 2.43.0 From nobody Mon Jun 15 06:30:21 2026 Received: from mail-pl1-f172.google.com (mail-pl1-f172.google.com [209.85.214.172]) (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 33FB03D348B for ; Wed, 8 Apr 2026 14:00:52 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.172 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1775656854; cv=none; b=IsUKymc6XSP9oPAUeAh/0JsLoMSssjGVysTDeQ14wyr4fWHEyD2Ycj9kfi3xABVUzgdv/9qlonjFh0vTX303K0ZAp5rgRNs5zr9vugg+N1G27IPjll8MduswdMqKlDnR249FOZKeWXgbxZaFNj5Yye2AN+CYjPFyZHUHfSJKEZc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1775656854; c=relaxed/simple; bh=Bchb8OzVWWyDh/mxawPxf0XTr5yVBhmm6JV3/UG9Hjc=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=R53cp5oDnOeBhcOg/s42uPZWaUo59aG82t8PtimGRnTpdDcRs8fOWEVR6/LbYXBky/5Xv3njkzjVaglugBSV02vc4jd19JHgH7u7gxVJ9tTmA+zShsaZMohbBptmn+sc4OEZ9s+Lr4/m6mtucmP/8+OUcJckJUu1LXBWmrSjYLI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=furiosa.ai; spf=none smtp.mailfrom=furiosa.ai; dkim=pass (1024-bit key) header.d=furiosa.ai header.i=@furiosa.ai header.b=hKj+NKWE; arc=none smtp.client-ip=209.85.214.172 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=furiosa.ai Authentication-Results: smtp.subspace.kernel.org; spf=none smtp.mailfrom=furiosa.ai Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=furiosa.ai header.i=@furiosa.ai header.b="hKj+NKWE" Received: by mail-pl1-f172.google.com with SMTP id d9443c01a7336-2b256a4c6b5so37282575ad.0 for ; Wed, 08 Apr 2026 07:00:52 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=furiosa.ai; s=google; t=1775656851; x=1776261651; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=Sz2N6F5rlh3/V10zDwXAUHPxGo/+h1EXIThAywxTIJM=; b=hKj+NKWEjaz370Ktjg83QD/hBlkFLE34X+Y4NPS4wViCd34KDUiM3hyUWuTBtMbZ3Z SfcazX/QB0cNUXw96di2LyTpJ2ezYtGsKKAAPM5QRDqzwMMXhhyW5a7/3PMcXCWBQkbX o/cTX68xudQR+sE9mf3pPT4aAyBcifiFzrkVo= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1775656851; x=1776261651; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=Sz2N6F5rlh3/V10zDwXAUHPxGo/+h1EXIThAywxTIJM=; b=nSk5+WvNks+72nIzbMnJcpJuNDI2/6UhlLTCBCRDL6gb0alKfTwVa6ePcgiLf/XM86 q8GuYvVr2ehEeDdAmGDgHcrmJC12SEooKmsuhSJfEzdldqC8hYOe/cY1oUcpImIj59G2 8bCOoAMhRRV1k6KaJqHrHjwND4CY8fw/nO0ElQ+hyBmnR290uVL8beeUrjyuXrZMPdBx jJ1zudI4X0ndJoNB/jctVdGo8rBkZFQ2EahyPXkJAwFfgqJse093acnVnc0NN9BNn3Oo lHGDL5D0QEtyJcxMu73k+TWp4wsGOrdms3H4Nd7LBmEMwosRUoUHC7MHG131lQ83bmgF ekvw== X-Forwarded-Encrypted: i=1; AJvYcCUBt/QKFBTw6w1Fiea4p/RdJKd8qMu8CUU3SEZ+OYHJqSis1zErAJRQpIKGdbG0sSl5hIJwF2J97Gddhww=@vger.kernel.org X-Gm-Message-State: AOJu0Yz40WyLv39NeHLd5DyctWNzsUCBvP3kb9+sj4OhdAEmC4hPT3d3 CwmoxPQu2XRA1LX04q9Vp+dIdw6Fl+c14Gd6CEtWXuVngVQFQka626bwgd05pXOcQO4= X-Gm-Gg: AeBDiesIZYZ7ELeAorwHhMalxXu0KV3lZ4j/HDD0V3+Z66TSzkfQ9c6SVbXFmq0cbRI Zr1MMANW5/ICDh8LuxqkTaxukQs8qc85YSM2g1+4s7gycxvZFVnzFTp6EEBDBNlp50TQp52C4QB GJRF3IbcShwdDVesUIyLszrtwCrtSwKVocCo5KcJOE06WhcGx/NSn4E834e0NlwDeTquxwzpc+9 8N8ebrgqyg7vYBCxdKBNBmEhjZPSy06q4jKaQFtwP2uAxcMhI1L3RDtEMyNpHkJj/AdtL2I8aUS xwOthlxrO2tFeoBEUjLQCZlVwUZdEsQoee2w0+v1iuvz2Vtquya/Tvf2vNMMre1GRL/b+J8LB8S NxffkP0qMyeN6xnv0tZVTrMA/rBTQiB6DQ/9iuPDsbsxtoJu6ieoxJyUGk/bdcULvQUrbjMauIy fhbTsUhuIQSKEU65YRr5kHcxhw4BG1zlA+jbQMoYaATzdEH1wM4IlJEhEAXUk= X-Received: by 2002:a17:902:ef08:b0:2b0:a957:304 with SMTP id d9443c01a7336-2b28163b7d3mr240742995ad.6.1775656850121; Wed, 08 Apr 2026 07:00:50 -0700 (PDT) Received: from sidong.sidong.yang.office.furiosa.vpn ([61.83.209.48]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-2b2747612b7sm204465145ad.23.2026.04.08.07.00.47 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 08 Apr 2026 07:00:49 -0700 (PDT) From: Sidong Yang To: Jens Axboe , Daniel Almeida , Caleb Sander Mateos , Benno Lossin Cc: Miguel Ojeda , Arnd Bergmann , Greg Kroah-Hartman , rust-for-linux@vger.kernel.org, linux-kernel@vger.kernel.org, io-uring@vger.kernel.org, Sidong Yang Subject: [PATCH v4 3/5] rust: io_uring: introduce rust abstraction for io-uring cmd Date: Wed, 8 Apr 2026 14:00:00 +0000 Message-ID: <20260408140007.8401-4-sidong.yang@furiosa.ai> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260408140007.8401-1-sidong.yang@furiosa.ai> References: <20260408140007.8401-1-sidong.yang@furiosa.ai> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Implement the io-uring abstractions needed for miscdevices and other char devices that have io-uring command interface. * `io_uring::IoUringCmd` : Rust abstraction for `io_uring_cmd` which will be used as arg for `MiscDevice::uring_cmd()`. And driver can get `cmd_op` sent from userspace. Also it has `flags` which includes option that is reissued. * `io_uring::IoUringSqe` : Rust abstraction for `io_uring_sqe` which can be obtained from `IoUringCmd::sqe()` and driver could get `cmd_data` from userspace. Also `IoUringSqe` has more data like opcode which can be = used in drivers. Signed-off-by: Sidong Yang --- rust/helpers/helpers.c | 1 + rust/helpers/io_uring.c | 9 + rust/kernel/io_uring.rs | 457 ++++++++++++++++++++++++++++++++++++++++ rust/kernel/lib.rs | 1 + 4 files changed, 468 insertions(+) create mode 100644 rust/helpers/io_uring.c create mode 100644 rust/kernel/io_uring.rs diff --git a/rust/helpers/helpers.c b/rust/helpers/helpers.c index e05c6e7e4abb..3fa2b3d9f83a 100644 --- a/rust/helpers/helpers.c +++ b/rust/helpers/helpers.c @@ -62,6 +62,7 @@ #include "irq.c" #include "fs.c" #include "io.c" +#include "io_uring.c" #include "jump_label.c" #include "kunit.c" #include "maple_tree.c" diff --git a/rust/helpers/io_uring.c b/rust/helpers/io_uring.c new file mode 100644 index 000000000000..818859867b34 --- /dev/null +++ b/rust/helpers/io_uring.c @@ -0,0 +1,9 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include + +__rust_helper void rust_helper_io_uring_cmd_done32(struct io_uring_cmd *cm= d, s32 ret, + u64 res2, unsigned int issue_flags) +{ + io_uring_cmd_done32(cmd, ret, res2, issue_flags); +} diff --git a/rust/kernel/io_uring.rs b/rust/kernel/io_uring.rs new file mode 100644 index 000000000000..adec60537cfb --- /dev/null +++ b/rust/kernel/io_uring.rs @@ -0,0 +1,457 @@ +// SPDX-License-Identifier: GPL-2.0 +// SPDX-FileCopyrightText: (C) 2025 Furiosa AI + +//! Abstractions for io-uring. +//! +//! This module provides abstractions for the io-uring interface for chara= cter devices. +//! +//! +//! C headers: [`include/linux/io_uring/cmd.h`](srctree/include/linux/io_u= ring/cmd.h) and +//! [`include/linux/io_uring/io_uring.h`](srctree/include/linux/io_uring/i= o_uring.h) + +use core::ptr::NonNull; + +use crate::error::from_result; +use crate::transmute::{AsBytes, FromBytes}; +use crate::{fs::File, types::Opaque}; + +use crate::prelude::*; + +/// Size in bytes of the protocol data unit (PDU) embedded in `io_uring_cm= d`. +/// +/// Matches the size of the `pdu` field in `struct io_uring_cmd` as define= d in +/// `include/linux/io_uring/cmd.h`. +pub(crate) const PDU_SIZE: usize =3D 32; + +/// Opcode of an [`IoUringSqe`]. +/// +/// Each submission queue entry in io_uring specifies an operation +/// to perform, such as read, write, or a driver-specific `URING_CMD`. +#[repr(transparent)] +#[derive(PartialEq)] +pub struct Opcode(u8); + +impl Opcode { + /// Driver-specific passthrough command. + pub const URING_CMD: Self =3D Self(bindings::io_uring_op_IORING_OP_URI= NG_CMD as u8); +} + +/// A fresh `io_uring_cmd` received from the driver callback. +/// +/// Represents a submission received from userspace via `IORING_OP_URING_C= MD`. +/// A driver obtains this from the `uring_cmd` callback in [`crate::miscde= vice::MiscDevice`]. +/// +/// The driver must either complete the command synchronously by calling +/// [`Self::complete`], or queue it for asynchronous completion by calling +/// [`Self::queue`], which yields a [`QueuedIoUringCmd`] handle. +/// +/// # Invariants +/// +/// `self.inner` is non-null, properly aligned, and points to a valid, live +/// `bindings::io_uring_cmd` for the duration of the driver callback. +pub struct IoUringCmd { + inner: NonNull, +} + +// SAFETY: `io_uring_cmd` is a kernel-allocated structure. The kernel +// guarantees that it remains alive until the driver either returns a +// non-`EIOCBQUEUED` result or calls `io_uring_cmd_done32()`. Moving the +// pointer to another thread is safe: the kernel object is not tied to any +// particular CPU or task context. +unsafe impl Send for IoUringCmd {} + +// SAFETY: All `&self` methods on `IoUringCmd` only read from the underlyi= ng +// `io_uring_cmd` (cmd_op, flags, sqe, file). `write_pdu` takes `&mut sel= f`, +// so the borrow checker prevents concurrent mutable access. Sharing +// `&IoUringCmd` across threads is therefore safe. +unsafe impl Sync for IoUringCmd {} + +/// An [`IoUringCmd`] that has been queued for asynchronous completion. +/// +/// The only way to obtain a `QueuedIoUringCmd` is through [`IoUringCmd::q= ueue`], +/// which ensures the command was properly handed off to the async path be= fore +/// [`UringCmdAction::Queued`] is returned to the vtable. +/// +/// Call [`Self::done`] exactly once to post the completion to userspace. +/// +/// # Invariants +/// +/// `self.inner` is non-null, properly aligned, and points to a valid, live +/// `bindings::io_uring_cmd` until [`Self::done`] is called. +pub struct QueuedIoUringCmd { + inner: NonNull, +} + +// SAFETY: Same reasoning as for `IoUringCmd`. After `queue()`, the handle= is +// intentionally moved to a different context (e.g. a workqueue) to call +// `done()` later. +unsafe impl Send for QueuedIoUringCmd {} + +// SAFETY: All `&self` methods on `QueuedIoUringCmd` only read from the +// underlying `io_uring_cmd`. +unsafe impl Sync for QueuedIoUringCmd {} + +/// Proof that a `uring_cmd` request completed synchronously. +pub struct CompleteAction { + ret: i32, +} + +impl CompleteAction { + /// Returns the userspace result for this synchronous completion. + #[inline] + pub fn ret(&self) -> i32 { + self.ret + } +} + +/// Proof that a `uring_cmd` request was queued for asynchronous completio= n. +/// +/// This type has a private field and can only be constructed inside this = module, +/// so it can only be obtained through [`IoUringCmd::queue`]. +pub struct QueuedAction { + _private: (), +} + +/// Completion mode for `uring_cmd`. +pub enum UringCmdAction { + /// Request is completed synchronously and returns this result to user= space. + Complete(CompleteAction), + /// Request is queued for asynchronous completion. + /// + /// This variant can only be constructed by calling [`IoUringCmd::queu= e`], + /// which enforces that the caller holds a [`QueuedIoUringCmd`] handle= and + /// will eventually call [`QueuedIoUringCmd::done`]. + Queued(QueuedAction), +} + +impl IoUringCmd { + /// Returns the `cmd_op` associated with this command. + #[inline] + pub fn cmd_op(&self) -> u32 { + // SAFETY: `self.inner` is guaranteed by the type invariant to poi= nt + // to a live `io_uring_cmd`, so dereferencing is safe. + unsafe { (*self.as_raw()).cmd_op } + } + + /// Returns the flags field of this command. + /// + /// The returned value is `io_uring_cmd.flags`, which is a combination= of: + /// - User-set flags from `sqe->uring_cmd_flags` (bits 0=E2=80=931): + /// `IORING_URING_CMD_FIXED`, `IORING_URING_CMD_MULTISHOT`. + /// - Kernel-set flags (bits 30=E2=80=9331): + /// `IORING_URING_CMD_CANCELABLE`, `IORING_URING_CMD_REISSUE`. + /// + /// Note: this is **not** the `issue_flags` parameter passed to the + /// `uring_cmd` callback, which carries `IO_URING_F_*` flags such as + /// `IO_URING_F_NONBLOCK`. + #[inline] + pub fn flags(&self) -> u32 { + // SAFETY: `self.inner` is guaranteed by the type invariant to poi= nt + // to a live `io_uring_cmd`, so dereferencing is safe. + unsafe { (*self.as_raw()).flags } + } + + /// Reads the protocol data unit (PDU) as a value of type `T`. + /// + /// # Errors + /// + /// Returns [`EINVAL`] if `size_of::()` exceeds the PDU size. + #[inline] + pub fn read_pdu(&self) -> Result { + // SAFETY: `self.inner` is guaranteed by the type invariant to poi= nt + // to a live `io_uring_cmd`, so dereferencing is safe. + let inner =3D unsafe { &*self.inner.as_ref() }; + + if size_of::() > inner.pdu.len() { + return Err(EINVAL); + } + + let ptr =3D inner.pdu.as_ptr() as *const T; + + // SAFETY: `ptr` is a valid pointer derived from `self.inner`, whi= ch + // is guaranteed by the type invariant. `size_of::()` bytes are + // available in the PDU (checked above). `read_unaligned` is used + // because the PDU is a byte array and may not satisfy `T`'s align= ment. + // `T: FromBytes` guarantees that every bit-pattern is a valid val= ue. + Ok(unsafe { core::ptr::read_unaligned(ptr) }) + } + + /// Writes `value` to the PDU of this command. + /// + /// # Errors + /// + /// Returns [`EINVAL`] if `size_of::()` exceeds the PDU size. + #[inline] + pub fn write_pdu(&mut self, value: &T) -> Result<()> { + // SAFETY: `self.inner` is guaranteed by the type invariant to poi= nt + // to a live `io_uring_cmd`, so dereferencing is safe. + let inner =3D unsafe { self.inner.as_mut() }; + + let len =3D size_of::(); + if len > inner.pdu.len() { + return Err(EINVAL); + } + + let src =3D (value as *const T).cast::(); + let dst =3D &raw mut inner.pdu as *mut u8; + + // SAFETY: + // * `src` points to valid memory because `T: AsBytes`. + // * `dst` is valid and derived from `self.inner`, which is guaran= teed + // by the type invariant. + // * The byte count does not exceed the PDU length (checked above). + unsafe { + core::ptr::copy_nonoverlapping(src, dst, len); + } + + Ok(()) + } + + /// Constructs an [`IoUringCmd`] from a raw pointer. + /// + /// # Safety + /// + /// The caller must guarantee that: + /// - `ptr` is non-null, properly aligned, and points to a valid, init= ialised + /// `bindings::io_uring_cmd`. + /// - The pointed-to object remains alive until the driver either retu= rns a + /// non-`EIOCBQUEUED` value or calls [`QueuedIoUringCmd::done`]. + /// - No other mutable reference to the same object exists for the dur= ation + /// of the returned handle's lifetime. + #[inline] + pub(crate) unsafe fn from_raw(ptr: *mut bindings::io_uring_cmd) -> Res= ult { + let Some(inner) =3D NonNull::new(ptr) else { + return Err(EINVAL); + }; + + Ok(Self { inner }) + } + + /// Returns a raw pointer to the underlying `io_uring_cmd`. + #[inline] + fn as_raw(&self) -> *mut bindings::io_uring_cmd { + self.inner.as_ptr() + } + + /// Returns the file associated with this command. + /// + /// The returned reference is valid for the lifetime of `&self`. The = kernel + /// holds a reference to the file for the entire lifetime of the enclo= sing + /// `io_kiocb`, so this is safe to call at any point while `IoUringCmd= ` is + /// alive. + #[inline] + pub fn file(&self) -> &File { + // SAFETY: `self.inner` is guaranteed by the type invariant to poi= nt + // to a live `io_uring_cmd`, so dereferencing is safe. + let file =3D unsafe { (*self.as_raw()).file }; + + // SAFETY: + // * The `io_kiocb` holds a reference to the file for its entire + // lifetime, so `file` is valid and has a positive refcount. + // * There is no active fdget_pos region on the file on this threa= d. + unsafe { File::from_raw_file(file) } + } + + /// Returns a reference to the [`IoUringSqe`] associated with this com= mand. + #[inline] + pub fn sqe(&self) -> &IoUringSqe { + // SAFETY: `self.inner` is guaranteed by the type invariant to poi= nt + // to a live `io_uring_cmd`, so dereferencing is safe. + let sqe =3D unsafe { self.inner.as_ref().sqe }; + // SAFETY: `sqe` is a valid pointer set by the io_uring core during + // submission queue entry preparation and remains valid for the li= fetime + // of the `io_uring_cmd`. + unsafe { IoUringSqe::from_raw(sqe) } + } + + /// Marks this command as completed synchronously with the provided re= turn value. + /// + /// The vtable will return `ret` directly to the io_uring core, which = posts + /// the completion queue entry. No further action is needed from the = driver. + #[inline] + pub fn complete(self, ret: i32) -> UringCmdAction { + UringCmdAction::Complete(CompleteAction { ret }) + } + + /// Queues this command for asynchronous completion. + /// + /// Returns a [`UringCmdAction::Queued`] token to return from the driv= er + /// callback and a [`QueuedIoUringCmd`] handle that must be used to ca= ll + /// [`QueuedIoUringCmd::done`] at a later point. + /// + /// Because [`QueuedAction`] has a private field, [`UringCmdAction::Qu= eued`] + /// can **only** be constructed through this method. This prevents a = driver + /// from accidentally returning `Queued` after already completing the = command + /// via `done()`. + #[inline] + pub fn queue(self) -> (UringCmdAction, QueuedIoUringCmd) { + let queued =3D QueuedIoUringCmd { inner: self.inner }; + (UringCmdAction::Queued(QueuedAction { _private: () }), queued) + } +} + +impl QueuedIoUringCmd { + /// Returns the `cmd_op` associated with this command. + #[inline] + pub fn cmd_op(&self) -> u32 { + // SAFETY: `self.inner` is guaranteed by the type invariant to poi= nt + // to a live `io_uring_cmd`, so dereferencing is safe. + unsafe { (*self.inner.as_ptr()).cmd_op } + } + + /// Returns the file associated with this command. + /// + /// See [`IoUringCmd::file`] for safety details. + #[inline] + pub fn file(&self) -> &File { + // SAFETY: Same as `IoUringCmd::file`. + let file =3D unsafe { (*self.inner.as_ptr()).file }; + // SAFETY: The `io_kiocb` holds a reference to the file for its en= tire + // lifetime, so `file` is valid and has a positive refcount. + unsafe { File::from_raw_file(file) } + } + + /// Reads the PDU as a value of type `T`. + /// + /// See [`IoUringCmd::read_pdu`] for details and error conditions. + #[inline] + pub fn read_pdu(&self) -> Result { + // SAFETY: `self.inner` is guaranteed by the type invariant to poi= nt + // to a live `io_uring_cmd`, so dereferencing is safe. + let inner =3D unsafe { &*self.inner.as_ref() }; + + if size_of::() > inner.pdu.len() { + return Err(EINVAL); + } + + let ptr =3D inner.pdu.as_ptr() as *const T; + + // SAFETY: Same as `IoUringCmd::read_pdu`. + Ok(unsafe { core::ptr::read_unaligned(ptr) }) + } + + /// Writes `value` to the PDU of this command. + /// + /// See [`IoUringCmd::write_pdu`] for details and error conditions. + #[inline] + pub fn write_pdu(&mut self, value: &T) -> Result<()> { + // SAFETY: `self.inner` is guaranteed by the type invariant to poi= nt + // to a live `io_uring_cmd`, so dereferencing is safe. + let inner =3D unsafe { self.inner.as_mut() }; + + let len =3D size_of::(); + if len > inner.pdu.len() { + return Err(EINVAL); + } + + let src =3D (value as *const T).cast::(); + let dst =3D &raw mut inner.pdu as *mut u8; + + // SAFETY: Same as `IoUringCmd::write_pdu`. + unsafe { + core::ptr::copy_nonoverlapping(src, dst, len); + } + + Ok(()) + } + + /// Posts the asynchronous completion to userspace. + /// + /// # Parameters + /// + /// - `ret`: Result to return to userspace. + /// - `res2`: Extra result word for `IORING_SETUP_CQE32` big-CQE rings; + /// pass `0` if not needed. + /// - `issue_flags`: The `issue_flags` value received by the `uring_cm= d` + /// callback; pass it through unchanged. + #[inline] + pub fn done(self, ret: Result, res2: u64, issue_flags: u32) { + let ret =3D from_result(|| ret); + // SAFETY: `self.inner` is a valid `io_uring_cmd` that was previou= sly + // queued (returned `EIOCBQUEUED` to io_uring). The kernel keeps = the + // `io_kiocb` alive until this call completes. + unsafe { + bindings::io_uring_cmd_done32(self.inner.as_ptr(), ret, res2, = issue_flags); + } + } +} + +/// A Rust abstraction for `io_uring_sqe`. +/// +/// Represents a Submission Queue Entry (SQE) that describes an I/O operat= ion +/// to be executed by the io_uring subsystem. Obtain an instance from +/// [`IoUringCmd::sqe`]. +/// +/// This type should not be constructed directly by drivers. +/// +/// # Invariants +/// +/// `self.inner` always points to a valid, live `bindings::io_uring_sqe`. +/// The `repr(transparent)` attribute guarantees the same memory layout as= the +/// underlying binding. +#[repr(transparent)] +pub struct IoUringSqe { + inner: Opaque, +} + +impl IoUringSqe { + /// Returns the opcode of this SQE. + pub fn opcode(&self) -> Opcode { + // SAFETY: `self.inner` guaranteed by the type invariant to point + // to a live `io_uring_sqe`, so dereferencing is safe. Volatile + // read is used because the SQE may reside in memory shared with + // userspace. + Opcode(unsafe { core::ptr::addr_of!((*self.inner.get()).opcode).re= ad_volatile() }) + } + + /// Reads the inline `cmd` data of this SQE as a value of type `T`. + /// + /// Only the standard `io_uring_sqe` layout is supported + /// (`IORING_SETUP_SQE128` is not handled here). + /// + /// # Errors + /// + /// Returns [`EINVAL`] if `size_of::()` exceeds the inline command = buffer. + pub fn cmd_data(&self) -> Result { + // SAFETY: `self.inner` guaranteed by the type invariant to point + // to a live `io_uring_sqe`, so dereferencing is safe. + let sqe =3D unsafe { &*self.inner.get() }; + + // SAFETY: Accessing the `sqe.cmd` union field is safe because + // `IoUringSqe` can only be obtained from `IoUringCmd::sqe()`, whi= ch + // is only available inside a `uring_cmd` callback where the opcode + // is guaranteed to be `IORING_OP_URING_CMD` by the io_uring core. + let cmd =3D unsafe { sqe.__bindgen_anon_6.cmd.as_ref() }; + let cmd_len =3D size_of_val(&sqe.__bindgen_anon_6.bindgen_union_fi= eld); + + if cmd_len < size_of::() { + return Err(EINVAL); + } + + let cmd_ptr =3D cmd.as_ptr() as *const T; + + // SAFETY: `cmd_ptr` is valid, derived from `self.inner` which is + // guaranteed by the type invariant. `read_unaligned` is used beca= use + // the cmd data may not satisfy `T`'s alignment requirements. + // `T: FromBytes` guarantees that every bit-pattern is a valid val= ue. + Ok(unsafe { core::ptr::read_unaligned(cmd_ptr) }) + } + + /// Constructs an [`IoUringSqe`] reference from a raw pointer. + /// + /// # Safety + /// + /// The caller must guarantee that: + /// - `ptr` is non-null, properly aligned, and points to a valid, init= ialised + /// `bindings::io_uring_sqe`. + /// - The pointed-to object remains valid for the entire lifetime `'a`. + /// - No mutable access to the same object occurs while the returned + /// reference is alive. + #[inline] + pub(crate) unsafe fn from_raw<'a>(ptr: *const bindings::io_uring_sqe) = -> &'a IoUringSqe { + // SAFETY: The caller guarantees that the pointer is not dangling = and + // stays valid for the duration of 'a. The cast is valid because + // `IoUringSqe` is `repr(transparent)` over `bindings::io_uring_sq= e`. + unsafe { &*ptr.cast() } + } +} diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs index 0fa9d820fe7c..235d1d03dde2 100644 --- a/rust/kernel/lib.rs +++ b/rust/kernel/lib.rs @@ -76,6 +76,7 @@ pub mod impl_flags; pub mod init; pub mod io; +pub mod io_uring; pub mod ioctl; pub mod iommu; pub mod iov; --=20 2.43.0 From nobody Mon Jun 15 06:30:21 2026 Received: from mail-pl1-f179.google.com (mail-pl1-f179.google.com [209.85.214.179]) (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 B07F63D3498 for ; Wed, 8 Apr 2026 14:00:53 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.179 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1775656856; cv=none; b=g9UOkGkMO0itiaWlS0MQUShrMqg5trv6G8YdPJL0vQAikrPg4cj3xlfRL+u43vplELU9IBVro6pIF5S0Pm6w/JhLMBNFGneTL3ElymPeceKPwf4hM6xCox9nxgYEWgSY/pa2Yx/qCaqBMml+OLzYtdoKQGd6PRhZfqgYuSl0RfA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1775656856; c=relaxed/simple; bh=qJPvaTDkdQnF6GB2/DJhWc0YSkNmMUsm38EVHAmFNn0=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=piSojuMLz8YuaAIzJJKI94C2oWkhR1DzPfQ3geszIXys43zCEELITMX+zq/CUonLODSMmVI+C3Uf2WtTZTbT1bxKhVk5lVjLbKbmfBdqlQ2hYo+R1WAVE+tTW41uHqZ4M97+2NqCZlwubyWMxqYc9ZGT8VtDHiIdc7GjmSax7ng= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=furiosa.ai; spf=none smtp.mailfrom=furiosa.ai; dkim=pass (1024-bit key) header.d=furiosa.ai header.i=@furiosa.ai header.b=PNlUV+I+; arc=none smtp.client-ip=209.85.214.179 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=furiosa.ai Authentication-Results: smtp.subspace.kernel.org; spf=none smtp.mailfrom=furiosa.ai Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=furiosa.ai header.i=@furiosa.ai header.b="PNlUV+I+" Received: by mail-pl1-f179.google.com with SMTP id d9443c01a7336-2b2589c26e3so55795945ad.1 for ; Wed, 08 Apr 2026 07:00:53 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=furiosa.ai; s=google; t=1775656853; x=1776261653; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=cb7E2CfVk9owGcBqZvU+iKSSUuaUHhRXNpFRwID2YDM=; b=PNlUV+I+Ca1UNcyqt0hxPVFYhnCySXEzJPFi+swiEGQ+qJ8KFOmPDTNWVPnYhWGoSW L41DtRrz+bdKjyEvwLOCMEXdtEsI3QQelaUHzJyaxu4wTlV6E1FtQ59WQxaTUkMgQEHI sZweFaK25pN9SmFWt+Ep29O58KKbVWf0Dgcjw= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1775656853; x=1776261653; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=cb7E2CfVk9owGcBqZvU+iKSSUuaUHhRXNpFRwID2YDM=; b=hmjYzGSDeTQG9HamICJSxHuw78QYWGPAZ+OUjJqpy4jeNtXodUvZyxivTHu5K59bUq dUiEGioJa+7AXdgK9aeuNKTpeDjRG+BnGMSyFyhjbbZ+TAWF0Hxj4UrwZatL26fWcOAy PeNk83P6ZPGqt03msPvRfINU2+ON8/DZgYmeTIMu9xiPRdGaIwPt6uBNdNwIq/2vPEvw PTZOcV1cDlNb/jfQjw2bQoqsdJCe1bLNlTvQzcaPeAThE5EfIrou7hKsAF+cdaotYcvc k+0HjHLSbu+EPZS6jThQePqVjY6LJzSN40VJUravC0P9SJ6/PHgG7Tycbdyh5UYs4+8Z bGqQ== X-Forwarded-Encrypted: i=1; AJvYcCVmjDXzYGzsFSHNWdfeRXfIdkGNYEocaMlIZrVqhXhSTp2R7v8N5SKYb80RClSk4LaPB/QSo3UtqN0K/5k=@vger.kernel.org X-Gm-Message-State: AOJu0YzbtPM/rtgvBsgqIZ2X4fgB+szbQnWkF/1iyrjIKNFAlMVLVu9v njkszcxhGXJq4WGEg2KMAN5EwGVPqvH5Ee8J2qqMnNtfhFnZrxedKDnnBk8ZWNBLCHU= X-Gm-Gg: AeBDieuynLF14xPBTbwnwfEqmD70HzTinjD7Int3rGrG+21jGSrpDBVH52tFYNkpwqJ eUP25ZuvzTbkVMGJgJ5Fmeike1HNbVKwPttkvJPnu8rBTAuORYqcawPy+ZTpOu8fKYWxTGahk71 zqA5cnxpixpCR7WuiXsHTI0l4PoVjyrqVBe13+25hd/LKgi1rhvJ93/2UUGe7eJn59OsLEl2N/u 13KTuHfeEilpYYXREbziP2qmi8YN/8k0hAXChoP9upXIL6sboOdPjnrveksVRhs0GB6rW8T8FDJ 4rrAqvyGSJFNx9gVioDKf09fyBTdQIvEIWC2CuH0IsvrO9v1VzTT9vDV0wt0mnG4vjdUm2NQPVZ HmykMJogENvYcGhgbmS9RxgbGF/5ezLeyPHdgaoYIS+W3XQFEhInNahzcTNEn4taCWUJUDj2AwB ALxPYEAcTnD+R0qqF4GwjVz4yvehG2SvdbEHop/qACFfu3fj/9f6TWDJgQQM4= X-Received: by 2002:a17:903:2ec7:b0:2b0:4554:9c24 with SMTP id d9443c01a7336-2b2817a20e9mr224313505ad.32.1775656853111; Wed, 08 Apr 2026 07:00:53 -0700 (PDT) Received: from sidong.sidong.yang.office.furiosa.vpn ([61.83.209.48]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-2b2747612b7sm204465145ad.23.2026.04.08.07.00.50 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 08 Apr 2026 07:00:52 -0700 (PDT) From: Sidong Yang To: Jens Axboe , Daniel Almeida , Caleb Sander Mateos , Benno Lossin Cc: Miguel Ojeda , Arnd Bergmann , Greg Kroah-Hartman , rust-for-linux@vger.kernel.org, linux-kernel@vger.kernel.org, io-uring@vger.kernel.org, Sidong Yang Subject: [PATCH v4 4/5] rust: miscdevice: Add `uring_cmd` support Date: Wed, 8 Apr 2026 14:00:01 +0000 Message-ID: <20260408140007.8401-5-sidong.yang@furiosa.ai> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260408140007.8401-1-sidong.yang@furiosa.ai> References: <20260408140007.8401-1-sidong.yang@furiosa.ai> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" This patch introduces support for `uring_cmd` to the `miscdevice` framework. This is achieved by adding a new `uring_cmd` method to the `MiscDevice` trait and wiring it up to the corresponding `file_operations` entry. The `uring_cmd` function provides a mechanism for `io_uring` to issue commands to a device driver. The new `uring_cmd` method takes the device, an `IoUringCmd` object, and issue flags as arguments. The `IoUringCmd` object is a safe Rust abstraction around the raw `io_uring_cmd` struct. To enable `uring_cmd` for a specific misc device, the `HAS_URING_CMD` constant must be set to `true` in the `MiscDevice` implementation. Signed-off-by: Sidong Yang --- rust/kernel/miscdevice.rs | 79 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) diff --git a/rust/kernel/miscdevice.rs b/rust/kernel/miscdevice.rs index c3c2052c9206..7fe6021c2c96 100644 --- a/rust/kernel/miscdevice.rs +++ b/rust/kernel/miscdevice.rs @@ -14,6 +14,7 @@ error::{to_result, Error, Result, VTABLE_DEFAULT_ERROR}, ffi::{c_int, c_long, c_uint, c_ulong}, fs::{File, Kiocb}, + io_uring::{self, IoUringCmd, UringCmdAction}, iov::{IovIterDest, IovIterSource}, mm::virt::VmaNew, prelude::*, @@ -190,6 +191,29 @@ fn show_fdinfo( ) { build_error!(VTABLE_DEFAULT_ERROR) } + + /// Handler for `uring_cmd`. + /// + /// Invoked when userspace submits an `IORING_OP_URING_CMD` entry to t= he + /// io-uring submission queue for a file backed by this driver. + /// + /// The driver must either complete the command synchronously by calli= ng + /// [`IoUringCmd::complete`] and returning `Ok(UringCmdAction::Complet= e(_))`, + /// or queue it for asynchronous completion by calling [`IoUringCmd::q= ueue`] + /// and returning `Ok(UringCmdAction::Queued(_))`. In the latter case= the + /// driver must eventually call [`crate::io_uring::QueuedIoUringCmd::d= one`] + /// to post the completion to userspace. + /// + /// `issue_flags` carries `IO_URING_F_*` flags (e.g. `IO_URING_F_NONBL= OCK`) + /// and should be forwarded to [`crate::io_uring::QueuedIoUringCmd::do= ne`] + /// unchanged when completing asynchronously. + fn uring_cmd( + _device: ::Borrowed<'_>, + _io_uring_cmd: IoUringCmd, + _issue_flags: u32, + ) -> Result { + build_error!(VTABLE_DEFAULT_ERROR) + } } =20 /// A vtable for the file operations of a Rust miscdevice. @@ -387,6 +411,56 @@ impl MiscdeviceVTable { T::show_fdinfo(device, m, file); } =20 + /// # Safety + /// + /// - The pointer `ioucmd` is not null and points to a valid `bindings= ::io_uring_cmd`. + unsafe extern "C" fn uring_cmd( + ioucmd: *mut bindings::io_uring_cmd, + issue_flags: ffi::c_uint, + ) -> c_int { + // SAFETY: `file` referenced by `ioucmd` is valid pointer. It's as= signed in + // uring cmd preparation. So dereferencing is safe. + let raw_file =3D unsafe { (*ioucmd).file }; + + // SAFETY: `private_data` is guaranteed that it has valid pointer = after + // this file opened. So dereferencing is safe. + let private =3D unsafe { (*raw_file).private_data }.cast(); + + // SAFETY: `ioucmd` is not null and points to valid memory `bindin= gs::io_uring_cmd` + // and the memory pointed by `ioucmd` is valid and will not be mov= ed or + // freed for the lifetime of returned value `ioucmd` + let ioucmd =3D unsafe { IoUringCmd::from_raw(ioucmd) }; + let mut ioucmd =3D match ioucmd { + Ok(ioucmd) =3D> ioucmd, + Err(e) =3D> { + return e.to_errno(); + } + }; + + // Zero-initialize the PDU for fresh (non-reissued) commands so th= at + // drivers reading from it always start from a clean state. On re= issue + // the PDU retains its contents from the previous attempt, which i= s the + // expected behaviour (e.g. a driver may store state there across + // -EAGAIN retries). + if (ioucmd.flags() & bindings::IORING_URING_CMD_REISSUE) =3D=3D 0 { + if let Err(e) =3D ioucmd.write_pdu(&[0u8; io_uring::PDU_SIZE])= { + return e.to_errno(); + } + } + + // SAFETY: This call is safe because `private` is returned by + // `into_foreign` in [`open`]. And it's guaranteed + // that `from_foreign` is called by [`release`] after the end of + // the lifetime of `device` + let device =3D unsafe { ::borrow(private= ) }; + + match T::uring_cmd(device, ioucmd, issue_flags) { + Ok(UringCmdAction::Complete(action)) =3D> action.ret(), + Ok(UringCmdAction::Queued(_)) =3D> EIOCBQUEUED.to_errno(), + Err(e) =3D> e.to_errno(), + } + } + const VTABLE: bindings::file_operations =3D bindings::file_operations { open: Some(Self::open), release: Some(Self::release), @@ -419,6 +493,11 @@ impl MiscdeviceVTable { } else { None }, + uring_cmd: if T::HAS_URING_CMD { + Some(Self::uring_cmd) + } else { + None + }, ..pin_init::zeroed() }; =20 --=20 2.43.0 From nobody Mon Jun 15 06:30:21 2026 Received: from mail-pg1-f181.google.com (mail-pg1-f181.google.com [209.85.215.181]) (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 12B3B3D3D07 for ; Wed, 8 Apr 2026 14:00:57 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.215.181 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1775656859; cv=none; b=oYgycUhr43wqvx6JqjI1zHn1JWl9n51XpirKKMXdtc31l96Ttzlkw9MmL+JkFjmlcnLay7X/f50HYewBoh4IeNsemnvCBkbjqM26/Q8hKGEzV9jfvVq4Hkfu1iPOoNuxZ/0QgTgTbw1OHHLcx8JKzcQdnxMwan1s+RlMY5P5GKg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1775656859; c=relaxed/simple; bh=1RUauL2RCVFelsgWteX9fUSv4uF/cElWij5jQkbisA4=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Xp1rDGK/BL+n4N2U3viruQcTLjbJimVmPv8kU36WunHEJUOj3TPlOFHjLSyy692/nkgkS5yuqAfVCn0JOAK7eVGg+wzQPS6/qoVMaBfokRfebmHN0FpDoAnqt1J9TQ9hMfO4lNa2Wpsph4PNNcuh9GEcOZe5MWnuUjBTqV32GU4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=furiosa.ai; spf=none smtp.mailfrom=furiosa.ai; dkim=pass (1024-bit key) header.d=furiosa.ai header.i=@furiosa.ai header.b=CetpzWbf; arc=none smtp.client-ip=209.85.215.181 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=furiosa.ai Authentication-Results: smtp.subspace.kernel.org; spf=none smtp.mailfrom=furiosa.ai Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=furiosa.ai header.i=@furiosa.ai header.b="CetpzWbf" Received: by mail-pg1-f181.google.com with SMTP id 41be03b00d2f7-c76af79f029so2577173a12.3 for ; Wed, 08 Apr 2026 07:00:57 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=furiosa.ai; s=google; t=1775656857; x=1776261657; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=vrpY2TRUYM3HpI2L60VlYb3B/Pcn97Bimqdq+op4nJ8=; b=CetpzWbfA8Q/tx2hmjRdyI3utdBF3O4M8YWcee1L0opioeYfO7iA6sUsbqLl63GS21 Yi2PR5JqiL14rNtcMa/k50flMyTNEsuyLLs/SMlRBlsHqQEJJbOsZ1wfVgQvaYKFzd/G pQsfivdVWBmwSrg/4x2ADdxt8GkDbvEU1TeWY= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1775656857; x=1776261657; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=vrpY2TRUYM3HpI2L60VlYb3B/Pcn97Bimqdq+op4nJ8=; b=AI5TXbFiW9OTtQ8/mPw6QAYQX6A7d5qS411ZjrPxa94jlT5D+KKGutetRLH+LcpFYW dIF9vZ9XLr917JVcTocyrg2ZsWQ/7iGYaLTdMuvNomHXEVKXDuFRA1G4Z7RL5lzhNLOo zfBm1OJTK3YHQqm1nfajQov+zKAj5i/Ef12SWic8/fW9W0Q6I0ah+h7LftI8UjXe6ihD diN5vEmaoiJWrNyOvCgsBslSXyFmsKn+Oqvx6qgNitoTBdHDgzfAIHJPg9VKs8naq/0U Tsr5pHKbyDWFjA87WEssk5U4UxOFAVikkqMT20ZrZRelBxYgmJTIxuHlr9Uz+PGJ85h6 jKHg== X-Forwarded-Encrypted: i=1; AJvYcCXTYsysVJ/htXQ6x4rBdxVNhiIBprq5a4j6C3Al0f8plsJf/JiEbKtUjHsdztdv/BLQWv2YXZo9LadN7qY=@vger.kernel.org X-Gm-Message-State: AOJu0Ywh/VufTmreVVoNeg5y9dingiOVNafdBsCSYfN3nZAPBMUO49Nb Tr+gw78xY0we+jMp2tioY86AxjbPQ1yLzsC/MHkBMTbeEtL1N/rjwfLgIa2NZJG2IJs= X-Gm-Gg: AeBDiethXjVgRN4LXLhlLdfAP+0HdL4ehuSuo+6mhQY52dQE9Kxi7y16kQo73h/OmJQ v9Y9y4hVGG+BkrXuLwd4qsMSObEsDv2TDra6AjChvrypV3JWwABePxHs3gmfihR6wAHJnFNIqJ+ 6vC16Giu3HifaiFt2vlvAvG9rypRkXilokrKqP7x/V3YOF4kRl+d0iR5mTLqQqcjHGbUtjKfhut TFk6BW9LjMAAyoE3//iOI0WTu90t+RSYr6h/wcI8oBINDTLEHE+ZWnLR1QkbKM4A7qy7yx/mwsV LYYCXZC3a/c8J65cJqCVIg6O9FIrzmhQ3xkbrntw1I/3ugmMHpkOTm0n9B9vlgDmwgCCH3zdEyq P57tatESkARGYbD8vCCr/cB2ZFWmrDFlGcgMHusWyE3gb6ginn7T9bvM++bnMv5t5YS8j7qeSaV 9XkXKdPe1Q+k/l5ZbaipgSCRb1wqIWudi2nMlEXPrAlAUjNmsQFGXgsZ/XJUA= X-Received: by 2002:a17:903:37ce:b0:2b2:4697:78f3 with SMTP id d9443c01a7336-2b2817b3469mr224774545ad.34.1775656857085; Wed, 08 Apr 2026 07:00:57 -0700 (PDT) Received: from sidong.sidong.yang.office.furiosa.vpn ([61.83.209.48]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-2b2747612b7sm204465145ad.23.2026.04.08.07.00.53 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 08 Apr 2026 07:00:55 -0700 (PDT) From: Sidong Yang To: Jens Axboe , Daniel Almeida , Caleb Sander Mateos , Benno Lossin Cc: Miguel Ojeda , Arnd Bergmann , Greg Kroah-Hartman , rust-for-linux@vger.kernel.org, linux-kernel@vger.kernel.org, io-uring@vger.kernel.org, Sidong Yang Subject: [PATCH v4 5/5] samples: rust: Add `uring_cmd` example to `rust_misc_device` Date: Wed, 8 Apr 2026 14:00:02 +0000 Message-ID: <20260408140007.8401-6-sidong.yang@furiosa.ai> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260408140007.8401-1-sidong.yang@furiosa.ai> References: <20260408140007.8401-1-sidong.yang@furiosa.ai> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" This patch extends the `rust_misc_device` sample to demonstrate how to use the `uring_cmd` interface for asynchronous device operations. The new implementation handles two `uring_cmd` operations: * `RUST_MISC_DEV_URING_CMD_SET_VALUE`: Sets a value in the device. * `RUST_MISC_DEV_URING_CMD_GET_VALUE`: Gets a value from the device. To use this new functionality, users can submit `IORING_OP_URING_CMD` operations to the `rust_misc_device` character device. Signed-off-by: Sidong Yang --- samples/rust/rust_misc_device.rs | 53 +++++++++++++++++++++++++++++++- 1 file changed, 52 insertions(+), 1 deletion(-) diff --git a/samples/rust/rust_misc_device.rs b/samples/rust/rust_misc_devi= ce.rs index 87a1fe63533a..ef506e8b26fe 100644 --- a/samples/rust/rust_misc_device.rs +++ b/samples/rust/rust_misc_device.rs @@ -98,13 +98,15 @@ use kernel::{ device::Device, fs::{File, Kiocb}, + io_uring::{IoUringCmd, QueuedIoUringCmd, UringCmdAction}, ioctl::{_IO, _IOC_SIZE, _IOR, _IOW}, iov::{IovIterDest, IovIterSource}, miscdevice::{MiscDevice, MiscDeviceOptions, MiscDeviceRegistration}, new_mutex, prelude::*, - sync::{aref::ARef, Mutex}, + sync::{Arc, aref::ARef, Mutex}, uaccess::{UserSlice, UserSliceReader, UserSliceWriter}, + workqueue::{impl_has_work, new_work, HasWork}, }; =20 const RUST_MISC_DEV_HELLO: u32 =3D _IO('|' as u32, 0x80); @@ -151,6 +153,42 @@ struct RustMiscDevice { dev: ARef, } =20 +#[pin_data] +struct IoUringCmdWork { + #[pin] + ioucmd: Mutex>, + #[pin] + work: kernel::workqueue::Work, +} + +impl_has_work! { + impl HasWork for IoUringCmdWork { self.work } +} + +impl kernel::workqueue::WorkItem for IoUringCmdWork { + type Pointer =3D Arc; + + fn run(work: Arc) { + pr_info!("IoUringCmdWork::run()"); + + if let Some((ioucmd, issue_flags)) =3D work.ioucmd.lock().take() { + ioucmd.done(Ok(0), 0, issue_flags); + } + } +} + +impl IoUringCmdWork { + fn new(ioucmd: QueuedIoUringCmd, issue_flags: u32) -> Result= > { + Arc::pin_init( + pin_init!(Self { + ioucmd <- new_mutex!(Some((ioucmd, issue_flags))), + work <- new_work!("IoUringCmdWork::work"), + }), + GFP_KERNEL, + ) + } +} + #[vtable] impl MiscDevice for RustMiscDevice { type Ptr =3D Pin>; @@ -220,6 +258,19 @@ fn ioctl(me: Pin<&RustMiscDevice>, _file: &File, cmd: = u32, arg: usize) -> Result =20 Ok(0) } + + fn uring_cmd( + me: Pin<&RustMiscDevice>, + ioucmd: IoUringCmd, + issue_flags: u32, + ) -> Result { + dev_info!(me.dev, "UringCmd Rust Misc Device Sample\n"); + + let (action, queued_ioucmd) =3D ioucmd.queue(); + let work =3D IoUringCmdWork::new(queued_ioucmd, issue_flags)?; + let _ =3D kernel::workqueue::system().enqueue(work); + Ok(action) + } } =20 #[pinned_drop] --=20 2.43.0