nfs4super.c (5eb005caf5383dd328199f0f2114cd7dad731d3d) nfs4super.c (f2aedb713c284429987dc66c7aaf38decfc8da2a)
1// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * Copyright (c) 2012 Bryan Schumaker <bjschuma@netapp.com>
4 */
5#include <linux/init.h>
6#include <linux/module.h>
1// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * Copyright (c) 2012 Bryan Schumaker <bjschuma@netapp.com>
4 */
5#include <linux/init.h>
6#include <linux/module.h>
7#include <linux/mount.h>
7#include <linux/nfs4_mount.h>
8#include <linux/nfs_fs.h>
9#include "delegation.h"
10#include "internal.h"
11#include "nfs4_fs.h"
12#include "nfs4idmap.h"
13#include "dns_resolve.h"
14#include "pnfs.h"
15#include "nfs.h"
16
17#define NFSDBG_FACILITY NFSDBG_VFS
18
19static int nfs4_write_inode(struct inode *inode, struct writeback_control *wbc);
20static void nfs4_evict_inode(struct inode *inode);
8#include <linux/nfs4_mount.h>
9#include <linux/nfs_fs.h>
10#include "delegation.h"
11#include "internal.h"
12#include "nfs4_fs.h"
13#include "nfs4idmap.h"
14#include "dns_resolve.h"
15#include "pnfs.h"
16#include "nfs.h"
17
18#define NFSDBG_FACILITY NFSDBG_VFS
19
20static int nfs4_write_inode(struct inode *inode, struct writeback_control *wbc);
21static void nfs4_evict_inode(struct inode *inode);
21static struct dentry *nfs4_referral_mount(struct file_system_type *fs_type,
22 int flags, const char *dev_name, void *raw_data);
23
22
24struct file_system_type nfs4_referral_fs_type = {
25 .owner = THIS_MODULE,
26 .name = "nfs4",
27 .mount = nfs4_referral_mount,
28 .kill_sb = nfs_kill_super,
29 .fs_flags = FS_RENAME_DOES_D_MOVE|FS_BINARY_MOUNTDATA,
30};
31
32static const struct super_operations nfs4_sops = {
33 .alloc_inode = nfs_alloc_inode,
34 .free_inode = nfs_free_inode,
35 .write_inode = nfs4_write_inode,
36 .drop_inode = nfs_drop_inode,
37 .statfs = nfs_statfs,
38 .evict_inode = nfs4_evict_inode,
39 .umount_begin = nfs_umount_begin,
40 .show_options = nfs_show_options,
41 .show_devname = nfs_show_devname,
42 .show_path = nfs_show_path,
43 .show_stats = nfs_show_stats,
23static const struct super_operations nfs4_sops = {
24 .alloc_inode = nfs_alloc_inode,
25 .free_inode = nfs_free_inode,
26 .write_inode = nfs4_write_inode,
27 .drop_inode = nfs_drop_inode,
28 .statfs = nfs_statfs,
29 .evict_inode = nfs4_evict_inode,
30 .umount_begin = nfs_umount_begin,
31 .show_options = nfs_show_options,
32 .show_devname = nfs_show_devname,
33 .show_path = nfs_show_path,
34 .show_stats = nfs_show_stats,
44 .remount_fs = nfs_remount,
45};
46
47struct nfs_subversion nfs_v4 = {
48 .owner = THIS_MODULE,
49 .nfs_fs = &nfs4_fs_type,
50 .rpc_vers = &nfs_version4,
51 .rpc_ops = &nfs_v4_clientops,
52 .sops = &nfs4_sops,

--- 89 unchanged lines hidden (view full) ---

142 if (p->referral_count == 0)
143 list_del(&p->list);
144 else
145 p = NULL;
146 spin_unlock(&nfs_referral_count_list_lock);
147 kfree(p);
148}
149
35};
36
37struct nfs_subversion nfs_v4 = {
38 .owner = THIS_MODULE,
39 .nfs_fs = &nfs4_fs_type,
40 .rpc_vers = &nfs_version4,
41 .rpc_ops = &nfs_v4_clientops,
42 .sops = &nfs4_sops,

--- 89 unchanged lines hidden (view full) ---

132 if (p->referral_count == 0)
133 list_del(&p->list);
134 else
135 p = NULL;
136 spin_unlock(&nfs_referral_count_list_lock);
137 kfree(p);
138}
139
150static struct dentry *do_nfs4_mount(struct nfs_server *server, int flags,
151 struct nfs_mount_info *info,
152 const char *hostname,
153 const char *export_path)
140static int do_nfs4_mount(struct nfs_server *server,
141 struct fs_context *fc,
142 const char *hostname,
143 const char *export_path)
154{
144{
145 struct nfs_fs_context *root_ctx;
146 struct fs_context *root_fc;
155 struct vfsmount *root_mnt;
156 struct dentry *dentry;
147 struct vfsmount *root_mnt;
148 struct dentry *dentry;
157 char *root_devname;
158 int err;
159 size_t len;
149 size_t len;
150 int ret;
160
151
152 struct fs_parameter param = {
153 .key = "source",
154 .type = fs_value_is_string,
155 .dirfd = -1,
156 };
157
161 if (IS_ERR(server))
158 if (IS_ERR(server))
162 return ERR_CAST(server);
159 return PTR_ERR(server);
163
160
164 len = strlen(hostname) + 5;
165 root_devname = kmalloc(len, GFP_KERNEL);
166 if (root_devname == NULL) {
161 root_fc = vfs_dup_fs_context(fc);
162 if (IS_ERR(root_fc)) {
167 nfs_free_server(server);
163 nfs_free_server(server);
168 return ERR_PTR(-ENOMEM);
164 return PTR_ERR(root_fc);
169 }
165 }
166 kfree(root_fc->source);
167 root_fc->source = NULL;
170
168
169 root_ctx = nfs_fc2context(root_fc);
170 root_ctx->internal = true;
171 root_ctx->mount_info.server = server;
172 /* We leave export_path unset as it's not used to find the root. */
173
174 len = strlen(hostname) + 5;
175 param.string = kmalloc(len, GFP_KERNEL);
176 if (param.string == NULL) {
177 put_fs_context(root_fc);
178 return -ENOMEM;
179 }
180
171 /* Does hostname needs to be enclosed in brackets? */
172 if (strchr(hostname, ':'))
181 /* Does hostname needs to be enclosed in brackets? */
182 if (strchr(hostname, ':'))
173 snprintf(root_devname, len, "[%s]:/", hostname);
183 param.size = snprintf(param.string, len, "[%s]:/", hostname);
174 else
184 else
175 snprintf(root_devname, len, "%s:/", hostname);
176 info->server = server;
177 root_mnt = vfs_kern_mount(&nfs_prepared_fs_type, flags, root_devname, info);
178 if (info->server)
179 nfs_free_server(info->server);
180 info->server = NULL;
181 kfree(root_devname);
185 param.size = snprintf(param.string, len, "%s:/", hostname);
186 ret = vfs_parse_fs_param(root_fc, &param);
187 kfree(param.string);
188 if (ret < 0) {
189 put_fs_context(root_fc);
190 return ret;
191 }
192 root_mnt = fc_mount(root_fc);
193 put_fs_context(root_fc);
182
183 if (IS_ERR(root_mnt))
194
195 if (IS_ERR(root_mnt))
184 return ERR_CAST(root_mnt);
196 return PTR_ERR(root_mnt);
185
197
186 err = nfs_referral_loop_protect();
187 if (err) {
198 ret = nfs_referral_loop_protect();
199 if (ret) {
188 mntput(root_mnt);
200 mntput(root_mnt);
189 return ERR_PTR(err);
201 return ret;
190 }
191
192 dentry = mount_subtree(root_mnt, export_path);
193 nfs_referral_loop_unprotect();
194
202 }
203
204 dentry = mount_subtree(root_mnt, export_path);
205 nfs_referral_loop_unprotect();
206
195 return dentry;
207 if (IS_ERR(dentry))
208 return PTR_ERR(dentry);
209
210 fc->root = dentry;
211 return 0;
196}
197
212}
213
198struct dentry *nfs4_try_mount(int flags, const char *dev_name,
199 struct nfs_mount_info *mount_info)
214int nfs4_try_get_tree(struct fs_context *fc)
200{
215{
201 struct nfs_fs_context *ctx = mount_info->ctx;
202 struct dentry *res;
216 struct nfs_fs_context *ctx = nfs_fc2context(fc);
217 int err;
203
218
204 dfprintk(MOUNT, "--> nfs4_try_mount()\n");
219 dfprintk(MOUNT, "--> nfs4_try_get_tree()\n");
205
220
206 res = do_nfs4_mount(nfs4_create_server(mount_info),
207 flags, mount_info,
208 ctx->nfs_server.hostname,
209 ctx->nfs_server.export_path);
210
211 dfprintk(MOUNT, "<-- nfs4_try_mount() = %d%s\n",
212 PTR_ERR_OR_ZERO(res),
213 IS_ERR(res) ? " [error]" : "");
214 return res;
221 /* We create a mount for the server's root, walk to the requested
222 * location and then create another mount for that.
223 */
224 err= do_nfs4_mount(nfs4_create_server(&ctx->mount_info),
225 fc, ctx->nfs_server.hostname,
226 ctx->nfs_server.export_path);
227 if (err) {
228 dfprintk(MOUNT, "<-- nfs4_try_get_tree() = %d [error]\n", err);
229 } else {
230 dfprintk(MOUNT, "<-- nfs4_try_get_tree() = 0\n");
231 }
232 return err;
215}
216
217/*
218 * Create an NFS4 server record on referral traversal
219 */
233}
234
235/*
236 * Create an NFS4 server record on referral traversal
237 */
220static struct dentry *nfs4_referral_mount(struct file_system_type *fs_type,
221 int flags, const char *dev_name, void *raw_data)
238int nfs4_get_referral_tree(struct fs_context *fc)
222{
239{
223 struct nfs_clone_mount *data = raw_data;
224 struct nfs_mount_info mount_info = {
225 .cloned = data,
226 .nfs_mod = &nfs_v4,
227 };
228 struct dentry *res;
240 struct nfs_fs_context *ctx = nfs_fc2context(fc);
241 int err;
229
230 dprintk("--> nfs4_referral_mount()\n");
231
242
243 dprintk("--> nfs4_referral_mount()\n");
244
232 mount_info.mntfh = nfs_alloc_fhandle();
233 if (!mount_info.mntfh)
234 return ERR_PTR(-ENOMEM);
235
236 res = do_nfs4_mount(nfs4_create_referral_server(mount_info.cloned,
237 mount_info.mntfh),
238 flags, &mount_info, data->hostname, data->mnt_path);
239
240 dprintk("<-- nfs4_referral_mount() = %d%s\n",
241 PTR_ERR_OR_ZERO(res),
242 IS_ERR(res) ? " [error]" : "");
243
244 nfs_free_fhandle(mount_info.mntfh);
245 return res;
245 /* create a new volume representation */
246 err = do_nfs4_mount(nfs4_create_referral_server(&ctx->clone_data, ctx->mount_info.mntfh),
247 fc, ctx->nfs_server.hostname,
248 ctx->nfs_server.export_path);
249 if (err) {
250 dfprintk(MOUNT, "<-- nfs4_get_referral_tree() = %d [error]\n", err);
251 } else {
252 dfprintk(MOUNT, "<-- nfs4_get_referral_tree() = 0\n");
253 }
254 return err;
246}
247
248
249static int __init init_nfs_v4(void)
250{
251 int err;
252
253 err = nfs_dns_resolver_init();

--- 36 unchanged lines hidden ---
255}
256
257
258static int __init init_nfs_v4(void)
259{
260 int err;
261
262 err = nfs_dns_resolver_init();

--- 36 unchanged lines hidden ---