aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/namespace.c
diff options
context:
space:
mode:
authorBryan Schumaker <bjschuma@netapp.com>2012-04-27 13:27:41 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2012-04-27 14:10:02 -0400
commitf05d147f7e3cf0d86b3a4bd5603029a7cb109633 (patch)
treee351ef7dd3d541626f5cccef86f50906bfb3a649 /fs/nfs/namespace.c
parent72de53ec4bca39c26709122a8f78bfefe7b6bca4 (diff)
NFS: Fix following referral mount points with different security
I create a new proc_lookup_mountpoint() to use when submounting an NFS v4 share. This function returns an rpc_clnt to use for performing an fs_locations() call on a referral's mountpoint. Signed-off-by: Bryan Schumaker <bjschuma@netapp.com> Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs/nfs/namespace.c')
-rw-r--r--fs/nfs/namespace.c44
1 files changed, 34 insertions, 10 deletions
diff --git a/fs/nfs/namespace.c b/fs/nfs/namespace.c
index 1807866bb3ab..b9a593d056b3 100644
--- a/fs/nfs/namespace.c
+++ b/fs/nfs/namespace.c
@@ -200,6 +200,22 @@ out_shutdown:
200out: 200out:
201 return err; 201 return err;
202} 202}
203
204static struct rpc_clnt *nfs_lookup_mountpoint(struct inode *dir,
205 struct qstr *name,
206 struct nfs_fh *fh,
207 struct nfs_fattr *fattr)
208{
209 int err;
210
211 if (NFS_PROTO(dir)->version == 4)
212 return nfs4_proc_lookup_mountpoint(dir, name, fh, fattr);
213
214 err = NFS_PROTO(dir)->lookup(NFS_SERVER(dir)->client, dir, name, fh, fattr);
215 if (err)
216 return ERR_PTR(err);
217 return rpc_clone_client(NFS_SERVER(dir)->client);
218}
203#else /* CONFIG_NFS_V4 */ 219#else /* CONFIG_NFS_V4 */
204static inline int nfs_lookup_with_sec(struct nfs_server *server, 220static inline int nfs_lookup_with_sec(struct nfs_server *server,
205 struct dentry *parent, struct dentry *dentry, 221 struct dentry *parent, struct dentry *dentry,
@@ -209,6 +225,17 @@ static inline int nfs_lookup_with_sec(struct nfs_server *server,
209{ 225{
210 return -EPERM; 226 return -EPERM;
211} 227}
228
229static inline struct rpc_clnt *nfs_lookup_mountpoint(struct inode *dir,
230 struct qstr *name,
231 struct nfs_fh *fh,
232 struct nfs_fattr *fattr)
233{
234 int err = NFS_PROTO(dir)->lookup(NFS_SERVER(dir)->client, dir, name, fh, fattr);
235 if (err)
236 return ERR_PTR(err);
237 return rpc_clone_client(NFS_SERVER(dir)->client);
238}
212#endif /* CONFIG_NFS_V4 */ 239#endif /* CONFIG_NFS_V4 */
213 240
214/* 241/*
@@ -226,11 +253,10 @@ static inline int nfs_lookup_with_sec(struct nfs_server *server,
226struct vfsmount *nfs_d_automount(struct path *path) 253struct vfsmount *nfs_d_automount(struct path *path)
227{ 254{
228 struct vfsmount *mnt; 255 struct vfsmount *mnt;
229 struct nfs_server *server = NFS_SERVER(path->dentry->d_inode);
230 struct dentry *parent; 256 struct dentry *parent;
231 struct nfs_fh *fh = NULL; 257 struct nfs_fh *fh = NULL;
232 struct nfs_fattr *fattr = NULL; 258 struct nfs_fattr *fattr = NULL;
233 int err; 259 struct rpc_clnt *client;
234 rpc_authflavor_t flavor = RPC_AUTH_UNIX; 260 rpc_authflavor_t flavor = RPC_AUTH_UNIX;
235 261
236 dprintk("--> nfs_d_automount()\n"); 262 dprintk("--> nfs_d_automount()\n");
@@ -249,21 +275,19 @@ struct vfsmount *nfs_d_automount(struct path *path)
249 275
250 /* Look it up again to get its attributes */ 276 /* Look it up again to get its attributes */
251 parent = dget_parent(path->dentry); 277 parent = dget_parent(path->dentry);
252 err = server->nfs_client->rpc_ops->lookup(server->client, parent->d_inode, 278 client = nfs_lookup_mountpoint(parent->d_inode, &path->dentry->d_name, fh, fattr);
253 &path->dentry->d_name,
254 fh, fattr);
255 if (err == -EPERM && NFS_PROTO(parent->d_inode)->secinfo != NULL)
256 err = nfs_lookup_with_sec(server, parent, path->dentry, path, fh, fattr, &flavor);
257 dput(parent); 279 dput(parent);
258 if (err != 0) { 280 if (IS_ERR(client)) {
259 mnt = ERR_PTR(err); 281 mnt = ERR_CAST(client);
260 goto out; 282 goto out;
261 } 283 }
262 284
263 if (fattr->valid & NFS_ATTR_FATTR_V4_REFERRAL) 285 if (fattr->valid & NFS_ATTR_FATTR_V4_REFERRAL)
264 mnt = nfs_do_refmount(path->dentry); 286 mnt = nfs_do_refmount(client, path->dentry);
265 else 287 else
266 mnt = nfs_do_submount(path->dentry, fh, fattr, flavor); 288 mnt = nfs_do_submount(path->dentry, fh, fattr, flavor);
289 rpc_shutdown_client(client);
290
267 if (IS_ERR(mnt)) 291 if (IS_ERR(mnt))
268 goto out; 292 goto out;
269 293