diff options
Diffstat (limited to 'net/sctp/socket.c')
| -rw-r--r-- | net/sctp/socket.c | 31 | 
1 files changed, 19 insertions, 12 deletions
| diff --git a/net/sctp/socket.c b/net/sctp/socket.c index 36ee34f483d7..1e5739858c20 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -72,8 +72,9 @@  /* Forward declarations for internal helper functions. */  static bool sctp_writeable(const struct sock *sk);  static void sctp_wfree(struct sk_buff *skb); -static int sctp_wait_for_sndbuf(struct sctp_association *asoc, long *timeo_p, -				size_t msg_len); +static int sctp_wait_for_sndbuf(struct sctp_association *asoc, +				struct sctp_transport *transport, +				long *timeo_p, size_t msg_len);  static int sctp_wait_for_packet(struct sock *sk, int *err, long *timeo_p);  static int sctp_wait_for_connect(struct sctp_association *, long *timeo_p);  static int sctp_wait_for_accept(struct sock *sk, long timeo); @@ -1828,7 +1829,7 @@ static int sctp_sendmsg_to_asoc(struct sctp_association *asoc,  	if (sctp_wspace(asoc) <= 0 || !sk_wmem_schedule(sk, msg_len)) {  		timeo = sock_sndtimeo(sk, msg->msg_flags & MSG_DONTWAIT); -		err = sctp_wait_for_sndbuf(asoc, &timeo, msg_len); +		err = sctp_wait_for_sndbuf(asoc, transport, &timeo, msg_len);  		if (err)  			goto err;  		if (unlikely(sinfo->sinfo_stream >= asoc->stream.outcnt)) { @@ -5626,7 +5627,8 @@ static int sctp_getsockopt_autoclose(struct sock *sk, int len, char __user *optv  }  /* Helper routine to branch off an association to a new socket.  */ -int sctp_do_peeloff(struct sock *sk, sctp_assoc_t id, struct socket **sockp) +static int sctp_do_peeloff(struct sock *sk, sctp_assoc_t id, +		struct socket **sockp)  {  	struct sctp_association *asoc = sctp_id2assoc(sk, id);  	struct sctp_sock *sp = sctp_sk(sk); @@ -5674,7 +5676,6 @@ int sctp_do_peeloff(struct sock *sk, sctp_assoc_t id, struct socket **sockp)  	return err;  } -EXPORT_SYMBOL(sctp_do_peeloff);  static int sctp_getsockopt_peeloff_common(struct sock *sk, sctp_peeloff_arg_t *peeloff,  					  struct file **newfile, unsigned flags) @@ -8320,7 +8321,7 @@ static int sctp_hash(struct sock *sk)  static void sctp_unhash(struct sock *sk)  { -	/* STUB */ +	sock_rps_delete_flow(sk);  }  /* Check if port is acceptable.  Possibly find first available port. @@ -9099,7 +9100,8 @@ static void __sctp_write_space(struct sctp_association *asoc)  		wq = rcu_dereference(sk->sk_wq);  		if (wq) {  			if (waitqueue_active(&wq->wait)) -				wake_up_interruptible(&wq->wait); +				wake_up_interruptible_poll(&wq->wait, EPOLLOUT | +						EPOLLWRNORM | EPOLLWRBAND);  			/* Note that we try to include the Async I/O support  			 * here by modeling from the current TCP/UDP code. @@ -9214,8 +9216,9 @@ void sctp_sock_rfree(struct sk_buff *skb)  /* Helper function to wait for space in the sndbuf.  */ -static int sctp_wait_for_sndbuf(struct sctp_association *asoc, long *timeo_p, -				size_t msg_len) +static int sctp_wait_for_sndbuf(struct sctp_association *asoc, +				struct sctp_transport *transport, +				long *timeo_p, size_t msg_len)  {  	struct sock *sk = asoc->base.sk;  	long current_timeo = *timeo_p; @@ -9225,7 +9228,9 @@ static int sctp_wait_for_sndbuf(struct sctp_association *asoc, long *timeo_p,  	pr_debug("%s: asoc:%p, timeo:%ld, msg_len:%zu\n", __func__, asoc,  		 *timeo_p, msg_len); -	/* Increment the association's refcnt.  */ +	/* Increment the transport and association's refcnt. */ +	if (transport) +		sctp_transport_hold(transport);  	sctp_association_hold(asoc);  	/* Wait on the association specific sndbuf space. */ @@ -9234,7 +9239,7 @@ static int sctp_wait_for_sndbuf(struct sctp_association *asoc, long *timeo_p,  					  TASK_INTERRUPTIBLE);  		if (asoc->base.dead)  			goto do_dead; -		if (!*timeo_p) +		if ((!*timeo_p) || (transport && transport->dead))  			goto do_nonblock;  		if (sk->sk_err || asoc->state >= SCTP_STATE_SHUTDOWN_PENDING)  			goto do_error; @@ -9259,7 +9264,9 @@ static int sctp_wait_for_sndbuf(struct sctp_association *asoc, long *timeo_p,  out:  	finish_wait(&asoc->wait, &wait); -	/* Release the association's refcnt.  */ +	/* Release the transport and association's refcnt. */ +	if (transport) +		sctp_transport_put(transport);  	sctp_association_put(asoc);  	return err; | 
