aboutsummaryrefslogtreecommitdiffstats
path: root/fs
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
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')
-rw-r--r--fs/nfs/internal.h3
-rw-r--r--fs/nfs/namespace.c2
-rw-r--r--fs/nfs/nfs4_fs.h2
-rw-r--r--fs/nfs/nfs4proc.c84
-rw-r--r--fs/nfs/nfs4xdr.c68
5 files changed, 157 insertions, 2 deletions
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h
index 2a55347a2daa..fc017eadfe08 100644
--- a/fs/nfs/internal.h
+++ b/fs/nfs/internal.h
@@ -277,6 +277,9 @@ extern void nfs_sb_deactive(struct super_block *sb);
277extern char *nfs_path(char **p, struct dentry *dentry, 277extern char *nfs_path(char **p, struct dentry *dentry,
278 char *buffer, ssize_t buflen); 278 char *buffer, ssize_t buflen);
279extern struct vfsmount *nfs_d_automount(struct path *path); 279extern struct vfsmount *nfs_d_automount(struct path *path);
280#ifdef CONFIG_NFS_V4
281rpc_authflavor_t nfs_find_best_sec(struct nfs4_secinfo_flavors *);
282#endif
280 283
281/* getroot.c */ 284/* getroot.c */
282extern struct dentry *nfs_get_root(struct super_block *, struct nfs_fh *, 285extern struct dentry *nfs_get_root(struct super_block *, struct nfs_fh *,
diff --git a/fs/nfs/namespace.c b/fs/nfs/namespace.c
index 1f063bacd285..8102391bb374 100644
--- a/fs/nfs/namespace.c
+++ b/fs/nfs/namespace.c
@@ -119,7 +119,7 @@ Elong:
119} 119}
120 120
121#ifdef CONFIG_NFS_V4 121#ifdef CONFIG_NFS_V4
122static rpc_authflavor_t nfs_find_best_sec(struct nfs4_secinfo_flavors *flavors) 122rpc_authflavor_t nfs_find_best_sec(struct nfs4_secinfo_flavors *flavors)
123{ 123{
124 struct gss_api_mech *mech; 124 struct gss_api_mech *mech;
125 struct xdr_netobj oid; 125 struct xdr_netobj oid;
diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h
index b47f0d4710fa..c30aed2c70f4 100644
--- a/fs/nfs/nfs4_fs.h
+++ b/fs/nfs/nfs4_fs.h
@@ -67,6 +67,8 @@ struct nfs4_minor_version_ops {
67 int cache_reply); 67 int cache_reply);
68 int (*validate_stateid)(struct nfs_delegation *, 68 int (*validate_stateid)(struct nfs_delegation *,
69 const nfs4_stateid *); 69 const nfs4_stateid *);
70 int (*find_root_sec)(struct nfs_server *, struct nfs_fh *,
71 struct nfs_fsinfo *);
70 const struct nfs4_state_recovery_ops *reboot_recovery_ops; 72 const struct nfs4_state_recovery_ops *reboot_recovery_ops;
71 const struct nfs4_state_recovery_ops *nograce_recovery_ops; 73 const struct nfs4_state_recovery_ops *nograce_recovery_ops;
72 const struct nfs4_state_maintenance_ops *state_renewal_ops; 74 const struct nfs4_state_maintenance_ops *state_renewal_ops;
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,
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c
index 1555c74dd336..c8c069a6319b 100644
--- a/fs/nfs/nfs4xdr.c
+++ b/fs/nfs/nfs4xdr.c
@@ -343,6 +343,8 @@ static int nfs4_stat_to_errno(int);
343 1 /* FIXME: opaque lrf_body always empty at the moment */) 343 1 /* FIXME: opaque lrf_body always empty at the moment */)
344#define decode_layoutreturn_maxsz (op_decode_hdr_maxsz + \ 344#define decode_layoutreturn_maxsz (op_decode_hdr_maxsz + \
345 1 + decode_stateid_maxsz) 345 1 + decode_stateid_maxsz)
346#define encode_secinfo_no_name_maxsz (op_encode_hdr_maxsz + 1)
347#define decode_secinfo_no_name_maxsz decode_secinfo_maxsz
346#else /* CONFIG_NFS_V4_1 */ 348#else /* CONFIG_NFS_V4_1 */
347#define encode_sequence_maxsz 0 349#define encode_sequence_maxsz 0
348#define decode_sequence_maxsz 0 350#define decode_sequence_maxsz 0
@@ -772,6 +774,14 @@ static int nfs4_stat_to_errno(int);
772 decode_sequence_maxsz + \ 774 decode_sequence_maxsz + \
773 decode_putfh_maxsz + \ 775 decode_putfh_maxsz + \
774 decode_layoutreturn_maxsz) 776 decode_layoutreturn_maxsz)
777#define NFS4_enc_secinfo_no_name_sz (compound_encode_hdr_maxsz + \
778 encode_sequence_maxsz + \
779 encode_putrootfh_maxsz +\
780 encode_secinfo_no_name_maxsz)
781#define NFS4_dec_secinfo_no_name_sz (compound_decode_hdr_maxsz + \
782 decode_sequence_maxsz + \
783 decode_putrootfh_maxsz + \
784 decode_secinfo_no_name_maxsz)
775 785
776const u32 nfs41_maxwrite_overhead = ((RPC_MAX_HEADER_WITH_AUTH + 786const u32 nfs41_maxwrite_overhead = ((RPC_MAX_HEADER_WITH_AUTH +
777 compound_encode_hdr_maxsz + 787 compound_encode_hdr_maxsz +
@@ -1938,6 +1948,20 @@ encode_layoutreturn(struct xdr_stream *xdr,
1938 hdr->nops++; 1948 hdr->nops++;
1939 hdr->replen += decode_layoutreturn_maxsz; 1949 hdr->replen += decode_layoutreturn_maxsz;
1940} 1950}
1951
1952static int
1953encode_secinfo_no_name(struct xdr_stream *xdr,
1954 const struct nfs41_secinfo_no_name_args *args,
1955 struct compound_hdr *hdr)
1956{
1957 __be32 *p;
1958 p = reserve_space(xdr, 8);
1959 *p++ = cpu_to_be32(OP_SECINFO_NO_NAME);
1960 *p++ = cpu_to_be32(args->style);
1961 hdr->nops++;
1962 hdr->replen += decode_secinfo_no_name_maxsz;
1963 return 0;
1964}
1941#endif /* CONFIG_NFS_V4_1 */ 1965#endif /* CONFIG_NFS_V4_1 */
1942 1966
1943/* 1967/*
@@ -2790,6 +2814,25 @@ static void nfs4_xdr_enc_layoutreturn(struct rpc_rqst *req,
2790 encode_layoutreturn(xdr, args, &hdr); 2814 encode_layoutreturn(xdr, args, &hdr);
2791 encode_nops(&hdr); 2815 encode_nops(&hdr);
2792} 2816}
2817
2818/*
2819 * Encode SECINFO_NO_NAME request
2820 */
2821static int nfs4_xdr_enc_secinfo_no_name(struct rpc_rqst *req,
2822 struct xdr_stream *xdr,
2823 struct nfs41_secinfo_no_name_args *args)
2824{
2825 struct compound_hdr hdr = {
2826 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
2827 };
2828
2829 encode_compound_hdr(xdr, req, &hdr);
2830 encode_sequence(xdr, &args->seq_args, &hdr);
2831 encode_putrootfh(xdr, &hdr);
2832 encode_secinfo_no_name(xdr, args, &hdr);
2833 encode_nops(&hdr);
2834 return 0;
2835}
2793#endif /* CONFIG_NFS_V4_1 */ 2836#endif /* CONFIG_NFS_V4_1 */
2794 2837
2795static void print_overflow_msg(const char *func, const struct xdr_stream *xdr) 2838static void print_overflow_msg(const char *func, const struct xdr_stream *xdr)
@@ -6467,6 +6510,30 @@ static int nfs4_xdr_dec_layoutcommit(struct rpc_rqst *rqstp,
6467out: 6510out:
6468 return status; 6511 return status;
6469} 6512}
6513
6514/*
6515 * Decode SECINFO_NO_NAME response
6516 */
6517static int nfs4_xdr_dec_secinfo_no_name(struct rpc_rqst *rqstp,
6518 struct xdr_stream *xdr,
6519 struct nfs4_secinfo_res *res)
6520{
6521 struct compound_hdr hdr;
6522 int status;
6523
6524 status = decode_compound_hdr(xdr, &hdr);
6525 if (status)
6526 goto out;
6527 status = decode_sequence(xdr, &res->seq_res, rqstp);
6528 if (status)
6529 goto out;
6530 status = decode_putrootfh(xdr);
6531 if (status)
6532 goto out;
6533 status = decode_secinfo(xdr, res);
6534out:
6535 return status;
6536}
6470#endif /* CONFIG_NFS_V4_1 */ 6537#endif /* CONFIG_NFS_V4_1 */
6471 6538
6472/** 6539/**
@@ -6669,6 +6736,7 @@ struct rpc_procinfo nfs4_procedures[] = {
6669 PROC(LAYOUTGET, enc_layoutget, dec_layoutget), 6736 PROC(LAYOUTGET, enc_layoutget, dec_layoutget),
6670 PROC(LAYOUTCOMMIT, enc_layoutcommit, dec_layoutcommit), 6737 PROC(LAYOUTCOMMIT, enc_layoutcommit, dec_layoutcommit),
6671 PROC(LAYOUTRETURN, enc_layoutreturn, dec_layoutreturn), 6738 PROC(LAYOUTRETURN, enc_layoutreturn, dec_layoutreturn),
6739 PROC(SECINFO_NO_NAME, enc_secinfo_no_name, dec_secinfo_no_name),
6672#endif /* CONFIG_NFS_V4_1 */ 6740#endif /* CONFIG_NFS_V4_1 */
6673}; 6741};
6674 6742