1/* 2 * linux/fs/fifo.c 3 * 4 * written by Paul H. Hargrove 5 * 6 * Fixes: 7 * 10-06-1999, AV: fixed OOM handling in fifo_open(), moved 8 * initialization there, switched to external 9 * allocation of pipe_inode_info. 10 */ 11 12#include <linux/mm.h> 13#include <linux/slab.h> 14#include <linux/fs.h> 15#include <linux/sched.h> 16#include <linux/pipe_fs_i.h> 17 18static void wait_for_partner(struct inode* inode, unsigned int *cnt) 19{ 20 int cur = *cnt; 21 22 while (cur == *cnt) { 23 pipe_wait(inode->i_pipe); 24 if (signal_pending(current)) 25 break; 26 } 27} 28 29static void wake_up_partner(struct inode* inode) 30{ 31 wake_up_interruptible(&inode->i_pipe->wait); 32} 33 34static int fifo_open(struct inode *inode, struct file *filp) 35{ 36 struct pipe_inode_info *pipe; 37 int ret; 38 39 mutex_lock(&inode->i_mutex); 40 pipe = inode->i_pipe; 41 if (!pipe) { 42 ret = -ENOMEM; 43 pipe = alloc_pipe_info(inode); 44 if (!pipe) 45 goto err_nocleanup; 46 inode->i_pipe = pipe; 47 } 48 filp->f_version = 0; 49 50 /* We can only do regular read/write on fifos */ 51 filp->f_mode &= (FMODE_READ | FMODE_WRITE); 52 53 switch (filp->f_mode) { 54 case FMODE_READ: 55 /* 56 * O_RDONLY 57 * POSIX.1 says that O_NONBLOCK means return with the FIFO 58 * opened, even when there is no process writing the FIFO. 59 */ 60 filp->f_op = &read_pipefifo_fops; 61 pipe->r_counter++; 62 if (pipe->readers++ == 0) 63 wake_up_partner(inode); 64 65 if (!pipe->writers) { 66 if ((filp->f_flags & O_NONBLOCK)) { 67 /* suppress POLLHUP until we have 68 * seen a writer */ 69 filp->f_version = pipe->w_counter; 70 } else 71 { 72 wait_for_partner(inode, &pipe->w_counter); 73 if(signal_pending(current)) 74 goto err_rd; 75 } 76 } 77 break; 78 79 case FMODE_WRITE: 80 /* 81 * O_WRONLY 82 * POSIX.1 says that O_NONBLOCK means return -1 with 83 * errno=ENXIO when there is no process reading the FIFO. 84 */ 85 ret = -ENXIO; 86 if ((filp->f_flags & O_NONBLOCK) && !pipe->readers) 87 goto err; 88 89 filp->f_op = &write_pipefifo_fops; 90 pipe->w_counter++; 91 if (!pipe->writers++) 92 wake_up_partner(inode); 93 94 if (!pipe->readers) { 95 wait_for_partner(inode, &pipe->r_counter); 96 if (signal_pending(current)) 97 goto err_wr; 98 } 99 break; 100 101 case FMODE_READ | FMODE_WRITE: 102 /* 103 * O_RDWR 104 * POSIX.1 leaves this case "undefined" when O_NONBLOCK is set. 105 * This implementation will NEVER block on a O_RDWR open, since 106 * the process can at least talk to itself. 107 */ 108 filp->f_op = &rdwr_pipefifo_fops; 109 110 pipe->readers++; 111 pipe->writers++; 112 pipe->r_counter++; 113 pipe->w_counter++; 114 if (pipe->readers == 1 || pipe->writers == 1) 115 wake_up_partner(inode); 116 break; 117 118 default: 119 ret = -EINVAL; 120 goto err; 121 } 122 123 /* Ok! */ 124 mutex_unlock(&inode->i_mutex); 125 return 0; 126 127err_rd: 128 if (!--pipe->readers) 129 wake_up_interruptible(&pipe->wait); 130 ret = -ERESTARTSYS; 131 goto err; 132 133err_wr: 134 if (!--pipe->writers) 135 wake_up_interruptible(&pipe->wait); 136 ret = -ERESTARTSYS; 137 goto err; 138 139err: 140 if (!pipe->readers && !pipe->writers) 141 free_pipe_info(inode); 142 143err_nocleanup: 144 mutex_unlock(&inode->i_mutex); 145 return ret; 146} 147 148/* 149 * Dummy default file-operations: the only thing this does 150 * is contain the open that then fills in the correct operations 151 * depending on the access mode of the file... 152 */ 153const struct file_operations def_fifo_fops = { 154 .open = fifo_open, /* will set read_ or write_pipefifo_fops */ 155}; 156