* [PATCH v2 1/4] ext4: convert extents KUnit test to sget_fc()
2026-05-29 8:43 [PATCH v2 0/4] super: retire sget() Christian Brauner
@ 2026-05-29 8:43 ` Christian Brauner
2026-06-02 11:17 ` Jan Kara
2026-05-29 8:43 ` [PATCH v2 2/4] ext4: convert mballoc " Christian Brauner
` (2 subsequent siblings)
3 siblings, 1 reply; 8+ messages in thread
From: Christian Brauner @ 2026-05-29 8:43 UTC (permalink / raw)
To: linux-fsdevel
Cc: Theodore Ts'o, Andreas Dilger, Jan Kara, Ritesh Harjani (IBM),
linux-ext4, linux-cifs, Alexander Viro,
Christian Brauner (Amutable)
The extents KUnit test uses sget() to get an initialized superblock for
its fake file_system_type. sget() predates fs_context and we want to
retire it. Switch this caller over to sget_fc().
Add a no-op ext_init_fs_context() so fs_context_for_mount() has
something to call on the fake fs_type. ext_set() now takes a struct
fs_context * (still a no-op). extents_kunit_init() allocates the fc,
hands it to sget_fc() and drops the fc reference once the sb is
published. sget_fc() does not retain a pointer to it.
No functional change for the test.
Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
---
fs/ext4/extents-test.c | 22 ++++++++++++++++++----
1 file changed, 18 insertions(+), 4 deletions(-)
diff --git a/fs/ext4/extents-test.c b/fs/ext4/extents-test.c
index 6b53a3f39fcd..bd7795a82607 100644
--- a/fs/ext4/extents-test.c
+++ b/fs/ext4/extents-test.c
@@ -37,6 +37,7 @@
#include <kunit/test.h>
#include <kunit/static_stub.h>
+#include <linux/fs_context.h>
#include <linux/gfp_types.h>
#include <linux/stddef.h>
@@ -130,14 +131,20 @@ static void ext_kill_sb(struct super_block *sb)
generic_shutdown_super(sb);
}
-static int ext_set(struct super_block *sb, void *data)
+static int ext_init_fs_context(struct fs_context *fc)
+{
+ return 0;
+}
+
+static int ext_set(struct super_block *sb, struct fs_context *fc)
{
return 0;
}
static struct file_system_type ext_fs_type = {
- .name = "extents test",
- .kill_sb = ext_kill_sb,
+ .name = "extents test",
+ .init_fs_context = ext_init_fs_context,
+ .kill_sb = ext_kill_sb,
};
static void extents_kunit_exit(struct kunit *test)
@@ -223,6 +230,7 @@ static int extents_kunit_init(struct kunit *test)
struct ext4_inode_info *ei;
struct inode *inode;
struct super_block *sb;
+ struct fs_context *fc;
struct ext4_sb_info *sbi = NULL;
struct kunit_ext_test_param *param =
(struct kunit_ext_test_param *)(test->param_value);
@@ -232,7 +240,13 @@ static int extents_kunit_init(struct kunit *test)
if (sbi == NULL)
return -ENOMEM;
- sb = sget(&ext_fs_type, NULL, ext_set, 0, NULL);
+ fc = fs_context_for_mount(&ext_fs_type, 0);
+ if (IS_ERR(fc)) {
+ kfree(sbi);
+ return PTR_ERR(fc);
+ }
+ sb = sget_fc(fc, NULL, ext_set);
+ put_fs_context(fc);
if (IS_ERR(sb)) {
kfree(sbi);
return PTR_ERR(sb);
--
2.47.3
^ permalink raw reply related [flat|nested] 8+ messages in thread* Re: [PATCH v2 1/4] ext4: convert extents KUnit test to sget_fc()
2026-05-29 8:43 ` [PATCH v2 1/4] ext4: convert extents KUnit test to sget_fc() Christian Brauner
@ 2026-06-02 11:17 ` Jan Kara
0 siblings, 0 replies; 8+ messages in thread
From: Jan Kara @ 2026-06-02 11:17 UTC (permalink / raw)
To: Christian Brauner
Cc: linux-fsdevel, Theodore Ts'o, Andreas Dilger, Jan Kara,
Ritesh Harjani (IBM), linux-ext4, linux-cifs, Alexander Viro
On Fri 29-05-26 10:43:40, Christian Brauner wrote:
> The extents KUnit test uses sget() to get an initialized superblock for
> its fake file_system_type. sget() predates fs_context and we want to
> retire it. Switch this caller over to sget_fc().
>
> Add a no-op ext_init_fs_context() so fs_context_for_mount() has
> something to call on the fake fs_type. ext_set() now takes a struct
> fs_context * (still a no-op). extents_kunit_init() allocates the fc,
> hands it to sget_fc() and drops the fc reference once the sb is
> published. sget_fc() does not retain a pointer to it.
>
> No functional change for the test.
>
> Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
Looks good. Feel free to add:
Reviewed-by: Jan Kara <jack@suse.cz>
Honza
> ---
> fs/ext4/extents-test.c | 22 ++++++++++++++++++----
> 1 file changed, 18 insertions(+), 4 deletions(-)
>
> diff --git a/fs/ext4/extents-test.c b/fs/ext4/extents-test.c
> index 6b53a3f39fcd..bd7795a82607 100644
> --- a/fs/ext4/extents-test.c
> +++ b/fs/ext4/extents-test.c
> @@ -37,6 +37,7 @@
>
> #include <kunit/test.h>
> #include <kunit/static_stub.h>
> +#include <linux/fs_context.h>
> #include <linux/gfp_types.h>
> #include <linux/stddef.h>
>
> @@ -130,14 +131,20 @@ static void ext_kill_sb(struct super_block *sb)
> generic_shutdown_super(sb);
> }
>
> -static int ext_set(struct super_block *sb, void *data)
> +static int ext_init_fs_context(struct fs_context *fc)
> +{
> + return 0;
> +}
> +
> +static int ext_set(struct super_block *sb, struct fs_context *fc)
> {
> return 0;
> }
>
> static struct file_system_type ext_fs_type = {
> - .name = "extents test",
> - .kill_sb = ext_kill_sb,
> + .name = "extents test",
> + .init_fs_context = ext_init_fs_context,
> + .kill_sb = ext_kill_sb,
> };
>
> static void extents_kunit_exit(struct kunit *test)
> @@ -223,6 +230,7 @@ static int extents_kunit_init(struct kunit *test)
> struct ext4_inode_info *ei;
> struct inode *inode;
> struct super_block *sb;
> + struct fs_context *fc;
> struct ext4_sb_info *sbi = NULL;
> struct kunit_ext_test_param *param =
> (struct kunit_ext_test_param *)(test->param_value);
> @@ -232,7 +240,13 @@ static int extents_kunit_init(struct kunit *test)
> if (sbi == NULL)
> return -ENOMEM;
>
> - sb = sget(&ext_fs_type, NULL, ext_set, 0, NULL);
> + fc = fs_context_for_mount(&ext_fs_type, 0);
> + if (IS_ERR(fc)) {
> + kfree(sbi);
> + return PTR_ERR(fc);
> + }
> + sb = sget_fc(fc, NULL, ext_set);
> + put_fs_context(fc);
> if (IS_ERR(sb)) {
> kfree(sbi);
> return PTR_ERR(sb);
>
> --
> 2.47.3
>
--
Jan Kara <jack@suse.com>
SUSE Labs, CR
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH v2 2/4] ext4: convert mballoc KUnit test to sget_fc()
2026-05-29 8:43 [PATCH v2 0/4] super: retire sget() Christian Brauner
2026-05-29 8:43 ` [PATCH v2 1/4] ext4: convert extents KUnit test to sget_fc() Christian Brauner
@ 2026-05-29 8:43 ` Christian Brauner
2026-06-02 11:18 ` Jan Kara
2026-05-29 8:43 ` [PATCH v2 3/4] smb: client: convert cifs_smb3_do_mount() " Christian Brauner
2026-05-29 8:43 ` [PATCH v2 4/4] fs: retire sget() Christian Brauner
3 siblings, 1 reply; 8+ messages in thread
From: Christian Brauner @ 2026-05-29 8:43 UTC (permalink / raw)
To: linux-fsdevel
Cc: Theodore Ts'o, Andreas Dilger, Jan Kara, Ritesh Harjani (IBM),
linux-ext4, linux-cifs, Alexander Viro,
Christian Brauner (Amutable)
Same treatment as the extents KUnit test. The mballoc test uses sget()
as a thin "give me an initialized superblock" wrapper for a fake
file_system_type. Move it onto sget_fc() so sget() can go away.
Add a no-op mbt_init_fs_context() so fs_context_for_mount() has
something to call on the fake fs_type. mbt_set() now takes a struct
fs_context * (still a no-op). mbt_ext4_alloc_super_block() allocates
the fc, hands it to sget_fc() and drops the fc reference once the sb
is published.
No functional change.
Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
---
fs/ext4/mballoc-test.c | 17 +++++++++++++++--
1 file changed, 15 insertions(+), 2 deletions(-)
diff --git a/fs/ext4/mballoc-test.c b/fs/ext4/mballoc-test.c
index 90ed505fa4b1..d90da44aadbd 100644
--- a/fs/ext4/mballoc-test.c
+++ b/fs/ext4/mballoc-test.c
@@ -5,6 +5,7 @@
#include <kunit/test.h>
#include <kunit/static_stub.h>
+#include <linux/fs_context.h>
#include <linux/random.h>
#include "ext4.h"
@@ -63,8 +64,14 @@ static void mbt_kill_sb(struct super_block *sb)
generic_shutdown_super(sb);
}
+static int mbt_init_fs_context(struct fs_context *fc)
+{
+ return 0;
+}
+
static struct file_system_type mbt_fs_type = {
.name = "mballoc test",
+ .init_fs_context = mbt_init_fs_context,
.kill_sb = mbt_kill_sb,
};
@@ -127,7 +134,7 @@ static void mbt_mb_release(struct super_block *sb)
kfree(sb->s_bdev);
}
-static int mbt_set(struct super_block *sb, void *data)
+static int mbt_set(struct super_block *sb, struct fs_context *fc)
{
return 0;
}
@@ -136,13 +143,19 @@ static struct super_block *mbt_ext4_alloc_super_block(void)
{
struct mbt_ext4_super_block *fsb;
struct super_block *sb;
+ struct fs_context *fc;
struct ext4_sb_info *sbi;
fsb = kzalloc_obj(*fsb);
if (fsb == NULL)
return NULL;
- sb = sget(&mbt_fs_type, NULL, mbt_set, 0, NULL);
+ fc = fs_context_for_mount(&mbt_fs_type, 0);
+ if (IS_ERR(fc))
+ goto out;
+
+ sb = sget_fc(fc, NULL, mbt_set);
+ put_fs_context(fc);
if (IS_ERR(sb))
goto out;
--
2.47.3
^ permalink raw reply related [flat|nested] 8+ messages in thread* Re: [PATCH v2 2/4] ext4: convert mballoc KUnit test to sget_fc()
2026-05-29 8:43 ` [PATCH v2 2/4] ext4: convert mballoc " Christian Brauner
@ 2026-06-02 11:18 ` Jan Kara
0 siblings, 0 replies; 8+ messages in thread
From: Jan Kara @ 2026-06-02 11:18 UTC (permalink / raw)
To: Christian Brauner
Cc: linux-fsdevel, Theodore Ts'o, Andreas Dilger, Jan Kara,
Ritesh Harjani (IBM), linux-ext4, linux-cifs, Alexander Viro
On Fri 29-05-26 10:43:41, Christian Brauner wrote:
> Same treatment as the extents KUnit test. The mballoc test uses sget()
> as a thin "give me an initialized superblock" wrapper for a fake
> file_system_type. Move it onto sget_fc() so sget() can go away.
>
> Add a no-op mbt_init_fs_context() so fs_context_for_mount() has
> something to call on the fake fs_type. mbt_set() now takes a struct
> fs_context * (still a no-op). mbt_ext4_alloc_super_block() allocates
> the fc, hands it to sget_fc() and drops the fc reference once the sb
> is published.
>
> No functional change.
>
> Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
Looks good. Feel free to add:
Reviewed-by: Jan Kara <jack@suse.cz>
Honza
> ---
> fs/ext4/mballoc-test.c | 17 +++++++++++++++--
> 1 file changed, 15 insertions(+), 2 deletions(-)
>
> diff --git a/fs/ext4/mballoc-test.c b/fs/ext4/mballoc-test.c
> index 90ed505fa4b1..d90da44aadbd 100644
> --- a/fs/ext4/mballoc-test.c
> +++ b/fs/ext4/mballoc-test.c
> @@ -5,6 +5,7 @@
>
> #include <kunit/test.h>
> #include <kunit/static_stub.h>
> +#include <linux/fs_context.h>
> #include <linux/random.h>
>
> #include "ext4.h"
> @@ -63,8 +64,14 @@ static void mbt_kill_sb(struct super_block *sb)
> generic_shutdown_super(sb);
> }
>
> +static int mbt_init_fs_context(struct fs_context *fc)
> +{
> + return 0;
> +}
> +
> static struct file_system_type mbt_fs_type = {
> .name = "mballoc test",
> + .init_fs_context = mbt_init_fs_context,
> .kill_sb = mbt_kill_sb,
> };
>
> @@ -127,7 +134,7 @@ static void mbt_mb_release(struct super_block *sb)
> kfree(sb->s_bdev);
> }
>
> -static int mbt_set(struct super_block *sb, void *data)
> +static int mbt_set(struct super_block *sb, struct fs_context *fc)
> {
> return 0;
> }
> @@ -136,13 +143,19 @@ static struct super_block *mbt_ext4_alloc_super_block(void)
> {
> struct mbt_ext4_super_block *fsb;
> struct super_block *sb;
> + struct fs_context *fc;
> struct ext4_sb_info *sbi;
>
> fsb = kzalloc_obj(*fsb);
> if (fsb == NULL)
> return NULL;
>
> - sb = sget(&mbt_fs_type, NULL, mbt_set, 0, NULL);
> + fc = fs_context_for_mount(&mbt_fs_type, 0);
> + if (IS_ERR(fc))
> + goto out;
> +
> + sb = sget_fc(fc, NULL, mbt_set);
> + put_fs_context(fc);
> if (IS_ERR(sb))
> goto out;
>
>
> --
> 2.47.3
>
--
Jan Kara <jack@suse.com>
SUSE Labs, CR
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH v2 3/4] smb: client: convert cifs_smb3_do_mount() to sget_fc()
2026-05-29 8:43 [PATCH v2 0/4] super: retire sget() Christian Brauner
2026-05-29 8:43 ` [PATCH v2 1/4] ext4: convert extents KUnit test to sget_fc() Christian Brauner
2026-05-29 8:43 ` [PATCH v2 2/4] ext4: convert mballoc " Christian Brauner
@ 2026-05-29 8:43 ` Christian Brauner
2026-05-29 8:43 ` [PATCH v2 4/4] fs: retire sget() Christian Brauner
3 siblings, 0 replies; 8+ messages in thread
From: Christian Brauner @ 2026-05-29 8:43 UTC (permalink / raw)
To: linux-fsdevel
Cc: Theodore Ts'o, Andreas Dilger, Jan Kara, Ritesh Harjani (IBM),
linux-ext4, linux-cifs, Alexander Viro,
Christian Brauner (Amutable)
The CIFS mount path already runs through fs_context: smb3_get_tree()
calls smb3_get_tree_common() with a struct fs_context * in hand. But
the fc is dropped on the way to sget(). Plumb it through to sget_fc()
so the legacy sget() interface can go.
cifs_smb3_do_mount() now takes (struct fs_context *, struct
smb3_fs_context *). The old (fs_type, flags) pair is reconstructed
from fc->fs_type and fc->sb_flags. The flags argument was always
passed as 0 by the sole caller anyway. The cifs_dbg diagnostic now
prints fc->sb_flags directly.
cifs_match_super() and cifs_set_super() were the two void-data
callbacks for sget(). The match callback now takes
(struct super_block *, struct fs_context *) and reads struct
cifs_mnt_data out of fc->sget_key. The set callback is gone entirely:
sget_fc() pre-populates sb->s_fs_info from fc->s_fs_info before
invoking set() so set_anon_super_fc() (which just allocates an anon
bdev) is sufficient.
Before sget_fc() we stash cifs_sb in fc->s_fs_info, the per-mount data
in fc->sget_key and force fc->sb_flags to SB_NODIRATIME | SB_NOATIME
to reproduce the previous hard-coded behaviour (alloc_super() reads
fc->sb_flags). The original sb_flags is saved and restored around the
call so the rest of the mount path sees the same fc semantics as
before.
mnt_data.flags keeps its historical value of 0 so the CIFS_MS_MASK
comparison in compare_mount_options() returns the same (always-equal)
result.
No functional change. With this in place sget() has no remaining CIFS
caller.
Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
---
fs/smb/client/cifsfs.c | 43 ++++++++++++++++++++++++++-----------------
fs/smb/client/cifsfs.h | 3 ++-
fs/smb/client/cifsproto.h | 3 ++-
fs/smb/client/connect.c | 5 +++--
fs/smb/client/fs_context.c | 2 +-
5 files changed, 34 insertions(+), 22 deletions(-)
diff --git a/fs/smb/client/cifsfs.c b/fs/smb/client/cifsfs.c
index 9f76b0347fa9..d5074e3fbb85 100644
--- a/fs/smb/client/cifsfs.c
+++ b/fs/smb/client/cifsfs.c
@@ -12,6 +12,7 @@
#include <linux/module.h>
#include <linux/fs.h>
+#include <linux/fs_context.h>
#include <linux/filelock.h>
#include <linux/mount.h>
#include <linux/slab.h>
@@ -966,26 +967,19 @@ cifs_get_root(struct smb3_fs_context *ctx, struct super_block *sb)
return dentry;
}
-static int cifs_set_super(struct super_block *sb, void *data)
-{
- struct cifs_mnt_data *mnt_data = data;
- sb->s_fs_info = mnt_data->cifs_sb;
- return set_anon_super(sb, NULL);
-}
-
struct dentry *
-cifs_smb3_do_mount(struct file_system_type *fs_type,
- int flags, struct smb3_fs_context *old_ctx)
+cifs_smb3_do_mount(struct fs_context *fc, struct smb3_fs_context *old_ctx)
{
struct cifs_mnt_data mnt_data;
struct cifs_sb_info *cifs_sb;
struct super_block *sb;
struct dentry *root;
+ unsigned int saved_sb_flags;
int rc;
if (cifsFYI) {
- cifs_dbg(FYI, "%s: devname=%s flags=0x%x\n", __func__,
- old_ctx->source, flags);
+ cifs_dbg(FYI, "%s: devname=%s sb_flags=0x%x\n", __func__,
+ old_ctx->source, fc->sb_flags);
} else {
cifs_info("Attempting to mount %s\n", old_ctx->source);
}
@@ -1012,7 +1006,7 @@ cifs_smb3_do_mount(struct file_system_type *fs_type,
rc = cifs_mount(cifs_sb, cifs_sb->ctx);
if (rc) {
- if (!(flags & SB_SILENT))
+ if (!(fc->sb_flags & SB_SILENT))
cifs_dbg(VFS, "cifs_mount failed w/return code = %d\n",
rc);
root = ERR_PTR(rc);
@@ -1021,12 +1015,27 @@ cifs_smb3_do_mount(struct file_system_type *fs_type,
mnt_data.ctx = cifs_sb->ctx;
mnt_data.cifs_sb = cifs_sb;
- mnt_data.flags = flags;
+ mnt_data.flags = 0;
- /* BB should we make this contingent on mount parm? */
- flags |= SB_NODIRATIME | SB_NOATIME;
-
- sb = sget(fs_type, cifs_match_super, cifs_set_super, flags, &mnt_data);
+ /*
+ * sb->s_flags is set from fc->sb_flags by alloc_super(). CIFS has
+ * historically forced SB_NODIRATIME | SB_NOATIME on every mount and
+ * ignored the caller-supplied SB_* flags. Preserve that behaviour by
+ * overriding fc->sb_flags around the sget_fc() call.
+ *
+ * Hand cifs_sb to sget_fc() via fc->s_fs_info; sget_fc() copies it
+ * onto sb->s_fs_info before running set() and clears fc->s_fs_info
+ * on successful publish. Pass the rest of the per-mount context to
+ * cifs_match_super() through fc->sget_key.
+ */
+ saved_sb_flags = fc->sb_flags;
+ fc->sb_flags = SB_NODIRATIME | SB_NOATIME;
+ fc->s_fs_info = cifs_sb;
+ fc->sget_key = &mnt_data;
+ sb = sget_fc(fc, cifs_match_super, set_anon_super_fc);
+ fc->sget_key = NULL;
+ fc->s_fs_info = NULL;
+ fc->sb_flags = saved_sb_flags;
if (IS_ERR(sb)) {
cifs_umount(cifs_sb);
return ERR_CAST(sb);
diff --git a/fs/smb/client/cifsfs.h b/fs/smb/client/cifsfs.h
index c455b15f2778..0a93f48924a5 100644
--- a/fs/smb/client/cifsfs.h
+++ b/fs/smb/client/cifsfs.h
@@ -144,8 +144,9 @@ ssize_t cifs_file_copychunk_range(unsigned int xid, struct file *src_file,
long cifs_ioctl(struct file *filep, unsigned int command, unsigned long arg);
void cifs_setsize(struct inode *inode, loff_t offset);
+struct fs_context;
struct smb3_fs_context;
-struct dentry *cifs_smb3_do_mount(struct file_system_type *fs_type, int flags,
+struct dentry *cifs_smb3_do_mount(struct fs_context *fc,
struct smb3_fs_context *old_ctx);
char *cifs_silly_fullpath(struct dentry *dentry);
diff --git a/fs/smb/client/cifsproto.h b/fs/smb/client/cifsproto.h
index 4a25afda9448..a39572cbaadb 100644
--- a/fs/smb/client/cifsproto.h
+++ b/fs/smb/client/cifsproto.h
@@ -19,6 +19,7 @@
struct statfs;
struct smb_rqst;
struct smb3_fs_context;
+struct fs_context;
/*
*****************************************************************
@@ -236,7 +237,7 @@ void cifs_mount_put_conns(struct cifs_mount_ctx *mnt_ctx);
int cifs_mount_get_session(struct cifs_mount_ctx *mnt_ctx);
int cifs_is_path_remote(struct cifs_mount_ctx *mnt_ctx);
int cifs_mount_get_tcon(struct cifs_mount_ctx *mnt_ctx);
-int cifs_match_super(struct super_block *sb, void *data);
+int cifs_match_super(struct super_block *sb, struct fs_context *fc);
int cifs_mount(struct cifs_sb_info *cifs_sb, struct smb3_fs_context *ctx);
void cifs_umount(struct cifs_sb_info *cifs_sb);
void cifs_mark_open_files_invalid(struct cifs_tcon *tcon);
diff --git a/fs/smb/client/connect.c b/fs/smb/client/connect.c
index dcde25da468d..79762e6bbe50 100644
--- a/fs/smb/client/connect.c
+++ b/fs/smb/client/connect.c
@@ -6,6 +6,7 @@
*
*/
#include <linux/fs.h>
+#include <linux/fs_context.h>
#include <linux/net.h>
#include <linux/string.h>
#include <linux/sched/mm.h>
@@ -2991,9 +2992,9 @@ static int match_prepath(struct super_block *sb,
}
int
-cifs_match_super(struct super_block *sb, void *data)
+cifs_match_super(struct super_block *sb, struct fs_context *fc)
{
- struct cifs_mnt_data *mnt_data = data;
+ struct cifs_mnt_data *mnt_data = fc->sget_key;
struct smb3_fs_context *ctx;
struct cifs_sb_info *cifs_sb;
struct TCP_Server_Info *tcp_srv;
diff --git a/fs/smb/client/fs_context.c b/fs/smb/client/fs_context.c
index b9544eb0381b..6aba4e1c9c27 100644
--- a/fs/smb/client/fs_context.c
+++ b/fs/smb/client/fs_context.c
@@ -920,7 +920,7 @@ static int smb3_get_tree_common(struct fs_context *fc)
struct dentry *root;
int rc = 0;
- root = cifs_smb3_do_mount(fc->fs_type, 0, ctx);
+ root = cifs_smb3_do_mount(fc, ctx);
if (IS_ERR(root))
return PTR_ERR(root);
--
2.47.3
^ permalink raw reply related [flat|nested] 8+ messages in thread* [PATCH v2 4/4] fs: retire sget()
2026-05-29 8:43 [PATCH v2 0/4] super: retire sget() Christian Brauner
` (2 preceding siblings ...)
2026-05-29 8:43 ` [PATCH v2 3/4] smb: client: convert cifs_smb3_do_mount() " Christian Brauner
@ 2026-05-29 8:43 ` Christian Brauner
2026-06-02 11:20 ` Jan Kara
3 siblings, 1 reply; 8+ messages in thread
From: Christian Brauner @ 2026-05-29 8:43 UTC (permalink / raw)
To: linux-fsdevel
Cc: Theodore Ts'o, Andreas Dilger, Jan Kara, Ritesh Harjani (IBM),
linux-ext4, linux-cifs, Alexander Viro,
Christian Brauner (Amutable)
sget() and sget_fc() have lived side by side as near-duplicate
find-or-create-and-publish helpers for the legacy and fs_context mount
APIs. The three remaining in-tree callers (CIFS plus the ext4 extents
and mballoc KUnit tests) have all been moved to sget_fc(). Nothing
calls sget() anymore.
Delete sget() from fs/super.c and the prototype in <linux/fs.h>.
Update the two comments that referred to "sget()" or "sget{_fc}()" to
just say "sget_fc()".
This removes ~60 lines of code that only existed to be kept in
lockstep with sget_fc() on every superblock publish-path change.
Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
---
fs/btrfs/super.c | 2 +-
fs/super.c | 71 ++++--------------------------------------------------
include/linux/fs.h | 4 ---
3 files changed, 6 insertions(+), 71 deletions(-)
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c
index b26aa9169e83..636154861d7c 100644
--- a/fs/btrfs/super.c
+++ b/fs/btrfs/super.c
@@ -2052,7 +2052,7 @@ static int btrfs_get_tree_subvol(struct fs_context *fc)
* then open_ctree will properly initialize the file system specific
* settings later. btrfs_init_fs_info initializes the static elements
* of the fs_info (locks and such) to make cleanup easier if we find a
- * superblock with our given fs_devices later on at sget() time.
+ * superblock with our given fs_devices later on at sget_fc() time.
*/
fs_info = kvzalloc_obj(struct btrfs_fs_info);
if (!fs_info)
diff --git a/fs/super.c b/fs/super.c
index 378e81efe643..5fe8cea9f8fe 100644
--- a/fs/super.c
+++ b/fs/super.c
@@ -328,7 +328,7 @@ static struct super_block *alloc_super(struct file_system_type *type, int flags,
init_rwsem(&s->s_umount);
lockdep_set_class(&s->s_umount, &type->s_umount_key);
/*
- * sget() can have s_umount recursion.
+ * sget_fc() can have s_umount recursion.
*
* When it cannot find a suitable sb, it allocates a new
* one (this one), and tries again to find a suitable old
@@ -439,7 +439,7 @@ static void kill_super_notify(struct super_block *sb)
/*
* Remove it from @fs_supers so it isn't found by new
- * sget{_fc}() walkers anymore. Any concurrent mounter still
+ * sget_fc() walkers anymore. Any concurrent mounter still
* managing to grab a temporary reference is guaranteed to
* already see SB_DYING and will wait until we notify them about
* SB_DEAD.
@@ -517,7 +517,7 @@ EXPORT_SYMBOL(deactivate_super);
* @sb: superblock to acquire
*
* Acquire a temporary reference on a superblock and try to trade it for
- * an active reference. This is used in sget{_fc}() to wait for a
+ * an active reference. This is used in sget_fc() to wait for a
* superblock to either become SB_BORN or for it to pass through
* sb->kill() and be marked as SB_DEAD.
*
@@ -673,11 +673,11 @@ void generic_shutdown_super(struct super_block *sb)
/*
* Broadcast to everyone that grabbed a temporary reference to this
* superblock before we removed it from @fs_supers that the superblock
- * is dying. Every walker of @fs_supers outside of sget{_fc}() will now
+ * is dying. Every walker of @fs_supers outside of sget_fc() will now
* discard this superblock and treat it as dead.
*
* We leave the superblock on @fs_supers so it can be found by
- * sget{_fc}() until we passed sb->kill_sb().
+ * sget_fc() until we passed sb->kill_sb().
*/
super_wake(sb, SB_DYING);
super_unlock_excl(sb);
@@ -808,67 +808,6 @@ struct super_block *sget_fc(struct fs_context *fc,
}
EXPORT_SYMBOL(sget_fc);
-/**
- * sget - find or create a superblock
- * @type: filesystem type superblock should belong to
- * @test: comparison callback
- * @set: setup callback
- * @flags: mount flags
- * @data: argument to each of them
- */
-struct super_block *sget(struct file_system_type *type,
- int (*test)(struct super_block *,void *),
- int (*set)(struct super_block *,void *),
- int flags,
- void *data)
-{
- struct user_namespace *user_ns = current_user_ns();
- struct super_block *s = NULL;
- struct super_block *old;
- int err;
-
-retry:
- spin_lock(&sb_lock);
- if (test) {
- hlist_for_each_entry(old, &type->fs_supers, s_instances) {
- if (!test(old, data))
- continue;
- if (user_ns != old->s_user_ns) {
- spin_unlock(&sb_lock);
- destroy_unused_super(s);
- return ERR_PTR(-EBUSY);
- }
- if (!grab_super(old))
- goto retry;
- destroy_unused_super(s);
- return old;
- }
- }
- if (!s) {
- spin_unlock(&sb_lock);
- s = alloc_super(type, flags, user_ns);
- if (!s)
- return ERR_PTR(-ENOMEM);
- goto retry;
- }
-
- err = set(s, data);
- if (err) {
- spin_unlock(&sb_lock);
- destroy_unused_super(s);
- return ERR_PTR(err);
- }
- s->s_type = type;
- strscpy(s->s_id, type->name, sizeof(s->s_id));
- list_add_tail(&s->s_list, &super_blocks);
- hlist_add_head(&s->s_instances, &type->fs_supers);
- spin_unlock(&sb_lock);
- get_filesystem(type);
- shrinker_register(s->s_shrink);
- return s;
-}
-EXPORT_SYMBOL(sget);
-
void drop_super(struct super_block *sb)
{
super_unlock_shared(sb);
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 11559c513dfb..6dbe3218dc1e 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -2327,10 +2327,6 @@ void free_anon_bdev(dev_t);
struct super_block *sget_fc(struct fs_context *fc,
int (*test)(struct super_block *, struct fs_context *),
int (*set)(struct super_block *, struct fs_context *));
-struct super_block *sget(struct file_system_type *type,
- int (*test)(struct super_block *,void *),
- int (*set)(struct super_block *,void *),
- int flags, void *data);
struct super_block *sget_dev(struct fs_context *fc, dev_t dev);
/* Alas, no aliases. Too much hassle with bringing module.h everywhere */
--
2.47.3
^ permalink raw reply related [flat|nested] 8+ messages in thread* Re: [PATCH v2 4/4] fs: retire sget()
2026-05-29 8:43 ` [PATCH v2 4/4] fs: retire sget() Christian Brauner
@ 2026-06-02 11:20 ` Jan Kara
0 siblings, 0 replies; 8+ messages in thread
From: Jan Kara @ 2026-06-02 11:20 UTC (permalink / raw)
To: Christian Brauner
Cc: linux-fsdevel, Theodore Ts'o, Andreas Dilger, Jan Kara,
Ritesh Harjani (IBM), linux-ext4, linux-cifs, Alexander Viro
On Fri 29-05-26 10:43:43, Christian Brauner wrote:
> sget() and sget_fc() have lived side by side as near-duplicate
> find-or-create-and-publish helpers for the legacy and fs_context mount
> APIs. The three remaining in-tree callers (CIFS plus the ext4 extents
> and mballoc KUnit tests) have all been moved to sget_fc(). Nothing
> calls sget() anymore.
>
> Delete sget() from fs/super.c and the prototype in <linux/fs.h>.
> Update the two comments that referred to "sget()" or "sget{_fc}()" to
> just say "sget_fc()".
>
> This removes ~60 lines of code that only existed to be kept in
> lockstep with sget_fc() on every superblock publish-path change.
>
> Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
Looks good. Feel free to add:
Reviewed-by: Jan Kara <jack@suse.cz>
Honza
> ---
> fs/btrfs/super.c | 2 +-
> fs/super.c | 71 ++++--------------------------------------------------
> include/linux/fs.h | 4 ---
> 3 files changed, 6 insertions(+), 71 deletions(-)
>
> diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c
> index b26aa9169e83..636154861d7c 100644
> --- a/fs/btrfs/super.c
> +++ b/fs/btrfs/super.c
> @@ -2052,7 +2052,7 @@ static int btrfs_get_tree_subvol(struct fs_context *fc)
> * then open_ctree will properly initialize the file system specific
> * settings later. btrfs_init_fs_info initializes the static elements
> * of the fs_info (locks and such) to make cleanup easier if we find a
> - * superblock with our given fs_devices later on at sget() time.
> + * superblock with our given fs_devices later on at sget_fc() time.
> */
> fs_info = kvzalloc_obj(struct btrfs_fs_info);
> if (!fs_info)
> diff --git a/fs/super.c b/fs/super.c
> index 378e81efe643..5fe8cea9f8fe 100644
> --- a/fs/super.c
> +++ b/fs/super.c
> @@ -328,7 +328,7 @@ static struct super_block *alloc_super(struct file_system_type *type, int flags,
> init_rwsem(&s->s_umount);
> lockdep_set_class(&s->s_umount, &type->s_umount_key);
> /*
> - * sget() can have s_umount recursion.
> + * sget_fc() can have s_umount recursion.
> *
> * When it cannot find a suitable sb, it allocates a new
> * one (this one), and tries again to find a suitable old
> @@ -439,7 +439,7 @@ static void kill_super_notify(struct super_block *sb)
>
> /*
> * Remove it from @fs_supers so it isn't found by new
> - * sget{_fc}() walkers anymore. Any concurrent mounter still
> + * sget_fc() walkers anymore. Any concurrent mounter still
> * managing to grab a temporary reference is guaranteed to
> * already see SB_DYING and will wait until we notify them about
> * SB_DEAD.
> @@ -517,7 +517,7 @@ EXPORT_SYMBOL(deactivate_super);
> * @sb: superblock to acquire
> *
> * Acquire a temporary reference on a superblock and try to trade it for
> - * an active reference. This is used in sget{_fc}() to wait for a
> + * an active reference. This is used in sget_fc() to wait for a
> * superblock to either become SB_BORN or for it to pass through
> * sb->kill() and be marked as SB_DEAD.
> *
> @@ -673,11 +673,11 @@ void generic_shutdown_super(struct super_block *sb)
> /*
> * Broadcast to everyone that grabbed a temporary reference to this
> * superblock before we removed it from @fs_supers that the superblock
> - * is dying. Every walker of @fs_supers outside of sget{_fc}() will now
> + * is dying. Every walker of @fs_supers outside of sget_fc() will now
> * discard this superblock and treat it as dead.
> *
> * We leave the superblock on @fs_supers so it can be found by
> - * sget{_fc}() until we passed sb->kill_sb().
> + * sget_fc() until we passed sb->kill_sb().
> */
> super_wake(sb, SB_DYING);
> super_unlock_excl(sb);
> @@ -808,67 +808,6 @@ struct super_block *sget_fc(struct fs_context *fc,
> }
> EXPORT_SYMBOL(sget_fc);
>
> -/**
> - * sget - find or create a superblock
> - * @type: filesystem type superblock should belong to
> - * @test: comparison callback
> - * @set: setup callback
> - * @flags: mount flags
> - * @data: argument to each of them
> - */
> -struct super_block *sget(struct file_system_type *type,
> - int (*test)(struct super_block *,void *),
> - int (*set)(struct super_block *,void *),
> - int flags,
> - void *data)
> -{
> - struct user_namespace *user_ns = current_user_ns();
> - struct super_block *s = NULL;
> - struct super_block *old;
> - int err;
> -
> -retry:
> - spin_lock(&sb_lock);
> - if (test) {
> - hlist_for_each_entry(old, &type->fs_supers, s_instances) {
> - if (!test(old, data))
> - continue;
> - if (user_ns != old->s_user_ns) {
> - spin_unlock(&sb_lock);
> - destroy_unused_super(s);
> - return ERR_PTR(-EBUSY);
> - }
> - if (!grab_super(old))
> - goto retry;
> - destroy_unused_super(s);
> - return old;
> - }
> - }
> - if (!s) {
> - spin_unlock(&sb_lock);
> - s = alloc_super(type, flags, user_ns);
> - if (!s)
> - return ERR_PTR(-ENOMEM);
> - goto retry;
> - }
> -
> - err = set(s, data);
> - if (err) {
> - spin_unlock(&sb_lock);
> - destroy_unused_super(s);
> - return ERR_PTR(err);
> - }
> - s->s_type = type;
> - strscpy(s->s_id, type->name, sizeof(s->s_id));
> - list_add_tail(&s->s_list, &super_blocks);
> - hlist_add_head(&s->s_instances, &type->fs_supers);
> - spin_unlock(&sb_lock);
> - get_filesystem(type);
> - shrinker_register(s->s_shrink);
> - return s;
> -}
> -EXPORT_SYMBOL(sget);
> -
> void drop_super(struct super_block *sb)
> {
> super_unlock_shared(sb);
> diff --git a/include/linux/fs.h b/include/linux/fs.h
> index 11559c513dfb..6dbe3218dc1e 100644
> --- a/include/linux/fs.h
> +++ b/include/linux/fs.h
> @@ -2327,10 +2327,6 @@ void free_anon_bdev(dev_t);
> struct super_block *sget_fc(struct fs_context *fc,
> int (*test)(struct super_block *, struct fs_context *),
> int (*set)(struct super_block *, struct fs_context *));
> -struct super_block *sget(struct file_system_type *type,
> - int (*test)(struct super_block *,void *),
> - int (*set)(struct super_block *,void *),
> - int flags, void *data);
> struct super_block *sget_dev(struct fs_context *fc, dev_t dev);
>
> /* Alas, no aliases. Too much hassle with bringing module.h everywhere */
>
> --
> 2.47.3
>
--
Jan Kara <jack@suse.com>
SUSE Labs, CR
^ permalink raw reply [flat|nested] 8+ messages in thread