/** * nfs_do_submount - set up mountpoint when crossing a filesystem boundary * @mnt_parent - mountpoint of parent directory * @dentry - parent directory * @fh - filehandle for new root dentry * @fattr - attributes for new root inode * */ static struct vfsmount *nfs_do_submount(const struct vfsmount *mnt_parent, const struct dentry *dentry, struct nfs_fh *fh, struct nfs_fattr *fattr) { struct nfs_clone_mount mountdata = { .sb = mnt_parent->mnt_sb, .dentry = dentry, .fh = fh, .fattr = fattr, }; struct vfsmount *mnt = ERR_PTR(-ENOMEM); char *page = (char *) __get_free_page(GFP_USER); char *devname; dprintk("--> nfs_do_submount()\n"); dprintk("%s: submounting on %s/%s\n", __func__, dentry->d_parent->d_name.name, dentry->d_name.name); if (page == NULL) goto out; devname = nfs_devname(mnt_parent, dentry, page, PAGE_SIZE); mnt = (struct vfsmount *)devname; if (IS_ERR(devname)) goto free_page; mnt = nfs_do_clone_mount(NFS_SB(mnt_parent->mnt_sb), devname, &mountdata); free_page: free_page((unsigned long)page); out: dprintk("%s: done\n", __func__); dprintk("<-- nfs_do_submount() = %p\n", mnt); return mnt; }
/** * nfs_do_submount - set up mountpoint when crossing a filesystem boundary * @dentry - parent directory * @fh - filehandle for new root dentry * @fattr - attributes for new root inode * @authflavor - security flavor to use when performing the mount * */ struct vfsmount *nfs_do_submount(struct dentry *dentry, struct nfs_fh *fh, struct nfs_fattr *fattr, rpc_authflavor_t authflavor) { struct nfs_clone_mount mountdata = { .sb = dentry->d_sb, .dentry = dentry, .fh = fh, .fattr = fattr, .authflavor = authflavor, }; struct vfsmount *mnt = ERR_PTR(-ENOMEM); char *page = (char *) __get_free_page(GFP_USER); char *devname; dprintk("--> nfs_do_submount()\n"); dprintk("%s: submounting on %s/%s\n", __func__, dentry->d_parent->d_name.name, dentry->d_name.name); if (page == NULL) goto out; devname = nfs_devname(dentry, page, PAGE_SIZE); mnt = (struct vfsmount *)devname; if (IS_ERR(devname)) goto free_page; mnt = nfs_do_clone_mount(NFS_SB(dentry->d_sb), devname, &mountdata); free_page: free_page((unsigned long)page); out: dprintk("%s: done\n", __func__); dprintk("<-- nfs_do_submount() = %p\n", mnt); return mnt; } EXPORT_SYMBOL_GPL(nfs_do_submount); struct vfsmount *nfs_submount(struct nfs_server *server, struct dentry *dentry, struct nfs_fh *fh, struct nfs_fattr *fattr) { int err; struct dentry *parent = dget_parent(dentry); /* Look it up again to get its attributes */ err = server->nfs_client->rpc_ops->lookup(parent->d_inode, &dentry->d_name, fh, fattr); dput(parent); if (err != 0) return ERR_PTR(err); return nfs_do_submount(dentry, fh, fattr, server->client->cl_auth->au_flavor); }
/** * nfs_do_submount - set up mountpoint when crossing a filesystem boundary * @dentry - parent directory * @fh - filehandle for new root dentry * @fattr - attributes for new root inode * @authflavor - security flavor to use when performing the mount * */ struct vfsmount *nfs_do_submount(struct dentry *dentry, struct nfs_fh *fh, struct nfs_fattr *fattr, rpc_authflavor_t authflavor) { struct nfs_clone_mount mountdata = { .sb = dentry->d_sb, .dentry = dentry, .fh = fh, .fattr = fattr, .authflavor = authflavor, }; struct vfsmount *mnt; char *page = (char *) __get_free_page(GFP_USER); char *devname; if (page == NULL) return ERR_PTR(-ENOMEM); devname = nfs_devname(dentry, page, PAGE_SIZE); if (IS_ERR(devname)) mnt = (struct vfsmount *)devname; else mnt = nfs_do_clone_mount(NFS_SB(dentry->d_sb), devname, &mountdata); free_page((unsigned long)page); return mnt; } EXPORT_SYMBOL_GPL(nfs_do_submount); struct vfsmount *nfs_submount(struct nfs_server *server, struct dentry *dentry, struct nfs_fh *fh, struct nfs_fattr *fattr) { int err; struct dentry *parent = dget_parent(dentry); /* Look it up again to get its attributes */ err = server->nfs_client->rpc_ops->lookup(d_inode(parent), &dentry->d_name, fh, fattr, NULL); dput(parent); if (err != 0) return ERR_PTR(err); return nfs_do_submount(dentry, fh, fattr, server->client->cl_auth->au_flavor); }