]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - net/sunrpc/xprtsock.c
Merge branch 'for-linus' of master.kernel.org:/pub/scm/linux/kernel/git/roland/infiniband
[linux-2.6-omap-h63xx.git] / net / sunrpc / xprtsock.c
index 2e1529217e656a380b9d934917561959b58c5ad0..4b4e7dfdff14538dcb172d66ab68ef44b44bdd11 100644 (file)
@@ -28,6 +28,7 @@
 #include <linux/udp.h>
 #include <linux/tcp.h>
 #include <linux/sunrpc/clnt.h>
+#include <linux/sunrpc/sched.h>
 #include <linux/file.h>
 
 #include <net/sock.h>
 #include <net/udp.h>
 #include <net/tcp.h>
 
+/*
+ * xprtsock tunables
+ */
+unsigned int xprt_udp_slot_table_entries = RPC_DEF_SLOT_TABLE;
+unsigned int xprt_tcp_slot_table_entries = RPC_DEF_SLOT_TABLE;
+
+unsigned int xprt_min_resvport = RPC_DEF_MIN_RESVPORT;
+unsigned int xprt_max_resvport = RPC_DEF_MAX_RESVPORT;
+
 /*
  * How many times to try sending a request on a socket before waiting
  * for the socket buffer to clear.
@@ -372,6 +382,7 @@ static int xs_tcp_send_request(struct rpc_task *task)
                /* If we've sent the entire packet, immediately
                 * reset the count of bytes sent. */
                req->rq_bytes_sent += status;
+               task->tk_bytes_sent += status;
                if (likely(req->rq_bytes_sent >= req->rq_slen)) {
                        req->rq_bytes_sent = 0;
                        return 0;
@@ -415,7 +426,7 @@ static void xs_close(struct rpc_xprt *xprt)
        struct sock *sk = xprt->inet;
 
        if (!sk)
-               return;
+               goto clear_close_wait;
 
        dprintk("RPC:      xs_close xprt %p\n", xprt);
 
@@ -432,6 +443,10 @@ static void xs_close(struct rpc_xprt *xprt)
        sk->sk_no_check = 0;
 
        sock_release(sock);
+clear_close_wait:
+       smp_mb__before_clear_bit();
+       clear_bit(XPRT_CLOSE_WAIT, &xprt->state);
+       smp_mb__after_clear_bit();
 }
 
 /**
@@ -791,9 +806,13 @@ static void xs_tcp_state_change(struct sock *sk)
        case TCP_SYN_SENT:
        case TCP_SYN_RECV:
                break;
+       case TCP_CLOSE_WAIT:
+               /* Try to schedule an autoclose RPC calls */
+               set_bit(XPRT_CLOSE_WAIT, &xprt->state);
+               if (test_and_set_bit(XPRT_LOCKED, &xprt->state) == 0)
+                       schedule_work(&xprt->task_cleanup);
        default:
                xprt_disconnect(xprt);
-               break;
        }
  out:
        read_unlock(&sk->sk_callback_lock);
@@ -911,6 +930,18 @@ static void xs_udp_timer(struct rpc_task *task)
        xprt_adjust_cwnd(task, -ETIMEDOUT);
 }
 
+/**
+ * xs_set_port - reset the port number in the remote endpoint address
+ * @xprt: generic transport
+ * @port: new port number
+ *
+ */
+static void xs_set_port(struct rpc_xprt *xprt, unsigned short port)
+{
+       dprintk("RPC:      setting port for xprt %p to %u\n", xprt, port);
+       xprt->addr.sin_port = htons(port);
+}
+
 static int xs_bindresvport(struct rpc_xprt *xprt, struct socket *sock)
 {
        struct sockaddr_in myaddr = {
@@ -981,6 +1012,7 @@ static void xs_udp_connect_worker(void *args)
                sk->sk_data_ready = xs_udp_data_ready;
                sk->sk_write_space = xs_udp_write_space;
                sk->sk_no_check = UDP_CSUM_NORCV;
+               sk->sk_allocation = GFP_ATOMIC;
 
                xprt_set_connected(xprt);
 
@@ -1065,6 +1097,7 @@ static void xs_tcp_connect_worker(void *args)
                sk->sk_data_ready = xs_tcp_data_ready;
                sk->sk_state_change = xs_tcp_state_change;
                sk->sk_write_space = xs_tcp_write_space;
+               sk->sk_allocation = GFP_ATOMIC;
 
                /* socket options */
                sk->sk_userlocks |= SOCK_BINDPORT_LOCK;
@@ -1082,6 +1115,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",
@@ -1145,27 +1180,79 @@ 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,
        .release_xprt           = xprt_release_xprt_cong,
+       .set_port               = xs_set_port,
        .connect                = xs_connect,
+       .buf_alloc              = rpc_malloc,
+       .buf_free               = rpc_free,
        .send_request           = xs_udp_send_request,
        .set_retrans_timeout    = xprt_set_retrans_timeout_rtt,
        .timer                  = xs_udp_timer,
        .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 = {
        .reserve_xprt           = xprt_reserve_xprt,
        .release_xprt           = xprt_release_xprt,
+       .set_port               = xs_set_port,
        .connect                = xs_connect,
+       .buf_alloc              = rpc_malloc,
+       .buf_free               = rpc_free,
        .send_request           = xs_tcp_send_request,
        .set_retrans_timeout    = xprt_set_retrans_timeout_def,
        .close                  = xs_close,
        .destroy                = xs_destroy,
+       .print_stats            = xs_tcp_print_stats,
 };
 
 /**