Rust-for-linux archive mirror
 help / color / mirror / Atom feed
From: Thomas Bertschinger <tahbertschinger@gmail.com>
To: rust-for-linux@vger.kernel.org, linux-bcachefs@vger.kernel.org,
	linux-fsdevel@vger.kernel.org, kent.overstreet@linux.dev,
	bfoster@redhat.com, ojeda@kernel.org, alex.gaynor@gmail.com,
	wedsonaf@gmail.com
Cc: Thomas Bertschinger <tahbertschinger@gmail.com>
Subject: [PATCH RFC 3/3] bcachefs: introduce Rust module implementation
Date: Tue,  6 Feb 2024 22:58:45 -0700	[thread overview]
Message-ID: <20240207055845.611710-1-tahbertschinger@gmail.com> (raw)

This patch uses the bcachefs bindgen framework to introduce a Rust
implementation of the module entry and exit functions. With this change,
bcachefs is now a Rust kernel module (that calls C functions to do most
of its work).

This is only if CONFIG_BCACHEFS_RUST is defined; the C implementation of
the module init and exit code is left around so that bcachefs remains
usable in kernels compiled without Rust support.

Signed-off-by: Thomas Bertschinger <tahbertschinger@gmail.com>
---
 fs/bcachefs/Makefile                   |  3 ++
 fs/bcachefs/bcachefs.h                 |  5 ++
 fs/bcachefs/bcachefs_module.rs         | 66 ++++++++++++++++++++++++++
 fs/bcachefs/bindgen_parameters         | 13 ++++-
 fs/bcachefs/bindings/bindings_helper.h |  4 ++
 fs/bcachefs/bindings/mod.rs            |  2 +
 fs/bcachefs/super.c                    | 31 ++++++++++--
 7 files changed, 120 insertions(+), 4 deletions(-)
 create mode 100644 fs/bcachefs/bcachefs_module.rs

diff --git a/fs/bcachefs/Makefile b/fs/bcachefs/Makefile
index 3f209511149c..252810a4d9a0 100644
--- a/fs/bcachefs/Makefile
+++ b/fs/bcachefs/Makefile
@@ -89,8 +89,11 @@ bcachefs-y		:=	\
 	varint.o		\
 	xattr.o
 
+bcachefs-$(CONFIG_BCACHEFS_RUST)	+= bcachefs_module.o
 always-$(CONFIG_BCACHEFS_RUST)		+= bindings/bcachefs_generated.rs
 
+$(obj)/bcachefs_module.o: $(src)/bindings/bcachefs_generated.rs
+
 $(obj)/bindings/bcachefs_generated.rs: private bindgen_target_flags = \
     $(shell grep -Ev '^#|^$$' $(srctree)/$(src)/bindgen_parameters)
 
