2005-04-17 02:20:36 +04:00
/*
* linux / fs / fifo . c
*
* written by Paul H . Hargrove
*
* Fixes :
* 10 - 06 - 1999 , AV : fixed OOM handling in fifo_open ( ) , moved
* initialization there , switched to external
* allocation of pipe_inode_info .
*/
# include <linux/mm.h>
# include <linux/slab.h>
# include <linux/smp_lock.h>
# include <linux/fs.h>
# include <linux/pipe_fs_i.h>
2006-04-10 17:18:35 +04:00
static void wait_for_partner ( struct inode * inode , unsigned int * cnt )
2005-04-17 02:20:36 +04:00
{
int cur = * cnt ;
2006-04-10 17:18:35 +04:00
while ( cur = = * cnt ) {
pipe_wait ( inode - > i_pipe ) ;
if ( signal_pending ( current ) )
2005-04-17 02:20:36 +04:00
break ;
}
}
static void wake_up_partner ( struct inode * inode )
{
2006-04-11 15:53:10 +04:00
wake_up_interruptible ( & inode - > i_pipe - > wait ) ;
2005-04-17 02:20:36 +04:00
}
static int fifo_open ( struct inode * inode , struct file * filp )
{
2006-04-11 15:53:33 +04:00
struct pipe_inode_info * pipe ;
2005-04-17 02:20:36 +04:00
int ret ;
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 ;
if ( ! pipe ) {
2005-04-17 02:20:36 +04:00
ret = - ENOMEM ;
2006-04-11 15:53:33 +04:00
pipe = alloc_pipe_info ( inode ) ;
if ( ! pipe )
2005-04-17 02:20:36 +04:00
goto err_nocleanup ;
2006-04-11 15:53:33 +04:00
inode - > i_pipe = pipe ;
2005-04-17 02:20:36 +04:00
}
filp - > f_version = 0 ;
/* We can only do regular read/write on fifos */
filp - > f_mode & = ( FMODE_READ | FMODE_WRITE ) ;
switch ( filp - > f_mode ) {
case 1 :
/*
* O_RDONLY
* POSIX .1 says that O_NONBLOCK means return with the FIFO
* opened , even when there is no process writing the FIFO .
*/
filp - > f_op = & read_fifo_fops ;
2006-04-11 15:53:33 +04:00
pipe - > r_counter + + ;
if ( pipe - > readers + + = = 0 )
2005-04-17 02:20:36 +04:00
wake_up_partner ( inode ) ;
2006-04-11 15:53:33 +04:00
if ( ! pipe - > writers ) {
2005-04-17 02:20:36 +04:00
if ( ( filp - > f_flags & O_NONBLOCK ) ) {
/* suppress POLLHUP until we have
* seen a writer */
2006-04-11 15:53:33 +04:00
filp - > f_version = pipe - > w_counter ;
2005-04-17 02:20:36 +04:00
} else
{
2006-04-11 15:53:33 +04:00
wait_for_partner ( inode , & pipe - > w_counter ) ;
2005-04-17 02:20:36 +04:00
if ( signal_pending ( current ) )
goto err_rd ;
}
}
break ;
case 2 :
/*
* O_WRONLY
* POSIX .1 says that O_NONBLOCK means return - 1 with
* errno = ENXIO when there is no process reading the FIFO .
*/
ret = - ENXIO ;
2006-04-11 15:53:33 +04:00
if ( ( filp - > f_flags & O_NONBLOCK ) & & ! pipe - > readers )
2005-04-17 02:20:36 +04:00
goto err ;
filp - > f_op = & write_fifo_fops ;
2006-04-11 15:53:33 +04:00
pipe - > w_counter + + ;
if ( ! pipe - > writers + + )
2005-04-17 02:20:36 +04:00
wake_up_partner ( inode ) ;
2006-04-11 15:53:33 +04:00
if ( ! pipe - > readers ) {
wait_for_partner ( inode , & pipe - > r_counter ) ;
2005-04-17 02:20:36 +04:00
if ( signal_pending ( current ) )
goto err_wr ;
}
break ;
case 3 :
/*
* O_RDWR
* POSIX .1 leaves this case " undefined " when O_NONBLOCK is set .
* This implementation will NEVER block on a O_RDWR open , since
* the process can at least talk to itself .
*/
filp - > f_op = & rdwr_fifo_fops ;
2006-04-11 15:53:33 +04:00
pipe - > readers + + ;
pipe - > writers + + ;
pipe - > r_counter + + ;
pipe - > w_counter + + ;
if ( pipe - > readers = = 1 | | pipe - > writers = = 1 )
2005-04-17 02:20:36 +04:00
wake_up_partner ( inode ) ;
break ;
default :
ret = - EINVAL ;
goto err ;
}
/* Ok! */
2006-04-11 15:53:10 +04:00
mutex_unlock ( & inode - > i_mutex ) ;
2005-04-17 02:20:36 +04:00
return 0 ;
err_rd :
2006-04-11 15:53:33 +04:00
if ( ! - - pipe - > readers )
wake_up_interruptible ( & pipe - > wait ) ;
2005-04-17 02:20:36 +04:00
ret = - ERESTARTSYS ;
goto err ;
err_wr :
2006-04-11 15:53:33 +04:00
if ( ! - - pipe - > writers )
wake_up_interruptible ( & pipe - > wait ) ;
2005-04-17 02:20:36 +04:00
ret = - ERESTARTSYS ;
goto err ;
err :
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 ) ;
err_nocleanup :
2006-04-11 15:53:10 +04:00
mutex_unlock ( & inode - > i_mutex ) ;
2005-04-17 02:20:36 +04:00
return ret ;
}
/*
* Dummy default file - operations : the only thing this does
* is contain the open that then fills in the correct operations
* depending on the access mode of the file . . .
*/
2006-03-28 13:56:42 +04:00
const struct file_operations def_fifo_fops = {
2005-04-17 02:20:36 +04:00
. open = fifo_open , /* will set read or write pipe_fops */
} ;