mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-09-18 22:14:16 +00:00
nfsd: Fill NFSv4.1 server implementation fields in OP_EXCHANGE_ID response
NFSv4.1 OP_EXCHANGE_ID response from server may contain server implementation details (domain, name and build time) in optional nfs_impl_id4 field. Currently nfsd does not fill this field. Send these information in NFSv4.1 OP_EXCHANGE_ID response. Fill them with the same values as what is Linux NFSv4.1 client doing. Domain is hardcoded to "kernel.org", name is composed in the same way as "uname -srvm" output and build time is hardcoded to zeros. NFSv4.1 client and server implementation fields are useful for statistic purposes or for identifying type of clients and servers. Signed-off-by: Pali Rohár <pali@kernel.org> Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
This commit is contained in:
parent
2dc84a7522
commit
600020927b
4 changed files with 57 additions and 1 deletions
|
|
@ -3453,6 +3453,7 @@ static const struct nfsd4_operation nfsd4_ops[] = {
|
||||||
/* NFSv4.1 operations */
|
/* NFSv4.1 operations */
|
||||||
[OP_EXCHANGE_ID] = {
|
[OP_EXCHANGE_ID] = {
|
||||||
.op_func = nfsd4_exchange_id,
|
.op_func = nfsd4_exchange_id,
|
||||||
|
.op_release = nfsd4_exchange_id_release,
|
||||||
.op_flags = ALLOWED_WITHOUT_FH | ALLOWED_AS_FIRST_OP
|
.op_flags = ALLOWED_WITHOUT_FH | ALLOWED_AS_FIRST_OP
|
||||||
| OP_MODIFIES_SOMETHING,
|
| OP_MODIFIES_SOMETHING,
|
||||||
.op_name = "OP_EXCHANGE_ID",
|
.op_name = "OP_EXCHANGE_ID",
|
||||||
|
|
|
||||||
|
|
@ -3524,6 +3524,12 @@ nfsd4_exchange_id(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
|
||||||
__func__, rqstp, exid, exid->clname.len, exid->clname.data,
|
__func__, rqstp, exid, exid->clname.len, exid->clname.data,
|
||||||
addr_str, exid->flags, exid->spa_how);
|
addr_str, exid->flags, exid->spa_how);
|
||||||
|
|
||||||
|
exid->server_impl_name = kasprintf(GFP_KERNEL, "%s %s %s %s",
|
||||||
|
utsname()->sysname, utsname()->release,
|
||||||
|
utsname()->version, utsname()->machine);
|
||||||
|
if (!exid->server_impl_name)
|
||||||
|
return nfserr_jukebox;
|
||||||
|
|
||||||
if (exid->flags & ~EXCHGID4_FLAG_MASK_A)
|
if (exid->flags & ~EXCHGID4_FLAG_MASK_A)
|
||||||
return nfserr_inval;
|
return nfserr_inval;
|
||||||
|
|
||||||
|
|
@ -3661,6 +3667,23 @@ out_copy:
|
||||||
exid->seqid = conf->cl_cs_slot.sl_seqid + 1;
|
exid->seqid = conf->cl_cs_slot.sl_seqid + 1;
|
||||||
nfsd4_set_ex_flags(conf, exid);
|
nfsd4_set_ex_flags(conf, exid);
|
||||||
|
|
||||||
|
exid->nii_domain.len = sizeof("kernel.org") - 1;
|
||||||
|
exid->nii_domain.data = "kernel.org";
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Note that RFC 8881 places no length limit on
|
||||||
|
* nii_name, but this implementation permits no
|
||||||
|
* more than NFS4_OPAQUE_LIMIT bytes.
|
||||||
|
*/
|
||||||
|
exid->nii_name.len = strlen(exid->server_impl_name);
|
||||||
|
if (exid->nii_name.len > NFS4_OPAQUE_LIMIT)
|
||||||
|
exid->nii_name.len = NFS4_OPAQUE_LIMIT;
|
||||||
|
exid->nii_name.data = exid->server_impl_name;
|
||||||
|
|
||||||
|
/* just send zeros - the date is in nii_name */
|
||||||
|
exid->nii_time.tv_sec = 0;
|
||||||
|
exid->nii_time.tv_nsec = 0;
|
||||||
|
|
||||||
dprintk("nfsd4_exchange_id seqid %d flags %x\n",
|
dprintk("nfsd4_exchange_id seqid %d flags %x\n",
|
||||||
conf->cl_cs_slot.sl_seqid, conf->cl_exchange_flags);
|
conf->cl_cs_slot.sl_seqid, conf->cl_exchange_flags);
|
||||||
status = nfs_ok;
|
status = nfs_ok;
|
||||||
|
|
@ -3677,6 +3700,14 @@ out_nolock:
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
nfsd4_exchange_id_release(union nfsd4_op_u *u)
|
||||||
|
{
|
||||||
|
struct nfsd4_exchange_id *exid = &u->exchange_id;
|
||||||
|
|
||||||
|
kfree(exid->server_impl_name);
|
||||||
|
}
|
||||||
|
|
||||||
static __be32 check_slot_seqid(u32 seqid, u32 slot_seqid, bool slot_inuse)
|
static __be32 check_slot_seqid(u32 seqid, u32 slot_seqid, bool slot_inuse)
|
||||||
{
|
{
|
||||||
/* The slot is in use, and no response has been sent. */
|
/* The slot is in use, and no response has been sent. */
|
||||||
|
|
|
||||||
|
|
@ -4825,6 +4825,25 @@ nfsd4_encode_server_owner4(struct xdr_stream *xdr, struct svc_rqst *rqstp)
|
||||||
return nfsd4_encode_opaque(xdr, nn->nfsd_name, strlen(nn->nfsd_name));
|
return nfsd4_encode_opaque(xdr, nn->nfsd_name, strlen(nn->nfsd_name));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static __be32
|
||||||
|
nfsd4_encode_nfs_impl_id4(struct xdr_stream *xdr, struct nfsd4_exchange_id *exid)
|
||||||
|
{
|
||||||
|
__be32 status;
|
||||||
|
|
||||||
|
/* nii_domain */
|
||||||
|
status = nfsd4_encode_opaque(xdr, exid->nii_domain.data,
|
||||||
|
exid->nii_domain.len);
|
||||||
|
if (status != nfs_ok)
|
||||||
|
return status;
|
||||||
|
/* nii_name */
|
||||||
|
status = nfsd4_encode_opaque(xdr, exid->nii_name.data,
|
||||||
|
exid->nii_name.len);
|
||||||
|
if (status != nfs_ok)
|
||||||
|
return status;
|
||||||
|
/* nii_time */
|
||||||
|
return nfsd4_encode_nfstime4(xdr, &exid->nii_time);
|
||||||
|
}
|
||||||
|
|
||||||
static __be32
|
static __be32
|
||||||
nfsd4_encode_exchange_id(struct nfsd4_compoundres *resp, __be32 nfserr,
|
nfsd4_encode_exchange_id(struct nfsd4_compoundres *resp, __be32 nfserr,
|
||||||
union nfsd4_op_u *u)
|
union nfsd4_op_u *u)
|
||||||
|
|
@ -4859,8 +4878,11 @@ nfsd4_encode_exchange_id(struct nfsd4_compoundres *resp, __be32 nfserr,
|
||||||
if (nfserr != nfs_ok)
|
if (nfserr != nfs_ok)
|
||||||
return nfserr;
|
return nfserr;
|
||||||
/* eir_server_impl_id<1> */
|
/* eir_server_impl_id<1> */
|
||||||
if (xdr_stream_encode_u32(xdr, 0) != XDR_UNIT)
|
if (xdr_stream_encode_u32(xdr, 1) != XDR_UNIT)
|
||||||
return nfserr_resource;
|
return nfserr_resource;
|
||||||
|
nfserr = nfsd4_encode_nfs_impl_id4(xdr, exid);
|
||||||
|
if (nfserr != nfs_ok)
|
||||||
|
return nfserr;
|
||||||
|
|
||||||
return nfs_ok;
|
return nfs_ok;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -567,6 +567,7 @@ struct nfsd4_exchange_id {
|
||||||
struct xdr_netobj nii_domain;
|
struct xdr_netobj nii_domain;
|
||||||
struct xdr_netobj nii_name;
|
struct xdr_netobj nii_name;
|
||||||
struct timespec64 nii_time;
|
struct timespec64 nii_time;
|
||||||
|
char *server_impl_name;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct nfsd4_sequence {
|
struct nfsd4_sequence {
|
||||||
|
|
@ -930,6 +931,7 @@ extern __be32 nfsd4_setclientid(struct svc_rqst *rqstp,
|
||||||
struct nfsd4_compound_state *, union nfsd4_op_u *u);
|
struct nfsd4_compound_state *, union nfsd4_op_u *u);
|
||||||
extern __be32 nfsd4_setclientid_confirm(struct svc_rqst *rqstp,
|
extern __be32 nfsd4_setclientid_confirm(struct svc_rqst *rqstp,
|
||||||
struct nfsd4_compound_state *, union nfsd4_op_u *u);
|
struct nfsd4_compound_state *, union nfsd4_op_u *u);
|
||||||
|
void nfsd4_exchange_id_release(union nfsd4_op_u *u);
|
||||||
extern __be32 nfsd4_exchange_id(struct svc_rqst *rqstp,
|
extern __be32 nfsd4_exchange_id(struct svc_rqst *rqstp,
|
||||||
struct nfsd4_compound_state *, union nfsd4_op_u *u);
|
struct nfsd4_compound_state *, union nfsd4_op_u *u);
|
||||||
extern __be32 nfsd4_backchannel_ctl(struct svc_rqst *,
|
extern __be32 nfsd4_backchannel_ctl(struct svc_rqst *,
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue