mirror of
https://github.com/Fishwaldo/linux-bl808.git
synced 2025-06-17 20:25:19 +00:00
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>
This commit is contained in:
parent
6382a44138
commit
fca78d6d2c
7 changed files with 166 additions and 2 deletions
|
@ -277,6 +277,9 @@ extern void nfs_sb_deactive(struct super_block *sb);
|
||||||
extern char *nfs_path(char **p, struct dentry *dentry,
|
extern char *nfs_path(char **p, struct dentry *dentry,
|
||||||
char *buffer, ssize_t buflen);
|
char *buffer, ssize_t buflen);
|
||||||
extern struct vfsmount *nfs_d_automount(struct path *path);
|
extern struct vfsmount *nfs_d_automount(struct path *path);
|
||||||
|
#ifdef CONFIG_NFS_V4
|
||||||
|
rpc_authflavor_t nfs_find_best_sec(struct nfs4_secinfo_flavors *);
|
||||||
|
#endif
|
||||||
|
|
||||||
/* getroot.c */
|
/* getroot.c */
|
||||||
extern struct dentry *nfs_get_root(struct super_block *, struct nfs_fh *,
|
extern struct dentry *nfs_get_root(struct super_block *, struct nfs_fh *,
|
||||||
|
|
|
@ -119,7 +119,7 @@ Elong:
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_NFS_V4
|
#ifdef CONFIG_NFS_V4
|
||||||
static rpc_authflavor_t nfs_find_best_sec(struct nfs4_secinfo_flavors *flavors)
|
rpc_authflavor_t nfs_find_best_sec(struct nfs4_secinfo_flavors *flavors)
|
||||||
{
|
{
|
||||||
struct gss_api_mech *mech;
|
struct gss_api_mech *mech;
|
||||||
struct xdr_netobj oid;
|
struct xdr_netobj oid;
|
||||||
|
|
|
@ -67,6 +67,8 @@ struct nfs4_minor_version_ops {
|
||||||
int cache_reply);
|
int cache_reply);
|
||||||
int (*validate_stateid)(struct nfs_delegation *,
|
int (*validate_stateid)(struct nfs_delegation *,
|
||||||
const nfs4_stateid *);
|
const nfs4_stateid *);
|
||||||
|
int (*find_root_sec)(struct nfs_server *, struct nfs_fh *,
|
||||||
|
struct nfs_fsinfo *);
|
||||||
const struct nfs4_state_recovery_ops *reboot_recovery_ops;
|
const struct nfs4_state_recovery_ops *reboot_recovery_ops;
|
||||||
const struct nfs4_state_recovery_ops *nograce_recovery_ops;
|
const struct nfs4_state_recovery_ops *nograce_recovery_ops;
|
||||||
const struct nfs4_state_maintenance_ops *state_renewal_ops;
|
const struct nfs4_state_maintenance_ops *state_renewal_ops;
|
||||||
|
|
|
@ -2251,13 +2251,14 @@ static int nfs4_find_root_sec(struct nfs_server *server, struct nfs_fh *fhandle,
|
||||||
static int nfs4_proc_get_root(struct nfs_server *server, struct nfs_fh *fhandle,
|
static int nfs4_proc_get_root(struct nfs_server *server, struct nfs_fh *fhandle,
|
||||||
struct nfs_fsinfo *info)
|
struct nfs_fsinfo *info)
|
||||||
{
|
{
|
||||||
|
int minor_version = server->nfs_client->cl_minorversion;
|
||||||
int status = nfs4_lookup_root(server, fhandle, info);
|
int status = nfs4_lookup_root(server, fhandle, info);
|
||||||
if ((status == -NFS4ERR_WRONGSEC) && !(server->flags & NFS_MOUNT_SECFLAVOUR))
|
if ((status == -NFS4ERR_WRONGSEC) && !(server->flags & NFS_MOUNT_SECFLAVOUR))
|
||||||
/*
|
/*
|
||||||
* A status of -NFS4ERR_WRONGSEC will be mapped to -EPERM
|
* A status of -NFS4ERR_WRONGSEC will be mapped to -EPERM
|
||||||
* by nfs4_map_errors() as this function exits.
|
* by nfs4_map_errors() as this function exits.
|
||||||
*/
|
*/
|
||||||
status = nfs4_find_root_sec(server, fhandle, info);
|
status = nfs_v4_minor_ops[minor_version]->find_root_sec(server, fhandle, info);
|
||||||
if (status == 0)
|
if (status == 0)
|
||||||
status = nfs4_server_capabilities(server, fhandle);
|
status = nfs4_server_capabilities(server, fhandle);
|
||||||
if (status == 0)
|
if (status == 0)
|
||||||
|
@ -5935,6 +5936,85 @@ out:
|
||||||
rpc_put_task(task);
|
rpc_put_task(task);
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
_nfs41_proc_secinfo_no_name(struct nfs_server *server, struct nfs_fh *fhandle,
|
||||||
|
struct nfs_fsinfo *info, struct nfs4_secinfo_flavors *flavors)
|
||||||
|
{
|
||||||
|
struct nfs41_secinfo_no_name_args args = {
|
||||||
|
.style = SECINFO_STYLE_CURRENT_FH,
|
||||||
|
};
|
||||||
|
struct nfs4_secinfo_res res = {
|
||||||
|
.flavors = flavors,
|
||||||
|
};
|
||||||
|
struct rpc_message msg = {
|
||||||
|
.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_SECINFO_NO_NAME],
|
||||||
|
.rpc_argp = &args,
|
||||||
|
.rpc_resp = &res,
|
||||||
|
};
|
||||||
|
return nfs4_call_sync(server->client, server, &msg, &args.seq_args, &res.seq_res, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
nfs41_proc_secinfo_no_name(struct nfs_server *server, struct nfs_fh *fhandle,
|
||||||
|
struct nfs_fsinfo *info, struct nfs4_secinfo_flavors *flavors)
|
||||||
|
{
|
||||||
|
struct nfs4_exception exception = { };
|
||||||
|
int err;
|
||||||
|
do {
|
||||||
|
err = _nfs41_proc_secinfo_no_name(server, fhandle, info, flavors);
|
||||||
|
switch (err) {
|
||||||
|
case 0:
|
||||||
|
case -NFS4ERR_WRONGSEC:
|
||||||
|
case -NFS4ERR_NOTSUPP:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
err = nfs4_handle_exception(server, err, &exception);
|
||||||
|
}
|
||||||
|
} while (exception.retry);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
nfs41_find_root_sec(struct nfs_server *server, struct nfs_fh *fhandle,
|
||||||
|
struct nfs_fsinfo *info)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
struct page *page;
|
||||||
|
rpc_authflavor_t flavor;
|
||||||
|
struct nfs4_secinfo_flavors *flavors;
|
||||||
|
|
||||||
|
page = alloc_page(GFP_KERNEL);
|
||||||
|
if (!page) {
|
||||||
|
err = -ENOMEM;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
flavors = page_address(page);
|
||||||
|
err = nfs41_proc_secinfo_no_name(server, fhandle, info, flavors);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Fall back on "guess and check" method if
|
||||||
|
* the server doesn't support SECINFO_NO_NAME
|
||||||
|
*/
|
||||||
|
if (err == -NFS4ERR_WRONGSEC || err == -NFS4ERR_NOTSUPP) {
|
||||||
|
err = nfs4_find_root_sec(server, fhandle, info);
|
||||||
|
goto out_freepage;
|
||||||
|
}
|
||||||
|
if (err)
|
||||||
|
goto out_freepage;
|
||||||
|
|
||||||
|
flavor = nfs_find_best_sec(flavors);
|
||||||
|
if (err == 0)
|
||||||
|
err = nfs4_lookup_root_sec(server, fhandle, info, flavor);
|
||||||
|
|
||||||
|
out_freepage:
|
||||||
|
put_page(page);
|
||||||
|
if (err == -EACCES)
|
||||||
|
return -EPERM;
|
||||||
|
out:
|
||||||
|
return err;
|
||||||
|
}
|
||||||
#endif /* CONFIG_NFS_V4_1 */
|
#endif /* CONFIG_NFS_V4_1 */
|
||||||
|
|
||||||
struct nfs4_state_recovery_ops nfs40_reboot_recovery_ops = {
|
struct nfs4_state_recovery_ops nfs40_reboot_recovery_ops = {
|
||||||
|
@ -5996,6 +6076,7 @@ static const struct nfs4_minor_version_ops nfs_v4_0_minor_ops = {
|
||||||
.minor_version = 0,
|
.minor_version = 0,
|
||||||
.call_sync = _nfs4_call_sync,
|
.call_sync = _nfs4_call_sync,
|
||||||
.validate_stateid = nfs4_validate_delegation_stateid,
|
.validate_stateid = nfs4_validate_delegation_stateid,
|
||||||
|
.find_root_sec = nfs4_find_root_sec,
|
||||||
.reboot_recovery_ops = &nfs40_reboot_recovery_ops,
|
.reboot_recovery_ops = &nfs40_reboot_recovery_ops,
|
||||||
.nograce_recovery_ops = &nfs40_nograce_recovery_ops,
|
.nograce_recovery_ops = &nfs40_nograce_recovery_ops,
|
||||||
.state_renewal_ops = &nfs40_state_renewal_ops,
|
.state_renewal_ops = &nfs40_state_renewal_ops,
|
||||||
|
@ -6006,6 +6087,7 @@ static const struct nfs4_minor_version_ops nfs_v4_1_minor_ops = {
|
||||||
.minor_version = 1,
|
.minor_version = 1,
|
||||||
.call_sync = _nfs4_call_sync_session,
|
.call_sync = _nfs4_call_sync_session,
|
||||||
.validate_stateid = nfs41_validate_delegation_stateid,
|
.validate_stateid = nfs41_validate_delegation_stateid,
|
||||||
|
.find_root_sec = nfs41_find_root_sec,
|
||||||
.reboot_recovery_ops = &nfs41_reboot_recovery_ops,
|
.reboot_recovery_ops = &nfs41_reboot_recovery_ops,
|
||||||
.nograce_recovery_ops = &nfs41_nograce_recovery_ops,
|
.nograce_recovery_ops = &nfs41_nograce_recovery_ops,
|
||||||
.state_renewal_ops = &nfs41_state_renewal_ops,
|
.state_renewal_ops = &nfs41_state_renewal_ops,
|
||||||
|
|
|
@ -343,6 +343,8 @@ static int nfs4_stat_to_errno(int);
|
||||||
1 /* FIXME: opaque lrf_body always empty at the moment */)
|
1 /* FIXME: opaque lrf_body always empty at the moment */)
|
||||||
#define decode_layoutreturn_maxsz (op_decode_hdr_maxsz + \
|
#define decode_layoutreturn_maxsz (op_decode_hdr_maxsz + \
|
||||||
1 + decode_stateid_maxsz)
|
1 + decode_stateid_maxsz)
|
||||||
|
#define encode_secinfo_no_name_maxsz (op_encode_hdr_maxsz + 1)
|
||||||
|
#define decode_secinfo_no_name_maxsz decode_secinfo_maxsz
|
||||||
#else /* CONFIG_NFS_V4_1 */
|
#else /* CONFIG_NFS_V4_1 */
|
||||||
#define encode_sequence_maxsz 0
|
#define encode_sequence_maxsz 0
|
||||||
#define decode_sequence_maxsz 0
|
#define decode_sequence_maxsz 0
|
||||||
|
@ -772,6 +774,14 @@ static int nfs4_stat_to_errno(int);
|
||||||
decode_sequence_maxsz + \
|
decode_sequence_maxsz + \
|
||||||
decode_putfh_maxsz + \
|
decode_putfh_maxsz + \
|
||||||
decode_layoutreturn_maxsz)
|
decode_layoutreturn_maxsz)
|
||||||
|
#define NFS4_enc_secinfo_no_name_sz (compound_encode_hdr_maxsz + \
|
||||||
|
encode_sequence_maxsz + \
|
||||||
|
encode_putrootfh_maxsz +\
|
||||||
|
encode_secinfo_no_name_maxsz)
|
||||||
|
#define NFS4_dec_secinfo_no_name_sz (compound_decode_hdr_maxsz + \
|
||||||
|
decode_sequence_maxsz + \
|
||||||
|
decode_putrootfh_maxsz + \
|
||||||
|
decode_secinfo_no_name_maxsz)
|
||||||
|
|
||||||
const u32 nfs41_maxwrite_overhead = ((RPC_MAX_HEADER_WITH_AUTH +
|
const u32 nfs41_maxwrite_overhead = ((RPC_MAX_HEADER_WITH_AUTH +
|
||||||
compound_encode_hdr_maxsz +
|
compound_encode_hdr_maxsz +
|
||||||
|
@ -1938,6 +1948,20 @@ encode_layoutreturn(struct xdr_stream *xdr,
|
||||||
hdr->nops++;
|
hdr->nops++;
|
||||||
hdr->replen += decode_layoutreturn_maxsz;
|
hdr->replen += decode_layoutreturn_maxsz;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
encode_secinfo_no_name(struct xdr_stream *xdr,
|
||||||
|
const struct nfs41_secinfo_no_name_args *args,
|
||||||
|
struct compound_hdr *hdr)
|
||||||
|
{
|
||||||
|
__be32 *p;
|
||||||
|
p = reserve_space(xdr, 8);
|
||||||
|
*p++ = cpu_to_be32(OP_SECINFO_NO_NAME);
|
||||||
|
*p++ = cpu_to_be32(args->style);
|
||||||
|
hdr->nops++;
|
||||||
|
hdr->replen += decode_secinfo_no_name_maxsz;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
#endif /* CONFIG_NFS_V4_1 */
|
#endif /* CONFIG_NFS_V4_1 */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -2790,6 +2814,25 @@ static void nfs4_xdr_enc_layoutreturn(struct rpc_rqst *req,
|
||||||
encode_layoutreturn(xdr, args, &hdr);
|
encode_layoutreturn(xdr, args, &hdr);
|
||||||
encode_nops(&hdr);
|
encode_nops(&hdr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Encode SECINFO_NO_NAME request
|
||||||
|
*/
|
||||||
|
static int nfs4_xdr_enc_secinfo_no_name(struct rpc_rqst *req,
|
||||||
|
struct xdr_stream *xdr,
|
||||||
|
struct nfs41_secinfo_no_name_args *args)
|
||||||
|
{
|
||||||
|
struct compound_hdr hdr = {
|
||||||
|
.minorversion = nfs4_xdr_minorversion(&args->seq_args),
|
||||||
|
};
|
||||||
|
|
||||||
|
encode_compound_hdr(xdr, req, &hdr);
|
||||||
|
encode_sequence(xdr, &args->seq_args, &hdr);
|
||||||
|
encode_putrootfh(xdr, &hdr);
|
||||||
|
encode_secinfo_no_name(xdr, args, &hdr);
|
||||||
|
encode_nops(&hdr);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
#endif /* CONFIG_NFS_V4_1 */
|
#endif /* CONFIG_NFS_V4_1 */
|
||||||
|
|
||||||
static void print_overflow_msg(const char *func, const struct xdr_stream *xdr)
|
static 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,
|
||||||
out:
|
out:
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Decode SECINFO_NO_NAME response
|
||||||
|
*/
|
||||||
|
static int nfs4_xdr_dec_secinfo_no_name(struct rpc_rqst *rqstp,
|
||||||
|
struct xdr_stream *xdr,
|
||||||
|
struct nfs4_secinfo_res *res)
|
||||||
|
{
|
||||||
|
struct compound_hdr hdr;
|
||||||
|
int status;
|
||||||
|
|
||||||
|
status = decode_compound_hdr(xdr, &hdr);
|
||||||
|
if (status)
|
||||||
|
goto out;
|
||||||
|
status = decode_sequence(xdr, &res->seq_res, rqstp);
|
||||||
|
if (status)
|
||||||
|
goto out;
|
||||||
|
status = decode_putrootfh(xdr);
|
||||||
|
if (status)
|
||||||
|
goto out;
|
||||||
|
status = decode_secinfo(xdr, res);
|
||||||
|
out:
|
||||||
|
return status;
|
||||||
|
}
|
||||||
#endif /* CONFIG_NFS_V4_1 */
|
#endif /* CONFIG_NFS_V4_1 */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -6669,6 +6736,7 @@ struct rpc_procinfo nfs4_procedures[] = {
|
||||||
PROC(LAYOUTGET, enc_layoutget, dec_layoutget),
|
PROC(LAYOUTGET, enc_layoutget, dec_layoutget),
|
||||||
PROC(LAYOUTCOMMIT, enc_layoutcommit, dec_layoutcommit),
|
PROC(LAYOUTCOMMIT, enc_layoutcommit, dec_layoutcommit),
|
||||||
PROC(LAYOUTRETURN, enc_layoutreturn, dec_layoutreturn),
|
PROC(LAYOUTRETURN, enc_layoutreturn, dec_layoutreturn),
|
||||||
|
PROC(SECINFO_NO_NAME, enc_secinfo_no_name, dec_secinfo_no_name),
|
||||||
#endif /* CONFIG_NFS_V4_1 */
|
#endif /* CONFIG_NFS_V4_1 */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -563,6 +563,7 @@ enum {
|
||||||
NFSPROC4_CLNT_GETDEVICEINFO,
|
NFSPROC4_CLNT_GETDEVICEINFO,
|
||||||
NFSPROC4_CLNT_LAYOUTCOMMIT,
|
NFSPROC4_CLNT_LAYOUTCOMMIT,
|
||||||
NFSPROC4_CLNT_LAYOUTRETURN,
|
NFSPROC4_CLNT_LAYOUTRETURN,
|
||||||
|
NFSPROC4_CLNT_SECINFO_NO_NAME,
|
||||||
};
|
};
|
||||||
|
|
||||||
/* nfs41 types */
|
/* nfs41 types */
|
||||||
|
|
|
@ -1084,6 +1084,14 @@ struct nfs41_reclaim_complete_args {
|
||||||
struct nfs41_reclaim_complete_res {
|
struct nfs41_reclaim_complete_res {
|
||||||
struct nfs4_sequence_res seq_res;
|
struct nfs4_sequence_res seq_res;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define SECINFO_STYLE_CURRENT_FH 0
|
||||||
|
#define SECINFO_STYLE_PARENT 1
|
||||||
|
struct nfs41_secinfo_no_name_args {
|
||||||
|
int style;
|
||||||
|
struct nfs4_sequence_args seq_args;
|
||||||
|
};
|
||||||
|
|
||||||
#endif /* CONFIG_NFS_V4_1 */
|
#endif /* CONFIG_NFS_V4_1 */
|
||||||
|
|
||||||
struct nfs_page;
|
struct nfs_page;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue