|
@@ -398,7 +398,6 @@ static int xs_sendpages(struct socket *sock, struct sockaddr *addr, int addrlen,
|
|
if (unlikely(!sock))
|
|
if (unlikely(!sock))
|
|
return -ENOTSOCK;
|
|
return -ENOTSOCK;
|
|
|
|
|
|
- clear_bit(SOCKWQ_ASYNC_NOSPACE, &sock->flags);
|
|
|
|
if (base != 0) {
|
|
if (base != 0) {
|
|
addr = NULL;
|
|
addr = NULL;
|
|
addrlen = 0;
|
|
addrlen = 0;
|
|
@@ -442,7 +441,6 @@ static void xs_nospace_callback(struct rpc_task *task)
|
|
struct sock_xprt *transport = container_of(task->tk_rqstp->rq_xprt, struct sock_xprt, xprt);
|
|
struct sock_xprt *transport = container_of(task->tk_rqstp->rq_xprt, struct sock_xprt, xprt);
|
|
|
|
|
|
transport->inet->sk_write_pending--;
|
|
transport->inet->sk_write_pending--;
|
|
- clear_bit(SOCKWQ_ASYNC_NOSPACE, &transport->sock->flags);
|
|
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
/**
|
|
@@ -467,20 +465,11 @@ static int xs_nospace(struct rpc_task *task)
|
|
|
|
|
|
/* Don't race with disconnect */
|
|
/* Don't race with disconnect */
|
|
if (xprt_connected(xprt)) {
|
|
if (xprt_connected(xprt)) {
|
|
- if (test_bit(SOCKWQ_ASYNC_NOSPACE, &transport->sock->flags)) {
|
|
|
|
- /*
|
|
|
|
- * Notify TCP that we're limited by the application
|
|
|
|
- * window size
|
|
|
|
- */
|
|
|
|
- set_bit(SOCK_NOSPACE, &transport->sock->flags);
|
|
|
|
- sk->sk_write_pending++;
|
|
|
|
- /* ...and wait for more buffer space */
|
|
|
|
- xprt_wait_for_buffer_space(task, xs_nospace_callback);
|
|
|
|
- }
|
|
|
|
- } else {
|
|
|
|
- clear_bit(SOCKWQ_ASYNC_NOSPACE, &transport->sock->flags);
|
|
|
|
|
|
+ /* wait for more buffer space */
|
|
|
|
+ sk->sk_write_pending++;
|
|
|
|
+ xprt_wait_for_buffer_space(task, xs_nospace_callback);
|
|
|
|
+ } else
|
|
ret = -ENOTCONN;
|
|
ret = -ENOTCONN;
|
|
- }
|
|
|
|
|
|
|
|
spin_unlock_bh(&xprt->transport_lock);
|
|
spin_unlock_bh(&xprt->transport_lock);
|
|
|
|
|
|
@@ -616,9 +605,6 @@ process_status:
|
|
case -EAGAIN:
|
|
case -EAGAIN:
|
|
status = xs_nospace(task);
|
|
status = xs_nospace(task);
|
|
break;
|
|
break;
|
|
- default:
|
|
|
|
- dprintk("RPC: sendmsg returned unrecognized error %d\n",
|
|
|
|
- -status);
|
|
|
|
case -ENETUNREACH:
|
|
case -ENETUNREACH:
|
|
case -ENOBUFS:
|
|
case -ENOBUFS:
|
|
case -EPIPE:
|
|
case -EPIPE:
|
|
@@ -626,7 +612,10 @@ process_status:
|
|
case -EPERM:
|
|
case -EPERM:
|
|
/* When the server has died, an ICMP port unreachable message
|
|
/* When the server has died, an ICMP port unreachable message
|
|
* prompts ECONNREFUSED. */
|
|
* prompts ECONNREFUSED. */
|
|
- clear_bit(SOCKWQ_ASYNC_NOSPACE, &transport->sock->flags);
|
|
|
|
|
|
+ break;
|
|
|
|
+ default:
|
|
|
|
+ dprintk("RPC: sendmsg returned unrecognized error %d\n",
|
|
|
|
+ -status);
|
|
}
|
|
}
|
|
|
|
|
|
return status;
|
|
return status;
|
|
@@ -706,16 +695,16 @@ static int xs_tcp_send_request(struct rpc_task *task)
|
|
case -EAGAIN:
|
|
case -EAGAIN:
|
|
status = xs_nospace(task);
|
|
status = xs_nospace(task);
|
|
break;
|
|
break;
|
|
- default:
|
|
|
|
- dprintk("RPC: sendmsg returned unrecognized error %d\n",
|
|
|
|
- -status);
|
|
|
|
case -ECONNRESET:
|
|
case -ECONNRESET:
|
|
case -ECONNREFUSED:
|
|
case -ECONNREFUSED:
|
|
case -ENOTCONN:
|
|
case -ENOTCONN:
|
|
case -EADDRINUSE:
|
|
case -EADDRINUSE:
|
|
case -ENOBUFS:
|
|
case -ENOBUFS:
|
|
case -EPIPE:
|
|
case -EPIPE:
|
|
- clear_bit(SOCKWQ_ASYNC_NOSPACE, &transport->sock->flags);
|
|
|
|
|
|
+ break;
|
|
|
|
+ default:
|
|
|
|
+ dprintk("RPC: sendmsg returned unrecognized error %d\n",
|
|
|
|
+ -status);
|
|
}
|
|
}
|
|
|
|
|
|
return status;
|
|
return status;
|
|
@@ -1609,19 +1598,23 @@ static void xs_tcp_state_change(struct sock *sk)
|
|
|
|
|
|
static void xs_write_space(struct sock *sk)
|
|
static void xs_write_space(struct sock *sk)
|
|
{
|
|
{
|
|
- struct socket *sock;
|
|
|
|
|
|
+ struct socket_wq *wq;
|
|
struct rpc_xprt *xprt;
|
|
struct rpc_xprt *xprt;
|
|
|
|
|
|
- if (unlikely(!(sock = sk->sk_socket)))
|
|
|
|
|
|
+ if (!sk->sk_socket)
|
|
return;
|
|
return;
|
|
- clear_bit(SOCK_NOSPACE, &sock->flags);
|
|
|
|
|
|
+ clear_bit(SOCK_NOSPACE, &sk->sk_socket->flags);
|
|
|
|
|
|
if (unlikely(!(xprt = xprt_from_sock(sk))))
|
|
if (unlikely(!(xprt = xprt_from_sock(sk))))
|
|
return;
|
|
return;
|
|
- if (test_and_clear_bit(SOCKWQ_ASYNC_NOSPACE, &sock->flags) == 0)
|
|
|
|
- return;
|
|
|
|
|
|
+ rcu_read_lock();
|
|
|
|
+ wq = rcu_dereference(sk->sk_wq);
|
|
|
|
+ if (!wq || test_and_clear_bit(SOCKWQ_ASYNC_NOSPACE, &wq->flags) == 0)
|
|
|
|
+ goto out;
|
|
|
|
|
|
xprt_write_space(xprt);
|
|
xprt_write_space(xprt);
|
|
|
|
+out:
|
|
|
|
+ rcu_read_unlock();
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
/**
|