2005-04-17 02:20:36 +04:00
/*
* linux / fs / pipe . c
*
* Copyright ( C ) 1991 , 1992 , 1999 Linus Torvalds
*/
# include <linux/mm.h>
# include <linux/file.h>
# include <linux/poll.h>
# include <linux/slab.h>
# include <linux/module.h>
# include <linux/init.h>
# include <linux/fs.h>
# include <linux/mount.h>
# include <linux/pipe_fs_i.h>
# include <linux/uio.h>
# include <linux/highmem.h>
2006-03-30 17:15:30 +04:00
# include <linux/pagemap.h>
2005-04-17 02:20:36 +04:00
# include <asm/uaccess.h>
# include <asm/ioctls.h>
/*
* We use a start + len construction , which provides full use of the
* allocated memory .
* - - Florian Coosmann ( FGC )
*
* Reads with count = 0 should always return 0.
* - - Julian Bradfield 1999 - 06 - 07.
*
* FIFOs and Pipes now generate SIGIO for both readers and writers .
* - - Jeremy Elson < jelson @ circlemud . org > 2001 - 08 - 16
*
* pipe_read & write cleanup
* - - Manfred Spraul < manfred @ colorfullife . com > 2002 - 05 - 09
*/
/* Drop the inode semaphore and wait for a pipe event, atomically */
2006-04-10 17:18:35 +04:00
void pipe_wait ( struct pipe_inode_info * pipe )
2005-04-17 02:20:36 +04:00
{
DEFINE_WAIT ( wait ) ;
2005-09-10 11:26:12 +04:00
/*
* Pipes are system - local resources , so sleeping on them
* is considered a noninteractive wait :
*/
2006-04-11 15:57:45 +04:00
prepare_to_wait ( & pipe - > wait , & wait ,
TASK_INTERRUPTIBLE | TASK_NONINTERACTIVE ) ;
2006-04-10 17:18:35 +04:00
if ( pipe - > inode )
mutex_unlock ( & pipe - > inode - > i_mutex ) ;
2005-04-17 02:20:36 +04:00
schedule ( ) ;
2006-04-10 17:18:35 +04:00
finish_wait ( & pipe - > wait , & wait ) ;
if ( pipe - > inode )
mutex_lock ( & pipe - > inode - > i_mutex ) ;
2005-04-17 02:20:36 +04:00
}
2006-01-15 00:20:43 +03:00
static int
2006-05-01 22:02:05 +04:00
pipe_iov_copy_from_user ( void * to , struct iovec * iov , unsigned long len ,
int atomic )
2005-04-17 02:20:36 +04:00
{
unsigned long copy ;
while ( len > 0 ) {
while ( ! iov - > iov_len )
iov + + ;
copy = min_t ( unsigned long , len , iov - > iov_len ) ;
2006-05-01 22:02:05 +04:00
if ( atomic ) {
if ( __copy_from_user_inatomic ( to , iov - > iov_base , copy ) )
return - EFAULT ;
} else {
if ( copy_from_user ( to , iov - > iov_base , copy ) )
return - EFAULT ;
}
2005-04-17 02:20:36 +04:00
to + = copy ;
len - = copy ;
iov - > iov_base + = copy ;
iov - > iov_len - = copy ;
}
return 0 ;
}
2006-01-15 00:20:43 +03:00
static int
2006-05-01 22:02:05 +04:00
pipe_iov_copy_to_user ( struct iovec * iov , const void * from , unsigned long len ,
int atomic )
2005-04-17 02:20:36 +04:00
{
unsigned long copy ;
while ( len > 0 ) {
while ( ! iov - > iov_len )
iov + + ;
copy = min_t ( unsigned long , len , iov - > iov_len ) ;
2006-05-01 22:02:05 +04:00
if ( atomic ) {
if ( __copy_to_user_inatomic ( iov - > iov_base , from , copy ) )
return - EFAULT ;
} else {
if ( copy_to_user ( iov - > iov_base , from , copy ) )
return - EFAULT ;
}
2005-04-17 02:20:36 +04:00
from + = copy ;
len - = copy ;
iov - > iov_base + = copy ;
iov - > iov_len - = copy ;
}
return 0 ;
}
2006-05-01 22:02:05 +04:00
/*
* Attempt to pre - fault in the user memory , so we can use atomic copies .
* Returns the number of bytes not faulted in .
*/
static int iov_fault_in_pages_write ( struct iovec * iov , unsigned long len )
{
while ( ! iov - > iov_len )
iov + + ;
while ( len > 0 ) {
unsigned long this_len ;
this_len = min_t ( unsigned long , len , iov - > iov_len ) ;
if ( fault_in_pages_writeable ( iov - > iov_base , this_len ) )
break ;
len - = this_len ;
iov + + ;
}
return len ;
}
/*
* Pre - fault in the user memory , so we can use atomic copies .
*/
static void iov_fault_in_pages_read ( struct iovec * iov , unsigned long len )
{
while ( ! iov - > iov_len )
iov + + ;
while ( len > 0 ) {
unsigned long this_len ;
this_len = min_t ( unsigned long , len , iov - > iov_len ) ;
fault_in_pages_readable ( iov - > iov_base , this_len ) ;
len - = this_len ;
iov + + ;
}
}
2006-04-11 15:57:45 +04:00
static void anon_pipe_buf_release ( struct pipe_inode_info * pipe ,
struct pipe_buffer * buf )
2005-04-17 02:20:36 +04:00
{
struct page * page = buf - > page ;
2006-03-30 17:15:30 +04:00
/*
* If nobody else uses this page , and we don ' t already have a
* temporary page , let ' s keep track of it as a one - deep
2006-04-11 15:57:45 +04:00
* allocation cache . ( Otherwise just release our reference to it )
2006-03-30 17:15:30 +04:00
*/
2006-04-11 15:57:45 +04:00
if ( page_count ( page ) = = 1 & & ! pipe - > tmp_page )
2006-04-11 15:53:33 +04:00
pipe - > tmp_page = page ;
2006-04-11 15:57:45 +04:00
else
page_cache_release ( page ) ;
2005-04-17 02:20:36 +04:00
}
2006-05-01 21:59:03 +04:00
void * generic_pipe_buf_map ( struct pipe_inode_info * pipe ,
2006-05-01 22:02:05 +04:00
struct pipe_buffer * buf , int atomic )
2005-04-17 02:20:36 +04:00
{
2006-05-01 22:02:05 +04:00
if ( atomic ) {
buf - > flags | = PIPE_BUF_FLAG_ATOMIC ;
return kmap_atomic ( buf - > page , KM_USER0 ) ;
}
2005-04-17 02:20:36 +04:00
return kmap ( buf - > page ) ;
}
2006-05-01 21:59:03 +04:00
void generic_pipe_buf_unmap ( struct pipe_inode_info * pipe ,
2006-05-01 22:02:05 +04:00
struct pipe_buffer * buf , void * map_data )
2005-04-17 02:20:36 +04:00
{
2006-05-01 22:02:05 +04:00
if ( buf - > flags & PIPE_BUF_FLAG_ATOMIC ) {
buf - > flags & = ~ PIPE_BUF_FLAG_ATOMIC ;
kunmap_atomic ( map_data , KM_USER0 ) ;
} else
kunmap ( buf - > page ) ;
2005-04-17 02:20:36 +04:00
}
2006-05-02 17:29:57 +04:00
int generic_pipe_buf_steal ( struct pipe_inode_info * pipe ,
struct pipe_buffer * buf )
2006-03-30 17:16:46 +04:00
{
2006-04-30 18:36:32 +04:00
struct page * page = buf - > page ;
if ( page_count ( page ) = = 1 ) {
lock_page ( page ) ;
return 0 ;
}
return 1 ;
2006-03-30 17:16:46 +04:00
}
2006-05-01 21:59:03 +04:00
void generic_pipe_buf_get ( struct pipe_inode_info * info , struct pipe_buffer * buf )
2006-04-11 17:51:17 +04:00
{
page_cache_get ( buf - > page ) ;
}
2006-05-01 21:59:03 +04:00
int generic_pipe_buf_pin ( struct pipe_inode_info * info , struct pipe_buffer * buf )
{
return 0 ;
}
2005-04-17 02:20:36 +04:00
static struct pipe_buf_operations anon_pipe_buf_ops = {
. can_merge = 1 ,
2006-05-01 21:59:03 +04:00
. map = generic_pipe_buf_map ,
. unmap = generic_pipe_buf_unmap ,
. pin = generic_pipe_buf_pin ,
2005-04-17 02:20:36 +04:00
. release = anon_pipe_buf_release ,
2006-05-02 17:29:57 +04:00
. steal = generic_pipe_buf_steal ,
2006-05-01 21:59:03 +04:00
. get = generic_pipe_buf_get ,
2005-04-17 02:20:36 +04:00
} ;
static ssize_t
pipe_readv ( struct file * filp , const struct iovec * _iov ,
unsigned long nr_segs , loff_t * ppos )
{
struct inode * inode = filp - > f_dentry - > d_inode ;
2006-04-11 15:53:33 +04:00
struct pipe_inode_info * pipe ;
2005-04-17 02:20:36 +04:00
int do_wakeup ;
ssize_t ret ;
struct iovec * iov = ( struct iovec * ) _iov ;
size_t total_len ;
total_len = iov_length ( iov , nr_segs ) ;
/* Null read succeeds. */
if ( unlikely ( total_len = = 0 ) )
return 0 ;
do_wakeup = 0 ;
ret = 0 ;
2006-04-11 15:53:10 +04:00
mutex_lock ( & inode - > i_mutex ) ;
2006-04-11 15:53:33 +04:00
pipe = inode - > i_pipe ;
2005-04-17 02:20:36 +04:00
for ( ; ; ) {
2006-04-11 15:53:33 +04:00
int bufs = pipe - > nrbufs ;
2005-04-17 02:20:36 +04:00
if ( bufs ) {
2006-04-11 15:53:33 +04:00
int curbuf = pipe - > curbuf ;
struct pipe_buffer * buf = pipe - > bufs + curbuf ;
2005-04-17 02:20:36 +04:00
struct pipe_buf_operations * ops = buf - > ops ;
void * addr ;
size_t chars = buf - > len ;
2006-05-01 22:02:05 +04:00
int error , atomic ;
2005-04-17 02:20:36 +04:00
if ( chars > total_len )
chars = total_len ;
2006-05-01 21:59:03 +04:00
error = ops - > pin ( pipe , buf ) ;
if ( error ) {
2006-03-30 17:15:30 +04:00
if ( ! ret )
2006-05-01 21:59:03 +04:00
error = ret ;
2006-03-30 17:15:30 +04:00
break ;
}
2006-05-01 21:59:03 +04:00
2006-05-01 22:02:05 +04:00
atomic = ! iov_fault_in_pages_write ( iov , chars ) ;
redo :
addr = ops - > map ( pipe , buf , atomic ) ;
error = pipe_iov_copy_to_user ( iov , addr + buf - > offset , chars , atomic ) ;
ops - > unmap ( pipe , buf , addr ) ;
2005-04-17 02:20:36 +04:00
if ( unlikely ( error ) ) {
2006-05-01 22:02:05 +04:00
/*
* Just retry with the slow path if we failed .
*/
if ( atomic ) {
atomic = 0 ;
goto redo ;
}
2006-04-11 15:57:45 +04:00
if ( ! ret )
2006-05-01 22:02:05 +04:00
ret = error ;
2005-04-17 02:20:36 +04:00
break ;
}
ret + = chars ;
buf - > offset + = chars ;
buf - > len - = chars ;
if ( ! buf - > len ) {
buf - > ops = NULL ;
2006-04-11 15:53:33 +04:00
ops - > release ( pipe , buf ) ;
2005-04-17 02:20:36 +04:00
curbuf = ( curbuf + 1 ) & ( PIPE_BUFFERS - 1 ) ;
2006-04-11 15:53:33 +04:00
pipe - > curbuf = curbuf ;
pipe - > nrbufs = - - bufs ;
2005-04-17 02:20:36 +04:00
do_wakeup = 1 ;
}
total_len - = chars ;
if ( ! total_len )
break ; /* common path: read succeeded */
}
if ( bufs ) /* More to do? */
continue ;
2006-04-11 15:53:33 +04:00
if ( ! pipe - > writers )
2005-04-17 02:20:36 +04:00
break ;
2006-04-11 15:53:33 +04:00
if ( ! pipe - > waiting_writers ) {
2005-04-17 02:20:36 +04:00
/* syscall merging: Usually we must not sleep
* if O_NONBLOCK is set , or if we got some data .
* But if a writer sleeps in kernel space , then
* we can wait for that data without violating POSIX .
*/
if ( ret )
break ;
if ( filp - > f_flags & O_NONBLOCK ) {
ret = - EAGAIN ;
break ;
}
}
if ( signal_pending ( current ) ) {
2006-04-11 15:57:45 +04:00
if ( ! ret )
ret = - ERESTARTSYS ;
2005-04-17 02:20:36 +04:00
break ;
}
if ( do_wakeup ) {
2006-04-11 15:53:33 +04:00
wake_up_interruptible_sync ( & pipe - > wait ) ;
kill_fasync ( & pipe - > fasync_writers , SIGIO , POLL_OUT ) ;
2005-04-17 02:20:36 +04:00
}
2006-04-11 15:53:33 +04:00
pipe_wait ( pipe ) ;
2005-04-17 02:20:36 +04:00
}
2006-04-11 15:53:10 +04:00
mutex_unlock ( & inode - > i_mutex ) ;
2006-04-11 15:57:45 +04:00
/* Signal writers asynchronously that there is more room. */
2005-04-17 02:20:36 +04:00
if ( do_wakeup ) {
2006-04-11 15:53:33 +04:00
wake_up_interruptible ( & pipe - > wait ) ;
kill_fasync ( & pipe - > fasync_writers , SIGIO , POLL_OUT ) ;
2005-04-17 02:20:36 +04:00
}
if ( ret > 0 )
file_accessed ( filp ) ;
return ret ;
}
static ssize_t
pipe_read ( struct file * filp , char __user * buf , size_t count , loff_t * ppos )
{
struct iovec iov = { . iov_base = buf , . iov_len = count } ;
2006-04-11 15:57:45 +04:00
2005-04-17 02:20:36 +04:00
return pipe_readv ( filp , & iov , 1 , ppos ) ;
}
static ssize_t
pipe_writev ( struct file * filp , const struct iovec * _iov ,
unsigned long nr_segs , loff_t * ppos )
{
struct inode * inode = filp - > f_dentry - > d_inode ;
2006-04-11 15:53:33 +04:00
struct pipe_inode_info * pipe ;
2005-04-17 02:20:36 +04:00
ssize_t ret ;
int do_wakeup ;
struct iovec * iov = ( struct iovec * ) _iov ;
size_t total_len ;
ssize_t chars ;
total_len = iov_length ( iov , nr_segs ) ;
/* Null write succeeds. */
if ( unlikely ( total_len = = 0 ) )
return 0 ;
do_wakeup = 0 ;
ret = 0 ;
2006-04-11 15:53:10 +04:00
mutex_lock ( & inode - > i_mutex ) ;
2006-04-11 15:53:33 +04:00
pipe = inode - > i_pipe ;
2005-04-17 02:20:36 +04:00
2006-04-11 15:53:33 +04:00
if ( ! pipe - > readers ) {
2005-04-17 02:20:36 +04:00
send_sig ( SIGPIPE , current , 0 ) ;
ret = - EPIPE ;
goto out ;
}
/* We try to merge small writes */
chars = total_len & ( PAGE_SIZE - 1 ) ; /* size of the last buffer */
2006-04-11 15:53:33 +04:00
if ( pipe - > nrbufs & & chars ! = 0 ) {
2006-04-11 15:57:45 +04:00
int lastbuf = ( pipe - > curbuf + pipe - > nrbufs - 1 ) &
( PIPE_BUFFERS - 1 ) ;
2006-04-11 15:53:33 +04:00
struct pipe_buffer * buf = pipe - > bufs + lastbuf ;
2005-04-17 02:20:36 +04:00
struct pipe_buf_operations * ops = buf - > ops ;
int offset = buf - > offset + buf - > len ;
2006-04-11 15:57:45 +04:00
2005-04-17 02:20:36 +04:00
if ( ops - > can_merge & & offset + chars < = PAGE_SIZE ) {
2006-05-01 22:02:05 +04:00
int error , atomic = 1 ;
2006-03-30 17:15:30 +04:00
void * addr ;
2006-05-01 21:59:03 +04:00
error = ops - > pin ( pipe , buf ) ;
if ( error )
2006-03-30 17:15:30 +04:00
goto out ;
2006-05-01 21:59:03 +04:00
2006-05-01 22:02:05 +04:00
iov_fault_in_pages_read ( iov , chars ) ;
redo1 :
addr = ops - > map ( pipe , buf , atomic ) ;
2006-03-30 17:15:30 +04:00
error = pipe_iov_copy_from_user ( offset + addr , iov ,
2006-05-01 22:02:05 +04:00
chars , atomic ) ;
ops - > unmap ( pipe , buf , addr ) ;
2005-04-17 02:20:36 +04:00
ret = error ;
do_wakeup = 1 ;
2006-05-01 22:02:05 +04:00
if ( error ) {
if ( atomic ) {
atomic = 0 ;
goto redo1 ;
}
2005-04-17 02:20:36 +04:00
goto out ;
2006-05-01 22:02:05 +04:00
}
2005-04-17 02:20:36 +04:00
buf - > len + = chars ;
total_len - = chars ;
ret = chars ;
if ( ! total_len )
goto out ;
}
}
for ( ; ; ) {
int bufs ;
2006-04-11 15:57:45 +04:00
2006-04-11 15:53:33 +04:00
if ( ! pipe - > readers ) {
2005-04-17 02:20:36 +04:00
send_sig ( SIGPIPE , current , 0 ) ;
2006-04-11 15:57:45 +04:00
if ( ! ret )
ret = - EPIPE ;
2005-04-17 02:20:36 +04:00
break ;
}
2006-04-11 15:53:33 +04:00
bufs = pipe - > nrbufs ;
2005-04-17 02:20:36 +04:00
if ( bufs < PIPE_BUFFERS ) {
2006-04-11 15:53:33 +04:00
int newbuf = ( pipe - > curbuf + bufs ) & ( PIPE_BUFFERS - 1 ) ;
struct pipe_buffer * buf = pipe - > bufs + newbuf ;
struct page * page = pipe - > tmp_page ;
2006-05-01 22:02:05 +04:00
char * src ;
int error , atomic = 1 ;
2005-04-17 02:20:36 +04:00
if ( ! page ) {
page = alloc_page ( GFP_HIGHUSER ) ;
if ( unlikely ( ! page ) ) {
ret = ret ? : - ENOMEM ;
break ;
}
2006-04-11 15:53:33 +04:00
pipe - > tmp_page = page ;
2005-04-17 02:20:36 +04:00
}
2006-04-11 15:57:45 +04:00
/* Always wake up, even if the copy fails. Otherwise
2005-04-17 02:20:36 +04:00
* we lock up ( O_NONBLOCK - ) readers that sleep due to
* syscall merging .
* FIXME ! Is this really true ?
*/
do_wakeup = 1 ;
chars = PAGE_SIZE ;
if ( chars > total_len )
chars = total_len ;
2006-05-01 22:02:05 +04:00
iov_fault_in_pages_read ( iov , chars ) ;
redo2 :
if ( atomic )
src = kmap_atomic ( page , KM_USER0 ) ;
else
src = kmap ( page ) ;
error = pipe_iov_copy_from_user ( src , iov , chars ,
atomic ) ;
if ( atomic )
kunmap_atomic ( src , KM_USER0 ) ;
else
kunmap ( page ) ;
2005-04-17 02:20:36 +04:00
if ( unlikely ( error ) ) {
2006-05-01 22:02:05 +04:00
if ( atomic ) {
atomic = 0 ;
goto redo2 ;
}
2006-04-11 15:57:45 +04:00
if ( ! ret )
2006-05-01 22:02:05 +04:00
ret = error ;
2005-04-17 02:20:36 +04:00
break ;
}
ret + = chars ;
/* Insert it into the buffer array */
buf - > page = page ;
buf - > ops = & anon_pipe_buf_ops ;
buf - > offset = 0 ;
buf - > len = chars ;
2006-04-11 15:53:33 +04:00
pipe - > nrbufs = + + bufs ;
pipe - > tmp_page = NULL ;
2005-04-17 02:20:36 +04:00
total_len - = chars ;
if ( ! total_len )
break ;
}
if ( bufs < PIPE_BUFFERS )
continue ;
if ( filp - > f_flags & O_NONBLOCK ) {
2006-04-11 15:57:45 +04:00
if ( ! ret )
ret = - EAGAIN ;
2005-04-17 02:20:36 +04:00
break ;
}
if ( signal_pending ( current ) ) {
2006-04-11 15:57:45 +04:00
if ( ! ret )
ret = - ERESTARTSYS ;
2005-04-17 02:20:36 +04:00
break ;
}
if ( do_wakeup ) {
2006-04-11 15:53:33 +04:00
wake_up_interruptible_sync ( & pipe - > wait ) ;
kill_fasync ( & pipe - > fasync_readers , SIGIO , POLL_IN ) ;
2005-04-17 02:20:36 +04:00
do_wakeup = 0 ;
}
2006-04-11 15:53:33 +04:00
pipe - > waiting_writers + + ;
pipe_wait ( pipe ) ;
pipe - > waiting_writers - - ;
2005-04-17 02:20:36 +04:00
}
out :
2006-04-11 15:53:10 +04:00
mutex_unlock ( & inode - > i_mutex ) ;
2005-04-17 02:20:36 +04:00
if ( do_wakeup ) {
2006-04-11 15:53:33 +04:00
wake_up_interruptible ( & pipe - > wait ) ;
kill_fasync ( & pipe - > fasync_readers , SIGIO , POLL_IN ) ;
2005-04-17 02:20:36 +04:00
}
if ( ret > 0 )
2006-01-10 07:52:01 +03:00
file_update_time ( filp ) ;
2005-04-17 02:20:36 +04:00
return ret ;
}
static ssize_t
pipe_write ( struct file * filp , const char __user * buf ,
size_t count , loff_t * ppos )
{
struct iovec iov = { . iov_base = ( void __user * ) buf , . iov_len = count } ;
2006-04-11 15:57:45 +04:00
2005-04-17 02:20:36 +04:00
return pipe_writev ( filp , & iov , 1 , ppos ) ;
}
static ssize_t
bad_pipe_r ( struct file * filp , char __user * buf , size_t count , loff_t * ppos )
{
return - EBADF ;
}
static ssize_t
2006-04-11 15:57:45 +04:00
bad_pipe_w ( struct file * filp , const char __user * buf , size_t count ,
loff_t * ppos )
2005-04-17 02:20:36 +04:00
{
return - EBADF ;
}
static int
pipe_ioctl ( struct inode * pino , struct file * filp ,
unsigned int cmd , unsigned long arg )
{
struct inode * inode = filp - > f_dentry - > d_inode ;
2006-04-11 15:53:33 +04:00
struct pipe_inode_info * pipe ;
2005-04-17 02:20:36 +04:00
int count , buf , nrbufs ;
switch ( cmd ) {
case FIONREAD :
2006-04-11 15:53:10 +04:00
mutex_lock ( & inode - > i_mutex ) ;
2006-04-11 15:53:33 +04:00
pipe = inode - > i_pipe ;
2005-04-17 02:20:36 +04:00
count = 0 ;
2006-04-11 15:53:33 +04:00
buf = pipe - > curbuf ;
nrbufs = pipe - > nrbufs ;
2005-04-17 02:20:36 +04:00
while ( - - nrbufs > = 0 ) {
2006-04-11 15:53:33 +04:00
count + = pipe - > bufs [ buf ] . len ;
2005-04-17 02:20:36 +04:00
buf = ( buf + 1 ) & ( PIPE_BUFFERS - 1 ) ;
}
2006-04-11 15:53:10 +04:00
mutex_unlock ( & inode - > i_mutex ) ;
2006-04-11 15:53:33 +04:00
2005-04-17 02:20:36 +04:00
return put_user ( count , ( int __user * ) arg ) ;
default :
return - EINVAL ;
}
}
/* No kernel lock held - fine */
static unsigned int
pipe_poll ( struct file * filp , poll_table * wait )
{
unsigned int mask ;
struct inode * inode = filp - > f_dentry - > d_inode ;
2006-04-11 15:53:33 +04:00
struct pipe_inode_info * pipe = inode - > i_pipe ;
2005-04-17 02:20:36 +04:00
int nrbufs ;
2006-04-11 15:53:33 +04:00
poll_wait ( filp , & pipe - > wait , wait ) ;
2005-04-17 02:20:36 +04:00
/* Reading only -- no need for acquiring the semaphore. */
2006-04-11 15:53:33 +04:00
nrbufs = pipe - > nrbufs ;
2005-04-17 02:20:36 +04:00
mask = 0 ;
if ( filp - > f_mode & FMODE_READ ) {
mask = ( nrbufs > 0 ) ? POLLIN | POLLRDNORM : 0 ;
2006-04-11 15:53:33 +04:00
if ( ! pipe - > writers & & filp - > f_version ! = pipe - > w_counter )
2005-04-17 02:20:36 +04:00
mask | = POLLHUP ;
}
if ( filp - > f_mode & FMODE_WRITE ) {
mask | = ( nrbufs < PIPE_BUFFERS ) ? POLLOUT | POLLWRNORM : 0 ;
2005-09-07 02:17:48 +04:00
/*
* Most Unices do not set POLLERR for FIFOs but on Linux they
* behave exactly like pipes for poll ( ) .
*/
2006-04-11 15:53:33 +04:00
if ( ! pipe - > readers )
2005-04-17 02:20:36 +04:00
mask | = POLLERR ;
}
return mask ;
}
static int
pipe_release ( struct inode * inode , int decr , int decw )
{
2006-04-11 15:53:33 +04:00
struct pipe_inode_info * pipe ;
2006-04-11 15:53:10 +04:00
mutex_lock ( & inode - > i_mutex ) ;
2006-04-11 15:53:33 +04:00
pipe = inode - > i_pipe ;
pipe - > readers - = decr ;
pipe - > writers - = decw ;
2006-04-11 15:57:45 +04:00
2006-04-11 15:53:33 +04:00
if ( ! pipe - > readers & & ! pipe - > writers ) {
2005-04-17 02:20:36 +04:00
free_pipe_info ( inode ) ;
} else {
2006-04-11 15:53:33 +04:00
wake_up_interruptible ( & pipe - > wait ) ;
kill_fasync ( & pipe - > fasync_readers , SIGIO , POLL_IN ) ;
kill_fasync ( & pipe - > fasync_writers , SIGIO , POLL_OUT ) ;
2005-04-17 02:20:36 +04:00
}
2006-04-11 15:53:10 +04:00
mutex_unlock ( & inode - > i_mutex ) ;
2005-04-17 02:20:36 +04:00
return 0 ;
}
static int
pipe_read_fasync ( int fd , struct file * filp , int on )
{
struct inode * inode = filp - > f_dentry - > d_inode ;
int retval ;
2006-04-11 15:53:10 +04:00
mutex_lock ( & inode - > i_mutex ) ;
retval = fasync_helper ( fd , filp , on , & inode - > i_pipe - > fasync_readers ) ;
mutex_unlock ( & inode - > i_mutex ) ;
2005-04-17 02:20:36 +04:00
if ( retval < 0 )
return retval ;
return 0 ;
}
static int
pipe_write_fasync ( int fd , struct file * filp , int on )
{
struct inode * inode = filp - > f_dentry - > d_inode ;
int retval ;
2006-04-11 15:53:10 +04:00
mutex_lock ( & inode - > i_mutex ) ;
retval = fasync_helper ( fd , filp , on , & inode - > i_pipe - > fasync_writers ) ;
mutex_unlock ( & inode - > i_mutex ) ;
2005-04-17 02:20:36 +04:00
if ( retval < 0 )
return retval ;
return 0 ;
}
static int
pipe_rdwr_fasync ( int fd , struct file * filp , int on )
{
struct inode * inode = filp - > f_dentry - > d_inode ;
2006-04-11 15:57:45 +04:00
struct pipe_inode_info * pipe = inode - > i_pipe ;
2005-04-17 02:20:36 +04:00
int retval ;
2006-04-11 15:53:10 +04:00
mutex_lock ( & inode - > i_mutex ) ;
2005-04-17 02:20:36 +04:00
2006-04-11 15:57:45 +04:00
retval = fasync_helper ( fd , filp , on , & pipe - > fasync_readers ) ;
2005-04-17 02:20:36 +04:00
if ( retval > = 0 )
2006-04-11 15:57:45 +04:00
retval = fasync_helper ( fd , filp , on , & pipe - > fasync_writers ) ;
2005-04-17 02:20:36 +04:00
2006-04-11 15:53:10 +04:00
mutex_unlock ( & inode - > i_mutex ) ;
2005-04-17 02:20:36 +04:00
if ( retval < 0 )
return retval ;
return 0 ;
}
static int
pipe_read_release ( struct inode * inode , struct file * filp )
{
pipe_read_fasync ( - 1 , filp , 0 ) ;
return pipe_release ( inode , 1 , 0 ) ;
}
static int
pipe_write_release ( struct inode * inode , struct file * filp )
{
pipe_write_fasync ( - 1 , filp , 0 ) ;
return pipe_release ( inode , 0 , 1 ) ;
}
static int
pipe_rdwr_release ( struct inode * inode , struct file * filp )
{
int decr , decw ;
pipe_rdwr_fasync ( - 1 , filp , 0 ) ;
decr = ( filp - > f_mode & FMODE_READ ) ! = 0 ;
decw = ( filp - > f_mode & FMODE_WRITE ) ! = 0 ;
return pipe_release ( inode , decr , decw ) ;
}
static int
pipe_read_open ( struct inode * inode , struct file * filp )
{
/* We could have perhaps used atomic_t, but this and friends
below are the only places . So it doesn ' t seem worthwhile . */
2006-04-11 15:53:10 +04:00
mutex_lock ( & inode - > i_mutex ) ;
inode - > i_pipe - > readers + + ;
mutex_unlock ( & inode - > i_mutex ) ;
2005-04-17 02:20:36 +04:00
return 0 ;
}
static int
pipe_write_open ( struct inode * inode , struct file * filp )
{
2006-04-11 15:53:10 +04:00
mutex_lock ( & inode - > i_mutex ) ;
inode - > i_pipe - > writers + + ;
mutex_unlock ( & inode - > i_mutex ) ;
2005-04-17 02:20:36 +04:00
return 0 ;
}
static int
pipe_rdwr_open ( struct inode * inode , struct file * filp )
{
2006-04-11 15:53:10 +04:00
mutex_lock ( & inode - > i_mutex ) ;
2005-04-17 02:20:36 +04:00
if ( filp - > f_mode & FMODE_READ )
2006-04-11 15:53:10 +04:00
inode - > i_pipe - > readers + + ;
2005-04-17 02:20:36 +04:00
if ( filp - > f_mode & FMODE_WRITE )
2006-04-11 15:53:10 +04:00
inode - > i_pipe - > writers + + ;
mutex_unlock ( & inode - > i_mutex ) ;
2005-04-17 02:20:36 +04:00
return 0 ;
}
/*
* The file_operations structs are not static because they
* are also used in linux / fs / fifo . c to do operations on FIFOs .
*/
2006-03-28 13:56:42 +04:00
const struct file_operations read_fifo_fops = {
2005-04-17 02:20:36 +04:00
. llseek = no_llseek ,
. read = pipe_read ,
. readv = pipe_readv ,
. write = bad_pipe_w ,
2005-09-07 02:17:48 +04:00
. poll = pipe_poll ,
2005-04-17 02:20:36 +04:00
. ioctl = pipe_ioctl ,
. open = pipe_read_open ,
. release = pipe_read_release ,
. fasync = pipe_read_fasync ,
} ;
2006-03-28 13:56:42 +04:00
const struct file_operations write_fifo_fops = {
2005-04-17 02:20:36 +04:00
. llseek = no_llseek ,
. read = bad_pipe_r ,
. write = pipe_write ,
. writev = pipe_writev ,
2005-09-07 02:17:48 +04:00
. poll = pipe_poll ,
2005-04-17 02:20:36 +04:00
. ioctl = pipe_ioctl ,
. open = pipe_write_open ,
. release = pipe_write_release ,
. fasync = pipe_write_fasync ,
} ;
2006-03-28 13:56:42 +04:00
const struct file_operations rdwr_fifo_fops = {
2005-04-17 02:20:36 +04:00
. llseek = no_llseek ,
. read = pipe_read ,
. readv = pipe_readv ,
. write = pipe_write ,
. writev = pipe_writev ,
2005-09-07 02:17:48 +04:00
. poll = pipe_poll ,
2005-04-17 02:20:36 +04:00
. ioctl = pipe_ioctl ,
. open = pipe_rdwr_open ,
. release = pipe_rdwr_release ,
. fasync = pipe_rdwr_fasync ,
} ;
2006-03-09 01:03:09 +03:00
static struct file_operations read_pipe_fops = {
2005-04-17 02:20:36 +04:00
. llseek = no_llseek ,
. read = pipe_read ,
. readv = pipe_readv ,
. write = bad_pipe_w ,
. poll = pipe_poll ,
. ioctl = pipe_ioctl ,
. open = pipe_read_open ,
. release = pipe_read_release ,
. fasync = pipe_read_fasync ,
} ;
2006-03-09 01:03:09 +03:00
static struct file_operations write_pipe_fops = {
2005-04-17 02:20:36 +04:00
. llseek = no_llseek ,
. read = bad_pipe_r ,
. write = pipe_write ,
. writev = pipe_writev ,
. poll = pipe_poll ,
. ioctl = pipe_ioctl ,
. open = pipe_write_open ,
. release = pipe_write_release ,
. fasync = pipe_write_fasync ,
} ;
2006-03-09 01:03:09 +03:00
static struct file_operations rdwr_pipe_fops = {
2005-04-17 02:20:36 +04:00
. llseek = no_llseek ,
. read = pipe_read ,
. readv = pipe_readv ,
. write = pipe_write ,
. writev = pipe_writev ,
. poll = pipe_poll ,
. ioctl = pipe_ioctl ,
. open = pipe_rdwr_open ,
. release = pipe_rdwr_release ,
. fasync = pipe_rdwr_fasync ,
} ;
2006-04-10 17:18:35 +04:00
struct pipe_inode_info * alloc_pipe_info ( struct inode * inode )
{
2006-04-11 15:53:33 +04:00
struct pipe_inode_info * pipe ;
2006-04-10 17:18:35 +04:00
2006-04-11 15:53:33 +04:00
pipe = kzalloc ( sizeof ( struct pipe_inode_info ) , GFP_KERNEL ) ;
if ( pipe ) {
init_waitqueue_head ( & pipe - > wait ) ;
pipe - > r_counter = pipe - > w_counter = 1 ;
pipe - > inode = inode ;
2006-04-10 17:18:35 +04:00
}
2006-04-11 15:53:33 +04:00
return pipe ;
2006-04-10 17:18:35 +04:00
}
2006-04-11 15:53:33 +04:00
void __free_pipe_info ( struct pipe_inode_info * pipe )
2005-04-17 02:20:36 +04:00
{
int i ;
for ( i = 0 ; i < PIPE_BUFFERS ; i + + ) {
2006-04-11 15:53:33 +04:00
struct pipe_buffer * buf = pipe - > bufs + i ;
2005-04-17 02:20:36 +04:00
if ( buf - > ops )
2006-04-11 15:53:33 +04:00
buf - > ops - > release ( pipe , buf ) ;
2005-04-17 02:20:36 +04:00
}
2006-04-11 15:53:33 +04:00
if ( pipe - > tmp_page )
__free_page ( pipe - > tmp_page ) ;
kfree ( pipe ) ;
2005-04-17 02:20:36 +04:00
}
2006-04-11 15:52:07 +04:00
void free_pipe_info ( struct inode * inode )
{
__free_pipe_info ( inode - > i_pipe ) ;
inode - > i_pipe = NULL ;
}
2006-03-26 13:37:24 +04:00
static struct vfsmount * pipe_mnt __read_mostly ;
2005-04-17 02:20:36 +04:00
static int pipefs_delete_dentry ( struct dentry * dentry )
{
return 1 ;
}
2006-04-11 15:57:45 +04:00
2005-04-17 02:20:36 +04:00
static struct dentry_operations pipefs_dentry_operations = {
. d_delete = pipefs_delete_dentry ,
} ;
static struct inode * get_pipe_inode ( void )
{
struct inode * inode = new_inode ( pipe_mnt - > mnt_sb ) ;
2006-04-11 15:53:33 +04:00
struct pipe_inode_info * pipe ;
2005-04-17 02:20:36 +04:00
if ( ! inode )
goto fail_inode ;
2006-04-11 15:53:33 +04:00
pipe = alloc_pipe_info ( inode ) ;
if ( ! pipe )
2005-04-17 02:20:36 +04:00
goto fail_iput ;
2006-04-11 15:53:33 +04:00
inode - > i_pipe = pipe ;
2006-04-10 17:18:35 +04:00
2006-04-11 15:53:33 +04:00
pipe - > readers = pipe - > writers = 1 ;
2005-04-17 02:20:36 +04:00
inode - > i_fop = & rdwr_pipe_fops ;
/*
* Mark the inode dirty from the very beginning ,
* that way it will never be moved to the dirty
* list because " mark_inode_dirty() " will think
* that it already _is_ on the dirty list .
*/
inode - > i_state = I_DIRTY ;
inode - > i_mode = S_IFIFO | S_IRUSR | S_IWUSR ;
inode - > i_uid = current - > fsuid ;
inode - > i_gid = current - > fsgid ;
inode - > i_atime = inode - > i_mtime = inode - > i_ctime = CURRENT_TIME ;
inode - > i_blksize = PAGE_SIZE ;
2006-04-11 15:53:33 +04:00
2005-04-17 02:20:36 +04:00
return inode ;
fail_iput :
iput ( inode ) ;
2006-04-11 15:57:45 +04:00
2005-04-17 02:20:36 +04:00
fail_inode :
return NULL ;
}
int do_pipe ( int * fd )
{
struct qstr this ;
char name [ 32 ] ;
struct dentry * dentry ;
struct inode * inode ;
struct file * f1 , * f2 ;
int error ;
2006-04-11 15:57:45 +04:00
int i , j ;
2005-04-17 02:20:36 +04:00
error = - ENFILE ;
f1 = get_empty_filp ( ) ;
if ( ! f1 )
goto no_files ;
f2 = get_empty_filp ( ) ;
if ( ! f2 )
goto close_f1 ;
inode = get_pipe_inode ( ) ;
if ( ! inode )
goto close_f12 ;
error = get_unused_fd ( ) ;
if ( error < 0 )
goto close_f12_inode ;
i = error ;
error = get_unused_fd ( ) ;
if ( error < 0 )
goto close_f12_inode_i ;
j = error ;
error = - ENOMEM ;
sprintf ( name , " [%lu] " , inode - > i_ino ) ;
this . name = name ;
this . len = strlen ( name ) ;
this . hash = inode - > i_ino ; /* will go */
dentry = d_alloc ( pipe_mnt - > mnt_sb - > s_root , & this ) ;
if ( ! dentry )
goto close_f12_inode_i_j ;
2006-04-11 15:57:45 +04:00
2005-04-17 02:20:36 +04:00
dentry - > d_op = & pipefs_dentry_operations ;
d_add ( dentry , inode ) ;
f1 - > f_vfsmnt = f2 - > f_vfsmnt = mntget ( mntget ( pipe_mnt ) ) ;
f1 - > f_dentry = f2 - > f_dentry = dget ( dentry ) ;
f1 - > f_mapping = f2 - > f_mapping = inode - > i_mapping ;
/* read file */
f1 - > f_pos = f2 - > f_pos = 0 ;
f1 - > f_flags = O_RDONLY ;
f1 - > f_op = & read_pipe_fops ;
f1 - > f_mode = FMODE_READ ;
f1 - > f_version = 0 ;
/* write file */
f2 - > f_flags = O_WRONLY ;
f2 - > f_op = & write_pipe_fops ;
f2 - > f_mode = FMODE_WRITE ;
f2 - > f_version = 0 ;
fd_install ( i , f1 ) ;
fd_install ( j , f2 ) ;
fd [ 0 ] = i ;
fd [ 1 ] = j ;
2006-04-11 15:57:45 +04:00
2005-04-17 02:20:36 +04:00
return 0 ;
close_f12_inode_i_j :
put_unused_fd ( j ) ;
close_f12_inode_i :
put_unused_fd ( i ) ;
close_f12_inode :
free_pipe_info ( inode ) ;
iput ( inode ) ;
close_f12 :
put_filp ( f2 ) ;
close_f1 :
put_filp ( f1 ) ;
no_files :
return error ;
}
/*
* pipefs should _never_ be mounted by userland - too much of security hassle ,
* no real gain from having the whole whorehouse mounted . So we don ' t need
* any operations on the root directory . However , we need a non - trivial
* d_name - pipe : will go nicely and kill the special - casing in procfs .
*/
2006-04-11 15:57:45 +04:00
static struct super_block *
pipefs_get_sb ( struct file_system_type * fs_type , int flags ,
const char * dev_name , void * data )
2005-04-17 02:20:36 +04:00
{
return get_sb_pseudo ( fs_type , " pipe: " , NULL , PIPEFS_MAGIC ) ;
}
static struct file_system_type pipe_fs_type = {
. name = " pipefs " ,
. get_sb = pipefs_get_sb ,
. kill_sb = kill_anon_super ,
} ;
static int __init init_pipe_fs ( void )
{
int err = register_filesystem ( & pipe_fs_type ) ;
2006-04-11 15:57:45 +04:00
2005-04-17 02:20:36 +04:00
if ( ! err ) {
pipe_mnt = kern_mount ( & pipe_fs_type ) ;
if ( IS_ERR ( pipe_mnt ) ) {
err = PTR_ERR ( pipe_mnt ) ;
unregister_filesystem ( & pipe_fs_type ) ;
}
}
return err ;
}
static void __exit exit_pipe_fs ( void )
{
unregister_filesystem ( & pipe_fs_type ) ;
mntput ( pipe_mnt ) ;
}
fs_initcall ( init_pipe_fs ) ;
module_exit ( exit_pipe_fs ) ;