diff options
author | Bryan Schumaker <bjschuma@netapp.com> | 2012-04-27 13:27:41 -0400 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2012-04-27 14:10:02 -0400 |
commit | f05d147f7e3cf0d86b3a4bd5603029a7cb109633 (patch) | |
tree | e351ef7dd3d541626f5cccef86f50906bfb3a649 /fs/nfs/nfs4proc.c | |
parent | 72de53ec4bca39c26709122a8f78bfefe7b6bca4 (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/nfs4proc.c')
-rw-r--r-- | fs/nfs/nfs4proc.c | 40 |
1 files changed, 30 insertions, 10 deletions
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 3d92fe6be780..75eb883ed4ce 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
@@ -2377,8 +2377,9 @@ static int nfs4_proc_get_root(struct nfs_server *server, struct nfs_fh *fhandle, | |||
2377 | * Note that we'll actually follow the referral later when | 2377 | * Note that we'll actually follow the referral later when |
2378 | * we detect fsid mismatch in inode revalidation | 2378 | * we detect fsid mismatch in inode revalidation |
2379 | */ | 2379 | */ |
2380 | static int nfs4_get_referral(struct inode *dir, const struct qstr *name, | 2380 | static int nfs4_get_referral(struct rpc_clnt *client, struct inode *dir, |
2381 | struct nfs_fattr *fattr, struct nfs_fh *fhandle) | 2381 | const struct qstr *name, struct nfs_fattr *fattr, |
2382 | struct nfs_fh *fhandle) | ||
2382 | { | 2383 | { |
2383 | int status = -ENOMEM; | 2384 | int status = -ENOMEM; |
2384 | struct page *page = NULL; | 2385 | struct page *page = NULL; |
@@ -2391,7 +2392,7 @@ static int nfs4_get_referral(struct inode *dir, const struct qstr *name, | |||
2391 | if (locations == NULL) | 2392 | if (locations == NULL) |
2392 | goto out; | 2393 | goto out; |
2393 | 2394 | ||
2394 | status = nfs4_proc_fs_locations(dir, name, locations, page); | 2395 | status = nfs4_proc_fs_locations(client, dir, name, locations, page); |
2395 | if (status != 0) | 2396 | if (status != 0) |
2396 | goto out; | 2397 | goto out; |
2397 | /* Make sure server returned a different fsid for the referral */ | 2398 | /* Make sure server returned a different fsid for the referral */ |
@@ -2550,7 +2551,7 @@ static int nfs4_proc_lookup_common(struct rpc_clnt **clnt, struct inode *dir, | |||
2550 | err = -ENOENT; | 2551 | err = -ENOENT; |
2551 | goto out; | 2552 | goto out; |
2552 | case -NFS4ERR_MOVED: | 2553 | case -NFS4ERR_MOVED: |
2553 | err = nfs4_get_referral(dir, name, fattr, fhandle); | 2554 | err = nfs4_get_referral(client, dir, name, fattr, fhandle); |
2554 | goto out; | 2555 | goto out; |
2555 | case -NFS4ERR_WRONGSEC: | 2556 | case -NFS4ERR_WRONGSEC: |
2556 | err = -EPERM; | 2557 | err = -EPERM; |
@@ -2591,6 +2592,21 @@ static int nfs4_proc_lookup(struct rpc_clnt *clnt, struct inode *dir, struct qst | |||
2591 | return status; | 2592 | return status; |
2592 | } | 2593 | } |
2593 | 2594 | ||
2595 | struct rpc_clnt * | ||
2596 | nfs4_proc_lookup_mountpoint(struct inode *dir, struct qstr *name, | ||
2597 | struct nfs_fh *fhandle, struct nfs_fattr *fattr) | ||
2598 | { | ||
2599 | int status; | ||
2600 | struct rpc_clnt *client = rpc_clone_client(NFS_CLIENT(dir)); | ||
2601 | |||
2602 | status = nfs4_proc_lookup_common(&client, dir, name, fhandle, fattr); | ||
2603 | if (status < 0) { | ||
2604 | rpc_shutdown_client(client); | ||
2605 | return ERR_PTR(status); | ||
2606 | } | ||
2607 | return client; | ||
2608 | } | ||
2609 | |||
2594 | static int _nfs4_proc_access(struct inode *inode, struct nfs_access_entry *entry) | 2610 | static int _nfs4_proc_access(struct inode *inode, struct nfs_access_entry *entry) |
2595 | { | 2611 | { |
2596 | struct nfs_server *server = NFS_SERVER(inode); | 2612 | struct nfs_server *server = NFS_SERVER(inode); |
@@ -4951,8 +4967,10 @@ static void nfs_fixup_referral_attributes(struct nfs_fattr *fattr) | |||
4951 | fattr->nlink = 2; | 4967 | fattr->nlink = 2; |
4952 | } | 4968 | } |
4953 | 4969 | ||
4954 | static int _nfs4_proc_fs_locations(struct inode *dir, const struct qstr *name, | 4970 | static int _nfs4_proc_fs_locations(struct rpc_clnt *client, struct inode *dir, |
4955 | struct nfs4_fs_locations *fs_locations, struct page *page) | 4971 | const struct qstr *name, |
4972 | struct nfs4_fs_locations *fs_locations, | ||
4973 | struct page *page) | ||
4956 | { | 4974 | { |
4957 | struct nfs_server *server = NFS_SERVER(dir); | 4975 | struct nfs_server *server = NFS_SERVER(dir); |
4958 | u32 bitmask[2] = { | 4976 | u32 bitmask[2] = { |
@@ -4986,19 +5004,21 @@ static int _nfs4_proc_fs_locations(struct inode *dir, const struct qstr *name, | |||
4986 | nfs_fattr_init(&fs_locations->fattr); | 5004 | nfs_fattr_init(&fs_locations->fattr); |
4987 | fs_locations->server = server; | 5005 | fs_locations->server = server; |
4988 | fs_locations->nlocations = 0; | 5006 | fs_locations->nlocations = 0; |
4989 | status = nfs4_call_sync(server->client, server, &msg, &args.seq_args, &res.seq_res, 0); | 5007 | status = nfs4_call_sync(client, server, &msg, &args.seq_args, &res.seq_res, 0); |
4990 | dprintk("%s: returned status = %d\n", __func__, status); | 5008 | dprintk("%s: returned status = %d\n", __func__, status); |
4991 | return status; | 5009 | return status; |
4992 | } | 5010 | } |
4993 | 5011 | ||
4994 | int nfs4_proc_fs_locations(struct inode *dir, const struct qstr *name, | 5012 | int nfs4_proc_fs_locations(struct rpc_clnt *client, struct inode *dir, |
4995 | struct nfs4_fs_locations *fs_locations, struct page *page) | 5013 | const struct qstr *name, |
5014 | struct nfs4_fs_locations *fs_locations, | ||
5015 | struct page *page) | ||
4996 | { | 5016 | { |
4997 | struct nfs4_exception exception = { }; | 5017 | struct nfs4_exception exception = { }; |
4998 | int err; | 5018 | int err; |
4999 | do { | 5019 | do { |
5000 | err = nfs4_handle_exception(NFS_SERVER(dir), | 5020 | err = nfs4_handle_exception(NFS_SERVER(dir), |
5001 | _nfs4_proc_fs_locations(dir, name, fs_locations, page), | 5021 | _nfs4_proc_fs_locations(client, dir, name, fs_locations, page), |
5002 | &exception); | 5022 | &exception); |
5003 | } while (exception.retry); | 5023 | } while (exception.retry); |
5004 | return err; | 5024 | return err; |