diff options
Diffstat (limited to 'fs')
-rw-r--r-- | fs/nfs/client.c | 1 | ||||
-rw-r--r-- | fs/nfs/nfs4proc.c | 21 | ||||
-rw-r--r-- | fs/nfs/nfs4xdr.c | 42 | ||||
-rw-r--r-- | fs/nfs/super.c | 8 |
4 files changed, 67 insertions, 5 deletions
diff --git a/fs/nfs/client.c b/fs/nfs/client.c index 592b5583aa3a..1506adf4d4ed 100644 --- a/fs/nfs/client.c +++ b/fs/nfs/client.c | |||
@@ -304,6 +304,7 @@ static void nfs_free_client(struct nfs_client *clp) | |||
304 | put_net(clp->net); | 304 | put_net(clp->net); |
305 | kfree(clp->cl_hostname); | 305 | kfree(clp->cl_hostname); |
306 | kfree(clp->server_scope); | 306 | kfree(clp->server_scope); |
307 | kfree(clp->impl_id); | ||
307 | kfree(clp); | 308 | kfree(clp); |
308 | 309 | ||
309 | dprintk("<-- nfs_free_client()\n"); | 310 | dprintk("<-- nfs_free_client()\n"); |
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 20c3bb06763a..90a17cc3ebc9 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
@@ -4950,11 +4950,24 @@ int nfs4_proc_exchange_id(struct nfs_client *clp, struct rpc_cred *cred) | |||
4950 | goto out; | 4950 | goto out; |
4951 | } | 4951 | } |
4952 | 4952 | ||
4953 | res.impl_id = kzalloc(sizeof(struct nfs41_impl_id), GFP_KERNEL); | ||
4954 | if (unlikely(!res.impl_id)) { | ||
4955 | status = -ENOMEM; | ||
4956 | goto out_server_scope; | ||
4957 | } | ||
4958 | |||
4953 | status = rpc_call_sync(clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT); | 4959 | status = rpc_call_sync(clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT); |
4954 | if (!status) | 4960 | if (!status) |
4955 | status = nfs4_check_cl_exchange_flags(clp->cl_exchange_flags); | 4961 | status = nfs4_check_cl_exchange_flags(clp->cl_exchange_flags); |
4956 | 4962 | ||
4957 | if (!status) { | 4963 | if (!status) { |
4964 | /* use the most recent implementation id */ | ||
4965 | kfree(clp->impl_id); | ||
4966 | clp->impl_id = res.impl_id; | ||
4967 | } else | ||
4968 | kfree(res.impl_id); | ||
4969 | |||
4970 | if (!status) { | ||
4958 | if (clp->server_scope && | 4971 | if (clp->server_scope && |
4959 | !nfs41_same_server_scope(clp->server_scope, | 4972 | !nfs41_same_server_scope(clp->server_scope, |
4960 | res.server_scope)) { | 4973 | res.server_scope)) { |
@@ -4970,8 +4983,16 @@ int nfs4_proc_exchange_id(struct nfs_client *clp, struct rpc_cred *cred) | |||
4970 | goto out; | 4983 | goto out; |
4971 | } | 4984 | } |
4972 | } | 4985 | } |
4986 | |||
4987 | out_server_scope: | ||
4973 | kfree(res.server_scope); | 4988 | kfree(res.server_scope); |
4974 | out: | 4989 | out: |
4990 | if (clp->impl_id) | ||
4991 | dprintk("%s: Server Implementation ID: " | ||
4992 | "domain: %s, name: %s, date: %llu,%u\n", | ||
4993 | __func__, clp->impl_id->domain, clp->impl_id->name, | ||
4994 | clp->impl_id->date.seconds, | ||
4995 | clp->impl_id->date.nseconds); | ||
4975 | dprintk("<-- %s status= %d\n", __func__, status); | 4996 | dprintk("<-- %s status= %d\n", __func__, status); |
4976 | return status; | 4997 | return status; |
4977 | } | 4998 | } |
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c index d824aedb1237..b7c04339fdc1 100644 --- a/fs/nfs/nfs4xdr.c +++ b/fs/nfs/nfs4xdr.c | |||
@@ -291,7 +291,11 @@ static int nfs4_stat_to_errno(int); | |||
291 | /* eir_server_scope<> */ \ | 291 | /* eir_server_scope<> */ \ |
292 | XDR_QUADLEN(NFS4_OPAQUE_LIMIT) + 1 + \ | 292 | XDR_QUADLEN(NFS4_OPAQUE_LIMIT) + 1 + \ |
293 | 1 /* eir_server_impl_id array length */ + \ | 293 | 1 /* eir_server_impl_id array length */ + \ |
294 | 0 /* ignored eir_server_impl_id contents */) | 294 | 1 /* nii_domain */ + \ |
295 | XDR_QUADLEN(NFS4_OPAQUE_LIMIT) + \ | ||
296 | 1 /* nii_name */ + \ | ||
297 | XDR_QUADLEN(NFS4_OPAQUE_LIMIT) + \ | ||
298 | 3 /* nii_date */) | ||
295 | #define encode_channel_attrs_maxsz (6 + 1 /* ca_rdma_ird.len (0) */) | 299 | #define encode_channel_attrs_maxsz (6 + 1 /* ca_rdma_ird.len (0) */) |
296 | #define decode_channel_attrs_maxsz (6 + \ | 300 | #define decode_channel_attrs_maxsz (6 + \ |
297 | 1 /* ca_rdma_ird.len */ + \ | 301 | 1 /* ca_rdma_ird.len */ + \ |
@@ -5256,6 +5260,7 @@ static int decode_exchange_id(struct xdr_stream *xdr, | |||
5256 | char *dummy_str; | 5260 | char *dummy_str; |
5257 | int status; | 5261 | int status; |
5258 | struct nfs_client *clp = res->client; | 5262 | struct nfs_client *clp = res->client; |
5263 | uint32_t impl_id_count; | ||
5259 | 5264 | ||
5260 | status = decode_op_hdr(xdr, OP_EXCHANGE_ID); | 5265 | status = decode_op_hdr(xdr, OP_EXCHANGE_ID); |
5261 | if (status) | 5266 | if (status) |
@@ -5297,11 +5302,38 @@ static int decode_exchange_id(struct xdr_stream *xdr, | |||
5297 | memcpy(res->server_scope->server_scope, dummy_str, dummy); | 5302 | memcpy(res->server_scope->server_scope, dummy_str, dummy); |
5298 | res->server_scope->server_scope_sz = dummy; | 5303 | res->server_scope->server_scope_sz = dummy; |
5299 | 5304 | ||
5300 | /* Throw away Implementation id array */ | 5305 | /* Implementation Id */ |
5301 | status = decode_opaque_inline(xdr, &dummy, &dummy_str); | 5306 | p = xdr_inline_decode(xdr, 4); |
5302 | if (unlikely(status)) | 5307 | if (unlikely(!p)) |
5303 | return status; | 5308 | goto out_overflow; |
5309 | impl_id_count = be32_to_cpup(p++); | ||
5304 | 5310 | ||
5311 | if (impl_id_count) { | ||
5312 | /* nii_domain */ | ||
5313 | status = decode_opaque_inline(xdr, &dummy, &dummy_str); | ||
5314 | if (unlikely(status)) | ||
5315 | return status; | ||
5316 | if (unlikely(dummy > NFS4_OPAQUE_LIMIT)) | ||
5317 | return -EIO; | ||
5318 | memcpy(res->impl_id->domain, dummy_str, dummy); | ||
5319 | |||
5320 | /* nii_name */ | ||
5321 | status = decode_opaque_inline(xdr, &dummy, &dummy_str); | ||
5322 | if (unlikely(status)) | ||
5323 | return status; | ||
5324 | if (unlikely(dummy > NFS4_OPAQUE_LIMIT)) | ||
5325 | return -EIO; | ||
5326 | memcpy(res->impl_id->name, dummy_str, dummy); | ||
5327 | |||
5328 | /* nii_date */ | ||
5329 | p = xdr_inline_decode(xdr, 12); | ||
5330 | if (unlikely(!p)) | ||
5331 | goto out_overflow; | ||
5332 | p = xdr_decode_hyper(p, &res->impl_id->date.seconds); | ||
5333 | res->impl_id->date.nseconds = be32_to_cpup(p); | ||
5334 | |||
5335 | /* if there's more than one entry, ignore the rest */ | ||
5336 | } | ||
5305 | return 0; | 5337 | return 0; |
5306 | out_overflow: | 5338 | out_overflow: |
5307 | print_overflow_msg(__func__, xdr); | 5339 | print_overflow_msg(__func__, xdr); |
diff --git a/fs/nfs/super.c b/fs/nfs/super.c index 6708f3044eb0..8154accd1168 100644 --- a/fs/nfs/super.c +++ b/fs/nfs/super.c | |||
@@ -809,6 +809,14 @@ static int nfs_show_stats(struct seq_file *m, struct dentry *root) | |||
809 | 809 | ||
810 | seq_printf(m, "\n\tage:\t%lu", (jiffies - nfss->mount_time) / HZ); | 810 | seq_printf(m, "\n\tage:\t%lu", (jiffies - nfss->mount_time) / HZ); |
811 | 811 | ||
812 | if (nfss->nfs_client && nfss->nfs_client->impl_id) { | ||
813 | struct nfs41_impl_id *impl_id = nfss->nfs_client->impl_id; | ||
814 | seq_printf(m, "\n\timpl_id:\tname='%s',domain='%s'," | ||
815 | "date='%llu,%u'", | ||
816 | impl_id->name, impl_id->domain, | ||
817 | impl_id->date.seconds, impl_id->date.nseconds); | ||
818 | } | ||
819 | |||
812 | seq_printf(m, "\n\tcaps:\t"); | 820 | seq_printf(m, "\n\tcaps:\t"); |
813 | seq_printf(m, "caps=0x%x", nfss->caps); | 821 | seq_printf(m, "caps=0x%x", nfss->caps); |
814 | seq_printf(m, ",wtmult=%u", nfss->wtmult); | 822 | seq_printf(m, ",wtmult=%u", nfss->wtmult); |