Commit 262ca07d authored by Chuck Lever's avatar Chuck Lever Committed by Trond Myklebust
Browse files

SUNRPC: add a handful of per-xprt counters



Monitor generic transport events.  Add a transport switch callout to
format transport counters for export to user-land.

Test plan:
Compile kernel with CONFIG_NFS enabled.

Signed-off-by: default avatarChuck Lever <cel@netapp.com>
Signed-off-by: default avatarTrond Myklebust <Trond.Myklebust@netapp.com>
parent e19b63da
Loading
Loading
Loading
Loading
+13 −0
Original line number Diff line number Diff line
@@ -114,6 +114,7 @@ struct rpc_xprt_ops {
	void		(*release_request)(struct rpc_task *task);
	void		(*close)(struct rpc_xprt *xprt);
	void		(*destroy)(struct rpc_xprt *xprt);
	void		(*print_stats)(struct rpc_xprt *xprt, struct seq_file *seq);
};

struct rpc_xprt {
@@ -187,6 +188,18 @@ struct rpc_xprt {

	struct list_head	recv;

	struct {
		unsigned long		bind_count,	/* total number of binds */
					connect_count,	/* total number of connects */
					connect_start,	/* connect start timestamp */
					connect_time,	/* jiffies waiting for connect */
					sends,		/* how many complete requests */
					recvs,		/* how many complete requests */
					bad_xids;	/* lookup_rqst didn't find XID */

		unsigned long long	req_u,		/* average requests on the wire */
					bklog_u;	/* backlog queue utilization */
	} stat;

	void			(*old_data_ready)(struct sock *, int);
	void			(*old_state_change)(struct sock *);
+1 −0
Original line number Diff line number Diff line
@@ -82,6 +82,7 @@ rpc_getport(struct rpc_task *task, struct rpc_clnt *clnt)
	rpc_call_setup(child, &msg, 0);

	/* ... and run the child task */
	task->tk_xprt->stat.bind_count++;
	rpc_run_child(task, child, pmap_getport_done);
	return;

+15 −6
Original line number Diff line number Diff line
@@ -548,6 +548,7 @@ void xprt_connect(struct rpc_task *task)

		task->tk_timeout = xprt->connect_timeout;
		rpc_sleep_on(&xprt->pending, task, xprt_connect_status, NULL);
		xprt->stat.connect_start = jiffies;
		xprt->ops->connect(task);
	}
	return;
@@ -558,6 +559,8 @@ static void xprt_connect_status(struct rpc_task *task)
	struct rpc_xprt	*xprt = task->tk_xprt;

	if (task->tk_status >= 0) {
		xprt->stat.connect_count++;
		xprt->stat.connect_time += (long)jiffies - xprt->stat.connect_start;
		dprintk("RPC: %4d xprt_connect_status: connection established\n",
				task->tk_pid);
		return;
@@ -601,16 +604,14 @@ static void xprt_connect_status(struct rpc_task *task)
struct rpc_rqst *xprt_lookup_rqst(struct rpc_xprt *xprt, u32 xid)
{
	struct list_head *pos;
	struct rpc_rqst	*req = NULL;

	list_for_each(pos, &xprt->recv) {
		struct rpc_rqst *entry = list_entry(pos, struct rpc_rqst, rq_list);
		if (entry->rq_xid == xid) {
			req = entry;
			break;
		}
		if (entry->rq_xid == xid)
			return entry;
	}
	return req;
	xprt->stat.bad_xids++;
	return NULL;
}

/**
@@ -646,6 +647,7 @@ void xprt_complete_rqst(struct rpc_task *task, int copied)
	dprintk("RPC: %5u xid %08x complete (%d bytes received)\n",
			task->tk_pid, ntohl(req->rq_xid), copied);

	task->tk_xprt->stat.recvs++;
	list_del_init(&req->rq_list);
	req->rq_received = req->rq_private_buf.len = copied;
	rpc_wake_up_task(task);
@@ -744,12 +746,19 @@ void xprt_transmit(struct rpc_task *task)
	if (status == 0) {
		dprintk("RPC: %4d xmit complete\n", task->tk_pid);
		spin_lock_bh(&xprt->transport_lock);

		xprt->ops->set_retrans_timeout(task);

		xprt->stat.sends++;
		xprt->stat.req_u += xprt->stat.sends - xprt->stat.recvs;
		xprt->stat.bklog_u += xprt->backlog.qlen;

		/* Don't race with disconnect */
		if (!xprt_connected(xprt))
			task->tk_status = -ENOTCONN;
		else if (!req->rq_received)
			rpc_sleep_on(&xprt->pending, task, NULL, xprt_timer);

		xprt->ops->release_xprt(xprt, task);
		spin_unlock_bh(&xprt->transport_lock);
		return;
+48 −0
Original line number Diff line number Diff line
@@ -1114,6 +1114,8 @@ static void xs_tcp_connect_worker(void *args)
	}

	/* Tell the socket layer to start connecting... */
	xprt->stat.connect_count++;
	xprt->stat.connect_start = jiffies;
	status = sock->ops->connect(sock, (struct sockaddr *) &xprt->addr,
			sizeof(xprt->addr), O_NONBLOCK);
	dprintk("RPC: %p  connect status %d connected %d sock state %d\n",
@@ -1177,6 +1179,50 @@ static void xs_connect(struct rpc_task *task)
	}
}

/**
 * xs_udp_print_stats - display UDP socket-specifc stats
 * @xprt: rpc_xprt struct containing statistics
 * @seq: output file
 *
 */
static void xs_udp_print_stats(struct rpc_xprt *xprt, struct seq_file *seq)
{
	seq_printf(seq, "\txprt:\tudp %u %lu %lu %lu %lu %Lu %Lu\n",
			xprt->port,
			xprt->stat.bind_count,
			xprt->stat.sends,
			xprt->stat.recvs,
			xprt->stat.bad_xids,
			xprt->stat.req_u,
			xprt->stat.bklog_u);
}

/**
 * xs_tcp_print_stats - display TCP socket-specifc stats
 * @xprt: rpc_xprt struct containing statistics
 * @seq: output file
 *
 */
static void xs_tcp_print_stats(struct rpc_xprt *xprt, struct seq_file *seq)
{
	long idle_time = 0;

	if (xprt_connected(xprt))
		idle_time = (long)(jiffies - xprt->last_used) / HZ;

	seq_printf(seq, "\txprt:\ttcp %u %lu %lu %lu %ld %lu %lu %lu %Lu %Lu\n",
			xprt->port,
			xprt->stat.bind_count,
			xprt->stat.connect_count,
			xprt->stat.connect_time,
			idle_time,
			xprt->stat.sends,
			xprt->stat.recvs,
			xprt->stat.bad_xids,
			xprt->stat.req_u,
			xprt->stat.bklog_u);
}

static struct rpc_xprt_ops xs_udp_ops = {
	.set_buffer_size	= xs_udp_set_buffer_size,
	.reserve_xprt		= xprt_reserve_xprt_cong,
@@ -1191,6 +1237,7 @@ static struct rpc_xprt_ops xs_udp_ops = {
	.release_request	= xprt_release_rqst_cong,
	.close			= xs_close,
	.destroy		= xs_destroy,
	.print_stats		= xs_udp_print_stats,
};

static struct rpc_xprt_ops xs_tcp_ops = {
@@ -1204,6 +1251,7 @@ static struct rpc_xprt_ops xs_tcp_ops = {
	.set_retrans_timeout	= xprt_set_retrans_timeout_def,
	.close			= xs_close,
	.destroy		= xs_destroy,
	.print_stats		= xs_tcp_print_stats,
};

/**