• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * fs/sharefs/main.c
4  *
5  * Copyright (c) 1998-2022 Erez Zadok
6  * Copyright (c) 2009	   Shrikar Archak
7  * Copyright (c) 2003-2022 Stony Brook University
8  * Copyright (c) 2003-2022 The Research Foundation of SUNY
9  * Copyright (c) 2023 Huawei Device Co., Ltd.
10  */
11 
12 #include <linux/module.h>
13 #include "sharefs.h"
14 #include "authentication.h"
15 
16 
17 struct sharefs_mount_priv {
18 	const char *dev_name;
19 	const char *raw_data;
20 };
21 
22 /*
23  * There is no need to lock the sharefs_super_info's rwsem as there is no
24  * way anyone can have a reference to the superblock at this point in time.
25  */
sharefs_fill_super(struct super_block * sb,void * data,int silent)26 static int sharefs_fill_super(struct super_block *sb, void *data, int silent)
27 {
28 
29 	struct sharefs_mount_priv *priv = (struct sharefs_mount_priv *)data;
30 	const char *dev_name = priv->dev_name;
31 	const char *raw_data = priv->raw_data;
32 
33 	int err = 0;
34 	struct super_block *lower_sb;
35 	struct path lower_path;
36 	struct inode *inode;
37 
38 	/* parse lower path */
39 	err = kern_path(dev_name, LOOKUP_FOLLOW | LOOKUP_DIRECTORY,
40 			&lower_path);
41 	if (err) {
42 		printk(KERN_ERR	"sharefs: error accessing "
43 		       "lower directory '%s'\n", dev_name);
44 		goto out;
45 	}
46 
47 	/* allocate superblock private data */
48 	sb->s_fs_info = kzalloc(sizeof(struct sharefs_sb_info), GFP_KERNEL);
49 	if (!SHAREFS_SB(sb)) {
50 		printk(KERN_CRIT "sharefs: fill_super: out of memory\n");
51 		err = -ENOMEM;
52 		goto out_pput;
53 	}
54 
55 	/* set the lower superblock field of upper superblock */
56 	lower_sb = lower_path.dentry->d_sb;
57 	atomic_inc(&lower_sb->s_active);
58 	sharefs_set_lower_super(sb, lower_sb);
59 
60 	/* inherit maxbytes from lower file system */
61 	sb->s_maxbytes = lower_sb->s_maxbytes;
62 
63 	/*
64 	 * Our c/m/atime granularity is 1 ns because we may stack on file
65 	 * systems whose granularity is as good.
66 	 */
67 	sb->s_time_gran = 1;
68 
69 	sb->s_op = &sharefs_sops;
70 
71 	/* get a new inode and allocate our root dentry */
72 	inode = sharefs_iget(sb, d_inode(lower_path.dentry));
73 	if (IS_ERR(inode)) {
74 		err = PTR_ERR(inode);
75 		goto out_pput;
76 	}
77 	sharefs_root_inode_perm_init(inode);
78 	sb->s_root = d_make_root(inode);
79 	if (!sb->s_root) {
80 		err = -ENOMEM;
81 		goto out_pput;
82 	}
83 	d_set_d_op(sb->s_root, &sharefs_dops);
84 
85 	err = sharefs_parse_options(sb->s_fs_info, raw_data);
86 	if (err)
87 		goto out_pput;
88 
89 	/* link the upper and lower dentries */
90 	sb->s_root->d_fsdata = NULL;
91 	err = new_dentry_private_data(sb->s_root);
92 	if (err)
93 		goto out_pput;
94 
95 	/* if get here: cannot have error */
96 
97 	/* set the lower dentries for s_root */
98 	sharefs_set_lower_path(sb->s_root, &lower_path);
99 
100 	/*
101 	 * No need to call interpose because we already have a positive
102 	 * dentry, which was instantiated by d_make_root.  Just need to
103 	 * d_rehash it.
104 	 */
105 	d_rehash(sb->s_root);
106 	if (!silent)
107 		printk(KERN_INFO
108 		       "sharefs: mounted on top of %s type %s\n",
109 		       dev_name, lower_sb->s_type->name);
110 	goto out; /* all is well */
111 
112 	/*
113 	 * path_put is the only resource we need to free if an error occurred
114 	 * because returning an error from this function will cause
115 	 * generic_shutdown_super to be called, which will call
116 	 * sharefs_put_super, and that function will release any other
117 	 * resources we took.
118 	 */
119 out_pput:
120 	path_put(&lower_path);
121 out:
122 	return err;
123 }
124 
sharefs_mount(struct file_system_type * fs_type,int flags,const char * dev_name,void * raw_data)125 struct dentry *sharefs_mount(struct file_system_type *fs_type, int flags,
126 			    const char *dev_name, void *raw_data)
127 {
128 	struct sharefs_mount_priv priv = {
129 		.dev_name = dev_name,
130 		.raw_data = raw_data,
131 	};
132 
133 	/* sharefs needs a valid dev_name to get the lower_sb's metadata */
134 	if (!dev_name || !*dev_name)
135 		return ERR_PTR(-EINVAL);
136 
137 	return mount_nodev(fs_type, flags, &priv,
138 			   sharefs_fill_super);
139 }
140 
141 static struct file_system_type sharefs_fs_type = {
142 	.owner		= THIS_MODULE,
143 	.name		= SHAREFS_NAME,
144 	.mount		= sharefs_mount,
145 	.kill_sb	= generic_shutdown_super,
146 	.fs_flags	= 0,
147 };
148 MODULE_ALIAS_FS(SHAREFS_NAME);
149 
init_sharefs_fs(void)150 static int __init init_sharefs_fs(void)
151 {
152 	int err;
153 
154 	pr_info("Registering sharefs");
155 
156 	err = sharefs_init_inode_cache();
157 	if (err)
158 		goto out_err;
159 	err = sharefs_init_dentry_cache();
160 	if (err)
161 		goto out_err;
162 	err = register_filesystem(&sharefs_fs_type);
163 	if (err) {
164 		sharefs_err("share register failed!");
165 		goto out_err;
166 	}
167 
168 	err = sharefs_init_configfs();
169 	if (err)
170 		goto out_err;
171 	return 0;
172 out_err:
173 	sharefs_exit_configfs();
174 	sharefs_destroy_inode_cache();
175 	sharefs_destroy_dentry_cache();
176 	sharefs_err("sharefs init failed!");
177 	return err;
178 }
179 
exit_sharefs_fs(void)180 static void __exit exit_sharefs_fs(void)
181 {
182 	sharefs_destroy_inode_cache();
183 	sharefs_destroy_dentry_cache();
184 	unregister_filesystem(&sharefs_fs_type);
185 	pr_info("Completed sharefs module unload\n");
186 }
187 
188 MODULE_AUTHOR("Jingjing Mao");
189 MODULE_DESCRIPTION("Sharefs");
190 MODULE_LICENSE("GPL");
191 
192 module_init(init_sharefs_fs);
193 module_exit(exit_sharefs_fs);
194