diff options
author | Jim Schutt <jaschut@sandia.gov> | 2012-02-29 10:30:58 -0500 |
---|---|---|
committer | Alex Elder <elder@dreamhost.com> | 2012-03-22 11:47:45 -0400 |
commit | 182fac2689b769a96e7fc9defcd560c5cca92b1e (patch) | |
tree | 1944b5db730a3157cd8f3d2e50fa88db263c5114 /net/ceph | |
parent | c16fa4f2ad19908a47c63d8fa436a1178438c7e7 (diff) |
net/ceph: Only clear SOCK_NOSPACE when there is sufficient space in the socket buffer
The Ceph messenger would sometimes queue multiple work items to write
data to a socket when the socket buffer was full.
Fix this problem by making ceph_write_space() use SOCK_NOSPACE in the
same way that net/core/stream.c:sk_stream_write_space() does, i.e.,
clearing it only when sufficient space is available in the socket buffer.
Signed-off-by: Jim Schutt <jaschut@sandia.gov>
Reviewed-by: Alex Elder <elder@dreamhost.com>
Diffstat (limited to 'net/ceph')
-rw-r--r-- | net/ceph/messenger.c | 18 |
1 files changed, 12 insertions, 6 deletions
diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index ad5b70801f37..d11f91b05452 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c | |||
@@ -143,16 +143,22 @@ static void ceph_write_space(struct sock *sk) | |||
143 | struct ceph_connection *con = | 143 | struct ceph_connection *con = |
144 | (struct ceph_connection *)sk->sk_user_data; | 144 | (struct ceph_connection *)sk->sk_user_data; |
145 | 145 | ||
146 | /* only queue to workqueue if there is data we want to write. */ | 146 | /* only queue to workqueue if there is data we want to write, |
147 | * and there is sufficient space in the socket buffer to accept | ||
148 | * more data. clear SOCK_NOSPACE so that ceph_write_space() | ||
149 | * doesn't get called again until try_write() fills the socket | ||
150 | * buffer. See net/ipv4/tcp_input.c:tcp_check_space() | ||
151 | * and net/core/stream.c:sk_stream_write_space(). | ||
152 | */ | ||
147 | if (test_bit(WRITE_PENDING, &con->state)) { | 153 | if (test_bit(WRITE_PENDING, &con->state)) { |
148 | dout("ceph_write_space %p queueing write work\n", con); | 154 | if (sk_stream_wspace(sk) >= sk_stream_min_wspace(sk)) { |
149 | queue_con(con); | 155 | dout("ceph_write_space %p queueing write work\n", con); |
156 | clear_bit(SOCK_NOSPACE, &sk->sk_socket->flags); | ||
157 | queue_con(con); | ||
158 | } | ||
150 | } else { | 159 | } else { |
151 | dout("ceph_write_space %p nothing to write\n", con); | 160 | dout("ceph_write_space %p nothing to write\n", con); |
152 | } | 161 | } |
153 | |||
154 | /* since we have our own write_space, clear the SOCK_NOSPACE flag */ | ||
155 | clear_bit(SOCK_NOSPACE, &sk->sk_socket->flags); | ||
156 | } | 162 | } |
157 | 163 | ||
158 | /* socket's state has changed */ | 164 | /* socket's state has changed */ |