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. fifo_select
  9. connect_read
  10. connect_select
  11. pipe_read_release
  12. pipe_write_release
  13. pipe_rdwr_release
  14. 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 written?written:-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 long arg)
 112 {
 113         int error;
 114 
 115         switch (cmd) {
 116                 case FIONREAD:
 117                         error = verify_area(VERIFY_WRITE, (void *) arg,4);
 118                         if (!error)
 119                                 put_fs_long(PIPE_SIZE(*pino),(unsigned long *) arg);
 120                         return error;
 121                 default:
 122                         return -EINVAL;
 123         }
 124 }
 125 
 126 static int pipe_select(struct inode * inode, struct file * filp, int sel_type, select_table * wait)
     /* [previous][next][first][last][top][bottom][index][help] */
 127 {
 128         switch (sel_type) {
 129                 case SEL_IN:
 130                         if (!PIPE_EMPTY(*inode) || !PIPE_WRITERS(*inode))
 131                                 return 1;
 132                         select_wait(&PIPE_READ_WAIT(*inode), wait);
 133                         return 0;
 134                 case SEL_OUT:
 135                         if (!PIPE_FULL(*inode) || !PIPE_READERS(*inode))
 136                                 return 1;
 137                         select_wait(&PIPE_WRITE_WAIT(*inode), wait);
 138                         return 0;
 139                 case SEL_EX:
 140                         if (!PIPE_READERS(*inode) || !PIPE_WRITERS(*inode))
 141                                 return 1;
 142                         select_wait(&inode->i_wait,wait);
 143                         return 0;
 144         }
 145         return 0;
 146 }
 147 
 148 /*
 149  * Arggh. Why does SunOS have to have different select() behaviour
 150  * for pipes and fifos? Hate-Hate-Hate. See difference in SEL_IN..
 151  */
 152 static int fifo_select(struct inode * inode, struct file * filp, int sel_type, select_table * wait)
     /* [previous][next][first][last][top][bottom][index][help] */
 153 {
 154         switch (sel_type) {
 155                 case SEL_IN:
 156                         if (!PIPE_EMPTY(*inode))
 157                                 return 1;
 158                         select_wait(&PIPE_READ_WAIT(*inode), wait);
 159                         return 0;
 160                 case SEL_OUT:
 161                         if (!PIPE_FULL(*inode) || !PIPE_READERS(*inode))
 162                                 return 1;
 163                         select_wait(&PIPE_WRITE_WAIT(*inode), wait);
 164                         return 0;
 165                 case SEL_EX:
 166                         if (!PIPE_READERS(*inode) || !PIPE_WRITERS(*inode))
 167                                 return 1;
 168                         select_wait(&inode->i_wait,wait);
 169                         return 0;
 170         }
 171         return 0;
 172 }
 173 
 174 /*
 175  * The 'connect_xxx()' functions are needed for named pipes when
 176  * the open() code hasn't guaranteed a connection (O_NONBLOCK),
 177  * and we need to act differently until we do get a writer..
 178  */
 179 static int connect_read(struct inode * inode, struct file * filp, char * buf, int count)
     /* [previous][next][first][last][top][bottom][index][help] */
 180 {
 181         while (!PIPE_SIZE(*inode)) {
 182                 if (PIPE_WRITERS(*inode))
 183                         break;
 184                 if (filp->f_flags & O_NONBLOCK)
 185                         return -EAGAIN;
 186                 wake_up(& PIPE_WRITE_WAIT(*inode));
 187                 if (current->signal & ~current->blocked)
 188                         return -ERESTARTSYS;
 189                 interruptible_sleep_on(& PIPE_READ_WAIT(*inode));
 190         }
 191         filp->f_op = &read_fifo_fops;
 192         return pipe_read(inode,filp,buf,count);
 193 }
 194 
 195 static int connect_select(struct inode * inode, struct file * filp, int sel_type, select_table * wait)
     /* [previous][next][first][last][top][bottom][index][help] */
 196 {
 197         switch (sel_type) {
 198                 case SEL_IN:
 199                         if (!PIPE_EMPTY(*inode)) {
 200                                 filp->f_op = &read_fifo_fops;
 201                                 return 1;
 202                         }
 203                         select_wait(&PIPE_READ_WAIT(*inode), wait);
 204                         return 0;
 205                 case SEL_OUT:
 206                         if (!PIPE_FULL(*inode))
 207                                 return 1;
 208                         select_wait(&PIPE_WRITE_WAIT(*inode), wait);
 209                         return 0;
 210                 case SEL_EX:
 211                         if (!PIPE_READERS(*inode) || !PIPE_WRITERS(*inode))
 212                                 return 1;
 213                         select_wait(&inode->i_wait,wait);
 214                         return 0;
 215         }
 216         return 0;
 217 }
 218 
 219 /*
 220  * Ok, these three routines NOW keep track of readers/writers,
 221  * Linus previously did it with inode->i_count checking.
 222  */
 223 static void pipe_read_release(struct inode * inode, struct file * filp)
     /* [previous][next][first][last][top][bottom][index][help] */
 224 {
 225         PIPE_READERS(*inode)--;
 226         wake_up(&PIPE_WRITE_WAIT(*inode));
 227 }
 228 
 229 static void pipe_write_release(struct inode * inode, struct file * filp)
     /* [previous][next][first][last][top][bottom][index][help] */
 230 {
 231         PIPE_WRITERS(*inode)--;
 232         wake_up(&PIPE_READ_WAIT(*inode));
 233 }
 234 
 235 static void pipe_rdwr_release(struct inode * inode, struct file * filp)
     /* [previous][next][first][last][top][bottom][index][help] */
 236 {
 237         PIPE_READERS(*inode)--;
 238         PIPE_WRITERS(*inode)--;
 239         wake_up(&PIPE_READ_WAIT(*inode));
 240         wake_up(&PIPE_WRITE_WAIT(*inode));
 241 }
 242 
 243 /*
 244  * The file_operations structs are not static because they
 245  * are also used in linux/fs/fifo.c to do operations on fifo's.
 246  */
 247 struct file_operations connecting_fifo_fops = {
 248         pipe_lseek,
 249         connect_read,
 250         bad_pipe_rw,
 251         pipe_readdir,
 252         connect_select,
 253         pipe_ioctl,
 254         NULL,           /* no mmap on pipes.. surprise */
 255         NULL,           /* no special open code */
 256         pipe_read_release,
 257         NULL
 258 };
 259 
 260 struct file_operations read_fifo_fops = {
 261         pipe_lseek,
 262         pipe_read,
 263         bad_pipe_rw,
 264         pipe_readdir,
 265         fifo_select,
 266         pipe_ioctl,
 267         NULL,           /* no mmap on pipes.. surprise */
 268         NULL,           /* no special open code */
 269         pipe_read_release,
 270         NULL
 271 };
 272 
 273 struct file_operations write_fifo_fops = {
 274         pipe_lseek,
 275         bad_pipe_rw,
 276         pipe_write,
 277         pipe_readdir,
 278         fifo_select,
 279         pipe_ioctl,
 280         NULL,           /* mmap */
 281         NULL,           /* no special open code */
 282         pipe_write_release,
 283         NULL
 284 };
 285 
 286 struct file_operations rdwr_fifo_fops = {
 287         pipe_lseek,
 288         pipe_read,
 289         pipe_write,
 290         pipe_readdir,
 291         fifo_select,
 292         pipe_ioctl,
 293         NULL,           /* mmap */
 294         NULL,           /* no special open code */
 295         pipe_rdwr_release,
 296         NULL
 297 };
 298 
 299 struct file_operations read_pipe_fops = {
 300         pipe_lseek,
 301         pipe_read,
 302         bad_pipe_rw,
 303         pipe_readdir,
 304         pipe_select,
 305         pipe_ioctl,
 306         NULL,           /* no mmap on pipes.. surprise */
 307         NULL,           /* no special open code */
 308         pipe_read_release,
 309         NULL
 310 };
 311 
 312 struct file_operations write_pipe_fops = {
 313         pipe_lseek,
 314         bad_pipe_rw,
 315         pipe_write,
 316         pipe_readdir,
 317         pipe_select,
 318         pipe_ioctl,
 319         NULL,           /* mmap */
 320         NULL,           /* no special open code */
 321         pipe_write_release,
 322         NULL
 323 };
 324 
 325 struct file_operations rdwr_pipe_fops = {
 326         pipe_lseek,
 327         pipe_read,
 328         pipe_write,
 329         pipe_readdir,
 330         pipe_select,
 331         pipe_ioctl,
 332         NULL,           /* mmap */
 333         NULL,           /* no special open code */
 334         pipe_rdwr_release,
 335         NULL
 336 };
 337 
 338 struct inode_operations pipe_inode_operations = {
 339         &rdwr_pipe_fops,
 340         NULL,                   /* create */
 341         NULL,                   /* lookup */
 342         NULL,                   /* link */
 343         NULL,                   /* unlink */
 344         NULL,                   /* symlink */
 345         NULL,                   /* mkdir */
 346         NULL,                   /* rmdir */
 347         NULL,                   /* mknod */
 348         NULL,                   /* rename */
 349         NULL,                   /* readlink */
 350         NULL,                   /* follow_link */
 351         NULL,                   /* bmap */
 352         NULL,                   /* truncate */
 353         NULL                    /* permission */
 354 };
 355 
 356 asmlinkage int sys_pipe(unsigned long * fildes)
     /* [previous][next][first][last][top][bottom][index][help] */
 357 {
 358         struct inode * inode;
 359         struct file * f[2];
 360         int fd[2];
 361         int i,j;
 362 
 363         j = verify_area(VERIFY_WRITE,fildes,8);
 364         if (j)
 365                 return j;
 366         for(j=0 ; j<2 ; j++)
 367                 if (!(f[j] = get_empty_filp()))
 368                         break;
 369         if (j==1)
 370                 f[0]->f_count--;
 371         if (j<2)
 372                 return -ENFILE;
 373         j=0;
 374         for(i=0;j<2 && i<NR_OPEN;i++)
 375                 if (!current->filp[i]) {
 376                         current->filp[ fd[j]=i ] = f[j];
 377                         j++;
 378                 }
 379         if (j==1)
 380                 current->filp[fd[0]]=NULL;
 381         if (j<2) {
 382                 f[0]->f_count--;
 383                 f[1]->f_count--;
 384                 return -EMFILE;
 385         }
 386         if (!(inode=get_pipe_inode())) {
 387                 current->filp[fd[0]] = NULL;
 388                 current->filp[fd[1]] = NULL;
 389                 f[0]->f_count--;
 390                 f[1]->f_count--;
 391                 return -ENFILE;
 392         }
 393         f[0]->f_inode = f[1]->f_inode = inode;
 394         f[0]->f_pos = f[1]->f_pos = 0;
 395         f[0]->f_flags = O_RDONLY;
 396         f[0]->f_op = &read_pipe_fops;
 397         f[0]->f_mode = 1;               /* read */
 398         f[1]->f_flags = O_WRONLY;
 399         f[1]->f_op = &write_pipe_fops;
 400         f[1]->f_mode = 2;               /* write */
 401         put_fs_long(fd[0],0+fildes);
 402         put_fs_long(fd[1],1+fildes);
 403         return 0;
 404 }

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