diff --git a/fs/bcachefs/bcachefs.h b/fs/bcachefs/bcachefs.h
index b80c6c9efd8c..3a777592bff4 100644
--- a/fs/bcachefs/bcachefs.h
+++ b/fs/bcachefs/bcachefs.h
@@ -1252,4 +1252,9 @@ static inline struct stdio_redirect *bch2_fs_stdio_redirect(struct bch_fs *c)
 #define BKEY_PADDED_ONSTACK(key, pad)				\
 	struct { struct bkey_i key; __u64 key ## _pad[pad]; }
 
+#ifdef CONFIG_BCACHEFS_RUST
+int bch2_kset_init(void);
+void bch2_kset_exit(void);
+#endif
+
 #endif /* _BCACHEFS_H */
diff --git a/fs/bcachefs/bcachefs_module.rs b/fs/bcachefs/bcachefs_module.rs
new file mode 100644
index 000000000000..8db2de8139bc
--- /dev/null
+++ b/fs/bcachefs/bcachefs_module.rs
@@ -0,0 +1,66 @@
+// SPDX-License-Identifier: GPL-2.0
+
+//! bcachefs
+//!
+//! Rust kernel module for bcachefs.
+
+pub mod bindings;
+
+use kernel::prelude::*;
+
+use crate::bindings::*;
+
+module! {
+    type: Bcachefs,
+    name: "bcachefs",
+    author: "Kent Overstreet <kent.overstreet@gmail.com>",
+    description: "bcachefs filesystem",
+    license: "GPL",
+}
+
+struct Bcachefs;
+
+impl kernel::Module for Bcachefs {
+    #[link_section = ".init.text"]
+    fn init(_module: &'static ThisModule) -> Result<Self> {
+        // SAFETY: this block registers the bcachefs services with the kernel. After succesful
+        // registration, all such services are guaranteed by the kernel to exist as long as the
+        // driver is loaded. In the event of any failure in the registration, all registered
+        // services are unregistered.
+        unsafe {
+            bch2_bkey_pack_test();
+
+            if bch2_kset_init() != 0
+                || bch2_btree_key_cache_init() != 0
+                || bch2_chardev_init() != 0
+                || bch2_vfs_init() != 0
+                || bch2_debug_init() != 0
+            {
+                __drop();
+                return Err(ENOMEM);
+            }
+        }
+
+        Ok(Bcachefs)
+    }
+}
+
+fn __drop() {
+    // SAFETY: The kernel does not allow cleanup_module() (which results in
+    // drop()) to be called unless there are no users of the filesystem.
+    // The *_exit() functions only free data that they confirm is allocated, so
+    // this is safe to call even if the module's init() function did not finish.
+    unsafe {
+        bch2_debug_exit();
+        bch2_vfs_exit();
+        bch2_chardev_exit();
+        bch2_btree_key_cache_exit();
+        bch2_kset_exit();
+    }
+}
+
+impl Drop for Bcachefs {
+    fn drop(&mut self) {
+        __drop();
+    }
+}
diff --git a/fs/bcachefs/bindgen_parameters b/fs/bcachefs/bindgen_parameters
index 547212bebd6e..96a63e3a2cc3 100644
--- a/fs/bcachefs/bindgen_parameters
+++ b/fs/bcachefs/bindgen_parameters
@@ -1,5 +1,16 @@
 # SPDX-License-Identifier: GPL-2.0
 
---allowlist-function ''
+--allowlist-function bch2_bkey_pack_test
+--allowlist-function bch2_kset_init
+--allowlist-function bch2_btree_key_cache_init
+--allowlist-function bch2_chardev_init
+--allowlist-function bch2_vfs_init
+--allowlist-function bch2_debug_init
+--allowlist-function bch2_debug_exit
+--allowlist-function bch2_vfs_exit
+--allowlist-function bch2_chardev_exit
+--allowlist-function bch2_btree_key_cache_exit
+--allowlist-function bch2_kset_exit
+
 --allowlist-type ''
 --allowlist-var ''
diff --git a/fs/bcachefs/bindings/bindings_helper.h b/fs/bcachefs/bindings/bindings_helper.h
index f8bef3676f71..8cf3c35e8ca1 100644
--- a/fs/bcachefs/bindings/bindings_helper.h
+++ b/fs/bcachefs/bindings/bindings_helper.h
@@ -1,3 +1,7 @@
 /* SPDX-License-Identifier: GPL-2.0 */
 
 #include "../bcachefs.h"
+#include "../btree_key_cache.h"
+#include "../chardev.h"
+#include "../fs.h"
+#include "../debug.h"
diff --git a/fs/bcachefs/bindings/mod.rs b/fs/bcachefs/bindings/mod.rs
index 19a3ae3c63c6..d1c3bbbd7b5a 100644
--- a/fs/bcachefs/bindings/mod.rs
+++ b/fs/bcachefs/bindings/mod.rs
@@ -1,3 +1,5 @@
 // SPDX-License-Identifier: GPL-2.0
 
+#![allow(missing_docs)]
+
 include!("bcachefs_generated.rs");
diff --git a/fs/bcachefs/super.c b/fs/bcachefs/super.c
index da8697c79a97..343c4bc6e81c 100644
--- a/fs/bcachefs/super.c
+++ b/fs/bcachefs/super.c
@@ -69,9 +69,12 @@
 #include <linux/sysfs.h>
 #include <crypto/hash.h>
 
+#ifndef CONFIG_BCACHEFS_RUST
+/* when enabled, the Rust module exports these modinfo attributes */
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Kent Overstreet <kent.overstreet@gmail.com>");
 MODULE_DESCRIPTION("bcachefs filesystem");
+#endif
 MODULE_SOFTDEP("pre: crc32c");
 MODULE_SOFTDEP("pre: crc64");
 MODULE_SOFTDEP("pre: sha256");
@@ -2082,6 +2085,7 @@ struct bch_fs *bch2_fs_open(char * const *devices, unsigned nr_devices,
 
 /* Global interfaces/init */
 
+#ifndef CONFIG_BCACHEFS_RUST
 static void bcachefs_exit(void)
 {
 	bch2_debug_exit();
@@ -2109,6 +2113,30 @@ static int __init bcachefs_init(void)
 	return -ENOMEM;
 }
 
+module_exit(bcachefs_exit);
+module_init(bcachefs_init);
+
+#else /* CONFIG_BCACHEFS_RUST */
+/*
+ * bch2_kset_init() and bch2_kset_exit() are wrappers around the kset functions
+ * to be called from the Rust module init and exit because there is not
+ * currently a Rust API for ksets. If/when a Rust API is provided, these
+ * wrappers can be removed and the Rust kernel module can use that directly.
+ */
+int __init bch2_kset_init(void)
+{
+	bcachefs_kset = kset_create_and_add("bcachefs", NULL, fs_kobj);
+
+	return !bcachefs_kset;
+}
+
+void bch2_kset_exit(void)
+{
+	if (bcachefs_kset)
+		kset_unregister(bcachefs_kset);
+}
+#endif
+
 #define BCH_DEBUG_PARAM(name, description)			\
 	bool bch2_##name;					\
 	module_param_named(name, bch2_##name, bool, 0644);	\
@@ -2119,6 +2147,3 @@ BCH_DEBUG_PARAMS()
 __maybe_unused
 static unsigned bch2_metadata_version = bcachefs_metadata_version_current;
 module_param_named(version, bch2_metadata_version, uint, 0400);
-
-module_exit(bcachefs_exit);
-module_init(bcachefs_init);
-- 
2.43.0


             reply	other threads:[~2024-02-07  5:59 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-02-07  5:58 Thomas Bertschinger [this message]
2024-02-07  6:07 ` [PATCH RFC 3/3] bcachefs: introduce Rust module implementation Kent Overstreet
2024-02-07  6:58 ` Trevor Gross

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20240207055845.611710-1-tahbertschinger@gmail.com \
    --to=tahbertschinger@gmail.com \
    --cc=alex.gaynor@gmail.com \
    --cc=bfoster@redhat.com \
    --cc=kent.overstreet@linux.dev \
    --cc=linux-bcachefs@vger.kernel.org \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=ojeda@kernel.org \
    --cc=rust-for-linux@vger.kernel.org \
    --cc=wedsonaf@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).