forked from mirrors/linux
		
	NFSv4: parse and display server implementation ids
Shows the implementation ids in /proc/self/mountstats. This doesn't break the nfs-utils mountstats tool. Signed-off-by: Weston Andros Adamson <dros@netapp.com> Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
This commit is contained in:
		
							parent
							
								
									9edbd953f8
								
							
						
					
					
						commit
						7d2ed9ac22
					
				
					 6 changed files with 76 additions and 13 deletions
				
			
		| 
						 | 
					@ -304,6 +304,7 @@ static void nfs_free_client(struct nfs_client *clp)
 | 
				
			||||||
	put_net(clp->net);
 | 
						put_net(clp->net);
 | 
				
			||||||
	kfree(clp->cl_hostname);
 | 
						kfree(clp->cl_hostname);
 | 
				
			||||||
	kfree(clp->server_scope);
 | 
						kfree(clp->server_scope);
 | 
				
			||||||
 | 
						kfree(clp->impl_id);
 | 
				
			||||||
	kfree(clp);
 | 
						kfree(clp);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	dprintk("<-- nfs_free_client()\n");
 | 
						dprintk("<-- nfs_free_client()\n");
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -4950,10 +4950,23 @@ int nfs4_proc_exchange_id(struct nfs_client *clp, struct rpc_cred *cred)
 | 
				
			||||||
		goto out;
 | 
							goto out;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						res.impl_id = kzalloc(sizeof(struct nfs41_impl_id), GFP_KERNEL);
 | 
				
			||||||
 | 
						if (unlikely(!res.impl_id)) {
 | 
				
			||||||
 | 
							status = -ENOMEM;
 | 
				
			||||||
 | 
							goto out_server_scope;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	status = rpc_call_sync(clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT);
 | 
						status = rpc_call_sync(clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT);
 | 
				
			||||||
	if (!status)
 | 
						if (!status)
 | 
				
			||||||
		status = nfs4_check_cl_exchange_flags(clp->cl_exchange_flags);
 | 
							status = nfs4_check_cl_exchange_flags(clp->cl_exchange_flags);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!status) {
 | 
				
			||||||
 | 
							/* use the most recent implementation id */
 | 
				
			||||||
 | 
							kfree(clp->impl_id);
 | 
				
			||||||
 | 
							clp->impl_id = res.impl_id;
 | 
				
			||||||
 | 
						} else
 | 
				
			||||||
 | 
							kfree(res.impl_id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!status) {
 | 
						if (!status) {
 | 
				
			||||||
		if (clp->server_scope &&
 | 
							if (clp->server_scope &&
 | 
				
			||||||
		    !nfs41_same_server_scope(clp->server_scope,
 | 
							    !nfs41_same_server_scope(clp->server_scope,
 | 
				
			||||||
| 
						 | 
					@ -4970,8 +4983,16 @@ int nfs4_proc_exchange_id(struct nfs_client *clp, struct rpc_cred *cred)
 | 
				
			||||||
			goto out;
 | 
								goto out;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					out_server_scope:
 | 
				
			||||||
	kfree(res.server_scope);
 | 
						kfree(res.server_scope);
 | 
				
			||||||
out:
 | 
					out:
 | 
				
			||||||
 | 
						if (clp->impl_id)
 | 
				
			||||||
 | 
							dprintk("%s: Server Implementation ID: "
 | 
				
			||||||
 | 
								"domain: %s, name: %s, date: %llu,%u\n",
 | 
				
			||||||
 | 
								__func__, clp->impl_id->domain, clp->impl_id->name,
 | 
				
			||||||
 | 
								clp->impl_id->date.seconds,
 | 
				
			||||||
 | 
								clp->impl_id->date.nseconds);
 | 
				
			||||||
	dprintk("<-- %s status= %d\n", __func__, status);
 | 
						dprintk("<-- %s status= %d\n", __func__, status);
 | 
				
			||||||
	return status;
 | 
						return status;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -291,7 +291,11 @@ static int nfs4_stat_to_errno(int);
 | 
				
			||||||
				/* eir_server_scope<> */ \
 | 
									/* eir_server_scope<> */ \
 | 
				
			||||||
				XDR_QUADLEN(NFS4_OPAQUE_LIMIT) + 1 + \
 | 
									XDR_QUADLEN(NFS4_OPAQUE_LIMIT) + 1 + \
 | 
				
			||||||
				1 /* eir_server_impl_id array length */ + \
 | 
									1 /* eir_server_impl_id array length */ + \
 | 
				
			||||||
				0 /* ignored eir_server_impl_id contents */)
 | 
									1 /* nii_domain */ + \
 | 
				
			||||||
 | 
									XDR_QUADLEN(NFS4_OPAQUE_LIMIT) + \
 | 
				
			||||||
 | 
									1 /* nii_name */ + \
 | 
				
			||||||
 | 
									XDR_QUADLEN(NFS4_OPAQUE_LIMIT) + \
 | 
				
			||||||
 | 
									3 /* nii_date */)
 | 
				
			||||||
#define encode_channel_attrs_maxsz  (6 + 1 /* ca_rdma_ird.len (0) */)
 | 
					#define encode_channel_attrs_maxsz  (6 + 1 /* ca_rdma_ird.len (0) */)
 | 
				
			||||||
#define decode_channel_attrs_maxsz  (6 + \
 | 
					#define decode_channel_attrs_maxsz  (6 + \
 | 
				
			||||||
				     1 /* ca_rdma_ird.len */ + \
 | 
									     1 /* ca_rdma_ird.len */ + \
 | 
				
			||||||
| 
						 | 
					@ -5256,6 +5260,7 @@ static int decode_exchange_id(struct xdr_stream *xdr,
 | 
				
			||||||
	char *dummy_str;
 | 
						char *dummy_str;
 | 
				
			||||||
	int status;
 | 
						int status;
 | 
				
			||||||
	struct nfs_client *clp = res->client;
 | 
						struct nfs_client *clp = res->client;
 | 
				
			||||||
 | 
						uint32_t impl_id_count;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	status = decode_op_hdr(xdr, OP_EXCHANGE_ID);
 | 
						status = decode_op_hdr(xdr, OP_EXCHANGE_ID);
 | 
				
			||||||
	if (status)
 | 
						if (status)
 | 
				
			||||||
| 
						 | 
					@ -5297,11 +5302,38 @@ static int decode_exchange_id(struct xdr_stream *xdr,
 | 
				
			||||||
	memcpy(res->server_scope->server_scope, dummy_str, dummy);
 | 
						memcpy(res->server_scope->server_scope, dummy_str, dummy);
 | 
				
			||||||
	res->server_scope->server_scope_sz = dummy;
 | 
						res->server_scope->server_scope_sz = dummy;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Throw away Implementation id array */
 | 
						/* Implementation Id */
 | 
				
			||||||
	status = decode_opaque_inline(xdr, &dummy, &dummy_str);
 | 
						p = xdr_inline_decode(xdr, 4);
 | 
				
			||||||
	if (unlikely(status))
 | 
						if (unlikely(!p))
 | 
				
			||||||
		return status;
 | 
							goto out_overflow;
 | 
				
			||||||
 | 
						impl_id_count = be32_to_cpup(p++);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (impl_id_count) {
 | 
				
			||||||
 | 
							/* nii_domain */
 | 
				
			||||||
 | 
							status = decode_opaque_inline(xdr, &dummy, &dummy_str);
 | 
				
			||||||
 | 
							if (unlikely(status))
 | 
				
			||||||
 | 
								return status;
 | 
				
			||||||
 | 
							if (unlikely(dummy > NFS4_OPAQUE_LIMIT))
 | 
				
			||||||
 | 
								return -EIO;
 | 
				
			||||||
 | 
							memcpy(res->impl_id->domain, dummy_str, dummy);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/* nii_name */
 | 
				
			||||||
 | 
							status = decode_opaque_inline(xdr, &dummy, &dummy_str);
 | 
				
			||||||
 | 
							if (unlikely(status))
 | 
				
			||||||
 | 
								return status;
 | 
				
			||||||
 | 
							if (unlikely(dummy > NFS4_OPAQUE_LIMIT))
 | 
				
			||||||
 | 
								return -EIO;
 | 
				
			||||||
 | 
							memcpy(res->impl_id->name, dummy_str, dummy);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/* nii_date */
 | 
				
			||||||
 | 
							p = xdr_inline_decode(xdr, 12);
 | 
				
			||||||
 | 
							if (unlikely(!p))
 | 
				
			||||||
 | 
								goto out_overflow;
 | 
				
			||||||
 | 
							p = xdr_decode_hyper(p, &res->impl_id->date.seconds);
 | 
				
			||||||
 | 
							res->impl_id->date.nseconds = be32_to_cpup(p);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/* if there's more than one entry, ignore the rest */
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
out_overflow:
 | 
					out_overflow:
 | 
				
			||||||
	print_overflow_msg(__func__, xdr);
 | 
						print_overflow_msg(__func__, xdr);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -809,6 +809,14 @@ static int nfs_show_stats(struct seq_file *m, struct dentry *root)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	seq_printf(m, "\n\tage:\t%lu", (jiffies - nfss->mount_time) / HZ);
 | 
						seq_printf(m, "\n\tage:\t%lu", (jiffies - nfss->mount_time) / HZ);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (nfss->nfs_client && nfss->nfs_client->impl_id) {
 | 
				
			||||||
 | 
							struct nfs41_impl_id *impl_id = nfss->nfs_client->impl_id;
 | 
				
			||||||
 | 
							seq_printf(m, "\n\timpl_id:\tname='%s',domain='%s',"
 | 
				
			||||||
 | 
								   "date='%llu,%u'",
 | 
				
			||||||
 | 
								   impl_id->name, impl_id->domain,
 | 
				
			||||||
 | 
								   impl_id->date.seconds, impl_id->date.nseconds);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	seq_printf(m, "\n\tcaps:\t");
 | 
						seq_printf(m, "\n\tcaps:\t");
 | 
				
			||||||
	seq_printf(m, "caps=0x%x", nfss->caps);
 | 
						seq_printf(m, "caps=0x%x", nfss->caps);
 | 
				
			||||||
	seq_printf(m, ",wtmult=%u", nfss->wtmult);
 | 
						seq_printf(m, ",wtmult=%u", nfss->wtmult);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -18,6 +18,7 @@ struct nfs4_sequence_res;
 | 
				
			||||||
struct nfs_server;
 | 
					struct nfs_server;
 | 
				
			||||||
struct nfs4_minor_version_ops;
 | 
					struct nfs4_minor_version_ops;
 | 
				
			||||||
struct server_scope;
 | 
					struct server_scope;
 | 
				
			||||||
 | 
					struct nfs41_impl_id;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * The nfs_client identifies our client state to the server.
 | 
					 * The nfs_client identifies our client state to the server.
 | 
				
			||||||
| 
						 | 
					@ -86,6 +87,7 @@ struct nfs_client {
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	struct server_scope	*server_scope;	/* from exchange_id */
 | 
						struct server_scope	*server_scope;	/* from exchange_id */
 | 
				
			||||||
 | 
						struct nfs41_impl_id	*impl_id;	/* from exchange_id */
 | 
				
			||||||
	struct net		*net;
 | 
						struct net		*net;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1054,14 +1054,6 @@ struct nfstime4 {
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef CONFIG_NFS_V4_1
 | 
					#ifdef CONFIG_NFS_V4_1
 | 
				
			||||||
struct nfs_impl_id4 {
 | 
					 | 
				
			||||||
	u32		domain_len;
 | 
					 | 
				
			||||||
	char		*domain;
 | 
					 | 
				
			||||||
	u32		name_len;
 | 
					 | 
				
			||||||
	char		*name;
 | 
					 | 
				
			||||||
	struct nfstime4	date;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#define NFS4_EXCHANGE_ID_LEN	(48)
 | 
					#define NFS4_EXCHANGE_ID_LEN	(48)
 | 
				
			||||||
struct nfs41_exchange_id_args {
 | 
					struct nfs41_exchange_id_args {
 | 
				
			||||||
	struct nfs_client		*client;
 | 
						struct nfs_client		*client;
 | 
				
			||||||
| 
						 | 
					@ -1082,10 +1074,17 @@ struct server_scope {
 | 
				
			||||||
	char 				server_scope[NFS4_OPAQUE_LIMIT];
 | 
						char 				server_scope[NFS4_OPAQUE_LIMIT];
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct nfs41_impl_id {
 | 
				
			||||||
 | 
						char				domain[NFS4_OPAQUE_LIMIT + 1];
 | 
				
			||||||
 | 
						char				name[NFS4_OPAQUE_LIMIT + 1];
 | 
				
			||||||
 | 
						struct nfstime4			date;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct nfs41_exchange_id_res {
 | 
					struct nfs41_exchange_id_res {
 | 
				
			||||||
	struct nfs_client		*client;
 | 
						struct nfs_client		*client;
 | 
				
			||||||
	u32				flags;
 | 
						u32				flags;
 | 
				
			||||||
	struct server_scope		*server_scope;
 | 
						struct server_scope		*server_scope;
 | 
				
			||||||
 | 
						struct nfs41_impl_id		*impl_id;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct nfs41_create_session_args {
 | 
					struct nfs41_create_session_args {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue