Skip to content

Commit 6000209

Browse files
palichucklever
authored andcommitted
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 <[email protected]> Signed-off-by: Chuck Lever <[email protected]>
1 parent 2dc84a7 commit 6000209

File tree

4 files changed

+57
-1
lines changed

4 files changed

+57
-1
lines changed

fs/nfsd/nfs4proc.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3453,6 +3453,7 @@ static const struct nfsd4_operation nfsd4_ops[] = {
34533453
/* NFSv4.1 operations */
34543454
[OP_EXCHANGE_ID] = {
34553455
.op_func = nfsd4_exchange_id,
3456+
.op_release = nfsd4_exchange_id_release,
34563457
.op_flags = ALLOWED_WITHOUT_FH | ALLOWED_AS_FIRST_OP
34573458
| OP_MODIFIES_SOMETHING,
34583459
.op_name = "OP_EXCHANGE_ID",

fs/nfsd/nfs4state.c

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3524,6 +3524,12 @@ nfsd4_exchange_id(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
35243524
__func__, rqstp, exid, exid->clname.len, exid->clname.data,
35253525
addr_str, exid->flags, exid->spa_how);
35263526

3527+
exid->server_impl_name = kasprintf(GFP_KERNEL, "%s %s %s %s",
3528+
utsname()->sysname, utsname()->release,
3529+
utsname()->version, utsname()->machine);
3530+
if (!exid->server_impl_name)
3531+
return nfserr_jukebox;
3532+
35273533
if (exid->flags & ~EXCHGID4_FLAG_MASK_A)
35283534
return nfserr_inval;
35293535

@@ -3661,6 +3667,23 @@ nfsd4_exchange_id(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
36613667
exid->seqid = conf->cl_cs_slot.sl_seqid + 1;
36623668
nfsd4_set_ex_flags(conf, exid);
36633669

3670+
exid->nii_domain.len = sizeof("kernel.org") - 1;
3671+
exid->nii_domain.data = "kernel.org";
3672+
3673+
/*
3674+
* Note that RFC 8881 places no length limit on
3675+
* nii_name, but this implementation permits no
3676+
* more than NFS4_OPAQUE_LIMIT bytes.
3677+
*/
3678+
exid->nii_name.len = strlen(exid->server_impl_name);
3679+
if (exid->nii_name.len > NFS4_OPAQUE_LIMIT)
3680+
exid->nii_name.len = NFS4_OPAQUE_LIMIT;
3681+
exid->nii_name.data = exid->server_impl_name;
3682+
3683+
/* just send zeros - the date is in nii_name */
3684+
exid->nii_time.tv_sec = 0;
3685+
exid->nii_time.tv_nsec = 0;
3686+
36643687
dprintk("nfsd4_exchange_id seqid %d flags %x\n",
36653688
conf->cl_cs_slot.sl_seqid, conf->cl_exchange_flags);
36663689
status = nfs_ok;
@@ -3677,6 +3700,14 @@ nfsd4_exchange_id(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
36773700
return status;
36783701
}
36793702

3703+
void
3704+
nfsd4_exchange_id_release(union nfsd4_op_u *u)
3705+
{
3706+
struct nfsd4_exchange_id *exid = &u->exchange_id;
3707+
3708+
kfree(exid->server_impl_name);
3709+
}
3710+
36803711
static __be32 check_slot_seqid(u32 seqid, u32 slot_seqid, bool slot_inuse)
36813712
{
36823713
/* The slot is in use, and no response has been sent. */

fs/nfsd/nfs4xdr.c

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4825,6 +4825,25 @@ nfsd4_encode_server_owner4(struct xdr_stream *xdr, struct svc_rqst *rqstp)
48254825
return nfsd4_encode_opaque(xdr, nn->nfsd_name, strlen(nn->nfsd_name));
48264826
}
48274827

4828+
static __be32
4829+
nfsd4_encode_nfs_impl_id4(struct xdr_stream *xdr, struct nfsd4_exchange_id *exid)
4830+
{
4831+
__be32 status;
4832+
4833+
/* nii_domain */
4834+
status = nfsd4_encode_opaque(xdr, exid->nii_domain.data,
4835+
exid->nii_domain.len);
4836+
if (status != nfs_ok)
4837+
return status;
4838+
/* nii_name */
4839+
status = nfsd4_encode_opaque(xdr, exid->nii_name.data,
4840+
exid->nii_name.len);
4841+
if (status != nfs_ok)
4842+
return status;
4843+
/* nii_time */
4844+
return nfsd4_encode_nfstime4(xdr, &exid->nii_time);
4845+
}
4846+
48284847
static __be32
48294848
nfsd4_encode_exchange_id(struct nfsd4_compoundres *resp, __be32 nfserr,
48304849
union nfsd4_op_u *u)
@@ -4859,8 +4878,11 @@ nfsd4_encode_exchange_id(struct nfsd4_compoundres *resp, __be32 nfserr,
48594878
if (nfserr != nfs_ok)
48604879
return nfserr;
48614880
/* eir_server_impl_id<1> */
4862-
if (xdr_stream_encode_u32(xdr, 0) != XDR_UNIT)
4881+
if (xdr_stream_encode_u32(xdr, 1) != XDR_UNIT)
48634882
return nfserr_resource;
4883+
nfserr = nfsd4_encode_nfs_impl_id4(xdr, exid);
4884+
if (nfserr != nfs_ok)
4885+
return nfserr;
48644886

48654887
return nfs_ok;
48664888
}

fs/nfsd/xdr4.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -567,6 +567,7 @@ struct nfsd4_exchange_id {
567567
struct xdr_netobj nii_domain;
568568
struct xdr_netobj nii_name;
569569
struct timespec64 nii_time;
570+
char *server_impl_name;
570571
};
571572

572573
struct nfsd4_sequence {
@@ -930,6 +931,7 @@ extern __be32 nfsd4_setclientid(struct svc_rqst *rqstp,
930931
struct nfsd4_compound_state *, union nfsd4_op_u *u);
931932
extern __be32 nfsd4_setclientid_confirm(struct svc_rqst *rqstp,
932933
struct nfsd4_compound_state *, union nfsd4_op_u *u);
934+
void nfsd4_exchange_id_release(union nfsd4_op_u *u);
933935
extern __be32 nfsd4_exchange_id(struct svc_rqst *rqstp,
934936
struct nfsd4_compound_state *, union nfsd4_op_u *u);
935937
extern __be32 nfsd4_backchannel_ctl(struct svc_rqst *,

0 commit comments

Comments
 (0)