summaryrefslogtreecommitdiffstats
path: root/fs/nfsd/nfs4state.c
diff options
context:
space:
mode:
authorJ. Bruce Fields <bfields@redhat.com>2019-06-05 12:42:05 -0400
committerJ. Bruce Fields <bfields@redhat.com>2019-07-03 20:54:03 -0400
commit791234448d4798f589110c17d2baaf1bbcc56cb8 (patch)
treeec3385bef711d86168e70e4ef192a3af6071ff18 /fs/nfsd/nfs4state.c
parent6f4859b8a72638f60c7051247aac63a761f01933 (diff)
nfsd: decode implementation id
Decode the implementation ID and display in nfsd/clients/#/info. It may be help identify the client. It won't be used otherwise. (When this went into the protocol, I thought the implementation ID would be a slippery slope towards implementation-specific workarounds as with the http user-agent. But I guess I was wrong, the risk seems pretty low now.) Signed-off-by: J. Bruce Fields <bfields@redhat.com>
Diffstat (limited to 'fs/nfsd/nfs4state.c')
-rw-r--r--fs/nfsd/nfs4state.c30
1 files changed, 30 insertions, 0 deletions
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index 640cd221fc77..94de5c348a41 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -1899,6 +1899,8 @@ static void __free_client(struct kref *k)
1899 free_svc_cred(&clp->cl_cred); 1899 free_svc_cred(&clp->cl_cred);
1900 kfree(clp->cl_ownerstr_hashtbl); 1900 kfree(clp->cl_ownerstr_hashtbl);
1901 kfree(clp->cl_name.data); 1901 kfree(clp->cl_name.data);
1902 kfree(clp->cl_nii_domain.data);
1903 kfree(clp->cl_nii_name.data);
1902 idr_destroy(&clp->cl_stateids); 1904 idr_destroy(&clp->cl_stateids);
1903 kmem_cache_free(client_slab, clp); 1905 kmem_cache_free(client_slab, clp);
1904} 1906}
@@ -2261,6 +2263,15 @@ static int client_info_show(struct seq_file *m, void *v)
2261 seq_printf(m, "name: "); 2263 seq_printf(m, "name: ");
2262 seq_quote_mem(m, clp->cl_name.data, clp->cl_name.len); 2264 seq_quote_mem(m, clp->cl_name.data, clp->cl_name.len);
2263 seq_printf(m, "\nminor version: %d\n", clp->cl_minorversion); 2265 seq_printf(m, "\nminor version: %d\n", clp->cl_minorversion);
2266 if (clp->cl_nii_domain.data) {
2267 seq_printf(m, "Implementation domain: ");
2268 seq_quote_mem(m, clp->cl_nii_domain.data,
2269 clp->cl_nii_domain.len);
2270 seq_printf(m, "\nImplementation name: ");
2271 seq_quote_mem(m, clp->cl_nii_name.data, clp->cl_nii_name.len);
2272 seq_printf(m, "\nImplementation time: [%ld, %ld]\n",
2273 clp->cl_nii_time.tv_sec, clp->cl_nii_time.tv_nsec);
2274 }
2264 drop_client(clp); 2275 drop_client(clp);
2265 2276
2266 return 0; 2277 return 0;
@@ -2901,6 +2912,22 @@ static bool client_has_state(struct nfs4_client *clp)
2901 || !list_empty(&clp->async_copies); 2912 || !list_empty(&clp->async_copies);
2902} 2913}
2903 2914
2915static __be32 copy_impl_id(struct nfs4_client *clp,
2916 struct nfsd4_exchange_id *exid)
2917{
2918 if (!exid->nii_domain.data)
2919 return 0;
2920 xdr_netobj_dup(&clp->cl_nii_domain, &exid->nii_domain, GFP_KERNEL);
2921 if (!clp->cl_nii_domain.data)
2922 return nfserr_jukebox;
2923 xdr_netobj_dup(&clp->cl_nii_name, &exid->nii_name, GFP_KERNEL);
2924 if (!clp->cl_nii_name.data)
2925 return nfserr_jukebox;
2926 clp->cl_nii_time.tv_sec = exid->nii_time.tv_sec;
2927 clp->cl_nii_time.tv_nsec = exid->nii_time.tv_nsec;
2928 return 0;
2929}
2930
2904__be32 2931__be32
2905nfsd4_exchange_id(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, 2932nfsd4_exchange_id(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
2906 union nfsd4_op_u *u) 2933 union nfsd4_op_u *u)
@@ -2927,6 +2954,9 @@ nfsd4_exchange_id(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
2927 new = create_client(exid->clname, rqstp, &verf); 2954 new = create_client(exid->clname, rqstp, &verf);
2928 if (new == NULL) 2955 if (new == NULL)
2929 return nfserr_jukebox; 2956 return nfserr_jukebox;
2957 status = copy_impl_id(new, exid);
2958 if (status)
2959 goto out_nolock;
2930 2960
2931 switch (exid->spa_how) { 2961 switch (exid->spa_how) {
2932 case SP4_MACH_CRED: 2962 case SP4_MACH_CRED: