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 - pointer to dentry
36 * @buffer - result buffer
37 * @buflen - 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
, char *buffer
, ssize_t buflen
,
65 seq
= read_seqbegin(&rename_lock
);
68 spin_lock(&dentry
->d_lock
);
71 namelen
= dentry
->d_name
.len
;
72 buflen
-= namelen
+ 1;
76 memcpy(end
, dentry
->d_name
.name
, namelen
);
78 spin_unlock(&dentry
->d_lock
);
79 dentry
= dentry
->d_parent
;
81 if (read_seqretry(&rename_lock
, seq
)) {
82 spin_unlock(&dentry
->d_lock
);
86 if ((flags
& NFS_PATH_CANONICAL
) && *end
!= '/') {
88 spin_unlock(&dentry
->d_lock
);
95 base
= dentry
->d_fsdata
;
97 spin_unlock(&dentry
->d_lock
);
102 namelen
= strlen(base
);
104 /* Strip off excess slashes in base string */
105 while (namelen
> 0 && base
[namelen
- 1] == '/')
110 spin_unlock(&dentry
->d_lock
);
115 memcpy(end
, base
, namelen
);
116 spin_unlock(&dentry
->d_lock
);
120 spin_unlock(&dentry
->d_lock
);
122 if (read_seqretry(&rename_lock
, seq
))
125 return ERR_PTR(-ENAMETOOLONG
);
127 EXPORT_SYMBOL_GPL(nfs_path
);
130 * nfs_d_automount - Handle crossing a mountpoint on the server
131 * @path - The mountpoint
133 * When we encounter a mountpoint on the server, we want to set up
134 * a mountpoint on the client too, to prevent inode numbers from
135 * colliding, and to allow "df" to work properly.
136 * On NFSv4, we also want to allow for the fact that different
137 * filesystems may be migrated to different servers in a failover
138 * situation, and that different filesystems may want to use
139 * different security flavours.
141 struct vfsmount
*nfs_d_automount(struct path
*path
)
143 struct nfs_fs_context
*ctx
;
144 struct fs_context
*fc
;
145 struct vfsmount
*mnt
= ERR_PTR(-ENOMEM
);
146 struct nfs_server
*server
= NFS_SERVER(d_inode(path
->dentry
));
147 struct nfs_client
*client
= server
->nfs_client
;
148 int timeout
= READ_ONCE(nfs_mountpoint_expiry_timeout
);
151 if (IS_ROOT(path
->dentry
))
152 return ERR_PTR(-ESTALE
);
154 /* Open a new filesystem context, transferring parameters from the
155 * parent superblock, including the network namespace.
157 fc
= fs_context_for_submount(path
->mnt
->mnt_sb
->s_type
, path
->dentry
);
161 ctx
= nfs_fc2context(fc
);
162 ctx
->clone_data
.dentry
= path
->dentry
;
163 ctx
->clone_data
.sb
= path
->dentry
->d_sb
;
164 ctx
->clone_data
.fattr
= nfs_alloc_fattr();
165 if (!ctx
->clone_data
.fattr
)
168 if (fc
->net_ns
!= client
->cl_net
) {
170 fc
->net_ns
= get_net(client
->cl_net
);
173 /* for submounts we want the same server; referrals will reassign */
174 memcpy(&ctx
->nfs_server
.address
, &client
->cl_addr
, client
->cl_addrlen
);
175 ctx
->nfs_server
.addrlen
= client
->cl_addrlen
;
176 ctx
->nfs_server
.port
= server
->port
;
178 ctx
->version
= client
->rpc_ops
->version
;
179 ctx
->minorversion
= client
->cl_minorversion
;
180 ctx
->nfs_mod
= client
->cl_nfs_mod
;
181 __module_get(ctx
->nfs_mod
->owner
);
183 ret
= client
->rpc_ops
->submount(fc
, server
);
189 up_write(&fc
->root
->d_sb
->s_umount
);
190 mnt
= vfs_create_mount(fc
);
194 mntget(mnt
); /* prevent immediate expiration */
198 mnt_set_expiry(mnt
, &nfs_automount_list
);
199 schedule_delayed_work(&nfs_automount_task
, timeout
);
207 nfs_namespace_getattr(const struct path
*path
, struct kstat
*stat
,
208 u32 request_mask
, unsigned int query_flags
)
210 if (NFS_FH(d_inode(path
->dentry
))->size
!= 0)
211 return nfs_getattr(path
, stat
, request_mask
, query_flags
);
212 generic_fillattr(d_inode(path
->dentry
), stat
);
217 nfs_namespace_setattr(struct dentry
*dentry
, struct iattr
*attr
)
219 if (NFS_FH(d_inode(dentry
))->size
!= 0)
220 return nfs_setattr(dentry
, attr
);
224 const struct inode_operations nfs_mountpoint_inode_operations
= {
225 .getattr
= nfs_getattr
,
226 .setattr
= nfs_setattr
,
229 const struct inode_operations nfs_referral_inode_operations
= {
230 .getattr
= nfs_namespace_getattr
,
231 .setattr
= nfs_namespace_setattr
,
234 static void nfs_expire_automounts(struct work_struct
*work
)
236 struct list_head
*list
= &nfs_automount_list
;
237 int timeout
= READ_ONCE(nfs_mountpoint_expiry_timeout
);
239 mark_mounts_for_expiry(list
);
240 if (!list_empty(list
) && timeout
> 0)
241 schedule_delayed_work(&nfs_automount_task
, timeout
);
244 void nfs_release_automount_timer(void)
246 if (list_empty(&nfs_automount_list
))
247 cancel_delayed_work(&nfs_automount_task
);
251 * nfs_do_submount - set up mountpoint when crossing a filesystem boundary
252 * @fc: pointer to struct nfs_fs_context
255 int nfs_do_submount(struct fs_context
*fc
)
257 struct nfs_fs_context
*ctx
= nfs_fc2context(fc
);
258 struct dentry
*dentry
= ctx
->clone_data
.dentry
;
259 struct nfs_server
*server
;
263 /* create a new volume representation */
264 server
= ctx
->nfs_mod
->rpc_ops
->clone_server(NFS_SB(ctx
->clone_data
.sb
),
266 ctx
->clone_data
.fattr
,
267 ctx
->selected_flavor
);
270 return PTR_ERR(server
);
272 ctx
->server
= server
;
274 buffer
= kmalloc(4096, GFP_USER
);
278 ctx
->internal
= true;
279 ctx
->clone_data
.inherited_bsize
= ctx
->clone_data
.sb
->s_blocksize_bits
;
281 p
= nfs_devname(dentry
, buffer
, 4096);
283 nfs_errorf(fc
, "NFS: Couldn't determine submount pathname");
286 ret
= vfs_parse_fs_string(fc
, "source", p
, buffer
+ 4096 - p
);
288 ret
= vfs_get_tree(fc
);
293 EXPORT_SYMBOL_GPL(nfs_do_submount
);
295 int nfs_submount(struct fs_context
*fc
, struct nfs_server
*server
)
297 struct nfs_fs_context
*ctx
= nfs_fc2context(fc
);
298 struct dentry
*dentry
= ctx
->clone_data
.dentry
;
299 struct dentry
*parent
= dget_parent(dentry
);
302 /* Look it up again to get its attributes */
303 err
= server
->nfs_client
->rpc_ops
->lookup(d_inode(parent
), dentry
,
304 ctx
->mntfh
, ctx
->clone_data
.fattr
,
310 ctx
->selected_flavor
= server
->client
->cl_auth
->au_flavor
;
311 return nfs_do_submount(fc
);
313 EXPORT_SYMBOL_GPL(nfs_submount
);
315 static int param_set_nfs_timeout(const char *val
, const struct kernel_param
*kp
)
322 ret
= kstrtol(val
, 0, &num
);
326 if (num
>= INT_MAX
/ HZ
)
330 *((int *)kp
->arg
) = num
;
331 if (!list_empty(&nfs_automount_list
))
332 mod_delayed_work(system_wq
, &nfs_automount_task
, num
);
334 *((int *)kp
->arg
) = -1*HZ
;
335 cancel_delayed_work(&nfs_automount_task
);
340 static int param_get_nfs_timeout(char *buffer
, const struct kernel_param
*kp
)
342 long num
= *((int *)kp
->arg
);
345 if (num
>= INT_MAX
- (HZ
- 1))
348 num
= (num
+ (HZ
- 1)) / HZ
;
351 return scnprintf(buffer
, PAGE_SIZE
, "%li\n", num
);
354 static const struct kernel_param_ops param_ops_nfs_timeout
= {
355 .set
= param_set_nfs_timeout
,
356 .get
= param_get_nfs_timeout
,
358 #define param_check_nfs_timeout(name, p) __param_check(name, p, int);
360 module_param(nfs_mountpoint_expiry_timeout
, nfs_timeout
, 0644);
361 MODULE_PARM_DESC(nfs_mountpoint_expiry_timeout
,
362 "Set the NFS automounted mountpoint timeout value (seconds)."
363 "Values <= 0 turn expiration off.");