diff options
-rw-r--r-- | include/linux/sunrpc/xprt.h | 13 | ||||
-rw-r--r-- | net/sunrpc/pmap_clnt.c | 1 | ||||
-rw-r--r-- | net/sunrpc/xprt.c | 21 | ||||
-rw-r--r-- | net/sunrpc/xprtsock.c | 48 |
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 | ||
119 | struct rpc_xprt { | 120 | struct 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) | |||
601 | struct rpc_rqst *xprt_lookup_rqst(struct rpc_xprt *xprt, u32 xid) | 604 | struct 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 | */ | ||
1188 | static 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 | */ | ||
1206 | static 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 | |||
1180 | static struct rpc_xprt_ops xs_udp_ops = { | 1226 | static 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 | ||
1196 | static struct rpc_xprt_ops xs_tcp_ops = { | 1243 | static 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 | /** |