namespace.c (adf2314fe667565258f304a04990d334defabeaf) namespace.c (f2aedb713c284429987dc66c7aaf38decfc8da2a)
1// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * linux/fs/nfs/namespace.c
4 *
5 * Copyright (C) 2005 Trond Myklebust <Trond.Myklebust@netapp.com>
6 * - Modified by David Howells <dhowells@redhat.com>
7 *
8 * NFS namespace

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

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.
140 */
141struct vfsmount *nfs_d_automount(struct path *path)
142{
1// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * linux/fs/nfs/namespace.c
4 *
5 * Copyright (C) 2005 Trond Myklebust <Trond.Myklebust@netapp.com>
6 * - Modified by David Howells <dhowells@redhat.com>
7 *
8 * NFS namespace

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

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.
140 */
141struct vfsmount *nfs_d_automount(struct path *path)
142{
143 struct vfsmount *mnt;
143 struct nfs_fs_context *ctx;
144 struct fs_context *fc;
145 struct vfsmount *mnt = ERR_PTR(-ENOMEM);
144 struct nfs_server *server = NFS_SERVER(d_inode(path->dentry));
146 struct nfs_server *server = NFS_SERVER(d_inode(path->dentry));
145 struct nfs_fh *fh = NULL;
146 struct nfs_fattr *fattr = NULL;
147 struct nfs_client *client = server->nfs_client;
148 int ret;
147
148 if (IS_ROOT(path->dentry))
149 return ERR_PTR(-ESTALE);
150
149
150 if (IS_ROOT(path->dentry))
151 return ERR_PTR(-ESTALE);
152
151 mnt = ERR_PTR(-ENOMEM);
152 fh = nfs_alloc_fhandle();
153 fattr = nfs_alloc_fattr();
154 if (fh == NULL || fattr == NULL)
155 goto out;
153 /* Open a new filesystem context, transferring parameters from the
154 * parent superblock, including the network namespace.
155 */
156 fc = fs_context_for_submount(&nfs_fs_type, path->dentry);
157 if (IS_ERR(fc))
158 return ERR_CAST(fc);
156
159
157 mnt = server->nfs_client->rpc_ops->submount(server, path->dentry, fh, fattr);
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)
165 goto out_fc;
166
167 if (fc->net_ns != client->cl_net) {
168 put_net(fc->net_ns);
169 fc->net_ns = get_net(client->cl_net);
170 }
171
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;
176
177 ctx->version = client->rpc_ops->version;
178 ctx->minorversion = client->cl_minorversion;
179 ctx->mount_info.nfs_mod = client->cl_nfs_mod;
180 __module_get(ctx->mount_info.nfs_mod->owner);
181
182 ret = client->rpc_ops->submount(fc, server);
183 if (ret < 0) {
184 mnt = ERR_PTR(ret);
185 goto out_fc;
186 }
187
188 up_write(&fc->root->d_sb->s_umount);
189 mnt = vfs_create_mount(fc);
158 if (IS_ERR(mnt))
190 if (IS_ERR(mnt))
159 goto out;
191 goto out_fc;
160
161 if (nfs_mountpoint_expiry_timeout < 0)
192
193 if (nfs_mountpoint_expiry_timeout < 0)
162 goto out;
194 goto out_fc;
163
164 mntget(mnt); /* prevent immediate expiration */
165 mnt_set_expiry(mnt, &nfs_automount_list);
166 schedule_delayed_work(&nfs_automount_task, nfs_mountpoint_expiry_timeout);
167
195
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);
199
168out:
169 nfs_free_fattr(fattr);
170 nfs_free_fhandle(fh);
200out_fc:
201 put_fs_context(fc);
171 return mnt;
172}
173
174static int
175nfs_namespace_getattr(const struct path *path, struct kstat *stat,
176 u32 request_mask, unsigned int query_flags)
177{
178 if (NFS_FH(d_inode(path->dentry))->size != 0)

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

217/**
218 * nfs_do_submount - set up mountpoint when crossing a filesystem boundary
219 * @dentry: parent directory
220 * @fh: filehandle for new root dentry
221 * @fattr: attributes for new root inode
222 * @authflavor: security flavor to use when performing the mount
223 *
224 */
202 return mnt;
203}
204
205static int
206nfs_namespace_getattr(const struct path *path, struct kstat *stat,
207 u32 request_mask, unsigned int query_flags)
208{
209 if (NFS_FH(d_inode(path->dentry))->size != 0)

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

248/**
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
254 *
255 */
225struct vfsmount *nfs_do_submount(struct dentry *dentry, struct nfs_fh *fh,
226 struct nfs_fattr *fattr, rpc_authflavor_t authflavor)
256int nfs_do_submount(struct fs_context *fc)
227{
257{
228 struct super_block *sb = dentry->d_sb;
229 struct nfs_clone_mount mountdata = {
230 .sb = sb,
231 .dentry = dentry,
232 .authflavor = authflavor,
233 };
234 struct nfs_mount_info mount_info = {
235 .inherited_bsize = sb->s_blocksize_bits,
236 .cloned = &mountdata,
237 .mntfh = fh,
238 .nfs_mod = NFS_SB(sb)->nfs_client->cl_nfs_mod,
239 };
258 struct nfs_fs_context *ctx = nfs_fc2context(fc);
259 struct dentry *dentry = ctx->clone_data.dentry;
240 struct nfs_server *server;
260 struct nfs_server *server;
241 struct vfsmount *mnt;
242 char *page = (char *) __get_free_page(GFP_USER);
243 char *devname;
261 char *buffer, *p;
262 int ret;
244
263
245 if (page == NULL)
246 return ERR_PTR(-ENOMEM);
264 /* create a new volume representation */
265 server = ctx->mount_info.nfs_mod->rpc_ops->clone_server(NFS_SB(ctx->clone_data.sb),
266 ctx->mount_info.mntfh,
267 ctx->clone_data.fattr,
268 ctx->selected_flavor);
247
269
248 server = mount_info.nfs_mod->rpc_ops->clone_server(NFS_SB(sb), fh,
249 fattr, authflavor);
250 if (IS_ERR(server))
270 if (IS_ERR(server))
251 return ERR_CAST(server);
271 return PTR_ERR(server);
252
272
253 mount_info.server = server;
273 ctx->mount_info.server = server;
254
274
255 devname = nfs_devname(dentry, page, PAGE_SIZE);
256 if (IS_ERR(devname))
257 mnt = ERR_CAST(devname);
258 else
259 mnt = vfs_submount(dentry, &nfs_prepared_fs_type, devname, &mount_info);
275 buffer = kmalloc(4096, GFP_USER);
276 if (!buffer)
277 return -ENOMEM;
260
278
261 if (mount_info.server)
262 nfs_free_server(mount_info.server);
263 free_page((unsigned long)page);
264 return mnt;
279 ctx->internal = true;
280 ctx->mount_info.inherited_bsize = ctx->clone_data.sb->s_blocksize_bits;
281
282 p = nfs_devname(dentry, buffer, 4096);
283 if (IS_ERR(p)) {
284 dprintk("NFS: Couldn't determine submount pathname\n");
285 ret = PTR_ERR(p);
286 } else {
287 ret = vfs_parse_fs_string(fc, "source", p, buffer + 4096 - p);
288 if (!ret)
289 ret = vfs_get_tree(fc);
290 }
291 kfree(buffer);
292 return ret;
265}
266EXPORT_SYMBOL_GPL(nfs_do_submount);
267
293}
294EXPORT_SYMBOL_GPL(nfs_do_submount);
295
268struct vfsmount *nfs_submount(struct nfs_server *server, struct dentry *dentry,
269 struct nfs_fh *fh, struct nfs_fattr *fattr)
296int nfs_submount(struct fs_context *fc, struct nfs_server *server)
270{
297{
271 int err;
298 struct nfs_fs_context *ctx = nfs_fc2context(fc);
299 struct dentry *dentry = ctx->clone_data.dentry;
272 struct dentry *parent = dget_parent(dentry);
300 struct dentry *parent = dget_parent(dentry);
301 int err;
273
274 /* Look it up again to get its attributes */
302
303 /* Look it up again to get its attributes */
275 err = server->nfs_client->rpc_ops->lookup(d_inode(parent), &dentry->d_name, fh, fattr, NULL);
304 err = server->nfs_client->rpc_ops->lookup(d_inode(parent), &dentry->d_name,
305 ctx->mount_info.mntfh, ctx->clone_data.fattr,
306 NULL);
276 dput(parent);
277 if (err != 0)
307 dput(parent);
308 if (err != 0)
278 return ERR_PTR(err);
309 return err;
279
310
280 return nfs_do_submount(dentry, fh, fattr, server->client->cl_auth->au_flavor);
311 ctx->selected_flavor = server->client->cl_auth->au_flavor;
312 return nfs_do_submount(fc);
281}
282EXPORT_SYMBOL_GPL(nfs_submount);
313}
314EXPORT_SYMBOL_GPL(nfs_submount);