summaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
Diffstat (limited to 'net')
-rw-r--r--net/dccp/output.c34
1 files changed, 19 insertions, 15 deletions
diff --git a/net/dccp/output.c b/net/dccp/output.c
index 6a334ed5e9d..f49544618f2 100644
--- a/net/dccp/output.c
+++ b/net/dccp/output.c
@@ -177,34 +177,38 @@ void dccp_write_space(struct sock *sk)
/**
* dccp_wait_for_ccid - Wait for ccid to tell us we can send a packet
- * @sk: socket to wait for
+ * @sk: socket to wait for
+ * @skb: current skb to pass on for waiting
+ * @delay: sleep timeout in milliseconds (> 0)
+ * This function is called by default when the socket is closed, and
+ * when a non-zero linger time is set on the socket. For consistency
*/
-static int dccp_wait_for_ccid(struct sock *sk, struct sk_buff *skb)
+static int dccp_wait_for_ccid(struct sock *sk, struct sk_buff *skb, int delay)
{
struct dccp_sock *dp = dccp_sk(sk);
DEFINE_WAIT(wait);
- unsigned long delay;
+ unsigned long jiffdelay;
int rc;
- while (1) {
+ do {
+ dccp_pr_debug("delayed send by %d msec\n", delay);
+ jiffdelay = msecs_to_jiffies(delay);
+
prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE);
+ sk->sk_write_pending++;
+ release_sock(sk);
+ schedule_timeout(jiffdelay);
+ lock_sock(sk);
+ sk->sk_write_pending--;
+
if (sk->sk_err)
goto do_error;
if (signal_pending(current))
goto do_interrupted;
rc = ccid_hc_tx_send_packet(dp->dccps_hc_tx_ccid, sk, skb);
- if (rc <= 0)
- break;
- dccp_pr_debug("delayed send by %d msec\n", rc);
- delay = msecs_to_jiffies(rc);
- sk->sk_write_pending++;
- release_sock(sk);
- schedule_timeout(delay);
- lock_sock(sk);
- sk->sk_write_pending--;
- }
+ } while ((delay = rc) > 0);
out:
finish_wait(sk->sk_sleep, &wait);
return rc;
@@ -231,7 +235,7 @@ void dccp_write_xmit(struct sock *sk, int block)
msecs_to_jiffies(err)+jiffies);
break;
} else
- err = dccp_wait_for_ccid(sk, skb);
+ err = dccp_wait_for_ccid(sk, skb, err);
if (err && err != -EINTR)
DCCP_BUG("err=%d after dccp_wait_for_ccid", err);
}