[SUNRPC]: Remove the unnecessary check for highmem in xs_sendpages().
[sfrench/cifs-2.6.git] / net / sunrpc / xprtsock.c
index 4b4e7dfdff14538dcb172d66ab68ef44b44bdd11..897bdd98231559421f5bbcfc2477e62b49faeb81 100644 (file)
@@ -174,7 +174,6 @@ static inline int xs_sendpages(struct socket *sock, struct sockaddr *addr, int a
        struct page **ppage = xdr->pages;
        unsigned int len, pglen = xdr->page_len;
        int err, ret = 0;
-       ssize_t (*sendpage)(struct socket *, struct page *, int, size_t, int);
 
        if (unlikely(!sock))
                return -ENOTCONN;
@@ -207,7 +206,6 @@ static inline int xs_sendpages(struct socket *sock, struct sockaddr *addr, int a
                base &= ~PAGE_CACHE_MASK;
        }
 
-       sendpage = sock->ops->sendpage ? : sock_no_sendpage;
        do {
                int flags = XS_SENDMSG_FLAGS;
 
@@ -220,10 +218,7 @@ static inline int xs_sendpages(struct socket *sock, struct sockaddr *addr, int a
                if (pglen != len || xdr->tail[0].iov_len != 0)
                        flags |= MSG_MORE;
 
-               /* Hmm... We might be dealing with highmem pages */
-               if (PageHighMem(*ppage))
-                       sendpage = sock_no_sendpage;
-               err = sendpage(sock, *ppage, base, len, flags);
+               err = kernel_sendpage(sock, *ppage, base, len, flags);
                if (ret == 0)
                        ret = err;
                else if (err > 0)
@@ -413,6 +408,33 @@ static int xs_tcp_send_request(struct rpc_task *task)
        return status;
 }
 
+/**
+ * xs_tcp_release_xprt - clean up after a tcp transmission
+ * @xprt: transport
+ * @task: rpc task
+ *
+ * This cleans up if an error causes us to abort the transmission of a request.
+ * In this case, the socket may need to be reset in order to avoid confusing
+ * the server.
+ */
+static void xs_tcp_release_xprt(struct rpc_xprt *xprt, struct rpc_task *task)
+{
+       struct rpc_rqst *req;
+
+       if (task != xprt->snd_task)
+               return;
+       if (task == NULL)
+               goto out_release;
+       req = task->tk_rqstp;
+       if (req->rq_bytes_sent == 0)
+               goto out_release;
+       if (req->rq_bytes_sent == req->rq_snd_buf.len)
+               goto out_release;
+       set_bit(XPRT_CLOSE_WAIT, &task->tk_xprt->state);
+out_release:
+       xprt_release_xprt(xprt, task);
+}
+
 /**
  * xs_close - close a socket
  * @xprt: transport
@@ -930,6 +952,13 @@ static void xs_udp_timer(struct rpc_task *task)
        xprt_adjust_cwnd(task, -ETIMEDOUT);
 }
 
+static unsigned short xs_get_random_port(void)
+{
+       unsigned short range = xprt_max_resvport - xprt_min_resvport;
+       unsigned short rand = (unsigned short) net_random() % range;
+       return rand + xprt_min_resvport;
+}
+
 /**
  * xs_set_port - reset the port number in the remote endpoint address
  * @xprt: generic transport
@@ -952,7 +981,7 @@ static int xs_bindresvport(struct rpc_xprt *xprt, struct socket *sock)
 
        do {
                myaddr.sin_port = htons(port);
-               err = sock->ops->bind(sock, (struct sockaddr *) &myaddr,
+               err = kernel_bind(sock, (struct sockaddr *) &myaddr,
                                                sizeof(myaddr));
                if (err == 0) {
                        xprt->port = port;
@@ -1047,7 +1076,7 @@ static void xs_tcp_reuse_connection(struct rpc_xprt *xprt)
         */
        memset(&any, 0, sizeof(any));
        any.sa_family = AF_UNSPEC;
-       result = sock->ops->connect(sock, &any, sizeof(any), 0);
+       result = kernel_connect(sock, &any, sizeof(any), 0);
        if (result)
                dprintk("RPC:      AF_UNSPEC connect return code %d\n",
                                result);
@@ -1117,7 +1146,7 @@ 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,
+       status = kernel_connect(sock, (struct sockaddr *) &xprt->addr,
                        sizeof(xprt->addr), O_NONBLOCK);
        dprintk("RPC: %p  connect status %d connected %d sock state %d\n",
                        xprt, -status, xprt_connected(xprt), sock->sk->sk_state);
@@ -1243,7 +1272,7 @@ static struct rpc_xprt_ops xs_udp_ops = {
 
 static struct rpc_xprt_ops xs_tcp_ops = {
        .reserve_xprt           = xprt_reserve_xprt,
-       .release_xprt           = xprt_release_xprt,
+       .release_xprt           = xs_tcp_release_xprt,
        .set_port               = xs_set_port,
        .connect                = xs_connect,
        .buf_alloc              = rpc_malloc,
@@ -1269,13 +1298,12 @@ int xs_setup_udp(struct rpc_xprt *xprt, struct rpc_timeout *to)
 
        xprt->max_reqs = xprt_udp_slot_table_entries;
        slot_table_size = xprt->max_reqs * sizeof(xprt->slot[0]);
-       xprt->slot = kmalloc(slot_table_size, GFP_KERNEL);
+       xprt->slot = kzalloc(slot_table_size, GFP_KERNEL);
        if (xprt->slot == NULL)
                return -ENOMEM;
-       memset(xprt->slot, 0, slot_table_size);
 
        xprt->prot = IPPROTO_UDP;
-       xprt->port = xprt_max_resvport;
+       xprt->port = xs_get_random_port();
        xprt->tsh_size = 0;
        xprt->resvport = capable(CAP_NET_BIND_SERVICE) ? 1 : 0;
        /* XXX: header size can vary due to auth type, IPv6, etc. */
@@ -1311,13 +1339,12 @@ int xs_setup_tcp(struct rpc_xprt *xprt, struct rpc_timeout *to)
 
        xprt->max_reqs = xprt_tcp_slot_table_entries;
        slot_table_size = xprt->max_reqs * sizeof(xprt->slot[0]);
-       xprt->slot = kmalloc(slot_table_size, GFP_KERNEL);
+       xprt->slot = kzalloc(slot_table_size, GFP_KERNEL);
        if (xprt->slot == NULL)
                return -ENOMEM;
-       memset(xprt->slot, 0, slot_table_size);
 
        xprt->prot = IPPROTO_TCP;
-       xprt->port = xprt_max_resvport;
+       xprt->port = xs_get_random_port();
        xprt->tsh_size = sizeof(rpc_fraghdr) / sizeof(u32);
        xprt->resvport = capable(CAP_NET_BIND_SERVICE) ? 1 : 0;
        xprt->max_payload = RPC_MAX_FRAGMENT_SIZE;