From patchwork Tue Feb 18 13:00:43 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andreas Hindborg X-Patchwork-Id: 13979795 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (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 E058C267384; Tue, 18 Feb 2025 13:01:59 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739883720; cv=none; b=GdjXfJnutD5JklMOojjRUoQBGtYr7i3wB94GRk7RlfzjQMniTOK+tPBtOdbTY9bDJQxgznp3mHRvfQxSzpXkBL3+GXqMDzFf4kcuE/G1BKjdUBbrr9M05r9ul4bTI+IOs/QuRoDhquIBmv3gxto+QjQuhe0fw7uJpFRPwtpey7Q= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739883720; c=relaxed/simple; bh=lS6k9hPNj5ZHeaqOmPt5Xc0PPaJv+8aNNMGM3N8QSTo=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=uC3zbTFdWr3zKrbRUJ0AH2vddn59oCJxf9M031MPnColRI8VzdHry8f/jLjLwqedfO6F3cn4oICzUMNCiq8xiDdGhTGY5yRffcO3ZFJRRQK2X4f5AqeCsMdKioIGXBI6KJAcm5Dkd7frxvjGfOUyFRaxp7z1lt9JLiYC50QjIuw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=GlY7DYCE; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="GlY7DYCE" Received: by smtp.kernel.org (Postfix) with ESMTPSA id E6ABAC4CEE9; Tue, 18 Feb 2025 13:01:53 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1739883719; bh=lS6k9hPNj5ZHeaqOmPt5Xc0PPaJv+8aNNMGM3N8QSTo=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=GlY7DYCElFeSE1cGN+qJy3aHo2lXVcV3vYt9isJq5UYFfMBOiwU5o1OXDyB1N3IaJ ujCrmOZEACDWmi3FfdgJBpfJWxk/gJRR+z7pJ9PoevcMSLTTWQpoJr2wqE0hmXoXok jNCo2XaQkJ1rOfagFkWXU91jqnva/nX9o4/dzKb0iiW7qsllbLjt8+LZbh0Wu1ny42 jRPo+WO/cyeBk998BJuR39efH0xc3/J8dXZGfnXRcNdF4mlwbfsiFcioqqDmcUMIJY rOQ7bmuFpHAAi+8K7TQ0OdN2Ua2PDepeayW2FOBGl2YMunv/w6k1PW09iLPPiiIP95 MF20q7+v0iGMw== From: Andreas Hindborg Date: Tue, 18 Feb 2025 14:00:43 +0100 Subject: [PATCH v7 1/6] rust: str: implement `PartialEq` for `BStr` Precedence: bulk X-Mailing-List: linux-kbuild@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20250218-module-params-v3-v7-1-5e1afabcac1b@kernel.org> References: <20250218-module-params-v3-v7-0-5e1afabcac1b@kernel.org> In-Reply-To: <20250218-module-params-v3-v7-0-5e1afabcac1b@kernel.org> To: Miguel Ojeda , Alex Gaynor , Boqun Feng , Gary Guo , =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= , Benno Lossin , Andreas Hindborg , Alice Ryhl , Trevor Gross , Masahiro Yamada , Nathan Chancellor , Nicolas Schier , Luis Chamberlain Cc: rust-for-linux@vger.kernel.org, linux-kernel@vger.kernel.org, Adam Bratschi-Kaye , linux-kbuild@vger.kernel.org, Petr Pavlu , Sami Tolvanen , Daniel Gomez , Simona Vetter , Greg KH , linux-modules@vger.kernel.org X-Mailer: b4 0.15-dev X-Developer-Signature: v=1; a=openpgp-sha256; l=795; i=a.hindborg@kernel.org; h=from:subject:message-id; bh=lS6k9hPNj5ZHeaqOmPt5Xc0PPaJv+8aNNMGM3N8QSTo=; b=owEBbQKS/ZANAwAIAeG4Gj55KGN3AcsmYgBntISDe/g9sj0qtbt2WFCID4SSMJX3DYZyfuuUT QXZjQuPOWuJAjMEAAEIAB0WIQQSwflHVr98KhXWwBLhuBo+eShjdwUCZ7SEgwAKCRDhuBo+eShj d2XPD/93ewjgG8o4eD29rjq3tsl1YoF8jH9rHpZbfe05bazj9tds5lmeyJ6Bx0JvpxG3fNNg7Bj 7hdIZXOxLtU+WOVZOlVwBMu55xyITFaGmpbLdsUSNJR3ddVXElRCCaRQxVYfUDwW7TTVAa/w9Mm BzxU4cW/+bEUe9ASbVsjLdomSufSpE6VC1kWAjfTooCNhoSnUUEZtYmFtksMUQM0KDFi861Pw+S LmIBgzSYJ1Q0RGNzHi11cf3qY7uOfK1pdYLlG5C6DJG5B1E53rV2JoBjRVJto3C3SN16SYg2AW3 SkSvBHhvnbk0Ri4PRFNUeiJ3U6E7oxnQwfTSrr63cVgJXEY6L1W0cf0UQwKdY+cVtRUgc79Opwz 3vcS3NApeTkWd9OBvn1fDbO6ATBiHZlYllYK2eSJgx9UKjFa4gjnWQs8tMmUcmOV17qsy71cvZI 01PpGc9Egw5whajMUyzRrFf19bsUrlH1zS4pW8yrXxJ3ZzqRQuWczTl3nWqeJdRdr34Yldjg6Ih NCRB/LIrHT/cAKnPD0wQhAgqlImLD0p+aOe5bhuwumldbVG5v9js5+w213C4tidw9IRyGDEfGjp mWAOkWW8zUa89pOpXPXSUvwSXbrpsJwCSCf8paYbS5fAGiNDP9PuimTG7OCIp9+ViZmRVK7w7Aj bvPCObLyp8Q5dig== X-Developer-Key: i=a.hindborg@kernel.org; a=openpgp; fpr=3108C10F46872E248D1FB221376EB100563EF7A7 Implement `PartialEq` for `BStr` by comparing underlying byte slices. Reviewed-by: Alice Ryhl Reviewed-by: Gary Guo Signed-off-by: Andreas Hindborg Reviewed-by: Daniel Almeida --- rust/kernel/str.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/rust/kernel/str.rs b/rust/kernel/str.rs index 28e2201604d67..002dcddf7c768 100644 --- a/rust/kernel/str.rs +++ b/rust/kernel/str.rs @@ -108,6 +108,12 @@ fn deref(&self) -> &Self::Target { } } +impl PartialEq for BStr { + fn eq(&self, other: &Self) -> bool { + self.deref().eq(other.deref()) + } +} + /// Creates a new [`BStr`] from a string literal. /// /// `b_str!` converts the supplied string literal to byte string, so non-ASCII From patchwork Tue Feb 18 13:00:44 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andreas Hindborg X-Patchwork-Id: 13979798 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (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 BE86F2690C6; Tue, 18 Feb 2025 13:02:27 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739883747; cv=none; b=otXaeZIIJrllOHYRvQ3afXYAOphpnrcqA70GYsZa/AX3/lj2Xvhl6lEWPfnfEPMmHPHWoB/lSAl4Hf1YHY2nFQHB/avAcBmHDD2w/7PXLMql3jm74NBaG3Xlgow1U0ggdC3qkk3ObA5F35FPgpMnBRa+riSGASI8sNnMzoDQzi0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739883747; c=relaxed/simple; bh=ZCtD1w7YciQFFZSg9uxP+oTq2EUuClmnZ/gBWrvvPTg=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=PGG8KBTsQG8rLrPm07YA3BmTsAfxrQUJwMJdjZbU91bUhsP82qTBp9aU23DXatwxdtzGhw9EBpVWUymJuV7s6bQqcK9wjCIFYHpI86wwFSGV4Xn2XpL6V8Iy99wW5CJMqQAWingQ9IqJV7iDPIaYBQkdJgqXzO5zo5nLF0tTamA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=Hc8jpvEj; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="Hc8jpvEj" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 65444C4CEE2; Tue, 18 Feb 2025 13:02:22 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1739883747; bh=ZCtD1w7YciQFFZSg9uxP+oTq2EUuClmnZ/gBWrvvPTg=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=Hc8jpvEjOzvH8zofHL/NU33O3IiAeILQb254yZjp8AGR44Yq6AQxgudANZg300XtK VAw6oSxZzE/iE+Z3m1pUWVrx5td+Dyj2/EUgDhutWc5roNmZ/WaahQdJeKJ7P+14HZ Otyobahlz/sLDoiHcQYWm1fJ5Kvja1OWDABOvGaV59ccykLUQ4MKI9x5mw6479ikJR gJftQPfAzcZZu/IM+bIFixjykQorP2n9VV65aigQnv+VMg6u6tlGOPL5VtT2jxakhw JKsr3gOuqwEm2JT66zFafLSF6KyZVyTRjq+6wCqzFRsU1e1wdZ7K0s8Hc5JLYF84HQ LzUGH98l4dskA== From: Andreas Hindborg Date: Tue, 18 Feb 2025 14:00:44 +0100 Subject: [PATCH v7 2/6] rust: str: implement `Index` for `BStr` Precedence: bulk X-Mailing-List: linux-kbuild@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20250218-module-params-v3-v7-2-5e1afabcac1b@kernel.org> References: <20250218-module-params-v3-v7-0-5e1afabcac1b@kernel.org> In-Reply-To: <20250218-module-params-v3-v7-0-5e1afabcac1b@kernel.org> To: Miguel Ojeda , Alex Gaynor , Boqun Feng , Gary Guo , =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= , Benno Lossin , Andreas Hindborg , Alice Ryhl , Trevor Gross , Masahiro Yamada , Nathan Chancellor , Nicolas Schier , Luis Chamberlain Cc: rust-for-linux@vger.kernel.org, linux-kernel@vger.kernel.org, Adam Bratschi-Kaye , linux-kbuild@vger.kernel.org, Petr Pavlu , Sami Tolvanen , Daniel Gomez , Simona Vetter , Greg KH , linux-modules@vger.kernel.org X-Mailer: b4 0.15-dev X-Developer-Signature: v=1; a=openpgp-sha256; l=965; i=a.hindborg@kernel.org; h=from:subject:message-id; bh=ZCtD1w7YciQFFZSg9uxP+oTq2EUuClmnZ/gBWrvvPTg=; b=owEBbQKS/ZANAwAIAeG4Gj55KGN3AcsmYgBntISElCXiUpM+MmkbzANn72kRTg4AcuhWu3gZZ rFV245EChqJAjMEAAEIAB0WIQQSwflHVr98KhXWwBLhuBo+eShjdwUCZ7SEhAAKCRDhuBo+eShj d1yPD/9E9Yw2ABuGs7zFFraasCJGLy4+kM5T/AA9gZkGY1miE7AcgIHPm0nG64h1pyZ75vLNBDL WrSl8XT9KTq6XOi7GixZRVAMvIh2zqTcCZE6FFp21Yrf7sbxTriFPKcRZk/Po2WuxNlC1wfcbBU wyp9UmMf6aAAABSDijVStgtWfN/OoT9HGaH+XroHO1oOaM8YSstv7oim6IYUtT/U7+KVtWeXpyU HzQh2SWDJSNi9LEG2VxcoDznC7GeuH4ixu9qVmNosjDV1DTqWFkOIE7XAbrfM0DqHcQpAfXDvZN /B4WHCSNsq/+lpqyXjAEqu5JkcbXsf0jQby8Ct4webRgNoJzwJFnSXWSfdUDnZ14bmkZht7zjZX IbABfRGrPeD3glM1CuZcwqAP5/ulpfPiMvM8/5/km5bJ/+U+JOcMLuotp0JjAJzQLY6vA6mOKtK k1V786i+RQwB91qHDDZqmRRVsFDdcE56BuhYOq19cIEz/93VKvTAFHSBHvxFiryV8Mg52n1MG1t ZmdICxzxAPiqFjzxXnoX4NHGZw5Pl+pnS05UGtItAu9TQgS55c74PJyEBit8Hlc6McqBQNRZ3Ch 5N9NSLx3ywDxRxbu287G3I+Jlo+bFH015MLEY/+5jizF1hhhzx5bcpUAaVJmM7yHSWyEWJX0dds NrZcjW+WWvpiTWg== X-Developer-Key: i=a.hindborg@kernel.org; a=openpgp; fpr=3108C10F46872E248D1FB221376EB100563EF7A7 The `Index` implementation on `BStr` was lost when we switched `BStr` from a type alias of `[u8]` to a newtype. This patch adds back `Index` by implementing `Index` for `BStr` when `Index` would be implemented for `[u8]`. Signed-off-by: Andreas Hindborg Reviewed-by: Daniel Almeida --- rust/kernel/str.rs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/rust/kernel/str.rs b/rust/kernel/str.rs index 002dcddf7c768..ba6b1a5c4f99d 100644 --- a/rust/kernel/str.rs +++ b/rust/kernel/str.rs @@ -114,6 +114,17 @@ fn eq(&self, other: &Self) -> bool { } } +impl Index for BStr +where + [u8]: Index, +{ + type Output = Self; + + fn index(&self, index: Idx) -> &Self::Output { + BStr::from_bytes(&self.0[index]) + } +} + /// Creates a new [`BStr`] from a string literal. /// /// `b_str!` converts the supplied string literal to byte string, so non-ASCII From patchwork Tue Feb 18 13:00:45 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andreas Hindborg X-Patchwork-Id: 13979796 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (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 1DEC2267384; Tue, 18 Feb 2025 13:02:05 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739883725; cv=none; b=p5iUbll8NK77+v01K0tUme3SNSmbJ2+Yf41LLESx5C0d7AnZFHPdR4a1M8E0zfR6T1pNO0dsNZLAG7wJAPzqRg1UN8+UgSsdbyNoMbCthPX8GdoU6shM8w3a3eT9ukyoEEILr0Om+QkR/EY91+2neGbJhQPEwyv6MStGM7826aE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739883725; c=relaxed/simple; bh=kvGbpK9kXJddOYZoiGF2djCA1EY8EEWP9GNQBrdAngE=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=bFGNIShWNqiBA0YfsOYhCs8euA07MO8w3gwxq1AUS6o/1f3KRhC4+JEAi35ylQOrNxpYh/Xm5snIpFQjDU4kAPITMLxC+q2JXygSfnc7BHqeQIzABX02NNCd3Ko2yMA5DSUMne375DzgCWDv9H6IQl5VE8ox2pY+zxz8clCNwS0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=D5Ie2UPL; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="D5Ie2UPL" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 0A968C4CEE2; Tue, 18 Feb 2025 13:01:59 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1739883725; bh=kvGbpK9kXJddOYZoiGF2djCA1EY8EEWP9GNQBrdAngE=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=D5Ie2UPLiPm48/it8g6AvmzcXhTWyR8yEwmD/nAM6fyxJvxdkKUrn8XOSOu+2Bb25 oxBA3b+SXz/5ZwvOmsH8k/ahIX0BPQ7sm69fDVnE1eyVoxMx2XIfVFyDxsXcmJl28f KaydLtAJan2g8LOOg3OCViaEZNw9U6Q1op8GF1sLNYBt7gFeFXpJHs+yjN26HyIR/z OzVPNnugcfcTGFqFFd4ZxkVuaCrrLzVKr49ILbq6DeHm5+lecKFsYXtWY3IB4V4KF7 kF3phVtiJhlF94m17q469/VlZ2/hhE0HGwito842HH/jfWhkwVsOCwB1jSdwBi6IUY ecGOqy5ICTRUA== From: Andreas Hindborg Date: Tue, 18 Feb 2025 14:00:45 +0100 Subject: [PATCH v7 3/6] rust: str: implement `AsRef` for `[u8]` and `BStr` Precedence: bulk X-Mailing-List: linux-kbuild@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20250218-module-params-v3-v7-3-5e1afabcac1b@kernel.org> References: <20250218-module-params-v3-v7-0-5e1afabcac1b@kernel.org> In-Reply-To: <20250218-module-params-v3-v7-0-5e1afabcac1b@kernel.org> To: Miguel Ojeda , Alex Gaynor , Boqun Feng , Gary Guo , =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= , Benno Lossin , Andreas Hindborg , Alice Ryhl , Trevor Gross , Masahiro Yamada , Nathan Chancellor , Nicolas Schier , Luis Chamberlain Cc: rust-for-linux@vger.kernel.org, linux-kernel@vger.kernel.org, Adam Bratschi-Kaye , linux-kbuild@vger.kernel.org, Petr Pavlu , Sami Tolvanen , Daniel Gomez , Simona Vetter , Greg KH , linux-modules@vger.kernel.org X-Mailer: b4 0.15-dev X-Developer-Signature: v=1; a=openpgp-sha256; l=844; i=a.hindborg@kernel.org; h=from:subject:message-id; bh=kvGbpK9kXJddOYZoiGF2djCA1EY8EEWP9GNQBrdAngE=; b=owEBbQKS/ZANAwAIAeG4Gj55KGN3AcsmYgBntISFZJsHCDQ/fYrSsdwC6D0joyKK16I5hZxcv 1WrTIW05g2JAjMEAAEIAB0WIQQSwflHVr98KhXWwBLhuBo+eShjdwUCZ7SEhQAKCRDhuBo+eShj d9LlD/9AXD7x+fgK0eDF7+5eqzztOc9cyUmJRsa9caJUaZMK20kNv9/Wu8gi72DfGynreTyx1Am M+PywlvqQmQmf5njTmNkD0zRuDyCH/vJYmPKdHoe8Qt5CLVc0eKfLwQC0/A34I5l3GQB9YknLxt T7Psf5O5u/mNbckCCLOv8JAjzXBRQL9XV0pZsXBKG9IHaen/bk93lREws+biXEh2Y2RTJ8VEteF ZjxncX+FoFH5btwW1Viu/LrFYfOs/ufFvHhyHX4umcf0CH5cLqWsOoqzEWNtnqLk8StgT2cTwG0 B3HSXpmfNfy19yK3PFnvbmlMeFIO2pYcgqZ72n0IksJwiJJXLyOmz6/8sDqHYskpCoIx0flB1Wa Oe1owSXt2JotwiKJqnU3Ta3CX9zWTo5IgyRhlId8i5bT3rIwbv18vWPixwn13S6GvhPoec0VM1g iIvJ6xAOBipHc7vytgV/D0fNQ+6Mkzumseoq4uLYmZXMboAAyxai/QKf5zZExQh4453ie/tHViV eKB9m2dIIgkJ9t/1JXq1B0VVVtdcpnGqcOAzLGynE8HCMWcxLtHHZQce/SXWFDdObg2oLO7EVEN GLqrVTLoo5HUu23PDTZelJ0ZBO+BJoWLUIqT89n80pnJjmu9wxixM/IuO4Hdtiq32vZaKmBokZ4 sLbGNo0ugaCCgCw== X-Developer-Key: i=a.hindborg@kernel.org; a=openpgp; fpr=3108C10F46872E248D1FB221376EB100563EF7A7 Implement `AsRef` for `[u8]` and `BStr` so these can be used interchangeably for operations on `BStr`. Signed-off-by: Andreas Hindborg Reviewed-by: Daniel Almeida Reviewed-by: Gary Guo --- rust/kernel/str.rs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/rust/kernel/str.rs b/rust/kernel/str.rs index ba6b1a5c4f99d..c6bd2c69543dc 100644 --- a/rust/kernel/str.rs +++ b/rust/kernel/str.rs @@ -125,6 +125,18 @@ fn index(&self, index: Idx) -> &Self::Output { } } +impl AsRef for [u8] { + fn as_ref(&self) -> &BStr { + BStr::from_bytes(self) + } +} + +impl AsRef for BStr { + fn as_ref(&self) -> &BStr { + self + } +} + /// Creates a new [`BStr`] from a string literal. /// /// `b_str!` converts the supplied string literal to byte string, so non-ASCII From patchwork Tue Feb 18 13:00:46 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andreas Hindborg X-Patchwork-Id: 13979793 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (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 8D98B267F4C; Tue, 18 Feb 2025 13:01:47 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739883707; cv=none; b=TMAfGVPkWwzPCSTR1Uej9p6qkf+NNdp1CChPLarfzADxTB/IRMejazgAPrwxr5/NQ+lJtacdm/RjUiK3LN/9tbpMEz0pgPxL/GWSUmZKpVgclZ+9LzUuXW+ZqmsixIldmTQ5zZLjTcI8jOTUqOpiitp3ebWNBrInHsXQ+x0i2Zk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739883707; c=relaxed/simple; bh=i8wDoobO6bpiZd26u4+7TLx2QrCQIwRboF1OHEy8KdY=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=O22Iq07kt3h1nhZTIshr8cnw6uqwR3IUCABIdKnRs5oCp+58KIEyYMg5lx45x7EOBlynxn6WXfaViNHwbUpdEqSJX5euVFtJmYqVEmhD81W7OYZMTU2vdh92VCKDJ8MPiS3+yNWraQZOioifGB2JU1JsdzKwE7jqrkdwe3I68w8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=XFX7qWlO; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="XFX7qWlO" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 292E2C4CEE8; Tue, 18 Feb 2025 13:01:41 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1739883707; bh=i8wDoobO6bpiZd26u4+7TLx2QrCQIwRboF1OHEy8KdY=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=XFX7qWlO9SUhgdW7HQvoaB6iK2So0vYTIgDQgJigmZ4atQd8fb6YUkM/O+VYkCoxT 99imA0eFR3aLJ7MSKEwlGENFBHo5yCTm+AI3I4YJwG366dG2VE+qmQm5ojMZORU+gC Tbu3ntTK+vJMC2G68mAhr2osdQ7jvs0XaCv/xy0GSsImf3K7W0tmFGsEFRs4F3CHwe 0P2+Dzry/7Te69G/W82cuLeGVyuSVQYsfS1/a6WqytcUh04CCzKRhW1extSTgbtSKQ M54+LxM+DV0qhIwvI00jieyFNKh4c6OArERHykjfcIh5ae4wr87DFYqJ0JEhoS2CZ6 4XaDLDVnVdp3w== From: Andreas Hindborg Date: Tue, 18 Feb 2025 14:00:46 +0100 Subject: [PATCH v7 4/6] rust: str: implement `strip_prefix` for `BStr` Precedence: bulk X-Mailing-List: linux-kbuild@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20250218-module-params-v3-v7-4-5e1afabcac1b@kernel.org> References: <20250218-module-params-v3-v7-0-5e1afabcac1b@kernel.org> In-Reply-To: <20250218-module-params-v3-v7-0-5e1afabcac1b@kernel.org> To: Miguel Ojeda , Alex Gaynor , Boqun Feng , Gary Guo , =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= , Benno Lossin , Andreas Hindborg , Alice Ryhl , Trevor Gross , Masahiro Yamada , Nathan Chancellor , Nicolas Schier , Luis Chamberlain Cc: rust-for-linux@vger.kernel.org, linux-kernel@vger.kernel.org, Adam Bratschi-Kaye , linux-kbuild@vger.kernel.org, Petr Pavlu , Sami Tolvanen , Daniel Gomez , Simona Vetter , Greg KH , linux-modules@vger.kernel.org X-Mailer: b4 0.15-dev X-Developer-Signature: v=1; a=openpgp-sha256; l=1603; i=a.hindborg@kernel.org; h=from:subject:message-id; bh=i8wDoobO6bpiZd26u4+7TLx2QrCQIwRboF1OHEy8KdY=; b=owEBbQKS/ZANAwAIAeG4Gj55KGN3AcsmYgBntISGYFVJJPsX7afbpIBc/fwF692CI7LF5379D BeVodH8mNWJAjMEAAEIAB0WIQQSwflHVr98KhXWwBLhuBo+eShjdwUCZ7SEhgAKCRDhuBo+eShj dwpjD/wO5E4AFgGZvg4pqp74C2eRjkj1DWNc72uyZ+T2yS5yAgyl9ZOchb1IACBZLwg7dtQvmCc gfH4v39sOzJzGGEY5Tfq2U9T5Jhziobh/tmqZw9x3rJcaG6GK/HSx4pHnGCvN7km58JxjFUDHBg XUNzh8AkiNejZlZv+HfcHunUClrF1b9CGxJfJbo/LhctHNf+fjO5eFOuEB9nvQV4gqO+rt9OrxO btfk0PP2yRZY1mgAAOt0DathpcbA2VKtImhEYxqjKo4R7coK+Q6tW6DHhxHX4naInpmopCylCey tVxd86SYh4OEQwXF2TV1bC3cQsm9wy273n/gwoSCMr/OiimCJcwXBiEUvLDeLvG/PbEZ8Xbm/mc UdwKb/gvQmaP1atypWFjq7I95uNXKVPt0xfUHCXOp5bhnWnn8n1UteJRYvG8eNSE2KFBHhR+kLE OW0aomSHQ8zDON8DsGYVWF3DjxLDq3DOvcN84qYWYzcrEwfpjdMwfQ5zzHw8Vqwt0ZW41zorraZ c7ZlYZpDwRoPezfDIMBCwJsv5QxMMQlDQ1dkgth5yVaVSpiraBrU2+gMrQLaCjjVre9uQ1csmJb DC5lWWs9EmF4eu9itqmEOEKr5DEgRsqsQ7vLiA/zEKUCPZyTLGShCUbPaubgs3aOOUnXE+ZPac5 N3RPiD1pNP1nhpA== X-Developer-Key: i=a.hindborg@kernel.org; a=openpgp; fpr=3108C10F46872E248D1FB221376EB100563EF7A7 Implement `strip_prefix` for `BStr` by deferring to `slice::strip_prefix` on the underlying `&[u8]`. Reviewed-by: Gary Guo Reviewed-by: Alice Ryhl Signed-off-by: Andreas Hindborg Reviewed-by: Daniel Almeida --- It is also possible to get this method by implementing `core::slice::SlicePattern` for `BStr`. `SlicePattern` is unstable, so this seems more reasonable. --- rust/kernel/str.rs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/rust/kernel/str.rs b/rust/kernel/str.rs index c6bd2c69543dc..db272d2198fcc 100644 --- a/rust/kernel/str.rs +++ b/rust/kernel/str.rs @@ -31,6 +31,22 @@ pub const fn from_bytes(bytes: &[u8]) -> &Self { // SAFETY: `BStr` is transparent to `[u8]`. unsafe { &*(bytes as *const [u8] as *const BStr) } } + + /// Strip a prefix from `self`. Delegates to [`slice::strip_prefix`]. + /// + /// # Example + /// ``` + /// use kernel::b_str; + /// assert_eq!(Some(b_str!("bar")), b_str!("foobar").strip_prefix(b_str!("foo"))); + /// assert_eq!(None, b_str!("foobar").strip_prefix(b_str!("bar"))); + /// assert_eq!(Some(b_str!("foobar")), b_str!("foobar").strip_prefix(b_str!(""))); + /// assert_eq!(Some(b_str!("")), b_str!("foobar").strip_prefix(b_str!("foobar"))); + /// ``` + pub fn strip_prefix(&self, pattern: impl AsRef) -> Option<&BStr> { + self.deref() + .strip_prefix(pattern.as_ref().deref()) + .map(Self::from_bytes) + } } impl fmt::Display for BStr { From patchwork Tue Feb 18 13:00:47 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andreas Hindborg X-Patchwork-Id: 13979794 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (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 0E68C265CCE; Tue, 18 Feb 2025 13:01:53 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739883713; cv=none; b=e+PXZZUV+P8gbRrBCRUzjlXj3TpwBh4LqRRjGLVT3FBEThmKZANNsNyHbHAek0iVG8nMk1O0GLcWXjJih7v5tESlPkhzoEyV/fQTuFlYpuql78nSUaKWm80s2d5a/zMFWt1n99yeLLcA0kzduJdDLJgyTpZtCx24DebEBEqnXnc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739883713; c=relaxed/simple; bh=PCV7J741XsLI5Lf1r0pbxVGAOWX7VTsXjZUySE0EkOk=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=fOPCsvu70u8Eld7kf2ACKQBqZhK54NrI1beW5tOsmiI1tCsbKofKoboDNT9TPcuuNeQen1Etrh3JhgyiI41g+d41KYpIhraeGWZaYwe6axunFV53n8DpGcgU5Xb77EaQI74xEg6ue5vSTEfzHY7M1SLBI2PmpXAnACKss0/Ac1E= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=lSYrJnp2; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="lSYrJnp2" Received: by smtp.kernel.org (Postfix) with ESMTPSA id D2713C4CEE6; Tue, 18 Feb 2025 13:01:47 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1739883712; bh=PCV7J741XsLI5Lf1r0pbxVGAOWX7VTsXjZUySE0EkOk=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=lSYrJnp2FzLm0CpyLB6SBQIJlbIovOxZ8UGdoYQKdbrB3tBRFCJcZ0BrXUI4W4vUQ 6qlM1X5UFeTgpkjXz5Uaex4HimhnBGqBwnleIMFn59xDhE9tOpsymX0EP9R2VWKIC9 4WCphnmrK/4OykFt7/JconnZkC+JbKrzn0sHDaqgTxd9GR69Xtnvb/8m3jGYxIkeCd BUVQodJQQr+nJduQHQXe4jDmJk8Wkwa87RDD1I+zVRjlGcpv0fZSpYfkQFYGGquDNT jUImWr9tKeeqT6Md40pZKysxkgN/HN4jUZ9dJzwIaM4dIgjVWaD1WJqVynERC9Abt1 lbzaJ8xgkrJCg== From: Andreas Hindborg Date: Tue, 18 Feb 2025 14:00:47 +0100 Subject: [PATCH v7 5/6] rust: str: add radix prefixed integer parsing functions Precedence: bulk X-Mailing-List: linux-kbuild@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20250218-module-params-v3-v7-5-5e1afabcac1b@kernel.org> References: <20250218-module-params-v3-v7-0-5e1afabcac1b@kernel.org> In-Reply-To: <20250218-module-params-v3-v7-0-5e1afabcac1b@kernel.org> To: Miguel Ojeda , Alex Gaynor , Boqun Feng , Gary Guo , =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= , Benno Lossin , Andreas Hindborg , Alice Ryhl , Trevor Gross , Masahiro Yamada , Nathan Chancellor , Nicolas Schier , Luis Chamberlain Cc: rust-for-linux@vger.kernel.org, linux-kernel@vger.kernel.org, Adam Bratschi-Kaye , linux-kbuild@vger.kernel.org, Petr Pavlu , Sami Tolvanen , Daniel Gomez , Simona Vetter , Greg KH , linux-modules@vger.kernel.org X-Mailer: b4 0.15-dev X-Developer-Signature: v=1; a=openpgp-sha256; l=5711; i=a.hindborg@kernel.org; h=from:subject:message-id; bh=PCV7J741XsLI5Lf1r0pbxVGAOWX7VTsXjZUySE0EkOk=; b=owEBbQKS/ZANAwAIAeG4Gj55KGN3AcsmYgBntISHnjhpzfw5TGwhNAQrGg0Y+IeXAhe6Le9n/ 7o3cxrm2q2JAjMEAAEIAB0WIQQSwflHVr98KhXWwBLhuBo+eShjdwUCZ7SEhwAKCRDhuBo+eShj d0V2EACQd+cmGOqcfkVRFMfEJ3T9SlONnRMUUxBpd0QLiogLrMFbw6uV+eamk/lqv8rs41TwPr9 o/KPBKzzTZkegvsdel3rElRuMXEgV1rV+RUrOiJY7828nLlPlUKrRjpHLNK1Yc08KgWtE72Gu4I 6QzzfRRXaaxOzVGWkVmdjdCBbmCXQU03aE4orNzFP+DpUGPFGzzdGvJKFHjj4o4W1jrKxLG8ACi jXCLjawwbQL6nJN23aiVOtnvuPSXOTRCukE7AdA4PVsySxbmhy/cIUh1DxAGJJAY8NwhEtLazV2 AnBQAmLyAQ33WNVANDCBm761fPCV+OkLeAAMTg9Gv46Vl+xMAoGalfIP0mE6eJ61w/QN8hZvo7r Md0Jfa47nSnRqt78pReIhL6s1QrOwevIJ+bgb/2qCRPlX8hIpEYnFOUHBqvvvQC0F+Sd7SoFeBu SSMz5EsdcP2P1FeTMRk8FElUjQPgRjwlXGoMzyf6duOgMx9b9ToegGOAvfYKuAldARKaUgWVEvi jlXZQteAGjBbqUsNQCP/yNIYbcdxq6pNR5eF170q6rcr5rQ06a1sBs9pqjLNefggLBSeEgGPsVx HCG9Lysdg3jqd/s0Fq8rYq//CTY78rmbVLrEJlo/yaBVM1qMaizOaqhIEbLoW5pq4u1/X58O//R 7pZksyzWcCgJDtg== X-Developer-Key: i=a.hindborg@kernel.org; a=openpgp; fpr=3108C10F46872E248D1FB221376EB100563EF7A7 Add the trait `ParseInt` for parsing string representations of integers where the string representations are optionally prefixed by a radix specifier. Implement the trait for the primitive integer types. Signed-off-by: Andreas Hindborg --- rust/kernel/str.rs | 118 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 118 insertions(+) diff --git a/rust/kernel/str.rs b/rust/kernel/str.rs index db272d2198fcc..8b0d814b47f52 100644 --- a/rust/kernel/str.rs +++ b/rust/kernel/str.rs @@ -945,3 +945,121 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { macro_rules! fmt { ($($f:tt)*) => ( core::format_args!($($f)*) ) } + +pub mod parse_int { + //! Integer parsing functions for parsing signed and unsigned integers + //! potentially prefixed with `0x`, `0o`, or `0b`. + + use crate::prelude::*; + use crate::str::BStr; + use core::ops::Deref; + + /// Trait that allows parsing a [`&BStr`] to an integer with a radix. + /// + /// [`&BStr`]: kernel::str::BStr + // This is required because the `from_str_radix` function on the primitive + // integer types is not part of any trait. + pub trait FromStrRadix: Sized { + /// Parse `src` to `Self` using radix `radix`. + fn from_str_radix(src: &BStr, radix: u32) -> Result; + } + + /// Extract the radix from an integer literal optionally prefixed with + /// one of `0x`, `0X`, `0o`, `0O`, `0b`, `0B`, `0`. + fn strip_radix(src: &BStr) -> (u32, &BStr) { + match src.deref() { + [b'0', b'x' | b'X', rest @ ..] => (16, rest.as_ref()), + [b'0', b'o' | b'O', rest @ ..] => (8, rest.as_ref()), + [b'0', b'b' | b'B', rest @ ..] => (2, rest.as_ref()), + // NOTE: We are including the leading zero to be able to parse + // literal 0 here. If we removed it as a radix prefix, we would not + // be able to parse `0`. + [b'0', ..] => (8, src), + _ => (10, src), + } + } + + /// Trait for parsing string representations of integers. + /// + /// Strings beginning with `0x`, `0o`, or `0b` are parsed as hex, octal, or + /// binary respectively. Strings beginning with `0` otherwise are parsed as + /// octal. Anything else is parsed as decimal. A leading `+` or `-` is also + /// permitted. Any string parsed by [`kstrtol()`] or [`kstrtoul()`] will be + /// successfully parsed. + /// + /// [`kstrtol()`]: https://www.kernel.org/doc/html/latest/core-api/kernel-api.html#c.kstrtol + /// [`kstrtoul()`]: https://www.kernel.org/doc/html/latest/core-api/kernel-api.html#c.kstrtoul + /// + /// # Example + /// ``` + /// use kernel::str::parse_int::ParseInt; + /// use kernel::b_str; + /// + /// assert_eq!(Ok(0), u8::from_str(b_str!("0"))); + /// + /// assert_eq!(Ok(0xa2u8), u8::from_str(b_str!("0xa2"))); + /// assert_eq!(Ok(-0xa2i32), i32::from_str(b_str!("-0xa2"))); + /// + /// assert_eq!(Ok(-0o57i8), i8::from_str(b_str!("-0o57"))); + /// assert_eq!(Ok(0o57i8), i8::from_str(b_str!("057"))); + /// + /// assert_eq!(Ok(0b1001i16), i16::from_str(b_str!("0b1001"))); + /// assert_eq!(Ok(-0b1001i16), i16::from_str(b_str!("-0b1001"))); + /// + /// assert_eq!(Ok(127), i8::from_str(b_str!("127"))); + /// assert!(i8::from_str(b_str!("128")).is_err()); + /// assert_eq!(Ok(-128), i8::from_str(b_str!("-128"))); + /// assert!(i8::from_str(b_str!("-129")).is_err()); + /// assert_eq!(Ok(255), u8::from_str(b_str!("255"))); + /// assert!(u8::from_str(b_str!("256")).is_err()); + /// ``` + pub trait ParseInt: FromStrRadix + TryFrom { + /// Parse a string according to the description in [`Self`]. + fn from_str(src: &BStr) -> Result { + match src.deref() { + [b'-', rest @ ..] => { + let (radix, digits) = strip_radix(rest.as_ref()); + // 2's complement values range from -2^(b-1) to 2^(b-1)-1. + // So if we want to parse negative numbers as positive and + // later multiply by -1, we have to parse into a larger + // integer. We choose i128 as sufficiently large. + let val = i128::from_str_radix( + core::str::from_utf8(digits).map_err(|_| EINVAL)?, + radix, + ) + .map_err(|_| EINVAL)?; + let val = -val; + val.try_into().map_err(|_| EINVAL) + } + _ => { + let (radix, digits) = strip_radix(src); + Self::from_str_radix(digits, radix).map_err(|_| EINVAL) + } + } + } + } + + macro_rules! impl_parse_int { + ($ty:ty) => { + impl FromStrRadix for $ty { + fn from_str_radix(src: &BStr, radix: u32) -> Result { + <$ty>::from_str_radix(core::str::from_utf8(src).map_err(|_| EINVAL)?, radix) + .map_err(|_| EINVAL) + } + } + + impl ParseInt for $ty {} + }; + } + + impl_parse_int!(i8); + impl_parse_int!(u8); + impl_parse_int!(i16); + impl_parse_int!(u16); + impl_parse_int!(i32); + impl_parse_int!(u32); + impl_parse_int!(i64); + impl_parse_int!(u64); + impl_parse_int!(isize); + impl_parse_int!(usize); +} From patchwork Tue Feb 18 13:00:48 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andreas Hindborg X-Patchwork-Id: 13979797 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (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 C71FA266F12; Tue, 18 Feb 2025 13:02:16 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739883736; cv=none; b=BpCj8lFq4jP6Qd9huRu2uanyi72vCU2frdhTzQBe9QhnW+TIJeZMoaBpZQMZesKtPwkkDqBDcezM6ZjRWFqmdgRt6AGXGxdP46teFcVd9T2+hXa7h9m4sTUaRsq4urz5JGsMZyire41ObxrHbFYUtpNqWGAa/ac2SDlHXztCrO8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739883736; c=relaxed/simple; bh=adCN2Z3xM3zhbhj5a6agkSrWpDUndHtrzyKiHn+FIBI=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=HnmV0ouq/fMny3k7flAtuBYWX9QZ/jFV2pKgIhHOwtK3XkS8VVJVpDgCVPvb27E9Oe7DTJ0hfM/rFgI5/Nj40RWRwXhecF2uvcvmk39pE0Vz1NFQqKuYF9c1iOqzadorJt4gwglO+UsTynxe23ATWRSZ08VpilEGee1GsAnfOok= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=aZK429Da; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="aZK429Da" Received: by smtp.kernel.org (Postfix) with ESMTPSA id CC5E2C4CEE8; Tue, 18 Feb 2025 13:02:11 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1739883736; bh=adCN2Z3xM3zhbhj5a6agkSrWpDUndHtrzyKiHn+FIBI=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=aZK429DawBtz2q0skkpIwgLEG7vrS6VlUgx+dlwUM/wrMscdOZfPqD0IuJB2KeOB+ AbKMeMaqzmBg4l2n1DkgRGsg2uBcpqwoIKQK3oX0x1RWzpM6j+pooi/4mgC/OmarQj DJWEljpIOlhgKFM78yRjobhQqrBdil4SvojzULtJ+zpz0zk/N1xxbhlbQT1Hwcy13G SVij8dhJFDqzU7O0aAbTwQi0bHU8UnhxF+ZSeM+kTXnMbM9yfoxXTfyCh3lKlbFv0w IYwuAfppz6hVqg5wAJScmq9aA92uB928ATjBJYcWouCkBT6a6UcYF/or8iucRRaJSw PBg0ifMZrKb4g== From: Andreas Hindborg Date: Tue, 18 Feb 2025 14:00:48 +0100 Subject: [PATCH v7 6/6] rust: add parameter support to the `module!` macro Precedence: bulk X-Mailing-List: linux-kbuild@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20250218-module-params-v3-v7-6-5e1afabcac1b@kernel.org> References: <20250218-module-params-v3-v7-0-5e1afabcac1b@kernel.org> In-Reply-To: <20250218-module-params-v3-v7-0-5e1afabcac1b@kernel.org> To: Miguel Ojeda , Alex Gaynor , Boqun Feng , Gary Guo , =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= , Benno Lossin , Andreas Hindborg , Alice Ryhl , Trevor Gross , Masahiro Yamada , Nathan Chancellor , Nicolas Schier , Luis Chamberlain Cc: rust-for-linux@vger.kernel.org, linux-kernel@vger.kernel.org, Adam Bratschi-Kaye , linux-kbuild@vger.kernel.org, Petr Pavlu , Sami Tolvanen , Daniel Gomez , Simona Vetter , Greg KH , linux-modules@vger.kernel.org X-Mailer: b4 0.15-dev X-Developer-Signature: v=1; a=openpgp-sha256; l=24531; i=a.hindborg@kernel.org; h=from:subject:message-id; bh=adCN2Z3xM3zhbhj5a6agkSrWpDUndHtrzyKiHn+FIBI=; b=owEBbQKS/ZANAwAIAeG4Gj55KGN3AcsmYgBntISIXAbzXM8NCJRhd/fHQDZI/OKNnALCYEilz BqTGjNfFAWJAjMEAAEIAB0WIQQSwflHVr98KhXWwBLhuBo+eShjdwUCZ7SEiAAKCRDhuBo+eShj dwc9D/9EZfq1FfMPviYv5H23uamWp4TdxO9wMoqqcf468QegGhq7EOubnacwbcz5oXmIE/rCspL ZP+9kINHOMNIUHD4EdX7hLB7vxxRzaNMJuIatXxl8v9/jBgTjhAiTAm02b+dj65W1fVza7Qr9Bo zHL5gTgNYL1Z6D/nPwqnxtdF3y6WYO34IsblKsbinWHzXREg1PbU7lDb7YbZsjhAjMHJDlvlKRL LIPlnIUp3dKASIydv4X42b/Ulech+O/LPf6ZXnMCt5VDwhvLpjL0TVSwhUEoBkldEDYAQ37Lz1/ UpZcEbOALC75S+cWAPxtJblqo+Ef3ShIuQvXsFDR72R5bYr7eYJ+DQ4iQWInVV6dbK5+GMRNjeJ xJrEel2lDdFeMLPicjGDpT431AuSJH7H7JRBnIvGCx4p/stHdWDuVDTMGvTt8aRaEqkjf5fD3w/ q1hSMJFvCPxb3fEV6q7GTUpXO5c2BGcA6H4pTtH6XXFNQc01gbhadv7lVrGVwPKBiT1HKcRsyj8 qLA2ekAsL7nS4/kNPbxWIYPX4ITACLA9GLEzdlRPRtRG/DOY95pqLPXwci6RXz6AHnke/Cm7bsk YCOatRAXcyFnmYAuu6uXdOytF9vsH2mvtTRT/ebOnaevy7Wm2LiQjX0SFCu/2204xz/1DZP1DpY 8ZbUAe9ZWT5LA4A== X-Developer-Key: i=a.hindborg@kernel.org; a=openpgp; fpr=3108C10F46872E248D1FB221376EB100563EF7A7 This patch includes changes required for Rust kernel modules to utilize module parameters. This code implements read only support for integer types without `sysfs` support. Signed-off-by: Andreas Hindborg Acked-by: Petr Pavlu # from modules perspective --- rust/kernel/lib.rs | 1 + rust/kernel/module_param.rs | 226 +++++++++++++++++++++++++++++++++++++++++++ rust/macros/helpers.rs | 25 +++++ rust/macros/lib.rs | 31 ++++++ rust/macros/module.rs | 191 ++++++++++++++++++++++++++++++++---- samples/rust/rust_minimal.rs | 10 ++ 6 files changed, 466 insertions(+), 18 deletions(-) diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs index 496ed32b0911a..aec04df2bac9f 100644 --- a/rust/kernel/lib.rs +++ b/rust/kernel/lib.rs @@ -57,6 +57,7 @@ pub mod kunit; pub mod list; pub mod miscdevice; +pub mod module_param; #[cfg(CONFIG_NET)] pub mod net; pub mod of; diff --git a/rust/kernel/module_param.rs b/rust/kernel/module_param.rs new file mode 100644 index 0000000000000..0047126c917f4 --- /dev/null +++ b/rust/kernel/module_param.rs @@ -0,0 +1,226 @@ +// SPDX-License-Identifier: GPL-2.0 + +//! Types for module parameters. +//! +//! C header: [`include/linux/moduleparam.h`](srctree/include/linux/moduleparam.h) + +use crate::prelude::*; +use crate::str::BStr; + +/// Newtype to make `bindings::kernel_param` [`Sync`]. +#[repr(transparent)] +#[doc(hidden)] +pub struct RacyKernelParam(pub ::kernel::bindings::kernel_param); + +// SAFETY: C kernel handles serializing access to this type. We never access +// from Rust module. +unsafe impl Sync for RacyKernelParam {} + +/// Types that can be used for module parameters. +/// +/// Note that displaying the type in `sysfs` will fail if +/// [`Display`](core::fmt::Display) implementation would write more than +/// [`PAGE_SIZE`] - 1 bytes. +/// +/// [`PAGE_SIZE`]: `bindings::PAGE_SIZE` +pub trait ModuleParam: Sized { + /// The [`ModuleParam`] will be used by the kernel module through this type. + /// + /// This may differ from `Self` if, for example, `Self` needs to track + /// ownership without exposing it or allocate extra space for other possible + /// parameter values. + // This is required to support string parameters in the future. + type Value: ?Sized; + + /// Parse a parameter argument into the parameter value. + /// + /// `Err(_)` should be returned when parsing of the argument fails. + /// + /// Parameters passed at boot time will be set before [`kmalloc`] is + /// available (even if the module is loaded at a later time). However, in + /// this case, the argument buffer will be valid for the entire lifetime of + /// the kernel. So implementations of this method which need to allocate + /// should first check that the allocator is available (with + /// [`crate::bindings::slab_is_available`]) and when it is not available + /// provide an alternative implementation which doesn't allocate. In cases + /// where the allocator is not available it is safe to save references to + /// `arg` in `Self`, but in other cases a copy should be made. + /// + /// [`kmalloc`]: srctree/include/linux/slab.h + fn try_from_param_arg(arg: &'static [u8]) -> Result; +} + +/// Set the module parameter from a string. +/// +/// Used to set the parameter value at kernel initialization, when loading +/// the module or when set through `sysfs`. +/// +/// `param.arg` is a pointer to `*mut T` as set up by the [`module!`] +/// macro. +/// +/// See `struct kernel_param_ops.set`. +/// +/// # Safety +/// +/// If `val` is non-null then it must point to a valid null-terminated +/// string. The `arg` field of `param` must be an instance of `T`. +/// +/// # Invariants +/// +/// Currently, we only support read-only parameters that are not readable +/// from `sysfs`. Thus, this function is only called at kernel +/// initialization time, or at module load time, and we have exclusive +/// access to the parameter for the duration of the function. +/// +/// [`module!`]: macros::module +unsafe extern "C" fn set_param( + val: *const kernel::ffi::c_char, + param: *const crate::bindings::kernel_param, +) -> core::ffi::c_int +where + T: ModuleParam, +{ + // NOTE: If we start supporting arguments without values, val _is_ allowed + // to be null here. + if val.is_null() { + // TODO: Use pr_warn_once available. + crate::pr_warn!("Null pointer passed to `module_param::set_param`"); + return crate::error::code::EINVAL.to_errno(); + } + + // SAFETY: By function safety requirement, val is non-null and + // null-terminated. By C API contract, `val` is live and valid for reads + // for the duration of this function. + let arg = unsafe { CStr::from_char_ptr(val).as_bytes() }; + + crate::error::from_result(|| { + let new_value = T::try_from_param_arg(arg)?; + + // SAFETY: `param` is guaranteed to be valid by C API contract + // and `arg` is guaranteed to point to an instance of `T`. + let old_value = unsafe { (*param).__bindgen_anon_1.arg as *mut T }; + + // SAFETY: `old_value` is valid for writes, as we have exclusive + // access. `old_value` is pointing to an initialized static, and + // so it is properly initialized. + unsafe { core::ptr::replace(old_value, new_value) }; + Ok(0) + }) +} + +/// Drop the parameter. +/// +/// Called when unloading a module. +/// +/// # Safety +/// +/// The `arg` field of `param` must be an initialized instance of `T`. +unsafe extern "C" fn free(arg: *mut core::ffi::c_void) +where + T: ModuleParam, +{ + // SAFETY: By function safety requirement, `arg` is an initialized + // instance of `T`. By C API contract, `arg` will not be used after + // this function returns. + unsafe { core::ptr::drop_in_place(arg as *mut T) }; +} + +macro_rules! impl_int_module_param { + ($ty:ident) => { + impl ModuleParam for $ty { + type Value = $ty; + + fn try_from_param_arg(arg: &'static [u8]) -> Result { + let bstr = BStr::from_bytes(arg); + <$ty as crate::str::parse_int::ParseInt>::from_str(bstr) + } + } + }; +} + +impl_int_module_param!(i8); +impl_int_module_param!(u8); +impl_int_module_param!(i16); +impl_int_module_param!(u16); +impl_int_module_param!(i32); +impl_int_module_param!(u32); +impl_int_module_param!(i64); +impl_int_module_param!(u64); +impl_int_module_param!(isize); +impl_int_module_param!(usize); + +/// A wrapper for kernel parameters. +/// +/// This type is instantiated by the [`module!`] macro when module parameters are +/// defined. You should never need to instantiate this type directly. +#[repr(transparent)] +pub struct ModuleParamAccess { + data: core::cell::UnsafeCell, +} + +// SAFETY: We only create shared references to the contents of this container, +// so if `T` is `Sync`, so is `ModuleParamAccess`. +unsafe impl Sync for ModuleParamAccess {} + +impl ModuleParamAccess { + #[doc(hidden)] + pub const fn new(value: T) -> Self { + Self { + data: core::cell::UnsafeCell::new(value), + } + } + + /// Get a shared reference to the parameter value. + // Note: When sysfs access to parameters are enabled, we have to pass in a + // held lock guard here. + pub fn get(&self) -> &T { + // SAFETY: As we only support read only parameters with no sysfs + // exposure, the kernel will not touch the parameter data after module + // initialization. + unsafe { &*self.data.get() } + } + + /// Get a mutable pointer to the parameter value. + pub const fn as_mut_ptr(&self) -> *mut T { + self.data.get() + } +} + +#[doc(hidden)] +#[macro_export] +/// Generate a static [`kernel_param_ops`](srctree/include/linux/moduleparam.h) struct. +/// +/// # Examples +/// +/// ```ignore +/// make_param_ops!( +/// /// Documentation for new param ops. +/// PARAM_OPS_MYTYPE, // Name for the static. +/// MyType // A type which implements [`ModuleParam`]. +/// ); +/// ``` +macro_rules! make_param_ops { + ($ops:ident, $ty:ty) => { + /// + /// Static [`kernel_param_ops`](srctree/include/linux/moduleparam.h) + /// struct generated by `make_param_ops` + #[doc = concat!("for [`", stringify!($ty), "`].")] + pub static $ops: $crate::bindings::kernel_param_ops = $crate::bindings::kernel_param_ops { + flags: 0, + set: Some(set_param::<$ty>), + get: None, + free: Some(free::<$ty>), + }; + }; +} + +make_param_ops!(PARAM_OPS_I8, i8); +make_param_ops!(PARAM_OPS_U8, u8); +make_param_ops!(PARAM_OPS_I16, i16); +make_param_ops!(PARAM_OPS_U16, u16); +make_param_ops!(PARAM_OPS_I32, i32); +make_param_ops!(PARAM_OPS_U32, u32); +make_param_ops!(PARAM_OPS_I64, i64); +make_param_ops!(PARAM_OPS_U64, u64); +make_param_ops!(PARAM_OPS_ISIZE, isize); +make_param_ops!(PARAM_OPS_USIZE, usize); diff --git a/rust/macros/helpers.rs b/rust/macros/helpers.rs index 563dcd2b7ace5..ffc9f0cccddc8 100644 --- a/rust/macros/helpers.rs +++ b/rust/macros/helpers.rs @@ -10,6 +10,17 @@ pub(crate) fn try_ident(it: &mut token_stream::IntoIter) -> Option { } } +pub(crate) fn try_sign(it: &mut token_stream::IntoIter) -> Option { + let peek = it.clone().next(); + match peek { + Some(TokenTree::Punct(punct)) if punct.as_char() == '-' => { + let _ = it.next(); + Some(punct.as_char()) + } + _ => None, + } +} + pub(crate) fn try_literal(it: &mut token_stream::IntoIter) -> Option { if let Some(TokenTree::Literal(literal)) = it.next() { Some(literal.to_string()) @@ -107,6 +118,20 @@ pub(crate) struct Generics { pub(crate) ty_generics: Vec, } +/// Parse a token stream of the form `expected_name: "value",` and return the +/// string in the position of "value". +/// +/// # Panics +/// +/// - On parse error. +pub(crate) fn expect_string_field(it: &mut token_stream::IntoIter, expected_name: &str) -> String { + assert_eq!(expect_ident(it), expected_name); + assert_eq!(expect_punct(it), ':'); + let string = expect_string(it); + assert_eq!(expect_punct(it), ','); + string +} + /// Parses the given `TokenStream` into `Generics` and the rest. /// /// The generics are not present in the rest, but a where clause might remain. diff --git a/rust/macros/lib.rs b/rust/macros/lib.rs index d61bc6a56425e..2778292f8cee1 100644 --- a/rust/macros/lib.rs +++ b/rust/macros/lib.rs @@ -24,6 +24,30 @@ /// The `type` argument should be a type which implements the [`Module`] /// trait. Also accepts various forms of kernel metadata. /// +/// The `params` field describe module parameters. Each entry has the form +/// +/// ```ignore +/// parameter_name: type { +/// default: default_value, +/// description: "Description", +/// } +/// ``` +/// +/// `type` may be one of +/// +/// - [`i8`] +/// - [`u8`] +/// - [`i8`] +/// - [`u8`] +/// - [`i16`] +/// - [`u16`] +/// - [`i32`] +/// - [`u32`] +/// - [`i64`] +/// - [`u64`] +/// - [`isize`] +/// - [`usize`] +/// /// C header: [`include/linux/moduleparam.h`](srctree/include/linux/moduleparam.h) /// /// [`Module`]: ../kernel/trait.Module.html @@ -40,6 +64,12 @@ /// description: "My very own kernel module!", /// license: "GPL", /// alias: ["alternate_module_name"], +/// params: { +/// my_parameter: i64 { +/// default: 1, +/// description: "This parameter has a default of 1", +/// }, +/// }, /// } /// /// struct MyModule(i32); @@ -48,6 +78,7 @@ /// fn init(_module: &'static ThisModule) -> Result { /// let foo: i32 = 42; /// pr_info!("I contain: {}\n", foo); +/// pr_info!("i32 param is: {}\n", module_parameters::my_parameter.read()); /// Ok(Self(foo)) /// } /// } diff --git a/rust/macros/module.rs b/rust/macros/module.rs index cdf94f4982dfc..e6af3ae5fe80e 100644 --- a/rust/macros/module.rs +++ b/rust/macros/module.rs @@ -26,6 +26,7 @@ struct ModInfoBuilder<'a> { module: &'a str, counter: usize, buffer: String, + param_buffer: String, } impl<'a> ModInfoBuilder<'a> { @@ -34,10 +35,11 @@ fn new(module: &'a str) -> Self { module, counter: 0, buffer: String::new(), + param_buffer: String::new(), } } - fn emit_base(&mut self, field: &str, content: &str, builtin: bool) { + fn emit_base(&mut self, field: &str, content: &str, builtin: bool, param: bool) { let string = if builtin { // Built-in modules prefix their modinfo strings by `module.`. format!( @@ -51,8 +53,14 @@ fn emit_base(&mut self, field: &str, content: &str, builtin: bool) { format!("{field}={content}\0", field = field, content = content) }; + let buffer = if param { + &mut self.param_buffer + } else { + &mut self.buffer + }; + write!( - &mut self.buffer, + buffer, " {cfg} #[doc(hidden)] @@ -75,20 +83,116 @@ fn emit_base(&mut self, field: &str, content: &str, builtin: bool) { self.counter += 1; } - fn emit_only_builtin(&mut self, field: &str, content: &str) { - self.emit_base(field, content, true) + fn emit_only_builtin(&mut self, field: &str, content: &str, param: bool) { + self.emit_base(field, content, true, param) } - fn emit_only_loadable(&mut self, field: &str, content: &str) { - self.emit_base(field, content, false) + fn emit_only_loadable(&mut self, field: &str, content: &str, param: bool) { + self.emit_base(field, content, false, param) } fn emit(&mut self, field: &str, content: &str) { - self.emit_only_builtin(field, content); - self.emit_only_loadable(field, content); + self.emit_internal(field, content, false); + } + + fn emit_internal(&mut self, field: &str, content: &str, param: bool) { + self.emit_only_builtin(field, content, param); + self.emit_only_loadable(field, content, param); + } + + fn emit_param(&mut self, field: &str, param: &str, content: &str) { + let content = format!("{param}:{content}", param = param, content = content); + self.emit_internal(field, &content, true); + } + + fn emit_params(&mut self, info: &ModuleInfo) { + let Some(params) = &info.params else { + return; + }; + + for param in params { + let ops = param_ops_path(¶m.ptype); + + // Note: The spelling of these fields is dictated by the user space + // tool `modinfo`. + self.emit_param("parmtype", ¶m.name, ¶m.ptype); + self.emit_param("parm", ¶m.name, ¶m.description); + + write!( + self.param_buffer, + " + pub(crate) static {param_name}: + ::kernel::module_param::ModuleParamAccess<{param_type}> = + ::kernel::module_param::ModuleParamAccess::new({param_default}); + + #[link_section = \"__param\"] + #[used] + static __{module_name}_{param_name}_struct: + ::kernel::module_param::RacyKernelParam = + ::kernel::module_param::RacyKernelParam(::kernel::bindings::kernel_param {{ + name: if cfg!(MODULE) {{ + ::kernel::c_str!(\"{param_name}\").as_bytes_with_nul() + }} else {{ + ::kernel::c_str!(\"{module_name}.{param_name}\").as_bytes_with_nul() + }}.as_ptr(), + // SAFETY: `__this_module` is constructed by the kernel at load time + // and will not be freed until the module is unloaded. + #[cfg(MODULE)] + mod_: unsafe {{ + (&::kernel::bindings::__this_module + as *const ::kernel::bindings::module) + .cast_mut() + }}, + #[cfg(not(MODULE))] + mod_: ::core::ptr::null_mut(), + ops: &{ops} as *const ::kernel::bindings::kernel_param_ops, + perm: 0, // Will not appear in sysfs + level: -1, + flags: 0, + __bindgen_anon_1: + ::kernel::bindings::kernel_param__bindgen_ty_1 {{ + arg: {param_name}.as_mut_ptr().cast() + }}, + }}); + ", + module_name = info.name, + param_type = param.ptype, + param_default = param.default, + param_name = param.name, + ops = ops, + ) + .unwrap(); + } + } +} + +fn param_ops_path(param_type: &str) -> &'static str { + match param_type { + "i8" => "::kernel::module_param::PARAM_OPS_I8", + "u8" => "::kernel::module_param::PARAM_OPS_U8", + "i16" => "::kernel::module_param::PARAM_OPS_I16", + "u16" => "::kernel::module_param::PARAM_OPS_U16", + "i32" => "::kernel::module_param::PARAM_OPS_I32", + "u32" => "::kernel::module_param::PARAM_OPS_U32", + "i64" => "::kernel::module_param::PARAM_OPS_I64", + "u64" => "::kernel::module_param::PARAM_OPS_U64", + "isize" => "::kernel::module_param::PARAM_OPS_ISIZE", + "usize" => "::kernel::module_param::PARAM_OPS_USIZE", + t => panic!("Unsupported parameter type {}", t), } } +fn expect_param_default(param_it: &mut token_stream::IntoIter) -> String { + assert_eq!(expect_ident(param_it), "default"); + assert_eq!(expect_punct(param_it), ':'); + let sign = try_sign(param_it); + let default = try_literal(param_it).expect("Expected default param value"); + assert_eq!(expect_punct(param_it), ','); + let mut value = sign.map(String::from).unwrap_or_default(); + value.push_str(&default); + value +} + #[derive(Debug, Default)] struct ModuleInfo { type_: String, @@ -98,6 +202,50 @@ struct ModuleInfo { description: Option, alias: Option>, firmware: Option>, + params: Option>, +} + +#[derive(Debug)] +struct Parameter { + name: String, + ptype: String, + default: String, + description: String, +} + +fn expect_params(it: &mut token_stream::IntoIter) -> Vec { + let params = expect_group(it); + assert_eq!(params.delimiter(), Delimiter::Brace); + let mut it = params.stream().into_iter(); + let mut parsed = Vec::new(); + + loop { + let param_name = match it.next() { + Some(TokenTree::Ident(ident)) => ident.to_string(), + Some(_) => panic!("Expected Ident or end"), + None => break, + }; + + assert_eq!(expect_punct(&mut it), ':'); + let param_type = expect_ident(&mut it); + let group = expect_group(&mut it); + assert_eq!(group.delimiter(), Delimiter::Brace); + assert_eq!(expect_punct(&mut it), ','); + + let mut param_it = group.stream().into_iter(); + let param_default = expect_param_default(&mut param_it); + let param_description = expect_string_field(&mut param_it, "description"); + expect_end(&mut param_it); + + parsed.push(Parameter { + name: param_name, + ptype: param_type, + default: param_default, + description: param_description, + }) + } + + parsed } impl ModuleInfo { @@ -112,6 +260,7 @@ fn parse(it: &mut token_stream::IntoIter) -> Self { "license", "alias", "firmware", + "params", ]; const REQUIRED_KEYS: &[&str] = &["type", "name", "license"]; let mut seen_keys = Vec::new(); @@ -140,6 +289,7 @@ fn parse(it: &mut token_stream::IntoIter) -> Self { "license" => info.license = expect_string_ascii(it), "alias" => info.alias = Some(expect_string_array(it)), "firmware" => info.firmware = Some(expect_string_array(it)), + "params" => info.params = Some(expect_params(it)), _ => panic!( "Unknown key \"{}\". Valid keys are: {:?}.", key, EXPECTED_KEYS @@ -183,28 +333,30 @@ pub(crate) fn module(ts: TokenStream) -> TokenStream { let info = ModuleInfo::parse(&mut it); let mut modinfo = ModInfoBuilder::new(info.name.as_ref()); - if let Some(author) = info.author { - modinfo.emit("author", &author); + if let Some(author) = &info.author { + modinfo.emit("author", author); } - if let Some(description) = info.description { - modinfo.emit("description", &description); + if let Some(description) = &info.description { + modinfo.emit("description", description); } modinfo.emit("license", &info.license); - if let Some(aliases) = info.alias { + if let Some(aliases) = &info.alias { for alias in aliases { - modinfo.emit("alias", &alias); + modinfo.emit("alias", alias); } } - if let Some(firmware) = info.firmware { + if let Some(firmware) = &info.firmware { for fw in firmware { - modinfo.emit("firmware", &fw); + modinfo.emit("firmware", fw); } } // Built-in modules also export the `file` modinfo string. let file = std::env::var("RUST_MODFILE").expect("Unable to fetch RUST_MODFILE environmental variable"); - modinfo.emit_only_builtin("file", &file); + modinfo.emit_only_builtin("file", &file, false); + + modinfo.emit_params(&info); format!( " @@ -362,14 +514,17 @@ unsafe fn __exit() {{ __MOD.assume_init_drop(); }} }} - {modinfo} }} }} + mod module_parameters {{ + {params} + }} ", type_ = info.type_, name = info.name, modinfo = modinfo.buffer, + params = modinfo.param_buffer, initcall_section = ".initcall6.init" ) .parse() diff --git a/samples/rust/rust_minimal.rs b/samples/rust/rust_minimal.rs index 4aaf117bf8e3c..d999a77c6eb9a 100644 --- a/samples/rust/rust_minimal.rs +++ b/samples/rust/rust_minimal.rs @@ -10,6 +10,12 @@ author: "Rust for Linux Contributors", description: "Rust minimal sample", license: "GPL", + params: { + test_parameter: i64 { + default: 1, + description: "This parameter has a default of 1", + }, + }, } struct RustMinimal { @@ -20,6 +26,10 @@ impl kernel::Module for RustMinimal { fn init(_module: &'static ThisModule) -> Result { pr_info!("Rust minimal sample (init)\n"); pr_info!("Am I built-in? {}\n", !cfg!(MODULE)); + pr_info!( + "My parameter: {}\n", + *module_parameters::test_parameter.get() + ); let mut numbers = KVec::new(); numbers.push(72, GFP_KERNEL)?;