xref: /linux/fs/nullfs.c (revision 23b0f90ba871f096474e1c27c3d14f455189d2d9)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /* Copyright (c) 2026 Christian Brauner <brauner@kernel.org> */
3 #include <linux/fs/super_types.h>
4 #include <linux/fs_context.h>
5 #include <linux/magic.h>
6 
7 static const struct super_operations nullfs_super_operations = {
8 	.statfs	= simple_statfs,
9 };
10 
11 static int nullfs_fs_fill_super(struct super_block *s, struct fs_context *fc)
12 {
13 	struct inode *inode;
14 
15 	s->s_maxbytes		= MAX_LFS_FILESIZE;
16 	s->s_blocksize		= PAGE_SIZE;
17 	s->s_blocksize_bits	= PAGE_SHIFT;
18 	s->s_magic		= NULL_FS_MAGIC;
19 	s->s_op			= &nullfs_super_operations;
20 	s->s_export_op		= NULL;
21 	s->s_xattr		= NULL;
22 	s->s_time_gran		= 1;
23 	s->s_d_flags		= 0;
24 
25 	inode = new_inode(s);
26 	if (!inode)
27 		return -ENOMEM;
28 
29 	/* nullfs is permanently empty... */
30 	make_empty_dir_inode(inode);
31 	simple_inode_init_ts(inode);
32 	inode->i_ino	= 1;
33 	/* ... and immutable. */
34 	inode->i_flags |= S_IMMUTABLE;
35 
36 	s->s_root = d_make_root(inode);
37 	if (!s->s_root)
38 		return -ENOMEM;
39 
40 	return 0;
41 }
42 
43 /*
44  * For now this is a single global instance. If needed we can make it
45  * mountable by userspace at which point we will need to make it
46  * multi-instance.
47  */
48 static int nullfs_fs_get_tree(struct fs_context *fc)
49 {
50 	return get_tree_single(fc, nullfs_fs_fill_super);
51 }
52 
53 static const struct fs_context_operations nullfs_fs_context_ops = {
54 	.get_tree	= nullfs_fs_get_tree,
55 };
56 
57 static int nullfs_init_fs_context(struct fs_context *fc)
58 {
59 	fc->ops		= &nullfs_fs_context_ops;
60 	fc->global	= true;
61 	fc->sb_flags	= SB_NOUSER;
62 	fc->s_iflags	= SB_I_NOEXEC | SB_I_NODEV;
63 	return 0;
64 }
65 
66 struct file_system_type nullfs_fs_type = {
67 	.name			= "nullfs",
68 	.init_fs_context	= nullfs_init_fs_context,
69 	.kill_sb		= kill_anon_super,
70 };
71