2005-04-17 02:20:36 +04:00
/*
* SUCS NET3 :
*
* Generic stream handling routines . These are generic for most
* protocols . Even IP . Tonight 8 - ) .
* This is used because TCP , LLC ( others too ) layer all have mostly
* identical sendmsg ( ) and recvmsg ( ) code .
* So we ( will ) share it here .
*
* Authors : Arnaldo Carvalho de Melo < acme @ conectiva . com . br >
* ( from old tcp . c code )
2008-10-14 06:01:08 +04:00
* Alan Cox < alan @ lxorguk . ukuu . org . uk > ( Borrowed comments 8 - ) )
2005-04-17 02:20:36 +04:00
*/
# include <linux/module.h>
# include <linux/net.h>
# include <linux/signal.h>
# include <linux/tcp.h>
# include <linux/wait.h>
# include <net/sock.h>
/**
* sk_stream_write_space - stream socket write_space callback .
2005-05-01 19:59:25 +04:00
* @ sk : socket
2005-04-17 02:20:36 +04:00
*
* FIXME : write proper description
*/
void sk_stream_write_space ( struct sock * sk )
{
struct socket * sock = sk - > sk_socket ;
2010-04-29 15:01:49 +04:00
struct socket_wq * wq ;
2005-04-17 02:20:36 +04:00
2013-07-23 07:26:31 +04:00
if ( sk_stream_is_writeable ( sk ) & & sock ) {
2005-04-17 02:20:36 +04:00
clear_bit ( SOCK_NOSPACE , & sock - > flags ) ;
2010-04-29 15:01:49 +04:00
rcu_read_lock ( ) ;
wq = rcu_dereference ( sk - > sk_wq ) ;
if ( wq_has_sleeper ( wq ) )
wake_up_interruptible_poll ( & wq - > wait , POLLOUT |
2009-05-12 19:34:50 +04:00
POLLWRNORM | POLLWRBAND ) ;
2010-04-29 15:01:49 +04:00
if ( wq & & wq - > fasync_list & & ! ( sk - > sk_shutdown & SEND_SHUTDOWN ) )
2007-11-26 15:10:50 +03:00
sock_wake_async ( sock , SOCK_WAKE_SPACE , POLL_OUT ) ;
2010-04-29 15:01:49 +04:00
rcu_read_unlock ( ) ;
2005-04-17 02:20:36 +04:00
}
}
EXPORT_SYMBOL ( sk_stream_write_space ) ;
/**
* sk_stream_wait_connect - Wait for a socket to get into the connected state
2005-05-01 19:59:25 +04:00
* @ sk : sock to wait on
* @ timeo_p : for how long to wait
2005-04-17 02:20:36 +04:00
*
* Must be called with the socket locked .
*/
int sk_stream_wait_connect ( struct sock * sk , long * timeo_p )
{
struct task_struct * tsk = current ;
DEFINE_WAIT ( wait ) ;
2005-11-04 01:56:56 +03:00
int done ;
2005-04-17 02:20:36 +04:00
2005-11-04 01:56:56 +03:00
do {
2005-12-14 10:22:19 +03:00
int err = sock_error ( sk ) ;
if ( err )
return err ;
2005-04-17 02:20:36 +04:00
if ( ( 1 < < sk - > sk_state ) & ~ ( TCPF_SYN_SENT | TCPF_SYN_RECV ) )
return - EPIPE ;
if ( ! * timeo_p )
return - EAGAIN ;
if ( signal_pending ( tsk ) )
return sock_intr_errno ( * timeo_p ) ;
2010-04-20 17:03:51 +04:00
prepare_to_wait ( sk_sleep ( sk ) , & wait , TASK_INTERRUPTIBLE ) ;
2005-04-17 02:20:36 +04:00
sk - > sk_write_pending + + ;
2005-11-04 01:56:56 +03:00
done = sk_wait_event ( sk , timeo_p ,
2005-12-14 10:22:19 +03:00
! sk - > sk_err & &
2007-02-09 17:24:36 +03:00
! ( ( 1 < < sk - > sk_state ) &
2005-11-04 01:56:56 +03:00
~ ( TCPF_ESTABLISHED | TCPF_CLOSE_WAIT ) ) ) ;
2010-04-20 17:03:51 +04:00
finish_wait ( sk_sleep ( sk ) , & wait ) ;
2005-04-17 02:20:36 +04:00
sk - > sk_write_pending - - ;
2005-11-04 01:56:56 +03:00
} while ( ! done ) ;
2005-04-17 02:20:36 +04:00
return 0 ;
}
EXPORT_SYMBOL ( sk_stream_wait_connect ) ;
/**
* sk_stream_closing - Return 1 if we still have things to send in our buffers .
2005-05-01 19:59:25 +04:00
* @ sk : socket to verify
2005-04-17 02:20:36 +04:00
*/
static inline int sk_stream_closing ( struct sock * sk )
{
return ( 1 < < sk - > sk_state ) &
( TCPF_FIN_WAIT1 | TCPF_CLOSING | TCPF_LAST_ACK ) ;
}
void sk_stream_wait_close ( struct sock * sk , long timeout )
{
if ( timeout ) {
DEFINE_WAIT ( wait ) ;
do {
2010-04-20 17:03:51 +04:00
prepare_to_wait ( sk_sleep ( sk ) , & wait ,
2005-04-17 02:20:36 +04:00
TASK_INTERRUPTIBLE ) ;
if ( sk_wait_event ( sk , & timeout , ! sk_stream_closing ( sk ) ) )
break ;
} while ( ! signal_pending ( current ) & & timeout ) ;
2010-04-20 17:03:51 +04:00
finish_wait ( sk_sleep ( sk ) , & wait ) ;
2005-04-17 02:20:36 +04:00
}
}
EXPORT_SYMBOL ( sk_stream_wait_close ) ;
/**
* sk_stream_wait_memory - Wait for more memory for a socket
2005-05-01 19:59:25 +04:00
* @ sk : socket to wait for memory
* @ timeo_p : for how long
2005-04-17 02:20:36 +04:00
*/
int sk_stream_wait_memory ( struct sock * sk , long * timeo_p )
{
int err = 0 ;
long vm_wait = 0 ;
long current_timeo = * timeo_p ;
DEFINE_WAIT ( wait ) ;
if ( sk_stream_memory_free ( sk ) )
2014-01-11 16:15:59 +04:00
current_timeo = vm_wait = ( prandom_u32 ( ) % ( HZ / 5 ) ) + 2 ;
2005-04-17 02:20:36 +04:00
while ( 1 ) {
set_bit ( SOCK_ASYNC_NOSPACE , & sk - > sk_socket - > flags ) ;
2010-04-20 17:03:51 +04:00
prepare_to_wait ( sk_sleep ( sk ) , & wait , TASK_INTERRUPTIBLE ) ;
2005-04-17 02:20:36 +04:00
if ( sk - > sk_err | | ( sk - > sk_shutdown & SEND_SHUTDOWN ) )
goto do_error ;
if ( ! * timeo_p )
goto do_nonblock ;
if ( signal_pending ( current ) )
goto do_interrupted ;
clear_bit ( SOCK_ASYNC_NOSPACE , & sk - > sk_socket - > flags ) ;
if ( sk_stream_memory_free ( sk ) & & ! vm_wait )
break ;
set_bit ( SOCK_NOSPACE , & sk - > sk_socket - > flags ) ;
sk - > sk_write_pending + + ;
2010-10-03 03:45:06 +04:00
sk_wait_event ( sk , & current_timeo , sk - > sk_err | |
( sk - > sk_shutdown & SEND_SHUTDOWN ) | |
( sk_stream_memory_free ( sk ) & &
! vm_wait ) ) ;
2005-04-17 02:20:36 +04:00
sk - > sk_write_pending - - ;
if ( vm_wait ) {
vm_wait - = current_timeo ;
current_timeo = * timeo_p ;
if ( current_timeo ! = MAX_SCHEDULE_TIMEOUT & &
( current_timeo - = vm_wait ) < 0 )
current_timeo = 0 ;
vm_wait = 0 ;
}
* timeo_p = current_timeo ;
}
out :
2010-04-20 17:03:51 +04:00
finish_wait ( sk_sleep ( sk ) , & wait ) ;
2005-04-17 02:20:36 +04:00
return err ;
do_error :
err = - EPIPE ;
goto out ;
do_nonblock :
err = - EAGAIN ;
goto out ;
do_interrupted :
err = sock_intr_errno ( * timeo_p ) ;
goto out ;
}
EXPORT_SYMBOL ( sk_stream_wait_memory ) ;
int sk_stream_error ( struct sock * sk , int flags , int err )
{
if ( err = = - EPIPE )
err = sock_error ( sk ) ? : - EPIPE ;
if ( err = = - EPIPE & & ! ( flags & MSG_NOSIGNAL ) )
send_sig ( SIGPIPE , current , 0 ) ;
return err ;
}
EXPORT_SYMBOL ( sk_stream_error ) ;
void sk_stream_kill_queues ( struct sock * sk )
{
/* First the read buffer. */
__skb_queue_purge ( & sk - > sk_receive_queue ) ;
/* Next, the error queue. */
__skb_queue_purge ( & sk - > sk_error_queue ) ;
/* Next, the write queue. */
2008-07-26 08:43:18 +04:00
WARN_ON ( ! skb_queue_empty ( & sk - > sk_write_queue ) ) ;
2005-04-17 02:20:36 +04:00
/* Account for returned memory. */
2007-12-31 11:11:19 +03:00
sk_mem_reclaim ( sk ) ;
2005-04-17 02:20:36 +04:00
2008-07-26 08:43:18 +04:00
WARN_ON ( sk - > sk_wmem_queued ) ;
WARN_ON ( sk - > sk_forward_alloc ) ;
2005-04-17 02:20:36 +04:00
/* It is _impossible_ for the backlog to contain anything
* when we get here . All user references to this socket
* have gone away , only the net layer knows can touch it .
*/
}
EXPORT_SYMBOL ( sk_stream_kill_queues ) ;