hc
2024-12-19 9370bb92b2d16684ee45cf24e879c93c509162da
kernel/fs/nfs/nfs4super.c
....@@ -1,10 +1,13 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
23 * Copyright (c) 2012 Bryan Schumaker <bjschuma@netapp.com>
34 */
45 #include <linux/init.h>
56 #include <linux/module.h>
7
+#include <linux/mount.h>
68 #include <linux/nfs4_mount.h>
79 #include <linux/nfs_fs.h>
10
+#include <linux/nfs_ssc.h>
811 #include "delegation.h"
912 #include "internal.h"
1013 #include "nfs4_fs.h"
....@@ -17,40 +20,10 @@
1720
1821 static int nfs4_write_inode(struct inode *inode, struct writeback_control *wbc);
1922 static void nfs4_evict_inode(struct inode *inode);
20
-static struct dentry *nfs4_remote_mount(struct file_system_type *fs_type,
21
- int flags, const char *dev_name, void *raw_data);
22
-static struct dentry *nfs4_referral_mount(struct file_system_type *fs_type,
23
- int flags, const char *dev_name, void *raw_data);
24
-static struct dentry *nfs4_remote_referral_mount(struct file_system_type *fs_type,
25
- int flags, const char *dev_name, void *raw_data);
26
-
27
-static struct file_system_type nfs4_remote_fs_type = {
28
- .owner = THIS_MODULE,
29
- .name = "nfs4",
30
- .mount = nfs4_remote_mount,
31
- .kill_sb = nfs_kill_super,
32
- .fs_flags = FS_RENAME_DOES_D_MOVE|FS_BINARY_MOUNTDATA,
33
-};
34
-
35
-static struct file_system_type nfs4_remote_referral_fs_type = {
36
- .owner = THIS_MODULE,
37
- .name = "nfs4",
38
- .mount = nfs4_remote_referral_mount,
39
- .kill_sb = nfs_kill_super,
40
- .fs_flags = FS_RENAME_DOES_D_MOVE|FS_BINARY_MOUNTDATA,
41
-};
42
-
43
-struct file_system_type nfs4_referral_fs_type = {
44
- .owner = THIS_MODULE,
45
- .name = "nfs4",
46
- .mount = nfs4_referral_mount,
47
- .kill_sb = nfs_kill_super,
48
- .fs_flags = FS_RENAME_DOES_D_MOVE|FS_BINARY_MOUNTDATA,
49
-};
5023
5124 static const struct super_operations nfs4_sops = {
5225 .alloc_inode = nfs_alloc_inode,
53
- .destroy_inode = nfs_destroy_inode,
26
+ .free_inode = nfs_free_inode,
5427 .write_inode = nfs4_write_inode,
5528 .drop_inode = nfs_drop_inode,
5629 .statfs = nfs_statfs,
....@@ -60,16 +33,15 @@
6033 .show_devname = nfs_show_devname,
6134 .show_path = nfs_show_path,
6235 .show_stats = nfs_show_stats,
63
- .remount_fs = nfs_remount,
6436 };
6537
6638 struct nfs_subversion nfs_v4 = {
67
- .owner = THIS_MODULE,
68
- .nfs_fs = &nfs4_fs_type,
69
- .rpc_vers = &nfs_version4,
70
- .rpc_ops = &nfs_v4_clientops,
71
- .sops = &nfs4_sops,
72
- .xattr = nfs4_xattr_handlers,
39
+ .owner = THIS_MODULE,
40
+ .nfs_fs = &nfs4_fs_type,
41
+ .rpc_vers = &nfs_version4,
42
+ .rpc_ops = &nfs_v4_clientops,
43
+ .sops = &nfs4_sops,
44
+ .xattr = nfs4_xattr_handlers,
7345 };
7446
7547 static int nfs4_write_inode(struct inode *inode, struct writeback_control *wbc)
....@@ -91,60 +63,14 @@
9163 {
9264 truncate_inode_pages_final(&inode->i_data);
9365 clear_inode(inode);
94
- /* If we are holding a delegation, return it! */
95
- nfs_inode_return_delegation_noreclaim(inode);
66
+ /* If we are holding a delegation, return and free it */
67
+ nfs_inode_evict_delegation(inode);
9668 /* Note that above delegreturn would trigger pnfs return-on-close */
9769 pnfs_return_layout(inode);
9870 pnfs_destroy_layout_final(NFS_I(inode));
9971 /* First call standard NFS clear_inode() code */
10072 nfs_clear_inode(inode);
101
-}
102
-
103
-/*
104
- * Get the superblock for the NFS4 root partition
105
- */
106
-static struct dentry *
107
-nfs4_remote_mount(struct file_system_type *fs_type, int flags,
108
- const char *dev_name, void *info)
109
-{
110
- struct nfs_mount_info *mount_info = info;
111
- struct nfs_server *server;
112
- struct dentry *mntroot = ERR_PTR(-ENOMEM);
113
-
114
- mount_info->set_security = nfs_set_sb_security;
115
-
116
- /* Get a volume representation */
117
- server = nfs4_create_server(mount_info, &nfs_v4);
118
- if (IS_ERR(server)) {
119
- mntroot = ERR_CAST(server);
120
- goto out;
121
- }
122
-
123
- mntroot = nfs_fs_mount_common(server, flags, dev_name, mount_info, &nfs_v4);
124
-
125
-out:
126
- return mntroot;
127
-}
128
-
129
-static struct vfsmount *nfs_do_root_mount(struct file_system_type *fs_type,
130
- int flags, void *data, const char *hostname)
131
-{
132
- struct vfsmount *root_mnt;
133
- char *root_devname;
134
- size_t len;
135
-
136
- len = strlen(hostname) + 5;
137
- root_devname = kmalloc(len, GFP_KERNEL);
138
- if (root_devname == NULL)
139
- return ERR_PTR(-ENOMEM);
140
- /* Does hostname needs to be enclosed in brackets? */
141
- if (strchr(hostname, ':'))
142
- snprintf(root_devname, len, "[%s]:/", hostname);
143
- else
144
- snprintf(root_devname, len, "%s:/", hostname);
145
- root_mnt = vfs_kern_mount(fs_type, flags, root_devname, data);
146
- kfree(root_devname);
147
- return root_mnt;
73
+ nfs4_xattr_cache_zap(inode);
14874 }
14975
15076 struct nfs_referral_count {
....@@ -213,110 +139,124 @@
213139 kfree(p);
214140 }
215141
216
-static struct dentry *nfs_follow_remote_path(struct vfsmount *root_mnt,
217
- const char *export_path)
142
+static int do_nfs4_mount(struct nfs_server *server,
143
+ struct fs_context *fc,
144
+ const char *hostname,
145
+ const char *export_path)
218146 {
147
+ struct nfs_fs_context *root_ctx;
148
+ struct fs_context *root_fc;
149
+ struct vfsmount *root_mnt;
219150 struct dentry *dentry;
220
- int err;
151
+ size_t len;
152
+ int ret;
153
+
154
+ struct fs_parameter param = {
155
+ .key = "source",
156
+ .type = fs_value_is_string,
157
+ .dirfd = -1,
158
+ };
159
+
160
+ if (IS_ERR(server))
161
+ return PTR_ERR(server);
162
+
163
+ root_fc = vfs_dup_fs_context(fc);
164
+ if (IS_ERR(root_fc)) {
165
+ nfs_free_server(server);
166
+ return PTR_ERR(root_fc);
167
+ }
168
+ kfree(root_fc->source);
169
+ root_fc->source = NULL;
170
+
171
+ root_ctx = nfs_fc2context(root_fc);
172
+ root_ctx->internal = true;
173
+ root_ctx->server = server;
174
+ /* We leave export_path unset as it's not used to find the root. */
175
+
176
+ len = strlen(hostname) + 5;
177
+ param.string = kmalloc(len, GFP_KERNEL);
178
+ if (param.string == NULL) {
179
+ put_fs_context(root_fc);
180
+ return -ENOMEM;
181
+ }
182
+
183
+ /* Does hostname needs to be enclosed in brackets? */
184
+ if (strchr(hostname, ':'))
185
+ param.size = snprintf(param.string, len, "[%s]:/", hostname);
186
+ else
187
+ param.size = snprintf(param.string, len, "%s:/", hostname);
188
+ ret = vfs_parse_fs_param(root_fc, &param);
189
+ kfree(param.string);
190
+ if (ret < 0) {
191
+ put_fs_context(root_fc);
192
+ return ret;
193
+ }
194
+ root_mnt = fc_mount(root_fc);
195
+ put_fs_context(root_fc);
221196
222197 if (IS_ERR(root_mnt))
223
- return ERR_CAST(root_mnt);
198
+ return PTR_ERR(root_mnt);
224199
225
- err = nfs_referral_loop_protect();
226
- if (err) {
200
+ ret = nfs_referral_loop_protect();
201
+ if (ret) {
227202 mntput(root_mnt);
228
- return ERR_PTR(err);
203
+ return ret;
229204 }
230205
231206 dentry = mount_subtree(root_mnt, export_path);
232207 nfs_referral_loop_unprotect();
233208
234
- return dentry;
209
+ if (IS_ERR(dentry))
210
+ return PTR_ERR(dentry);
211
+
212
+ fc->root = dentry;
213
+ return 0;
235214 }
236215
237
-struct dentry *nfs4_try_mount(int flags, const char *dev_name,
238
- struct nfs_mount_info *mount_info,
239
- struct nfs_subversion *nfs_mod)
216
+int nfs4_try_get_tree(struct fs_context *fc)
240217 {
241
- char *export_path;
242
- struct vfsmount *root_mnt;
243
- struct dentry *res;
244
- struct nfs_parsed_mount_data *data = mount_info->parsed;
218
+ struct nfs_fs_context *ctx = nfs_fc2context(fc);
219
+ int err;
245220
246
- dfprintk(MOUNT, "--> nfs4_try_mount()\n");
221
+ dfprintk(MOUNT, "--> nfs4_try_get_tree()\n");
247222
248
- export_path = data->nfs_server.export_path;
249
- data->nfs_server.export_path = "/";
250
- root_mnt = nfs_do_root_mount(&nfs4_remote_fs_type, flags, mount_info,
251
- data->nfs_server.hostname);
252
- data->nfs_server.export_path = export_path;
253
-
254
- res = nfs_follow_remote_path(root_mnt, export_path);
255
-
256
- dfprintk(MOUNT, "<-- nfs4_try_mount() = %d%s\n",
257
- PTR_ERR_OR_ZERO(res),
258
- IS_ERR(res) ? " [error]" : "");
259
- return res;
260
-}
261
-
262
-static struct dentry *
263
-nfs4_remote_referral_mount(struct file_system_type *fs_type, int flags,
264
- const char *dev_name, void *raw_data)
265
-{
266
- struct nfs_mount_info mount_info = {
267
- .fill_super = nfs_fill_super,
268
- .set_security = nfs_clone_sb_security,
269
- .cloned = raw_data,
270
- };
271
- struct nfs_server *server;
272
- struct dentry *mntroot = ERR_PTR(-ENOMEM);
273
-
274
- dprintk("--> nfs4_referral_get_sb()\n");
275
-
276
- mount_info.mntfh = nfs_alloc_fhandle();
277
- if (mount_info.cloned == NULL || mount_info.mntfh == NULL)
278
- goto out;
279
-
280
- /* create a new volume representation */
281
- server = nfs4_create_referral_server(mount_info.cloned, mount_info.mntfh);
282
- if (IS_ERR(server)) {
283
- mntroot = ERR_CAST(server);
284
- goto out;
223
+ /* We create a mount for the server's root, walk to the requested
224
+ * location and then create another mount for that.
225
+ */
226
+ err= do_nfs4_mount(nfs4_create_server(fc),
227
+ fc, ctx->nfs_server.hostname,
228
+ ctx->nfs_server.export_path);
229
+ if (err) {
230
+ nfs_ferrorf(fc, MOUNT, "NFS4: Couldn't follow remote path");
231
+ dfprintk(MOUNT, "<-- nfs4_try_get_tree() = %d [error]\n", err);
232
+ } else {
233
+ dfprintk(MOUNT, "<-- nfs4_try_get_tree() = 0\n");
285234 }
286
-
287
- mntroot = nfs_fs_mount_common(server, flags, dev_name, &mount_info, &nfs_v4);
288
-out:
289
- nfs_free_fhandle(mount_info.mntfh);
290
- return mntroot;
235
+ return err;
291236 }
292237
293238 /*
294239 * Create an NFS4 server record on referral traversal
295240 */
296
-static struct dentry *nfs4_referral_mount(struct file_system_type *fs_type,
297
- int flags, const char *dev_name, void *raw_data)
241
+int nfs4_get_referral_tree(struct fs_context *fc)
298242 {
299
- struct nfs_clone_mount *data = raw_data;
300
- char *export_path;
301
- struct vfsmount *root_mnt;
302
- struct dentry *res;
243
+ struct nfs_fs_context *ctx = nfs_fc2context(fc);
244
+ int err;
303245
304246 dprintk("--> nfs4_referral_mount()\n");
305247
306
- export_path = data->mnt_path;
307
- data->mnt_path = "/";
308
-
309
- root_mnt = nfs_do_root_mount(&nfs4_remote_referral_fs_type,
310
- flags, data, data->hostname);
311
- data->mnt_path = export_path;
312
-
313
- res = nfs_follow_remote_path(root_mnt, export_path);
314
- dprintk("<-- nfs4_referral_mount() = %d%s\n",
315
- PTR_ERR_OR_ZERO(res),
316
- IS_ERR(res) ? " [error]" : "");
317
- return res;
248
+ /* create a new volume representation */
249
+ err = do_nfs4_mount(nfs4_create_referral_server(fc),
250
+ fc, ctx->nfs_server.hostname,
251
+ ctx->nfs_server.export_path);
252
+ if (err) {
253
+ nfs_ferrorf(fc, MOUNT, "NFS4: Couldn't follow remote path");
254
+ dfprintk(MOUNT, "<-- nfs4_get_referral_tree() = %d [error]\n", err);
255
+ } else {
256
+ dfprintk(MOUNT, "<-- nfs4_get_referral_tree() = 0\n");
257
+ }
258
+ return err;
318259 }
319
-
320260
321261 static int __init init_nfs_v4(void)
322262 {
....@@ -330,10 +270,19 @@
330270 if (err)
331271 goto out1;
332272
273
+#ifdef CONFIG_NFS_V4_2
274
+ err = nfs4_xattr_cache_init();
275
+ if (err)
276
+ goto out2;
277
+#endif
278
+
333279 err = nfs4_register_sysctl();
334280 if (err)
335281 goto out2;
336282
283
+#ifdef CONFIG_NFS_V4_2
284
+ nfs42_ssc_register_ops();
285
+#endif
337286 register_nfs_version(&nfs_v4);
338287 return 0;
339288 out2:
....@@ -350,12 +299,17 @@
350299 nfs4_pnfs_v3_ds_connect_unload();
351300
352301 unregister_nfs_version(&nfs_v4);
302
+#ifdef CONFIG_NFS_V4_2
303
+ nfs4_xattr_cache_exit();
304
+ nfs42_ssc_unregister_ops();
305
+#endif
353306 nfs4_unregister_sysctl();
354307 nfs_idmap_quit();
355308 nfs_dns_resolver_destroy();
356309 }
357310
358311 MODULE_LICENSE("GPL");
312
+MODULE_IMPORT_NS(ANDROID_GKI_VFS_EXPORT_ONLY);
359313
360314 module_init(init_nfs_v4);
361315 module_exit(exit_nfs_v4);