Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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>

authored by

Pali Rohár and committed by
Chuck Lever
60002092 2dc84a75

+57 -1
+1
fs/nfsd/nfs4proc.c
··· 3453 3453 /* NFSv4.1 operations */ 3454 3454 [OP_EXCHANGE_ID] = { 3455 3455 .op_func = nfsd4_exchange_id, 3456 + .op_release = nfsd4_exchange_id_release, 3456 3457 .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_AS_FIRST_OP 3457 3458 | OP_MODIFIES_SOMETHING, 3458 3459 .op_name = "OP_EXCHANGE_ID",
+31
fs/nfsd/nfs4state.c
··· 3524 3524 __func__, rqstp, exid, exid->clname.len, exid->clname.data, 3525 3525 addr_str, exid->flags, exid->spa_how); 3526 3526 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 + 3527 3533 if (exid->flags & ~EXCHGID4_FLAG_MASK_A) 3528 3534 return nfserr_inval; 3529 3535 ··· 3667 3661 exid->seqid = conf->cl_cs_slot.sl_seqid + 1; 3668 3662 nfsd4_set_ex_flags(conf, exid); 3669 3663 3664 + exid->nii_domain.len = sizeof("kernel.org") - 1; 3665 + exid->nii_domain.data = "kernel.org"; 3666 + 3667 + /* 3668 + * Note that RFC 8881 places no length limit on 3669 + * nii_name, but this implementation permits no 3670 + * more than NFS4_OPAQUE_LIMIT bytes. 3671 + */ 3672 + exid->nii_name.len = strlen(exid->server_impl_name); 3673 + if (exid->nii_name.len > NFS4_OPAQUE_LIMIT) 3674 + exid->nii_name.len = NFS4_OPAQUE_LIMIT; 3675 + exid->nii_name.data = exid->server_impl_name; 3676 + 3677 + /* just send zeros - the date is in nii_name */ 3678 + exid->nii_time.tv_sec = 0; 3679 + exid->nii_time.tv_nsec = 0; 3680 + 3670 3681 dprintk("nfsd4_exchange_id seqid %d flags %x\n", 3671 3682 conf->cl_cs_slot.sl_seqid, conf->cl_exchange_flags); 3672 3683 status = nfs_ok; ··· 3698 3675 expire_client(unconf); 3699 3676 } 3700 3677 return status; 3678 + } 3679 + 3680 + void 3681 + nfsd4_exchange_id_release(union nfsd4_op_u *u) 3682 + { 3683 + struct nfsd4_exchange_id *exid = &u->exchange_id; 3684 + 3685 + kfree(exid->server_impl_name); 3701 3686 } 3702 3687 3703 3688 static __be32 check_slot_seqid(u32 seqid, u32 slot_seqid, bool slot_inuse)
+23 -1
fs/nfsd/nfs4xdr.c
··· 4826 4826 } 4827 4827 4828 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 + 4847 + static __be32 4829 4848 nfsd4_encode_exchange_id(struct nfsd4_compoundres *resp, __be32 nfserr, 4830 4849 union nfsd4_op_u *u) 4831 4850 { ··· 4878 4859 if (nfserr != nfs_ok) 4879 4860 return nfserr; 4880 4861 /* eir_server_impl_id<1> */ 4881 - if (xdr_stream_encode_u32(xdr, 0) != XDR_UNIT) 4862 + if (xdr_stream_encode_u32(xdr, 1) != XDR_UNIT) 4882 4863 return nfserr_resource; 4864 + nfserr = nfsd4_encode_nfs_impl_id4(xdr, exid); 4865 + if (nfserr != nfs_ok) 4866 + return nfserr; 4883 4867 4884 4868 return nfs_ok; 4885 4869 }
+2
fs/nfsd/xdr4.h
··· 567 567 struct xdr_netobj nii_domain; 568 568 struct xdr_netobj nii_name; 569 569 struct timespec64 nii_time; 570 + char *server_impl_name; 570 571 }; 571 572 572 573 struct nfsd4_sequence { ··· 931 930 struct nfsd4_compound_state *, union nfsd4_op_u *u); 932 931 extern __be32 nfsd4_setclientid_confirm(struct svc_rqst *rqstp, 933 932 struct nfsd4_compound_state *, union nfsd4_op_u *u); 933 + void nfsd4_exchange_id_release(union nfsd4_op_u *u); 934 934 extern __be32 nfsd4_exchange_id(struct svc_rqst *rqstp, 935 935 struct nfsd4_compound_state *, union nfsd4_op_u *u); 936 936 extern __be32 nfsd4_backchannel_ctl(struct svc_rqst *,