/* * linux/fs/pipe.c * * Copyright (C) 1991, 1992, 1999 Linus Torvalds */ #include #include #include #include #include #include /* * Define this if you want SunOS compatibility wrt braindead * select behaviour on FIFO's. */ #ifdef __sparc__ #define FIFO_SUNOS_BRAINDAMAGE #else #undef FIFO_SUNOS_BRAINDAMAGE #endif /* * We use a start+len construction, which provides full use of the * allocated memory. * -- Florian Coosmann (FGC) * * Reads with count = 0 should always return 0. * -- Julian Bradfield 1999-06-07. */ /* Drop the inode semaphore and wait for a pipe event, atomically */ static void pipe_wait(struct inode * inode) { DECLARE_WAITQUEUE(wait, current); current->state = TASK_INTERRUPTIBLE; add_wait_queue(PIPE_WAIT(*inode), &wait); up(PIPE_SEM(*inode)); schedule(); remove_wait_queue(PIPE_WAIT(*inode), &wait); current->state = TASK_RUNNING; } static ssize_t pipe_read(struct file *filp, char *buf, size_t count, loff_t *ppos) { struct inode *inode = filp->f_dentry->d_inode; ssize_t size, read, ret; /* Seeks are not allowed on pipes. */ ret = -ESPIPE; if (ppos != &filp->f_pos) goto out_nolock; /* Always return 0 on null read. */ ret = 0; if (count == 0) goto out_nolock; /* Get the pipe semaphore */ ret = -ERESTARTSYS; if (down_interruptible(PIPE_SEM(*inode))) goto out_nolock; if (PIPE_EMPTY(*inode)) { ret = 0; if (!PIPE_WRITERS(*inode)) goto out; ret = -EAGAIN; if (filp->f_flags & O_NONBLOCK) goto out; for (;;) { pipe_wait(inode); ret = -ERESTARTSYS; if (signal_pending(current)) goto out_nolock; if (down_interruptible(PIPE_SEM(*inode))) goto out_nolock; ret = 0; if (!PIPE_EMPTY(*inode)) break; if (!PIPE_WRITERS(*inode)) goto out; } } /* Read what data is available. */ ret = -EFAULT; read = 0; while (count > 0 && (size = PIPE_LEN(*inode))) { char *pipebuf = PIPE_BASE(*inode) + PIPE_START(*inode); ssize_t chars = PIPE_MAX_RCHUNK(*inode); if (chars > count) chars = count; if (chars > size) chars = size; if (copy_to_user(buf, pipebuf, chars)) goto out; read += chars; PIPE_START(*inode) += chars; PIPE_START(*inode) &= (PIPE_SIZE - 1); PIPE_LEN(*inode) -= chars; count -= chars; buf += chars; } /* Cache behaviour optimization */ if (!PIPE_LEN(*inode)) PIPE_START(*inode) = 0; /* Signal writers there is more room. */ wake_up_interruptible(PIPE_WAIT(*inode)); if (read) UPDATE_ATIME(inode); ret = read; out: up(PIPE_SEM(*inode)); out_nolock: return ret; } static ssize_t pipe_write(struct file *filp, const char *buf, size_t count, loff_t *ppos) { struct inode *inode = filp->f_dentry->d_inode; ssize_t free, written, ret; /* Seeks are not allowed on pipes. */ ret = -ESPIPE; if (ppos != &filp->f_pos) goto out_nolock; /* Null write succeeds. */ ret = 0; if (count == 0) goto out_nolock; ret = -ERESTARTSYS; if (down_interruptible(PIPE_SEM(*inode))) goto out_nolock; /* No readers yields SIGPIPE. */ if (!PIPE_READERS(*inode)) goto sigpipe; /* If count <= PIPE_BUF, we have to make it atomic. */ free = (count <= PIPE_BUF ? count : 1); written = 0; /* Wait, or check for, available space. */ if (filp->f_flags & O_NONBLOCK) { ret = -EAGAIN; if (PIPE_FREE(*inode) < free) goto out; } else { while (PIPE_FREE(*inode) < free) { pipe_wait(inode); ret = -ERESTARTSYS; if (signal_pending(current)) goto out_nolock; if (down_interruptible(PIPE_SEM(*inode))) goto out_nolock; if (!PIPE_READERS(*inode)) goto sigpipe; } } /* Copy into available space. */ ret = -EFAULT; while (count > 0) { int space; char *pipebuf = PIPE_BASE(*inode) + PIPE_END(*inode); ssize_t chars = PIPE_MAX_WCHUNK(*inode); if ((space = PIPE_FREE(*inode)) != 0) { if (chars > count) chars = count; if (chars > space) chars = space; if (copy_from_user(pipebuf, buf, chars)) goto out; written += chars; PIPE_LEN(*inode) += chars; count -= chars; buf += chars; space = PIPE_FREE(*inode); continue; } ret = written; if (filp->f_flags & O_NONBLOCK) break; do { /* This should be a synchronous wake-up: don't do idle reschedules! */ wake_up_interruptible(PIPE_WAIT(*inode)); pipe_wait(inode); if (signal_pending(current)) goto out_nolock; if (down_interruptible(PIPE_SEM(*inode))) goto out_nolock; if (!PIPE_READERS(*inode)) goto sigpipe; } while (!PIPE_FREE(*inode)); ret = -EFAULT; } /* Signal readers there is more data. */ wake_up_interruptible(PIPE_WAIT(*inode)); ret = (written ? written : -EAGAIN); inode->i_ctime = inode->i_mtime = CURRENT_TIME; mark_inode_dirty(inode); out: up(PIPE_SEM(*inode)); out_nolock: return ret; sigpipe: up(PIPE_SEM(*inode)); send_sig(SIGPIPE, current, 0); return -EPIPE; } static loff_t pipe_lseek(struct file *file, loff_t offset, int orig) { return -ESPIPE; } static ssize_t bad_pipe_r(struct file *filp, char *buf, size_t count, loff_t *ppos) { return -EBADF; } static ssize_t bad_pipe_w(struct file *filp, const char *buf, size_t count, loff_t *ppos) { return -EBADF; } static int pipe_ioctl(struct inode *pino, struct file *filp, unsigned int cmd, unsigned long arg) { switch (cmd) { case FIONREAD: return put_user(PIPE_LEN(*pino), (int *)arg); default: return -EINVAL; } } static unsigned int pipe_poll(struct file *filp, poll_table *wait) { unsigned int mask; struct inode *inode = filp->f_dentry->d_inode; poll_wait(filp, PIPE_WAIT(*inode), wait); /* Reading only -- no need for aquiring the semaphore. */ mask = POLLIN | POLLRDNORM; if (PIPE_EMPTY(*inode)) mask = POLLOUT | POLLWRNORM; if (!PIPE_WRITERS(*inode)) mask |= POLLHUP; if (!PIPE_READERS(*inode)) mask |= POLLERR; return mask; } #ifdef FIFO_SUNOS_BRAINDAMAGE /* * Argh! Why does SunOS have to have different select() behaviour * for pipes and FIFOs? Hate, hate, hate! SunOS lacks POLLHUP. */ static unsigned int fifo_poll(struct file *filp, poll_table *wait) { unsigned int mask; struct inode *inode = filp->f_dentry->d_inode; poll_wait(filp, PIPE_WAIT(*inode), wait); /* Reading only -- no need for aquiring the semaphore. */ mask = POLLIN | POLLRDNORM; if (PIPE_EMPTY(*inode)) mask = POLLOUT | POLLWRNORM; if (!PIPE_READERS(*inode)) mask |= POLLERR; return mask; } #else #define fifo_poll pipe_poll #endif /* FIFO_SUNOS_BRAINDAMAGE */ /* * The 'connect_xxx()' functions are needed for named pipes when * the open() code hasn't guaranteed a connection (O_NONBLOCK), * and we need to act differently until we do get a writer.. */ static ssize_t connect_read(struct file *filp, char *buf, size_t count, loff_t *ppos) { struct inode *inode = filp->f_dentry->d_inode; /* Reading only -- no need for aquiring the semaphore. */ if (PIPE_EMPTY(*inode) && !PIPE_WRITERS(*inode)) return 0; filp->f_op = &read_fifo_fops; return pipe_read(filp, buf, count, ppos); } static unsigned int connect_poll(struct file *filp, poll_table *wait) { struct inode *inode = filp->f_dentry->d_inode; unsigned int mask = 0; poll_wait(filp, PIPE_WAIT(*inode), wait); /* Reading only -- no need for aquiring the semaphore. */ if (!PIPE_EMPTY(*inode)) { filp->f_op = &read_fifo_fops; mask = POLLIN | POLLRDNORM; } else if (PIPE_WRITERS(*inode)) { filp->f_op = &read_fifo_fops; mask = POLLOUT | POLLWRNORM; } return mask; } static int pipe_release(struct inode *inode, int decr, int decw) { down(PIPE_SEM(*inode)); PIPE_READERS(*inode) -= decr; PIPE_WRITERS(*inode) -= decw; if (!PIPE_READERS(*inode) && !PIPE_WRITERS(*inode)) { struct pipe_inode_info *info = inode->i_pipe; inode->i_pipe = NULL; free_page((unsigned long) info->base); kfree(info); } else { wake_up_interruptible(PIPE_WAIT(*inode)); } up(PIPE_SEM(*inode)); return 0; } static int pipe_read_release(struct inode *inode, struct file *filp) { return pipe_release(inode, 1, 0); } static int pipe_write_release(struct inode *inode, struct file *filp) { return pipe_release(inode, 0, 1); } static int pipe_rdwr_release(struct inode *inode, struct file *filp) { int decr, decw; decr = (filp->f_mode & FMODE_READ) != 0; decw = (filp->f_mode & FMODE_WRITE) != 0; return pipe_release(inode, decr, decw); } static int pipe_read_open(struct inode *inode, struct file *filp) { /* We could have perhaps used atomic_t, but this and friends below are the only places. So it doesn't seem worthwhile. */ down(PIPE_SEM(*inode)); PIPE_READERS(*inode)++; up(PIPE_SEM(*inode)); return 0; } static int pipe_write_open(struct inode *inode, struct file *filp) { down(PIPE_SEM(*inode)); PIPE_WRITERS(*inode)++; up(PIPE_SEM(*inode)); return 0; } static int pipe_rdwr_open(struct inode *inode, struct file *filp) { down(PIPE_SEM(*inode)); if (filp->f_mode & FMODE_READ) PIPE_READERS(*inode)++; if (filp->f_mode & FMODE_WRITE) PIPE_WRITERS(*inode)++; up(PIPE_SEM(*inode)); return 0; } /* * The file_operations structs are not static because they * are also used in linux/fs/fifo.c to do operations on FIFOs. */ struct file_operations connecting_fifo_fops = { pipe_lseek, connect_read, bad_pipe_w, NULL, /* no readdir */ connect_poll, pipe_ioctl, NULL, /* no mmap on pipes.. surprise */ pipe_read_open, NULL, /* flush */ pipe_read_release, NULL }; struct file_operations read_fifo_fops = { pipe_lseek, pipe_read, bad_pipe_w, NULL, /* no readdir */ fifo_poll, pipe_ioctl, NULL, /* no mmap on pipes.. surprise */ pipe_read_open, NULL, /* flush */ pipe_read_release, NULL }; struct file_operations write_fifo_fops = { pipe_lseek, bad_pipe_r, pipe_write, NULL, /* no readdir */ fifo_poll, pipe_ioctl, NULL, /* mmap */ pipe_write_open, NULL, /* flush */ pipe_write_release, NULL }; struct file_operations rdwr_fifo_fops = { pipe_lseek, pipe_read, pipe_write, NULL, /* no readdir */ fifo_poll, pipe_ioctl, NULL, /* mmap */ pipe_rdwr_open, NULL, /* flush */ pipe_rdwr_release, NULL }; struct file_operations read_pipe_fops = { pipe_lseek, pipe_read, bad_pipe_w, NULL, /* no readdir */ pipe_poll, pipe_ioctl, NULL, /* no mmap on pipes.. surprise */ pipe_read_open, NULL, /* flush */ pipe_read_release, NULL }; struct file_operations write_pipe_fops = { pipe_lseek, bad_pipe_r, pipe_write, NULL, /* no readdir */ pipe_poll, pipe_ioctl, NULL, /* mmap */ pipe_write_open, NULL, /* flush */ pipe_write_release, NULL }; struct file_operations rdwr_pipe_fops = { pipe_lseek, pipe_read, pipe_write, NULL, /* no readdir */ pipe_poll, pipe_ioctl, NULL, /* mmap */ pipe_rdwr_open, NULL, /* flush */ pipe_rdwr_release, NULL }; static struct inode * get_pipe_inode(void) { extern struct inode_operations pipe_inode_operations; struct inode *inode = get_empty_inode(); unsigned long page; if (!inode) goto fail_inode; page = __get_free_page(GFP_USER); if (!page) goto fail_iput; inode->i_pipe = kmalloc(sizeof(struct pipe_inode_info), GFP_KERNEL); if (!inode->i_pipe) goto fail_page; inode->i_op = &pipe_inode_operations; init_waitqueue_head(PIPE_WAIT(*inode)); PIPE_BASE(*inode) = (char *) page; PIPE_START(*inode) = PIPE_LEN(*inode) = 0; PIPE_READERS(*inode) = PIPE_WRITERS(*inode) = 1; /* * Mark the inode dirty from the very beginning, * that way it will never be moved to the dirty * list because "mark_inode_dirty()" will think * that it already _is_ on the dirty list. */ inode->i_state = I_DIRTY; inode->i_mode = S_IFIFO | S_IRUSR | S_IWUSR; inode->i_uid = current->fsuid; inode->i_gid = current->fsgid; inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; inode->i_blksize = PAGE_SIZE; return inode; fail_page: free_page(page); fail_iput: iput(inode); fail_inode: return NULL; } struct inode_operations pipe_inode_operations = { &rdwr_pipe_fops, NULL, /* create */ NULL, /* lookup */ NULL, /* link */ NULL, /* unlink */ NULL, /* symlink */ NULL, /* mkdir */ NULL, /* rmdir */ NULL, /* mknod */ NULL, /* rename */ NULL, /* readlink */ NULL, /* follow_link */ NULL, /* get_block */ NULL, /* readpage */ NULL, /* writepage */ NULL, /* flushpage */ NULL, /* truncate */ NULL, /* permission */ NULL, /* smap */ NULL /* revalidate */ }; int do_pipe(int *fd) { struct inode * inode; struct file *f1, *f2; int error; int i,j; error = -ENFILE; f1 = get_empty_filp(); if (!f1) goto no_files; f2 = get_empty_filp(); if (!f2) goto close_f1; inode = get_pipe_inode(); if (!inode) goto close_f12; error = get_unused_fd(); if (error < 0) goto close_f12_inode; i = error; error = get_unused_fd(); if (error < 0) goto close_f12_inode_i; j = error; error = -ENOMEM; f1->f_dentry = f2->f_dentry = dget(d_alloc_root(inode)); if (!f1->f_dentry) goto close_f12_inode_i_j; /* read file */ f1->f_pos = f2->f_pos = 0; f1->f_flags = O_RDONLY; f1->f_op = &read_pipe_fops; f1->f_mode = 1; /* write file */ f2->f_flags = O_WRONLY; f2->f_op = &write_pipe_fops; f2->f_mode = 2; fd_install(i, f1); fd_install(j, f2); fd[0] = i; fd[1] = j; return 0; close_f12_inode_i_j: put_unused_fd(j); close_f12_inode_i: put_unused_fd(i); close_f12_inode: free_page((unsigned long) PIPE_BASE(*inode)); kfree(inode->i_pipe); inode->i_pipe = NULL; iput(inode); close_f12: put_filp(f2); close_f1: put_filp(f1); no_files: return error; }