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
;
150 if (IS_ROOT(path
->dentry
))
151 return ERR_PTR(-ESTALE
);
153 /* Open a new filesystem context, transferring parameters from the
154 * parent superblock, including the network namespace.
156 fc
= fs_context_for_submount(&nfs_fs_type
, path
->dentry
);
160 ctx
= nfs_fc2context(fc
);
161 ctx
->clone_data
.dentry
= path
->dentry
;
162 ctx
->clone_data
.sb
= path
->dentry
->d_sb
;
163 ctx
->clone_data
.fattr
= nfs_alloc_fattr();
164 if (!ctx
->clone_data
.fattr
)
167 if (fc
->net_ns
!= client
->cl_net
) {
169 fc
->net_ns
= get_net(client
->cl_net
);
172 /* for submounts we want the same server; referrals will reassign */
173 memcpy(&ctx
->nfs_server
.address
, &client
->cl_addr
, client
->cl_addrlen
);
174 ctx
->nfs_server
.addrlen
= client
->cl_addrlen
;
175 ctx
->nfs_server
.port
= server
->port
;
177 ctx
->version
= client
->rpc_ops
->version
;
178 ctx
->minorversion
= client
->cl_minorversion
;
179 ctx
->nfs_mod
= client
->cl_nfs_mod
;
180 __module_get(ctx
->nfs_mod
->owner
);
182 ret
= client
->rpc_ops
->submount(fc
, server
);
188 up_write(&fc
->root
->d_sb
->s_umount
);
189 mnt
= vfs_create_mount(fc
);
193 if (nfs_mountpoint_expiry_timeout
< 0)
196 mntget(mnt
); /* prevent immediate expiration */
197 mnt_set_expiry(mnt
, &nfs_automount_list
);
198 schedule_delayed_work(&nfs_automount_task
, nfs_mountpoint_expiry_timeout
);
206 nfs_namespace_getattr(const struct path
*path
, struct kstat
*stat
,
207 u32 request_mask
, unsigned int query_flags
)
209 if (NFS_FH(d_inode(path
->dentry
))->size
!= 0)
210 return nfs_getattr(path
, stat
, request_mask
, query_flags
);
211 generic_fillattr(d_inode(path
->dentry
), stat
);
216 nfs_namespace_setattr(struct dentry
*dentry
, struct iattr
*attr
)
218 if (NFS_FH(d_inode(dentry
))->size
!= 0)
219 return nfs_setattr(dentry
, attr
);
223 const struct inode_operations nfs_mountpoint_inode_operations
= {
224 .getattr
= nfs_getattr
,
225 .setattr
= nfs_setattr
,
228 const struct inode_operations nfs_referral_inode_operations
= {
229 .getattr
= nfs_namespace_getattr
,
230 .setattr
= nfs_namespace_setattr
,
233 static void nfs_expire_automounts(struct work_struct
*work
)
235 struct list_head
*list
= &nfs_automount_list
;
237 mark_mounts_for_expiry(list
);
238 if (!list_empty(list
))
239 schedule_delayed_work(&nfs_automount_task
, nfs_mountpoint_expiry_timeout
);
242 void nfs_release_automount_timer(void)
244 if (list_empty(&nfs_automount_list
))
245 cancel_delayed_work(&nfs_automount_task
);
249 * nfs_do_submount - set up mountpoint when crossing a filesystem boundary
250 * @dentry: parent directory
251 * @fh: filehandle for new root dentry
252 * @fattr: attributes for new root inode
253 * @authflavor: security flavor to use when performing the mount
256 int nfs_do_submount(struct fs_context
*fc
)
258 struct nfs_fs_context
*ctx
= nfs_fc2context(fc
);
259 struct dentry
*dentry
= ctx
->clone_data
.dentry
;
260 struct nfs_server
*server
;
264 /* create a new volume representation */
265 server
= ctx
->nfs_mod
->rpc_ops
->clone_server(NFS_SB(ctx
->clone_data
.sb
),
267 ctx
->clone_data
.fattr
,
268 ctx
->selected_flavor
);
271 return PTR_ERR(server
);
273 ctx
->server
= server
;
275 buffer
= kmalloc(4096, GFP_USER
);
279 ctx
->internal
= true;
280 ctx
->clone_data
.inherited_bsize
= ctx
->clone_data
.sb
->s_blocksize_bits
;
282 p
= nfs_devname(dentry
, buffer
, 4096);
284 nfs_errorf(fc
, "NFS: Couldn't determine submount pathname");
287 ret
= vfs_parse_fs_string(fc
, "source", p
, buffer
+ 4096 - p
);
289 ret
= vfs_get_tree(fc
);
294 EXPORT_SYMBOL_GPL(nfs_do_submount
);
296 int nfs_submount(struct fs_context
*fc
, struct nfs_server
*server
)
298 struct nfs_fs_context
*ctx
= nfs_fc2context(fc
);
299 struct dentry
*dentry
= ctx
->clone_data
.dentry
;
300 struct dentry
*parent
= dget_parent(dentry
);
303 /* Look it up again to get its attributes */
304 err
= server
->nfs_client
->rpc_ops
->lookup(d_inode(parent
), dentry
,
305 ctx
->mntfh
, ctx
->clone_data
.fattr
,
311 ctx
->selected_flavor
= server
->client
->cl_auth
->au_flavor
;
312 return nfs_do_submount(fc
);
314 EXPORT_SYMBOL_GPL(nfs_submount
);