aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/nfs4proc.c
diff options
context:
space:
mode:
authorBryan Schumaker <bjschuma@netapp.com>2011-06-02 14:59:07 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2011-07-12 13:40:27 -0400
commitfca78d6d2c77f87d7dbee89bbe4836a44da881e2 (patch)
tree5378bd6ad0917cf11ad7f7b739b71794df230c85 /fs/nfs/nfs4proc.c
parent6382a44138e7aa40bf52170e7afc014443a24806 (diff)
NFS: Add SECINFO_NO_NAME procedure
If the client is using NFS v4.1, then we can use SECINFO_NO_NAME to find the secflavor for the initial mount. If the server doesn't support SECINFO_NO_NAME then I fall back on the "guess and check" method used for v4.0 mounts. 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.c84
1 files changed, 83 insertions, 1 deletions
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 5f4912f72282..892bff53f61d 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -2251,13 +2251,14 @@ static int nfs4_find_root_sec(struct nfs_server *server, struct nfs_fh *fhandle,
2251static int nfs4_proc_get_root(struct nfs_server *server, struct nfs_fh *fhandle, 2251static int nfs4_proc_get_root(struct nfs_server *server, struct nfs_fh *fhandle,
2252 struct nfs_fsinfo *info) 2252 struct nfs_fsinfo *info)
2253{ 2253{
2254 int minor_version = server->nfs_client->cl_minorversion;
2254 int status = nfs4_lookup_root(server, fhandle, info); 2255 int status = nfs4_lookup_root(server, fhandle, info);
2255 if ((status == -NFS4ERR_WRONGSEC) && !(server->flags & NFS_MOUNT_SECFLAVOUR)) 2256 if ((status == -NFS4ERR_WRONGSEC) && !(server->flags & NFS_MOUNT_SECFLAVOUR))
2256 /* 2257 /*
2257 * A status of -NFS4ERR_WRONGSEC will be mapped to -EPERM 2258 * A status of -NFS4ERR_WRONGSEC will be mapped to -EPERM
2258 * by nfs4_map_errors() as this function exits. 2259 * by nfs4_map_errors() as this function exits.
2259 */ 2260 */
2260 status = nfs4_find_root_sec(server, fhandle, info); 2261 status = nfs_v4_minor_ops[minor_version]->find_root_sec(server, fhandle, info);
2261 if (status == 0) 2262 if (status == 0)
2262 status = nfs4_server_capabilities(server, fhandle); 2263 status = nfs4_server_capabilities(server, fhandle);
2263 if (status == 0) 2264 if (status == 0)
@@ -5935,6 +5936,85 @@ out:
5935 rpc_put_task(task); 5936 rpc_put_task(task);
5936 return status; 5937 return status;
5937} 5938}
5939
5940static int
5941_nfs41_proc_secinfo_no_name(struct nfs_server *server, struct nfs_fh *fhandle,
5942 struct nfs_fsinfo *info, struct nfs4_secinfo_flavors *flavors)
5943{
5944 struct nfs41_secinfo_no_name_args args = {
5945 .style = SECINFO_STYLE_CURRENT_FH,
5946 };
5947 struct nfs4_secinfo_res res = {
5948 .flavors = flavors,
5949 };
5950 struct rpc_message msg = {
5951 .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_SECINFO_NO_NAME],
5952 .rpc_argp = &args,
5953 .rpc_resp = &res,
5954 };
5955 return nfs4_call_sync(server->client, server, &msg, &args.seq_args, &res.seq_res, 0);
5956}
5957
5958static int
5959nfs41_proc_secinfo_no_name(struct nfs_server *server, struct nfs_fh *fhandle,
5960 struct nfs_fsinfo *info, struct nfs4_secinfo_flavors *flavors)
5961{
5962 struct nfs4_exception exception = { };
5963 int err;
5964 do {
5965 err = _nfs41_proc_secinfo_no_name(server, fhandle, info, flavors);
5966 switch (err) {
5967 case 0:
5968 case -NFS4ERR_WRONGSEC:
5969 case -NFS4ERR_NOTSUPP:
5970 break;
5971 default:
5972 err = nfs4_handle_exception(server, err, &exception);
5973 }
5974 } while (exception.retry);
5975 return err;
5976}
5977
5978static int
5979nfs41_find_root_sec(struct nfs_server *server, struct nfs_fh *fhandle,
5980 struct nfs_fsinfo *info)
5981{
5982 int err;
5983 struct page *page;
5984 rpc_authflavor_t flavor;
5985 struct nfs4_secinfo_flavors *flavors;
5986
5987 page = alloc_page(GFP_KERNEL);
5988 if (!page) {
5989 err = -ENOMEM;
5990 goto out;
5991 }
5992
5993 flavors = page_address(page);
5994 err = nfs41_proc_secinfo_no_name(server, fhandle, info, flavors);
5995
5996 /*
5997 * Fall back on "guess and check" method if
5998 * the server doesn't support SECINFO_NO_NAME
5999 */
6000 if (err == -NFS4ERR_WRONGSEC || err == -NFS4ERR_NOTSUPP) {
6001 err = nfs4_find_root_sec(server, fhandle, info);
6002 goto out_freepage;
6003 }
6004 if (err)
6005 goto out_freepage;
6006
6007 flavor = nfs_find_best_sec(flavors);
6008 if (err == 0)
6009 err = nfs4_lookup_root_sec(server, fhandle, info, flavor);
6010
6011out_freepage:
6012 put_page(page);
6013 if (err == -EACCES)
6014 return -EPERM;
6015out:
6016 return err;
6017}
5938#endif /* CONFIG_NFS_V4_1 */ 6018#endif /* CONFIG_NFS_V4_1 */
5939 6019
5940struct nfs4_state_recovery_ops nfs40_reboot_recovery_ops = { 6020struct nfs4_state_recovery_ops nfs40_reboot_recovery_ops = {
@@ -5996,6 +6076,7 @@ static const struct nfs4_minor_version_ops nfs_v4_0_minor_ops = {
5996 .minor_version = 0, 6076 .minor_version = 0,
5997 .call_sync = _nfs4_call_sync, 6077 .call_sync = _nfs4_call_sync,
5998 .validate_stateid = nfs4_validate_delegation_stateid, 6078 .validate_stateid = nfs4_validate_delegation_stateid,
6079 .find_root_sec = nfs4_find_root_sec,
5999 .reboot_recovery_ops = &nfs40_reboot_recovery_ops, 6080 .reboot_recovery_ops = &nfs40_reboot_recovery_ops,
6000 .nograce_recovery_ops = &nfs40_nograce_recovery_ops, 6081 .nograce_recovery_ops = &nfs40_nograce_recovery_ops,
6001 .state_renewal_ops = &nfs40_state_renewal_ops, 6082 .state_renewal_ops = &nfs40_state_renewal_ops,
@@ -6006,6 +6087,7 @@ static const struct nfs4_minor_version_ops nfs_v4_1_minor_ops = {
6006 .minor_version = 1, 6087 .minor_version = 1,
6007 .call_sync = _nfs4_call_sync_session, 6088 .call_sync = _nfs4_call_sync_session,
6008 .validate_stateid = nfs41_validate_delegation_stateid, 6089 .validate_stateid = nfs41_validate_delegation_stateid,
6090 .find_root_sec = nfs41_find_root_sec,
6009 .reboot_recovery_ops = &nfs41_reboot_recovery_ops, 6091 .reboot_recovery_ops = &nfs41_reboot_recovery_ops,
6010 .nograce_recovery_ops = &nfs41_nograce_recovery_ops, 6092 .nograce_recovery_ops = &nfs41_nograce_recovery_ops,
6011 .state_renewal_ops = &nfs41_state_renewal_ops, 6093 .state_renewal_ops = &nfs41_state_renewal_ops,