aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChuck Lever <cel@netapp.com>2006-03-20 13:44:16 -0500
committerTrond Myklebust <Trond.Myklebust@netapp.com>2006-03-20 13:44:16 -0500
commit262ca07de4d7f1bff20361c1353bb14b3607afb2 (patch)
treee448a66b4549bbd660f76e81da0067d762a4732e
parente19b63dafdf7d615b0d36b90990a07e7792b9d3a (diff)
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: Chuck Lever <cel@netapp.com> Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
-rw-r--r--include/linux/sunrpc/xprt.h13
-rw-r--r--net/sunrpc/pmap_clnt.c1
-rw-r--r--net/sunrpc/xprt.c21
-rw-r--r--net/sunrpc/xprtsock.c48
4 files changed, 77 insertions, 6 deletions
diff --git a/include/linux/sunrpc/xprt.h b/include/linux/sunrpc/xprt.h
index 6ef99b14ff09..7eebbab7160b 100644
--- a/include/linux/sunrpc/xprt.h
+++ b/include/linux/sunrpc/xprt.h
@@ -114,6 +114,7 @@ struct rpc_xprt_ops {
114 void (*release_request)(struct rpc_task *task); 114 void (*release_request)(struct rpc_task *task);
115 void (*close)(struct rpc_xprt *xprt); 115 void (*close)(struct rpc_xprt *xprt);
116 void (*destroy)(struct rpc_xprt *xprt); 116 void (*destroy)(struct rpc_xprt *xprt);
117 void (*print_stats)(struct rpc_xprt *xprt, struct seq_file *seq);
117}; 118};
118 119
119struct rpc_xprt { 120struct rpc_xprt {
@@ -187,6 +188,18 @@ struct rpc_xprt {
187 188
188 struct list_head recv; 189 struct list_head recv;
189 190
191 struct {
192 unsigned long bind_count, /* total number of binds */
193 connect_count, /* total number of connects */
194 connect_start, /* connect start timestamp */
195 connect_time, /* jiffies waiting for connect */
196 sends, /* how many complete requests */
197 recvs, /* how many complete requests */
198 bad_xids; /* lookup_rqst didn't find XID */
199
200 unsigned long long req_u, /* average requests on the wire */
201 bklog_u; /* backlog queue utilization */
202 } stat;
190 203
191 void (*old_data_ready)(struct sock *, int); 204 void (*old_data_ready)(struct sock *, int);
192 void (*old_state_change)(struct sock *); 205 void (*old_state_change)(struct sock *);
diff --git a/net/sunrpc/pmap_clnt.c b/net/sunrpc/pmap_clnt.c
index 8139ce68e915..332cc5d362d5 100644
--- a/net/sunrpc/pmap_clnt.c
+++ b/net/sunrpc/pmap_clnt.c
@@ -82,6 +82,7 @@ rpc_getport(struct rpc_task *task, struct rpc_clnt *clnt)
82 rpc_call_setup(child, &msg, 0); 82 rpc_call_setup(child, &msg, 0);
83 83
84 /* ... and run the child task */ 84 /* ... and run the child task */
85 task->tk_xprt->stat.bind_count++;
85 rpc_run_child(task, child, pmap_getport_done); 86 rpc_run_child(task, child, pmap_getport_done);
86 return; 87 return;
87 88
diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c
index 8ff2c8acb223..93a0a3ca0d5f 100644
--- a/net/sunrpc/xprt.c
+++ b/net/sunrpc/xprt.c
@@ -548,6 +548,7 @@ void xprt_connect(struct rpc_task *task)
548 548
549 task->tk_timeout = xprt->connect_timeout; 549 task->tk_timeout = xprt->connect_timeout;
550 rpc_sleep_on(&xprt->pending, task, xprt_connect_status, NULL); 550 rpc_sleep_on(&xprt->pending, task, xprt_connect_status, NULL);
551 xprt->stat.connect_start = jiffies;
551 xprt->ops->connect(task); 552 xprt->ops->connect(task);
552 } 553 }
553 return; 554 return;
@@ -558,6 +559,8 @@ static void xprt_connect_status(struct rpc_task *task)
558 struct rpc_xprt *xprt = task->tk_xprt; 559 struct rpc_xprt *xprt = task->tk_xprt;
559 560
560 if (task->tk_status >= 0) { 561 if (task->tk_status >= 0) {
562 xprt->stat.connect_count++;
563 xprt->stat.connect_time += (long)jiffies - xprt->stat.connect_start;
561 dprintk("RPC: %4d xprt_connect_status: connection established\n", 564 dprintk("RPC: %4d xprt_connect_status: connection established\n",
562 task->tk_pid); 565 task->tk_pid);
563 return; 566 return;
@@ -601,16 +604,14 @@ static void xprt_connect_status(struct rpc_task *task)
601struct rpc_rqst *xprt_lookup_rqst(struct rpc_xprt *xprt, u32 xid) 604struct rpc_rqst *xprt_lookup_rqst(struct rpc_xprt *xprt, u32 xid)
602{ 605{
603 struct list_head *pos; 606 struct list_head *pos;
604 struct rpc_rqst *req = NULL;
605 607
606 list_for_each(pos, &xprt->recv) { 608 list_for_each(pos, &xprt->recv) {
607 struct rpc_rqst *entry = list_entry(pos, struct rpc_rqst, rq_list); 609 struct rpc_rqst *entry = list_entry(pos, struct rpc_rqst, rq_list);
608 if (entry->rq_xid == xid) { 610 if (entry->rq_xid == xid)
609 req = entry; 611 return entry;
610 break;
611 }
612 } 612 }
613 return req; 613 xprt->stat.bad_xids++;
614 return NULL;
614} 615}
615 616
616/** 617/**
@@ -646,6 +647,7 @@ void xprt_complete_rqst(struct rpc_task *task, int copied)
646 dprintk("RPC: %5u xid %08x complete (%d bytes received)\n", 647 dprintk("RPC: %5u xid %08x complete (%d bytes received)\n",
647 task->tk_pid, ntohl(req->rq_xid), copied); 648 task->tk_pid, ntohl(req->rq_xid), copied);
648 649
650 task->tk_xprt->stat.recvs++;
649 list_del_init(&req->rq_list); 651 list_del_init(&req->rq_list);
650 req->rq_received = req->rq_private_buf.len = copied; 652 req->rq_received = req->rq_private_buf.len = copied;
651 rpc_wake_up_task(task); 653 rpc_wake_up_task(task);
@@ -744,12 +746,19 @@ void xprt_transmit(struct rpc_task *task)
744 if (status == 0) { 746 if (status == 0) {
745 dprintk("RPC: %4d xmit complete\n", task->tk_pid); 747 dprintk("RPC: %4d xmit complete\n", task->tk_pid);
746 spin_lock_bh(&xprt->transport_lock); 748 spin_lock_bh(&xprt->transport_lock);
749
747 xprt->ops->set_retrans_timeout(task); 750 xprt->ops->set_retrans_timeout(task);
751
752 xprt->stat.sends++;
753 xprt->stat.req_u += xprt->stat.sends - xprt->stat.recvs;
754 xprt->stat.bklog_u += xprt->backlog.qlen;
755
748 /* Don't race with disconnect */ 756 /* Don't race with disconnect */
749 if (!xprt_connected(xprt)) 757 if (!xprt_connected(xprt))
750 task->tk_status = -ENOTCONN; 758 task->tk_status = -ENOTCONN;
751 else if (!req->rq_received) 759 else if (!req->rq_received)
752 rpc_sleep_on(&xprt->pending, task, NULL, xprt_timer); 760 rpc_sleep_on(&xprt->pending, task, NULL, xprt_timer);
761
753 xprt->ops->release_xprt(xprt, task); 762 xprt->ops->release_xprt(xprt, task);
754 spin_unlock_bh(&xprt->transport_lock); 763 spin_unlock_bh(&xprt->transport_lock);
755 return; 764 return;
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c
index c458f8d1d6d1..6766b7f1ecf9 100644
--- a/net/sunrpc/xprtsock.c
+++ b/net/sunrpc/xprtsock.c
@@ -1114,6 +1114,8 @@ static void xs_tcp_connect_worker(void *args)
1114 } 1114 }
1115 1115
1116 /* Tell the socket layer to start connecting... */ 1116 /* Tell the socket layer to start connecting... */
1117 xprt->stat.connect_count++;
1118 xprt->stat.connect_start = jiffies;
1117 status = sock->ops->connect(sock, (struct sockaddr *) &xprt->addr, 1119 status = sock->ops->connect(sock, (struct sockaddr *) &xprt->addr,
1118 sizeof(xprt->addr), O_NONBLOCK); 1120 sizeof(xprt->addr), O_NONBLOCK);
1119 dprintk("RPC: %p connect status %d connected %d sock state %d\n", 1121 dprintk("RPC: %p connect status %d connected %d sock state %d\n",
@@ -1177,6 +1179,50 @@ static void xs_connect(struct rpc_task *task)
1177 } 1179 }
1178} 1180}
1179 1181
1182/**
1183 * xs_udp_print_stats - display UDP socket-specifc stats
1184 * @xprt: rpc_xprt struct containing statistics
1185 * @seq: output file
1186 *
1187 */
1188static void xs_udp_print_stats(struct rpc_xprt *xprt, struct seq_file *seq)
1189{
1190 seq_printf(seq, "\txprt:\tudp %u %lu %lu %lu %lu %Lu %Lu\n",
1191 xprt->port,
1192 xprt->stat.bind_count,
1193 xprt->stat.sends,
1194 xprt->stat.recvs,
1195 xprt->stat.bad_xids,
1196 xprt->stat.req_u,
1197 xprt->stat.bklog_u);
1198}
1199
1200/**
1201 * xs_tcp_print_stats - display TCP socket-specifc stats
1202 * @xprt: rpc_xprt struct containing statistics
1203 * @seq: output file
1204 *
1205 */
1206static void xs_tcp_print_stats(struct rpc_xprt *xprt, struct seq_file *seq)
1207{
1208 long idle_time = 0;
1209
1210 if (xprt_connected(xprt))
1211 idle_time = (long)(jiffies - xprt->last_used) / HZ;
1212
1213 seq_printf(seq, "\txprt:\ttcp %u %lu %lu %lu %ld %lu %lu %lu %Lu %Lu\n",
1214 xprt->port,
1215 xprt->stat.bind_count,
1216 xprt->stat.connect_count,
1217 xprt->stat.connect_time,
1218 idle_time,
1219 xprt->stat.sends,
1220 xprt->stat.recvs,
1221 xprt->stat.bad_xids,
1222 xprt->stat.req_u,
1223 xprt->stat.bklog_u);
1224}
1225
1180static struct rpc_xprt_ops xs_udp_ops = { 1226static struct rpc_xprt_ops xs_udp_ops = {
1181 .set_buffer_size = xs_udp_set_buffer_size, 1227 .set_buffer_size = xs_udp_set_buffer_size,
1182 .reserve_xprt = xprt_reserve_xprt_cong, 1228 .reserve_xprt = xprt_reserve_xprt_cong,
@@ -1191,6 +1237,7 @@ static struct rpc_xprt_ops xs_udp_ops = {
1191 .release_request = xprt_release_rqst_cong, 1237 .release_request = xprt_release_rqst_cong,
1192 .close = xs_close, 1238 .close = xs_close,
1193 .destroy = xs_destroy, 1239 .destroy = xs_destroy,
1240 .print_stats = xs_udp_print_stats,
1194}; 1241};
1195 1242
1196static struct rpc_xprt_ops xs_tcp_ops = { 1243static struct rpc_xprt_ops xs_tcp_ops = {
@@ -1204,6 +1251,7 @@ static struct rpc_xprt_ops xs_tcp_ops = {
1204 .set_retrans_timeout = xprt_set_retrans_timeout_def, 1251 .set_retrans_timeout = xprt_set_retrans_timeout_def,
1205 .close = xs_close, 1252 .close = xs_close,
1206 .destroy = xs_destroy, 1253 .destroy = xs_destroy,
1254 .print_stats = xs_tcp_print_stats,
1207}; 1255};
1208 1256
1209/** 1257/**