diff options
Diffstat (limited to 'fs')
-rw-r--r-- | fs/dlm/lowcomms.c | 22 |
1 files changed, 21 insertions, 1 deletions
diff --git a/fs/dlm/lowcomms.c b/fs/dlm/lowcomms.c index 37a34c2c622a..77720f89c879 100644 --- a/fs/dlm/lowcomms.c +++ b/fs/dlm/lowcomms.c | |||
@@ -108,6 +108,7 @@ struct connection { | |||
108 | #define CF_INIT_PENDING 4 | 108 | #define CF_INIT_PENDING 4 |
109 | #define CF_IS_OTHERCON 5 | 109 | #define CF_IS_OTHERCON 5 |
110 | #define CF_CLOSE 6 | 110 | #define CF_CLOSE 6 |
111 | #define CF_APP_LIMITED 7 | ||
111 | struct list_head writequeue; /* List of outgoing writequeue_entries */ | 112 | struct list_head writequeue; /* List of outgoing writequeue_entries */ |
112 | spinlock_t writequeue_lock; | 113 | spinlock_t writequeue_lock; |
113 | int (*rx_action) (struct connection *); /* What to do when active */ | 114 | int (*rx_action) (struct connection *); /* What to do when active */ |
@@ -295,7 +296,17 @@ static void lowcomms_write_space(struct sock *sk) | |||
295 | { | 296 | { |
296 | struct connection *con = sock2con(sk); | 297 | struct connection *con = sock2con(sk); |
297 | 298 | ||
298 | if (con && !test_and_set_bit(CF_WRITE_PENDING, &con->flags)) | 299 | if (!con) |
300 | return; | ||
301 | |||
302 | clear_bit(SOCK_NOSPACE, &con->sock->flags); | ||
303 | |||
304 | if (test_and_clear_bit(CF_APP_LIMITED, &con->flags)) { | ||
305 | con->sock->sk->sk_write_pending--; | ||
306 | clear_bit(SOCK_ASYNC_NOSPACE, &con->sock->flags); | ||
307 | } | ||
308 | |||
309 | if (!test_and_set_bit(CF_WRITE_PENDING, &con->flags)) | ||
299 | queue_work(send_workqueue, &con->swork); | 310 | queue_work(send_workqueue, &con->swork); |
300 | } | 311 | } |
301 | 312 | ||
@@ -1319,6 +1330,15 @@ static void send_to_sock(struct connection *con) | |||
1319 | ret = kernel_sendpage(con->sock, e->page, offset, len, | 1330 | ret = kernel_sendpage(con->sock, e->page, offset, len, |
1320 | msg_flags); | 1331 | msg_flags); |
1321 | if (ret == -EAGAIN || ret == 0) { | 1332 | if (ret == -EAGAIN || ret == 0) { |
1333 | if (ret == -EAGAIN && | ||
1334 | test_bit(SOCK_ASYNC_NOSPACE, &con->sock->flags) && | ||
1335 | !test_and_set_bit(CF_APP_LIMITED, &con->flags)) { | ||
1336 | /* Notify TCP that we're limited by the | ||
1337 | * application window size. | ||
1338 | */ | ||
1339 | set_bit(SOCK_NOSPACE, &con->sock->flags); | ||
1340 | con->sock->sk->sk_write_pending++; | ||
1341 | } | ||
1322 | cond_resched(); | 1342 | cond_resched(); |
1323 | goto out; | 1343 | goto out; |
1324 | } | 1344 | } |