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. bad_pipe_r
  5. bad_pipe_w
  6. pipe_ioctl
  7. pipe_select
  8. fifo_select
  9. connect_read
  10. connect_select
  11. pipe_read_release
  12. pipe_write_release
  13. pipe_rdwr_release
  14. pipe_read_open
  15. pipe_write_open
  16. pipe_rdwr_open
  17. do_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 #include <linux/mm.h>
  16 
  17 /*
  18  * Define this if you want SunOS compatibility wrt braindead
  19  * select behaviour on FIFO's.
  20  */
  21 #undef FIFO_SUNOS_BRAINDAMAGE
  22 
  23 /* We don't use the head/tail construction any more. Now we use the start/len*/
  24 /* construction providing full use of PIPE_BUF (multiple of PAGE_SIZE) */
  25 /* Florian Coosmann (FGC)                                ^ current = 1       */
  26 /* Additionally, we now use locking technique. This prevents race condition  */
  27 /* in case of paging and multiple read/write on the same pipe. (FGC)         */
  28 
  29 
  30 static int pipe_read(struct inode * inode, struct file * filp, char * buf, int count)
     /* [previous][next][first][last][top][bottom][index][help] */
  31 {
  32         int chars = 0, size = 0, read = 0;
  33         char *pipebuf;
  34 
  35         if (filp->f_flags & O_NONBLOCK) {
  36                 if (PIPE_LOCK(*inode))
  37                         return -EAGAIN;
  38                 if (PIPE_EMPTY(*inode))
  39                         if (PIPE_WRITERS(*inode))
  40                                 return -EAGAIN;
  41                         else
  42                                 return 0;
  43         } else while (PIPE_EMPTY(*inode) || PIPE_LOCK(*inode)) {
  44                 if (PIPE_EMPTY(*inode)) {
  45                         if (!PIPE_WRITERS(*inode))
  46                                 return 0;
  47                 }
  48                 if (current->signal & ~current->blocked)
  49                         return -ERESTARTSYS;
  50                 interruptible_sleep_on(&PIPE_WAIT(*inode));
  51         }
  52         PIPE_LOCK(*inode)++;
  53         while (count>0 && (size = PIPE_SIZE(*inode))) {
  54                 chars = PIPE_MAX_RCHUNK(*inode);
  55                 if (chars > count)
  56                         chars = count;
  57                 if (chars > size)
  58                         chars = size;
  59                 read += chars;
  60                 pipebuf = PIPE_BASE(*inode)+PIPE_START(*inode);
  61                 PIPE_START(*inode) += chars;
  62                 PIPE_START(*inode) &= (PIPE_BUF-1);
  63                 PIPE_LEN(*inode) -= chars;
  64                 count -= chars;
  65                 memcpy_tofs(buf, pipebuf, chars );
  66                 buf += chars;
  67         }
  68         PIPE_LOCK(*inode)--;
  69         wake_up_interruptible(&PIPE_WAIT(*inode));
  70         if (read)
  71                 return read;
  72         if (PIPE_WRITERS(*inode))
  73                 return -EAGAIN;
  74         return 0;
  75 }
  76         
  77 static int pipe_write(struct inode * inode, struct file * filp, const char * buf, int count)
     /* [previous][next][first][last][top][bottom][index][help] */
  78 {
  79         int chars = 0, free = 0, written = 0;
  80         char *pipebuf;
  81 
  82         if (!PIPE_READERS(*inode)) { /* no readers */
  83                 send_sig(SIGPIPE,current,0);
  84                 return -EPIPE;
  85         }
  86 /* if count <= PIPE_BUF, we have to make it atomic */
  87         if (count <= PIPE_BUF)
  88                 free = count;
  89         else
  90                 free = 1; /* can't do it atomically, wait for any free space */
  91         while (count>0) {
  92                 while ((PIPE_FREE(*inode) < free) || PIPE_LOCK(*inode)) {
  93                         if (!PIPE_READERS(*inode)) { /* no readers */
  94                                 send_sig(SIGPIPE,current,0);
  95                                 return written? :-EPIPE;
  96                         }
  97                         if (current->signal & ~current->blocked)
  98                                 return written? :-ERESTARTSYS;
  99                         if (filp->f_flags & O_NONBLOCK)
 100                                 return written? :-EAGAIN;
 101                         interruptible_sleep_on(&PIPE_WAIT(*inode));
 102                 }
 103                 PIPE_LOCK(*inode)++;
 104                 while (count>0 && (free = PIPE_FREE(*inode))) {
 105                         chars = PIPE_MAX_WCHUNK(*inode);
 106                         if (chars > count)
 107                                 chars = count;
 108                         if (chars > free)
 109                                 chars = free;
 110                         pipebuf = PIPE_BASE(*inode)+PIPE_END(*inode);
 111                         written += chars;
 112                         PIPE_LEN(*inode) += chars;
 113                         count -= chars;
 114                         memcpy_fromfs(pipebuf, buf, chars );
 115                         buf += chars;
 116                 }
 117                 PIPE_LOCK(*inode)--;
 118                 wake_up_interruptible(&PIPE_WAIT(*inode));
 119                 free = 1;
 120         }
 121         return written;
 122 }
 123 
 124 static int pipe_lseek(struct inode * inode, struct file * file, off_t offset, int orig)
     /* [previous][next][first][last][top][bottom][index][help] */
 125 {
 126         return -ESPIPE;
 127 }
 128 
 129 static int bad_pipe_r(struct inode * inode, struct file * filp, char * buf, int count)
     /* [previous][next][first][last][top][bottom][index][help] */
 130 {
 131         return -EBADF;
 132 }
 133 
 134 static int bad_pipe_w(struct inode * inode, struct file * filp, const char * buf, int count)
     /* [previous][next][first][last][top][bottom][index][help] */
 135 {
 136         return -EBADF;
 137 }
 138 
 139 static int pipe_ioctl(struct inode *pino, struct file * filp,
     /* [previous][next][first][last][top][bottom][index][help] */
 140         unsigned int cmd, unsigned long arg)
 141 {
 142         int error;
 143 
 144         switch (cmd) {
 145                 case FIONREAD:
 146                         error = verify_area(VERIFY_WRITE, (void *) arg, sizeof(int));
 147                         if (!error)
 148                                 put_user(PIPE_SIZE(*pino),(int *) arg);
 149                         return error;
 150                 default:
 151                         return -EINVAL;
 152         }
 153 }
 154 
 155 static int pipe_select(struct inode * inode, struct file * filp, int sel_type, select_table * wait)
     /* [previous][next][first][last][top][bottom][index][help] */
 156 {
 157         switch (sel_type) {
 158                 case SEL_IN:
 159                         if (!PIPE_EMPTY(*inode) || !PIPE_WRITERS(*inode))
 160                                 return 1;
 161                         select_wait(&PIPE_WAIT(*inode), wait);
 162                         return 0;
 163                 case SEL_OUT:
 164                         if (!PIPE_FULL(*inode) || !PIPE_READERS(*inode))
 165                                 return 1;
 166                         select_wait(&PIPE_WAIT(*inode), wait);
 167                         return 0;
 168                 case SEL_EX:
 169                         if (!PIPE_READERS(*inode) || !PIPE_WRITERS(*inode))
 170                                 return 1;
 171                         select_wait(&inode->i_wait,wait);
 172                         return 0;
 173         }
 174         return 0;
 175 }
 176 
 177 #ifdef FIFO_SUNOS_BRAINDAMAGE
 178 /*
 179  * Arggh. Why does SunOS have to have different select() behaviour
 180  * for pipes and fifos? Hate-Hate-Hate. See difference in SEL_IN..
 181  */
 182 static int fifo_select(struct inode * inode, struct file * filp, int sel_type, select_table * wait)
     /* [previous][next][first][last][top][bottom][index][help] */
 183 {
 184         switch (sel_type) {
 185                 case SEL_IN:
 186                         if (!PIPE_EMPTY(*inode))
 187                                 return 1;
 188                         select_wait(&PIPE_WAIT(*inode), wait);
 189                         return 0;
 190                 case SEL_OUT:
 191                         if (!PIPE_FULL(*inode) || !PIPE_READERS(*inode))
 192                                 return 1;
 193                         select_wait(&PIPE_WAIT(*inode), wait);
 194                         return 0;
 195                 case SEL_EX:
 196                         if (!PIPE_READERS(*inode) || !PIPE_WRITERS(*inode))
 197                                 return 1;
 198                         select_wait(&inode->i_wait,wait);
 199                         return 0;
 200         }
 201         return 0;
 202 }
 203 #else
 204 
 205 #define fifo_select pipe_select
 206 
 207 #endif /* FIFO_SUNOS_BRAINDAMAGE */
 208 
 209 /*
 210  * The 'connect_xxx()' functions are needed for named pipes when
 211  * the open() code hasn't guaranteed a connection (O_NONBLOCK),
 212  * and we need to act differently until we do get a writer..
 213  */
 214 static int connect_read(struct inode * inode, struct file * filp, char * buf, int count)
     /* [previous][next][first][last][top][bottom][index][help] */
 215 {
 216         while (!PIPE_SIZE(*inode)) {
 217                 if (PIPE_WRITERS(*inode))
 218                         break;
 219                 if (filp->f_flags & O_NONBLOCK)
 220                         return -EAGAIN;
 221                 wake_up_interruptible(& PIPE_WAIT(*inode));
 222                 if (current->signal & ~current->blocked)
 223                         return -ERESTARTSYS;
 224                 interruptible_sleep_on(& PIPE_WAIT(*inode));
 225         }
 226         filp->f_op = &read_fifo_fops;
 227         return pipe_read(inode,filp,buf,count);
 228 }
 229 
 230 static int connect_select(struct inode * inode, struct file * filp, int sel_type, select_table * wait)
     /* [previous][next][first][last][top][bottom][index][help] */
 231 {
 232         switch (sel_type) {
 233                 case SEL_IN:
 234                         if (!PIPE_EMPTY(*inode)) {
 235                                 filp->f_op = &read_fifo_fops;
 236                                 return 1;
 237                         }
 238                         select_wait(&PIPE_WAIT(*inode), wait);
 239                         return 0;
 240                 case SEL_OUT:
 241                         if (!PIPE_FULL(*inode))
 242                                 return 1;
 243                         select_wait(&PIPE_WAIT(*inode), wait);
 244                         return 0;
 245                 case SEL_EX:
 246                         if (!PIPE_READERS(*inode) || !PIPE_WRITERS(*inode))
 247                                 return 1;
 248                         select_wait(&inode->i_wait,wait);
 249                         return 0;
 250         }
 251         return 0;
 252 }
 253 
 254 static void pipe_read_release(struct inode * inode, struct file * filp)
     /* [previous][next][first][last][top][bottom][index][help] */
 255 {
 256         PIPE_READERS(*inode)--;
 257         wake_up_interruptible(&PIPE_WAIT(*inode));
 258 }
 259 
 260 static void pipe_write_release(struct inode * inode, struct file * filp)
     /* [previous][next][first][last][top][bottom][index][help] */
 261 {
 262         PIPE_WRITERS(*inode)--;
 263         wake_up_interruptible(&PIPE_WAIT(*inode));
 264 }
 265 
 266 static void pipe_rdwr_release(struct inode * inode, struct file * filp)
     /* [previous][next][first][last][top][bottom][index][help] */
 267 {
 268         if (filp->f_mode & FMODE_READ)
 269                 PIPE_READERS(*inode)--;
 270         if (filp->f_mode & FMODE_WRITE)
 271                 PIPE_WRITERS(*inode)--;
 272         wake_up_interruptible(&PIPE_WAIT(*inode));
 273 }
 274 
 275 static int pipe_read_open(struct inode * inode, struct file * filp)
     /* [previous][next][first][last][top][bottom][index][help] */
 276 {
 277         PIPE_READERS(*inode)++;
 278         return 0;
 279 }
 280 
 281 static int pipe_write_open(struct inode * inode, struct file * filp)
     /* [previous][next][first][last][top][bottom][index][help] */
 282 {
 283         PIPE_WRITERS(*inode)++;
 284         return 0;
 285 }
 286 
 287 static int pipe_rdwr_open(struct inode * inode, struct file * filp)
     /* [previous][next][first][last][top][bottom][index][help] */
 288 {
 289         if (filp->f_mode & FMODE_READ)
 290                 PIPE_READERS(*inode)++;
 291         if (filp->f_mode & FMODE_WRITE)
 292                 PIPE_WRITERS(*inode)++;
 293         return 0;
 294 }
 295 
 296 /*
 297  * The file_operations structs are not static because they
 298  * are also used in linux/fs/fifo.c to do operations on fifo's.
 299  */
 300 struct file_operations connecting_fifo_fops = {
 301         pipe_lseek,
 302         connect_read,
 303         bad_pipe_w,
 304         NULL,           /* no readdir */
 305         connect_select,
 306         pipe_ioctl,
 307         NULL,           /* no mmap on pipes.. surprise */
 308         pipe_read_open,
 309         pipe_read_release,
 310         NULL
 311 };
 312 
 313 struct file_operations read_fifo_fops = {
 314         pipe_lseek,
 315         pipe_read,
 316         bad_pipe_w,
 317         NULL,           /* no readdir */
 318         fifo_select,
 319         pipe_ioctl,
 320         NULL,           /* no mmap on pipes.. surprise */
 321         pipe_read_open,
 322         pipe_read_release,
 323         NULL
 324 };
 325 
 326 struct file_operations write_fifo_fops = {
 327         pipe_lseek,
 328         bad_pipe_r,
 329         pipe_write,
 330         NULL,           /* no readdir */
 331         fifo_select,
 332         pipe_ioctl,
 333         NULL,           /* mmap */
 334         pipe_write_open,
 335         pipe_write_release,
 336         NULL
 337 };
 338 
 339 struct file_operations rdwr_fifo_fops = {
 340         pipe_lseek,
 341         pipe_read,
 342         pipe_write,
 343         NULL,           /* no readdir */
 344         fifo_select,
 345         pipe_ioctl,
 346         NULL,           /* mmap */
 347         pipe_rdwr_open,
 348         pipe_rdwr_release,
 349         NULL
 350 };
 351 
 352 struct file_operations read_pipe_fops = {
 353         pipe_lseek,
 354         pipe_read,
 355         bad_pipe_w,
 356         NULL,           /* no readdir */
 357         pipe_select,
 358         pipe_ioctl,
 359         NULL,           /* no mmap on pipes.. surprise */
 360         pipe_read_open,
 361         pipe_read_release,
 362         NULL
 363 };
 364 
 365 struct file_operations write_pipe_fops = {
 366         pipe_lseek,
 367         bad_pipe_r,
 368         pipe_write,
 369         NULL,           /* no readdir */
 370         pipe_select,
 371         pipe_ioctl,
 372         NULL,           /* mmap */
 373         pipe_write_open,
 374         pipe_write_release,
 375         NULL
 376 };
 377 
 378 struct file_operations rdwr_pipe_fops = {
 379         pipe_lseek,
 380         pipe_read,
 381         pipe_write,
 382         NULL,           /* no readdir */
 383         pipe_select,
 384         pipe_ioctl,
 385         NULL,           /* mmap */
 386         pipe_rdwr_open,
 387         pipe_rdwr_release,
 388         NULL
 389 };
 390 
 391 struct inode_operations pipe_inode_operations = {
 392         &rdwr_pipe_fops,
 393         NULL,                   /* create */
 394         NULL,                   /* lookup */
 395         NULL,                   /* link */
 396         NULL,                   /* unlink */
 397         NULL,                   /* symlink */
 398         NULL,                   /* mkdir */
 399         NULL,                   /* rmdir */
 400         NULL,                   /* mknod */
 401         NULL,                   /* rename */
 402         NULL,                   /* readlink */
 403         NULL,                   /* follow_link */
 404         NULL,                   /* readpage */
 405         NULL,                   /* writepage */
 406         NULL,                   /* bmap */
 407         NULL,                   /* truncate */
 408         NULL                    /* permission */
 409 };
 410 
 411 int do_pipe(int *fd)
     /* [previous][next][first][last][top][bottom][index][help] */
 412 {
 413         struct inode * inode;
 414         struct file *f[2];
 415         int i,j;
 416 
 417         inode = get_pipe_inode();
 418         if (!inode)
 419                 return -ENFILE;
 420 
 421         for(j=0 ; j<2 ; j++)
 422                 if (!(f[j] = get_empty_filp()))
 423                         break;
 424         if (j < 2) {
 425                 iput(inode);
 426                 if (j)
 427                         f[0]->f_count--;
 428                 return -ENFILE;
 429         }
 430         j=0;
 431         for(i=0;j<2 && i<NR_OPEN && i<current->rlim[RLIMIT_NOFILE].rlim_cur;i++)
 432                 if (!current->files->fd[i]) {
 433                         current->files->fd[ fd[j]=i ] = f[j];
 434                         j++;
 435                 }
 436         if (j<2) {
 437                 iput(inode);
 438                 f[0]->f_count--;
 439                 f[1]->f_count--;
 440                 if (j)
 441                         current->files->fd[fd[0]] = NULL;
 442                 return -EMFILE;
 443         }
 444         f[0]->f_inode = f[1]->f_inode = inode;
 445         f[0]->f_pos = f[1]->f_pos = 0;
 446         f[0]->f_flags = O_RDONLY;
 447         f[0]->f_op = &read_pipe_fops;
 448         f[0]->f_mode = 1;               /* read */
 449         f[1]->f_flags = O_WRONLY;
 450         f[1]->f_op = &write_pipe_fops;
 451         f[1]->f_mode = 2;               /* write */
 452         return 0;
 453 }

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