root/fs/pipe.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. pipe_read
  2. pipe_write
  3. pipe_lseek
  4. pipe_readdir
  5. bad_pipe_rw
  6. pipe_ioctl
  7. pipe_select
  8. pipe_read_release
  9. pipe_write_release
  10. pipe_rdwr_release
  11. sys_pipe

   1 /*
   2  *  linux/fs/pipe.c
   3  *
   4  *  Copyright (C) 1991, 1992  Linus Torvalds
   5  */
   6 
   7 #include <asm/segment.h>
   8 
   9 #include <linux/sched.h>
  10 #include <linux/kernel.h>
  11 #include <linux/errno.h>
  12 #include <linux/signal.h>
  13 #include <linux/fcntl.h>
  14 #include <linux/termios.h>
  15 
  16 static int pipe_read(struct inode * inode, struct file * filp, char * buf, int count)
     /* [previous][next][first][last][top][bottom][index][help] */
  17 {
  18         int chars, size, read = 0;
  19 
  20         if (!(filp->f_flags & O_NONBLOCK))
  21                 while (!PIPE_SIZE(*inode)) {
  22                         wake_up(& PIPE_WRITE_WAIT(*inode));
  23                         if (!PIPE_WRITERS(*inode)) /* are there any writers? */
  24                                 return 0;
  25                         if (current->signal & ~current->blocked)
  26                                 return -ERESTARTSYS;
  27                         interruptible_sleep_on(& PIPE_READ_WAIT(*inode));
  28                 }
  29         while (count>0 && (size = PIPE_SIZE(*inode))) {
  30                 chars = PAGE_SIZE-PIPE_TAIL(*inode);
  31                 if (chars > count)
  32                         chars = count;
  33                 if (chars > size)
  34                         chars = size;
  35                 memcpy_tofs(buf, PIPE_BASE(*inode)+PIPE_TAIL(*inode), chars );
  36                 read += chars;
  37                 PIPE_TAIL(*inode) += chars;
  38                 PIPE_TAIL(*inode) &= (PAGE_SIZE-1);
  39                 count -= chars;
  40                 buf += chars;
  41         }
  42         wake_up(& PIPE_WRITE_WAIT(*inode));
  43         if (read)
  44                 return read;
  45         if (PIPE_WRITERS(*inode))
  46                 return -EAGAIN;
  47         return 0;
  48 }
  49         
  50 static int pipe_write(struct inode * inode, struct file * filp, char * buf, int count)
     /* [previous][next][first][last][top][bottom][index][help] */
  51 {
  52         int chars, size, written = 0;
  53 
  54         if (!PIPE_READERS(*inode)) { /* no readers */
  55                 send_sig(SIGPIPE,current,0);
  56                 return -EPIPE;
  57         }
  58 /* if count < PAGE_SIZE, we have to make it atomic */
  59         if (count < PAGE_SIZE)
  60                 size = PAGE_SIZE-count;
  61         else
  62                 size = PAGE_SIZE-1;
  63         while (count>0) {
  64                 while (PIPE_SIZE(*inode) >= size) {
  65                         if (!PIPE_READERS(*inode)) { /* no readers */
  66                                 send_sig(SIGPIPE,current,0);
  67                                 return written?written:-EPIPE;
  68                         }
  69                         if (current->signal & ~current->blocked)
  70                                 return written?written:-ERESTARTSYS;
  71                         if (filp->f_flags & O_NONBLOCK)
  72                                 return -EAGAIN;
  73                         else
  74                                 interruptible_sleep_on(&PIPE_WRITE_WAIT(*inode));
  75                 }
  76                 while (count>0 && (size = (PAGE_SIZE-1)-PIPE_SIZE(*inode))) {
  77                         chars = PAGE_SIZE-PIPE_HEAD(*inode);
  78                         if (chars > count)
  79                                 chars = count;
  80                         if (chars > size)
  81                                 chars = size;
  82                         memcpy_fromfs(PIPE_BASE(*inode)+PIPE_HEAD(*inode), buf, chars );
  83                         written += chars;
  84                         PIPE_HEAD(*inode) += chars;
  85                         PIPE_HEAD(*inode) &= (PAGE_SIZE-1);
  86                         count -= chars;
  87                         buf += chars;
  88                 }
  89                 wake_up(& PIPE_READ_WAIT(*inode));
  90                 size = PAGE_SIZE-1;
  91         }
  92         return written;
  93 }
  94 
  95 static int pipe_lseek(struct inode * inode, struct file * file, off_t offset, int orig)
     /* [previous][next][first][last][top][bottom][index][help] */
  96 {
  97         return -ESPIPE;
  98 }
  99 
 100 static int pipe_readdir(struct inode * inode, struct file * file, struct dirent * de, int count)
     /* [previous][next][first][last][top][bottom][index][help] */
 101 {
 102         return -ENOTDIR;
 103 }
 104 
 105 static int bad_pipe_rw(struct inode * inode, struct file * filp, char * buf, int count)
     /* [previous][next][first][last][top][bottom][index][help] */
 106 {
 107         return -EBADF;
 108 }
 109 
 110 static int pipe_ioctl(struct inode *pino, struct file * filp,
     /* [previous][next][first][last][top][bottom][index][help] */
 111         unsigned int cmd, unsigned int arg)
 112 {
 113         switch (cmd) {
 114                 case FIONREAD:
 115                         verify_area((void *) arg,4);
 116                         put_fs_long(PIPE_SIZE(*pino),(unsigned long *) arg);
 117                         return 0;
 118                 default:
 119                         return -EINVAL;
 120         }
 121 }
 122 
 123 static int pipe_select(struct inode * inode, struct file * filp, int sel_type, select_table * wait)
     /* [previous][next][first][last][top][bottom][index][help] */
 124 {
 125         switch (sel_type) {
 126                 case SEL_IN:
 127                         if (!PIPE_EMPTY(*inode) || !PIPE_WRITERS(*inode))
 128                                 return 1;
 129                         select_wait(&PIPE_READ_WAIT(*inode), wait);
 130                         return 0;
 131                 case SEL_OUT:
 132                         if (!PIPE_FULL(*inode) || !PIPE_WRITERS(*inode))
 133                                 return 1;
 134                         select_wait(&PIPE_WRITE_WAIT(*inode), wait);
 135                         return 0;
 136                 case SEL_EX:
 137                         if (!PIPE_READERS(*inode) || !PIPE_WRITERS(*inode))
 138                                 return 1;
 139                         select_wait(&inode->i_wait,wait);
 140                         return 0;
 141         }
 142         return 0;
 143 }
 144 
 145 /*
 146  * Ok, these three routines NOW keep track of readers/writers,
 147  * Linus previously did it with inode->i_count checking.
 148  */
 149 static void pipe_read_release(struct inode * inode, struct file * filp)
     /* [previous][next][first][last][top][bottom][index][help] */
 150 {
 151         PIPE_READERS(*inode)--;
 152         wake_up(&PIPE_WRITE_WAIT(*inode));
 153 }
 154 
 155 static void pipe_write_release(struct inode * inode, struct file * filp)
     /* [previous][next][first][last][top][bottom][index][help] */
 156 {
 157         PIPE_WRITERS(*inode)--;
 158         wake_up(&PIPE_READ_WAIT(*inode));
 159 }
 160 
 161 static void pipe_rdwr_release(struct inode * inode, struct file * filp)
     /* [previous][next][first][last][top][bottom][index][help] */
 162 {
 163         PIPE_READERS(*inode)--;
 164         PIPE_WRITERS(*inode)--;
 165         wake_up(&PIPE_READ_WAIT(*inode));
 166         wake_up(&PIPE_WRITE_WAIT(*inode));
 167 }
 168 
 169 /*
 170  * The three file_operations structs are not static because they
 171  * are also used in linux/fs/fifo.c to do operations on fifo's.
 172  */
 173 struct file_operations read_pipe_fops = {
 174         pipe_lseek,
 175         pipe_read,
 176         bad_pipe_rw,
 177         pipe_readdir,
 178         pipe_select,
 179         pipe_ioctl,
 180         NULL,           /* no mmap on pipes.. surprise */
 181         NULL,           /* no special open code */
 182         pipe_read_release
 183 };
 184 
 185 struct file_operations write_pipe_fops = {
 186         pipe_lseek,
 187         bad_pipe_rw,
 188         pipe_write,
 189         pipe_readdir,
 190         pipe_select,
 191         pipe_ioctl,
 192         NULL,           /* mmap */
 193         NULL,           /* no special open code */
 194         pipe_write_release
 195 };
 196 
 197 struct file_operations rdwr_pipe_fops = {
 198         pipe_lseek,
 199         pipe_read,
 200         pipe_write,
 201         pipe_readdir,
 202         pipe_select,
 203         pipe_ioctl,
 204         NULL,           /* mmap */
 205         NULL,           /* no special open code */
 206         pipe_rdwr_release
 207 };
 208 
 209 int sys_pipe(unsigned long * fildes)
     /* [previous][next][first][last][top][bottom][index][help] */
 210 {
 211         struct inode * inode;
 212         struct file * f[2];
 213         int fd[2];
 214         int i,j;
 215 
 216         verify_area(fildes,8);
 217         for(j=0 ; j<2 ; j++)
 218                 if (!(f[j] = get_empty_filp()))
 219                         break;
 220         if (j==1)
 221                 f[0]->f_count--;
 222         if (j<2)
 223                 return -ENFILE;
 224         j=0;
 225         for(i=0;j<2 && i<NR_OPEN;i++)
 226                 if (!current->filp[i]) {
 227                         current->filp[ fd[j]=i ] = f[j];
 228                         j++;
 229                 }
 230         if (j==1)
 231                 current->filp[fd[0]]=NULL;
 232         if (j<2) {
 233                 f[0]->f_count--;
 234                 f[1]->f_count--;
 235                 return -EMFILE;
 236         }
 237         if (!(inode=get_pipe_inode())) {
 238                 current->filp[fd[0]] = NULL;
 239                 current->filp[fd[1]] = NULL;
 240                 f[0]->f_count--;
 241                 f[1]->f_count--;
 242                 return -ENFILE;
 243         }
 244         f[0]->f_inode = f[1]->f_inode = inode;
 245         f[0]->f_pos = f[1]->f_pos = 0;
 246         f[0]->f_flags = f[1]->f_flags = 0;
 247         f[0]->f_op = &read_pipe_fops;
 248         f[0]->f_mode = 1;               /* read */
 249         f[1]->f_op = &write_pipe_fops;
 250         f[1]->f_mode = 2;               /* write */
 251         put_fs_long(fd[0],0+fildes);
 252         put_fs_long(fd[1],1+fildes);
 253         return 0;
 254 }

/* [previous][next][first][last][top][bottom][index][help] */