1 // SPDX-License-Identifier: GPL-2.0-only
3 * linux/fs/nfs/namespace.c
5 * Copyright (C) 2005 Trond Myklebust <Trond.Myklebust@netapp.com>
6 * - Modified by David Howells <dhowells@redhat.com>
11 #include <linux/module.h>
12 #include <linux/dcache.h>
13 #include <linux/gfp.h>
14 #include <linux/mount.h>
15 #include <linux/namei.h>
16 #include <linux/nfs_fs.h>
17 #include <linux/string.h>
18 #include <linux/sunrpc/clnt.h>
19 #include <linux/vfs.h>
20 #include <linux/sunrpc/gss_api.h>
24 #define NFSDBG_FACILITY NFSDBG_VFS
26 static void nfs_expire_automounts(struct work_struct
*work
);
28 static LIST_HEAD(nfs_automount_list
);
29 static DECLARE_DELAYED_WORK(nfs_automount_task
, nfs_expire_automounts
);
30 int nfs_mountpoint_expiry_timeout
= 500 * HZ
;
33 * nfs_path - reconstruct the path given an arbitrary dentry
34 * @base - used to return pointer to the end of devname part of path
35 * @dentry_in - pointer to dentry
36 * @buffer - result buffer
37 * @buflen_in - length of buffer
38 * @flags - options (see below)
40 * Helper function for constructing the server pathname
41 * by arbitrary hashed dentry.
43 * This is mainly for use in figuring out the path on the
44 * server side when automounting on top of an existing partition
45 * and in generating /proc/mounts and friends.
48 * NFS_PATH_CANONICAL: ensure there is exactly one slash after
49 * the original device (export) name
50 * (if unset, the original name is returned verbatim)
52 char *nfs_path(char **p
, struct dentry
*dentry_in
, char *buffer
,
53 ssize_t buflen_in
, unsigned flags
)
59 struct dentry
*dentry
;
69 seq
= read_seqbegin(&rename_lock
);
72 spin_lock(&dentry
->d_lock
);
75 namelen
= dentry
->d_name
.len
;
76 buflen
-= namelen
+ 1;
80 memcpy(end
, dentry
->d_name
.name
, namelen
);
82 spin_unlock(&dentry
->d_lock
);
83 dentry
= dentry
->d_parent
;
85 if (read_seqretry(&rename_lock
, seq
)) {
86 spin_unlock(&dentry
->d_lock
);
90 if ((flags
& NFS_PATH_CANONICAL
) && *end
!= '/') {
92 spin_unlock(&dentry
->d_lock
);
99 base
= dentry
->d_fsdata
;
101 spin_unlock(&dentry
->d_lock
);
106 namelen
= strlen(base
);
108 /* Strip off excess slashes in base string */
109 while (namelen
> 0 && base
[namelen
- 1] == '/')
114 spin_unlock(&dentry
->d_lock
);
119 memcpy(end
, base
, namelen
);
120 spin_unlock(&dentry
->d_lock
);
124 spin_unlock(&dentry
->d_lock
);
126 if (read_seqretry(&rename_lock
, seq
))
129 return ERR_PTR(-ENAMETOOLONG
);
131 EXPORT_SYMBOL_GPL(nfs_path
);
134 * nfs_d_automount - Handle crossing a mountpoint on the server
135 * @path - The mountpoint
137 * When we encounter a mountpoint on the server, we want to set up
138 * a mountpoint on the client too, to prevent inode numbers from
139 * colliding, and to allow "df" to work properly.
140 * On NFSv4, we also want to allow for the fact that different
141 * filesystems may be migrated to different servers in a failover
142 * situation, and that different filesystems may want to use
143 * different security flavours.
145 struct vfsmount
*nfs_d_automount(struct path
*path
)
147 struct nfs_fs_context
*ctx
;
148 struct fs_context
*fc
;
149 struct vfsmount
*mnt
= ERR_PTR(-ENOMEM
);
150 struct nfs_server
*server
= NFS_SB(path
->dentry
->d_sb
);
151 struct nfs_client
*client
= server
->nfs_client
;
152 int timeout
= READ_ONCE(nfs_mountpoint_expiry_timeout
);
155 if (IS_ROOT(path
->dentry
))
156 return ERR_PTR(-ESTALE
);
158 /* Open a new filesystem context, transferring parameters from the
159 * parent superblock, including the network namespace.
161 fc
= fs_context_for_submount(path
->mnt
->mnt_sb
->s_type
, path
->dentry
);
165 ctx
= nfs_fc2context(fc
);
166 ctx
->clone_data
.dentry
= path
->dentry
;
167 ctx
->clone_data
.sb
= path
->dentry
->d_sb
;
168 ctx
->clone_data
.fattr
= nfs_alloc_fattr();
169 if (!ctx
->clone_data
.fattr
)
172 if (fc
->net_ns
!= client
->cl_net
) {
174 fc
->net_ns
= get_net(client
->cl_net
);
177 /* for submounts we want the same server; referrals will reassign */
178 memcpy(&ctx
->nfs_server
._address
, &client
->cl_addr
, client
->cl_addrlen
);
179 ctx
->nfs_server
.addrlen
= client
->cl_addrlen
;
180 ctx
->nfs_server
.port
= server
->port
;
182 ctx
->version
= client
->rpc_ops
->version
;
183 ctx
->minorversion
= client
->cl_minorversion
;
184 ctx
->nfs_mod
= client
->cl_nfs_mod
;
185 get_nfs_version(ctx
->nfs_mod
);
187 ret
= client
->rpc_ops
->submount(fc
, server
);
193 up_write(&fc
->root
->d_sb
->s_umount
);
194 mnt
= vfs_create_mount(fc
);
198 mntget(mnt
); /* prevent immediate expiration */
202 mnt_set_expiry(mnt
, &nfs_automount_list
);
203 schedule_delayed_work(&nfs_automount_task
, timeout
);
211 nfs_namespace_getattr(struct mnt_idmap
*idmap
,
212 const struct path
*path
, struct kstat
*stat
,
213 u32 request_mask
, unsigned int query_flags
)
215 if (NFS_FH(d_inode(path
->dentry
))->size
!= 0)
216 return nfs_getattr(idmap
, path
, stat
, request_mask
,
218 generic_fillattr(&nop_mnt_idmap
, request_mask
, d_inode(path
->dentry
),
224 nfs_namespace_setattr(struct mnt_idmap
*idmap
, struct dentry
*dentry
,
227 if (NFS_FH(d_inode(dentry
))->size
!= 0)
228 return nfs_setattr(idmap
, dentry
, attr
);
232 const struct inode_operations nfs_mountpoint_inode_operations
= {
233 .getattr
= nfs_getattr
,
234 .setattr
= nfs_setattr
,
237 const struct inode_operations nfs_referral_inode_operations
= {
238 .getattr
= nfs_namespace_getattr
,
239 .setattr
= nfs_namespace_setattr
,
242 static void nfs_expire_automounts(struct work_struct
*work
)
244 struct list_head
*list
= &nfs_automount_list
;
245 int timeout
= READ_ONCE(nfs_mountpoint_expiry_timeout
);
247 mark_mounts_for_expiry(list
);
248 if (!list_empty(list
) && timeout
> 0)
249 schedule_delayed_work(&nfs_automount_task
, timeout
);
252 void nfs_release_automount_timer(void)
254 if (list_empty(&nfs_automount_list
))
255 cancel_delayed_work(&nfs_automount_task
);
259 * nfs_do_submount - set up mountpoint when crossing a filesystem boundary
260 * @fc: pointer to struct nfs_fs_context
263 int nfs_do_submount(struct fs_context
*fc
)
265 struct nfs_fs_context
*ctx
= nfs_fc2context(fc
);
266 struct dentry
*dentry
= ctx
->clone_data
.dentry
;
267 struct nfs_server
*server
;
271 /* create a new volume representation */
272 server
= ctx
->nfs_mod
->rpc_ops
->clone_server(NFS_SB(ctx
->clone_data
.sb
),
274 ctx
->clone_data
.fattr
,
275 ctx
->selected_flavor
);
278 return PTR_ERR(server
);
280 ctx
->server
= server
;
282 buffer
= kmalloc(4096, GFP_USER
);
286 ctx
->internal
= true;
287 ctx
->clone_data
.inherited_bsize
= ctx
->clone_data
.sb
->s_blocksize_bits
;
289 p
= nfs_devname(dentry
, buffer
, 4096);
291 nfs_errorf(fc
, "NFS: Couldn't determine submount pathname");
294 ret
= vfs_parse_fs_string(fc
, "source", p
, buffer
+ 4096 - p
);
296 ret
= vfs_get_tree(fc
);
301 EXPORT_SYMBOL_GPL(nfs_do_submount
);
303 int nfs_submount(struct fs_context
*fc
, struct nfs_server
*server
)
305 struct nfs_fs_context
*ctx
= nfs_fc2context(fc
);
306 struct dentry
*dentry
= ctx
->clone_data
.dentry
;
307 struct dentry
*parent
= dget_parent(dentry
);
310 /* Look it up again to get its attributes */
311 err
= server
->nfs_client
->rpc_ops
->lookup(d_inode(parent
), dentry
,
312 ctx
->mntfh
, ctx
->clone_data
.fattr
);
317 ctx
->selected_flavor
= server
->client
->cl_auth
->au_flavor
;
318 return nfs_do_submount(fc
);
320 EXPORT_SYMBOL_GPL(nfs_submount
);
322 static int param_set_nfs_timeout(const char *val
, const struct kernel_param
*kp
)
329 ret
= kstrtol(val
, 0, &num
);
333 if (num
>= INT_MAX
/ HZ
)
337 *((int *)kp
->arg
) = num
;
338 if (!list_empty(&nfs_automount_list
))
339 mod_delayed_work(system_wq
, &nfs_automount_task
, num
);
341 *((int *)kp
->arg
) = -1*HZ
;
342 cancel_delayed_work(&nfs_automount_task
);
347 static int param_get_nfs_timeout(char *buffer
, const struct kernel_param
*kp
)
349 long num
= *((int *)kp
->arg
);
352 if (num
>= INT_MAX
- (HZ
- 1))
355 num
= (num
+ (HZ
- 1)) / HZ
;
358 return sysfs_emit(buffer
, "%li\n", num
);
361 static const struct kernel_param_ops param_ops_nfs_timeout
= {
362 .set
= param_set_nfs_timeout
,
363 .get
= param_get_nfs_timeout
,
365 #define param_check_nfs_timeout(name, p) __param_check(name, p, int)
367 module_param(nfs_mountpoint_expiry_timeout
, nfs_timeout
, 0644);
368 MODULE_PARM_DESC(nfs_mountpoint_expiry_timeout
,
369 "Set the NFS automounted mountpoint timeout value (seconds)."
370 "Values <= 0 turn expiration off.");