static struct inode * get_pipe_inode(void) { extern struct inode_operations pipe_inode_operations; struct inode *inode = get_empty_inode(); if (inode) { unsigned long page = __get_free_page(GFP_USER); if (!page) { iput(inode); inode = NULL; } else { PIPE_BASE(*inode) = (char *) page; inode->i_op = &pipe_inode_operations; PIPE_WAIT(*inode) = NULL; PIPE_START(*inode) = PIPE_LEN(*inode) = 0; PIPE_RD_OPENERS(*inode) = PIPE_WR_OPENERS(*inode) = 0; PIPE_READERS(*inode) = PIPE_WRITERS(*inode) = 1; PIPE_LOCK(*inode) = 0; /* * 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; }
struct inode *get_pipe_inode(void) { register struct inode *inode; extern struct inode_operations pipe_inode_operations; if ((inode = get_empty_inode())) { if (!(PIPE_BASE(*inode) = get_pipe_mem())) { iput(inode); return NULL; } inode->i_op = &pipe_inode_operations; inode->i_count = 2; /* sum of readers/writers */ PIPE_START(*inode) = PIPE_LEN(*inode) = 0; PIPE_RD_OPENERS(*inode) = PIPE_WR_OPENERS(*inode) = 0; PIPE_READERS(*inode) = PIPE_WRITERS(*inode) = 1; PIPE_LOCK(*inode) = 0; inode->i_pipe = 1; inode->i_mode |= S_IFIFO | S_IRUSR | S_IWUSR; inode->i_uid = current->euid; inode->i_gid = (__u8) current->egid; inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; #if 0 inode->i_blksize = PAGE_SIZE; #endif } return inode; }
struct inode* pipe_new(struct inode* inode) { unsigned long page; page = __get_free_page(GFP_USER); if (!page) return NULL; inode->i_pipe = kmalloc(sizeof(struct pipe_inode_info), GFP_KERNEL); if (!inode->i_pipe) goto fail_page; init_waitqueue_head(PIPE_WAIT(*inode)); PIPE_BASE(*inode) = (char*) page; PIPE_START(*inode) = PIPE_LEN(*inode) = 0; PIPE_READERS(*inode) = PIPE_WRITERS(*inode) = 0; PIPE_WAITING_WRITERS(*inode) = 0; PIPE_RCOUNTER(*inode) = PIPE_WCOUNTER(*inode) = 1; *PIPE_FASYNC_READERS(*inode) = *PIPE_FASYNC_WRITERS(*inode) = NULL; return inode; fail_page: free_page(page); return NULL; }
static struct inode * get_pipe_inode(void) { struct inode *inode = new_inode(pipe_mnt->mnt_sb); if (!inode) goto fail_inode; if(!pipe_new(inode)) goto fail_iput; PIPE_READERS(*inode) = PIPE_WRITERS(*inode) = 1; inode->i_fop = &rdwr_pipe_fops; /* * 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_iput: iput(inode); fail_inode: return NULL; }
static int pipe_rdwr_open(struct inode * inode, struct file * filp) { if (filp->f_mode & FMODE_READ) PIPE_READERS(*inode)++; if (filp->f_mode & FMODE_WRITE) PIPE_WRITERS(*inode)++; return 0; }
static int pipe_rdwr_release(struct inode * inode, struct file * filp) { if (filp->f_mode & FMODE_READ) PIPE_READERS(*inode)--; if (filp->f_mode & FMODE_WRITE) PIPE_WRITERS(*inode)--; return pipe_release(inode); }
static int pipe_release(struct inode * inode) { if (!PIPE_READERS(*inode) && !PIPE_WRITERS(*inode)) { free_page((unsigned long) PIPE_BASE(*inode)); PIPE_BASE(*inode) = NULL; } wake_up_interruptible(&PIPE_WAIT(*inode)); return 0; }
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_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; }
void init_fifo(struct inode * inode) { inode->i_op = &fifo_inode_operations; inode->i_pipe = 1; PIPE_LOCK(*inode) = 0; PIPE_BASE(*inode) = NULL; PIPE_START(*inode) = PIPE_LEN(*inode) = 0; PIPE_RD_OPENERS(*inode) = PIPE_WR_OPENERS(*inode) = 0; PIPE_WAIT(*inode) = NULL; PIPE_READERS(*inode) = PIPE_WRITERS(*inode) = 0; }
int PipeClose(struct File* file) { struct PipeInfo* info = (struct PipeInfo*)(file->vNode->extraInfo); /* TODO: Free info if there are no readers and no writers. */ if (file->vNode->mode & VFS_ATTR_READ) PIPE_READERS(file)--; if (file->vNode->mode & VFS_ATTR_WRITE) PIPE_WRITERS(file)--; if (!PIPE_READERS(file) && !PIPE_WRITERS(file)) { /* Remove the pipe. FIXME: Finish. */ MemFree(info->base); MemFree(info); } return 0; }
static ssize_t pipe_write(struct file *filp, const char __user *buf, size_t count, loff_t *ppos) { struct iovec iov = { .iov_base = (void __user *)buf, .iov_len = count }; return pipe_writev(filp, &iov, 1, ppos); } static ssize_t bad_pipe_r(struct file *filp, char __user *buf, size_t count, loff_t *ppos) { return -EBADF; } static ssize_t bad_pipe_w(struct file *filp, const char __user *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 __user *)arg); default: return -EINVAL; } } /* No kernel lock held - fine */ 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 acquiring the semaphore. */ mask = POLLIN | POLLRDNORM; if (PIPE_EMPTY(*inode)) mask = POLLOUT | POLLWRNORM; if (!PIPE_WRITERS(*inode) && filp->f_version != PIPE_WCOUNTER(*inode)) mask |= POLLHUP; if (!PIPE_READERS(*inode)) mask |= POLLERR; return mask; }
/* * 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); mask = POLLIN | POLLRDNORM; if (PIPE_EMPTY(*inode)) mask = POLLOUT | POLLWRNORM; if (!PIPE_READERS(*inode)) mask |= POLLERR; return mask; }
static int pipe_read_open(struct inode *inode, struct file *filp) { int ret = -ENOENT; down(PIPE_SEM(*inode)); if (inode->i_pipe) { ret = 0; PIPE_READERS(*inode)++; } up(PIPE_SEM(*inode)); return ret; }
static int pipe_rdwr_open(struct inode *inode, struct file *filp) { int ret = -ENOENT; down(PIPE_SEM(*inode)); if (inode->i_pipe) { ret = 0; if (filp->f_mode & FMODE_READ) PIPE_READERS(*inode)++; if (filp->f_mode & FMODE_WRITE) PIPE_WRITERS(*inode)++; } up(PIPE_SEM(*inode)); return ret; }
void minix_read_inode(struct inode * inode) { struct buffer_head * bh; struct minix_inode * raw_inode; int block; block = 2 + inode->i_sb->u.minix_sb.s_imap_blocks + inode->i_sb->u.minix_sb.s_zmap_blocks + (inode->i_ino-1)/MINIX_INODES_PER_BLOCK; if (!(bh=bread(inode->i_dev,block, BLOCK_SIZE))) panic("unable to read i-node block"); raw_inode = ((struct minix_inode *) bh->b_data) + (inode->i_ino-1)%MINIX_INODES_PER_BLOCK; inode->i_mode = raw_inode->i_mode; inode->i_uid = raw_inode->i_uid; inode->i_gid = raw_inode->i_gid; inode->i_nlink = raw_inode->i_nlinks; inode->i_size = raw_inode->i_size; inode->i_mtime = inode->i_atime = inode->i_ctime = raw_inode->i_time; inode->i_blocks = inode->i_blksize = 0; if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) inode->i_rdev = raw_inode->i_zone[0]; else for (block = 0; block < 9; block++) inode->u.minix_i.i_data[block] = raw_inode->i_zone[block]; brelse(bh); inode->i_op = NULL; if (S_ISREG(inode->i_mode)) inode->i_op = &minix_file_inode_operations; else if (S_ISDIR(inode->i_mode)) inode->i_op = &minix_dir_inode_operations; else if (S_ISLNK(inode->i_mode)) inode->i_op = &minix_symlink_inode_operations; else if (S_ISCHR(inode->i_mode)) inode->i_op = &minix_chrdev_inode_operations; else if (S_ISBLK(inode->i_mode)) inode->i_op = &minix_blkdev_inode_operations; else if (S_ISFIFO(inode->i_mode)) { inode->i_op = &minix_fifo_inode_operations; inode->i_pipe = 1; PIPE_BASE(*inode) = NULL; PIPE_HEAD(*inode) = PIPE_TAIL(*inode) = 0; PIPE_READ_WAIT(*inode) = PIPE_WRITE_WAIT(*inode) = NULL; PIPE_READERS(*inode) = PIPE_WRITERS(*inode) = 0; } }
static int pipe_rdwr_open(register struct inode *inode, register struct file *filp) { debug("PIPE: rdwr called.\n"); if(!PIPE_BASE(*inode)) { if(!(PIPE_BASE(*inode) = get_pipe_mem())) return -ENOMEM; #if 0 /* next fields already set to zero by get_empty_inode() */ PIPE_START(*inode) = PIPE_LEN(*inode) = 0; PIPE_RD_OPENERS(*inode) = PIPE_WR_OPENERS(*inode) = 0; PIPE_READERS(*inode) = PIPE_WRITERS(*inode) = 0; PIPE_LOCK(*inode) = 0; #endif } if (filp->f_mode & FMODE_READ) { (inode->u.pipe_i.readers)++; if(inode->u.pipe_i.writers > 0) { if(inode->u.pipe_i.readers < 2) wake_up_interruptible(&(inode->u.pipe_i.wait)); } else { if(!(filp->f_flags & O_NONBLOCK) && (inode->i_sb)) while(!(inode->u.pipe_i.writers)) interruptible_sleep_on(&(inode->u.pipe_i.wait)); } } if (filp->f_mode & FMODE_WRITE) { (inode->u.pipe_i.writers)++; if(inode->u.pipe_i.readers > 0) { if(inode->u.pipe_i.writers < 2) wake_up_interruptible(&(inode->u.pipe_i.wait)); } else { if(filp->f_flags & O_NONBLOCK) return -ENXIO; while(!(inode->u.pipe_i.readers)) interruptible_sleep_on(&(inode->u.pipe_i.wait)); } } return 0; }
/* No kernel lock held - fine */ 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 acquiring the semaphore. */ mask = POLLIN | POLLRDNORM; if (PIPE_EMPTY(*inode)) mask = POLLOUT | POLLWRNORM; if (!PIPE_WRITERS(*inode) && filp->f_version != PIPE_WCOUNTER(*inode)) mask |= POLLHUP; if (!PIPE_READERS(*inode)) mask |= POLLERR; return mask; }
static int fifo_open(struct inode * inode,struct file * filp) { int retval = 0; unsigned long page; switch( filp->f_mode ) { case 1: /* * O_RDONLY * POSIX.1 says that O_NONBLOCK means return with the FIFO * opened, even when there is no process writing the FIFO. */ filp->f_op = &connecting_fifo_fops; if (!PIPE_READERS(*inode)++) wake_up_interruptible(&PIPE_WAIT(*inode)); if (!(filp->f_flags & O_NONBLOCK) && !PIPE_WRITERS(*inode)) { PIPE_RD_OPENERS(*inode)++; while (!PIPE_WRITERS(*inode)) { if (current->signal & ~current->blocked) { retval = -ERESTARTSYS; break; } interruptible_sleep_on(&PIPE_WAIT(*inode)); } if (!--PIPE_RD_OPENERS(*inode)) wake_up_interruptible(&PIPE_WAIT(*inode)); } while (PIPE_WR_OPENERS(*inode)) interruptible_sleep_on(&PIPE_WAIT(*inode)); if (PIPE_WRITERS(*inode)) filp->f_op = &read_fifo_fops; if (retval && !--PIPE_READERS(*inode)) wake_up_interruptible(&PIPE_WAIT(*inode)); break; case 2: /* * O_WRONLY * POSIX.1 says that O_NONBLOCK means return -1 with * errno=ENXIO when there is no process reading the FIFO. */ if ((filp->f_flags & O_NONBLOCK) && !PIPE_READERS(*inode)) { retval = -ENXIO; break; } filp->f_op = &write_fifo_fops; if (!PIPE_WRITERS(*inode)++) wake_up_interruptible(&PIPE_WAIT(*inode)); if (!PIPE_READERS(*inode)) { PIPE_WR_OPENERS(*inode)++; while (!PIPE_READERS(*inode)) { if (current->signal & ~current->blocked) { retval = -ERESTARTSYS; break; } interruptible_sleep_on(&PIPE_WAIT(*inode)); } if (!--PIPE_WR_OPENERS(*inode)) wake_up_interruptible(&PIPE_WAIT(*inode)); } while (PIPE_RD_OPENERS(*inode)) interruptible_sleep_on(&PIPE_WAIT(*inode)); if (retval && !--PIPE_WRITERS(*inode)) wake_up_interruptible(&PIPE_WAIT(*inode)); break; case 3: /* * O_RDWR * POSIX.1 leaves this case "undefined" when O_NONBLOCK is set. * This implementation will NEVER block on a O_RDWR open, since * the process can at least talk to itself. */ filp->f_op = &rdwr_fifo_fops; if (!PIPE_READERS(*inode)++) wake_up_interruptible(&PIPE_WAIT(*inode)); while (PIPE_WR_OPENERS(*inode)) interruptible_sleep_on(&PIPE_WAIT(*inode)); if (!PIPE_WRITERS(*inode)++) wake_up_interruptible(&PIPE_WAIT(*inode)); while (PIPE_RD_OPENERS(*inode)) interruptible_sleep_on(&PIPE_WAIT(*inode)); break; default: retval = -EINVAL; } if (retval || PIPE_BASE(*inode)) return retval; page = __get_free_page(GFP_KERNEL); if (PIPE_BASE(*inode)) { free_page(page); return 0; } if (!page) return -ENOMEM; PIPE_LOCK(*inode) = 0; PIPE_START(*inode) = PIPE_LEN(*inode) = 0; PIPE_BASE(*inode) = (char *) page; return 0; }
static int pipe_read_release(struct inode * inode, struct file * filp) { PIPE_READERS(*inode)--; return pipe_release(inode); }
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; written = 0; 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); /* 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_WAITING_WRITERS(*inode)++; pipe_wait(inode); PIPE_WAITING_WRITERS(*inode)--; ret = -ERESTARTSYS; if (signal_pending(current)) goto out; 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 { /* * Synchronous wake-up: it knows that this process * is going to give up this CPU, so it doesn't have * to do idle reschedules. */ wake_up_interruptible_sync(PIPE_WAIT(*inode)); PIPE_WAITING_WRITERS(*inode)++; pipe_wait(inode); PIPE_WAITING_WRITERS(*inode)--; if (signal_pending(current)) goto out; if (!PIPE_READERS(*inode)) goto sigpipe; } while (!PIPE_FREE(*inode)); ret = -EFAULT; } /* Signal readers asynchronously that there is more data. */ wake_up_interruptible(PIPE_WAIT(*inode)); update_mctime(inode); out: up(PIPE_SEM(*inode)); out_nolock: if (written) ret = written; return ret; sigpipe: if (written) goto out; up(PIPE_SEM(*inode)); send_sig(SIGPIPE, current, 0); return -EPIPE; }
static int pipe_read_open(struct inode * inode, struct file * filp) { PIPE_READERS(*inode)++; return 0; }
static ssize_t pipe_writev(struct file *filp, const struct iovec *_iov, unsigned long nr_segs, loff_t *ppos) { struct inode *inode = filp->f_dentry->d_inode; ssize_t ret; size_t min; int do_wakeup; struct iovec *iov = (struct iovec *)_iov; size_t total_len; total_len = iov_length(iov, nr_segs); /* Null write succeeds. */ if (unlikely(total_len == 0)) return 0; do_wakeup = 0; ret = 0; min = total_len; if (min > PIPE_BUF) min = 1; down(PIPE_SEM(*inode)); for (;;) { int free; if (!PIPE_READERS(*inode)) { send_sig(SIGPIPE, current, 0); if (!ret) ret = -EPIPE; break; } free = PIPE_FREE(*inode); if (free >= min) { /* transfer data */ ssize_t chars = PIPE_MAX_WCHUNK(*inode); char *pipebuf = PIPE_BASE(*inode) + PIPE_END(*inode); /* Always wakeup, even if the copy fails. Otherwise * we lock up (O_NONBLOCK-)readers that sleep due to * syscall merging. */ do_wakeup = 1; if (chars > total_len) chars = total_len; if (chars > free) chars = free; if (pipe_iov_copy_from_user(pipebuf, iov, chars)) { if (!ret) ret = -EFAULT; break; } ret += chars; PIPE_LEN(*inode) += chars; total_len -= chars; if (!total_len) break; } if (PIPE_FREE(*inode) && ret) { /* handle cyclic data buffers */ min = 1; continue; } if (filp->f_flags & O_NONBLOCK) { if (!ret) ret = -EAGAIN; break; } if (signal_pending(current)) { if (!ret) ret = -ERESTARTSYS; break; } if (do_wakeup) { wake_up_interruptible_sync(PIPE_WAIT(*inode)); kill_fasync(PIPE_FASYNC_READERS(*inode), SIGIO, POLL_IN); do_wakeup = 0; } PIPE_WAITING_WRITERS(*inode)++; pipe_wait(inode); PIPE_WAITING_WRITERS(*inode)--; } up(PIPE_SEM(*inode)); if (do_wakeup) { wake_up_interruptible(PIPE_WAIT(*inode)); kill_fasync(PIPE_FASYNC_READERS(*inode), SIGIO, POLL_IN); } /* * Hack: we turn off atime updates for -RT kernels. * Who uses them on pipes anyway? */ #ifndef CONFIG_PREEMPT_RT if (ret > 0) inode_update_time(inode, 1); /* mtime and ctime */ #endif 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 chars = 0, free = 0, written = 0, err=0; char *pipebuf; if (ppos != &filp->f_pos) return -ESPIPE; if (!PIPE_READERS(*inode)) { /* no readers */ send_sig(SIGPIPE,current,0); return -EPIPE; } /* if count <= PIPE_BUF, we have to make it atomic */ if (count <= PIPE_BUF) free = count; else free = 1; /* can't do it atomically, wait for any free space */ up(&inode->i_sem); if (down_interruptible(&inode->i_atomic_write)) { down(&inode->i_sem); return -ERESTARTSYS; } while (count>0) { while ((PIPE_FREE(*inode) < free) || PIPE_LOCK(*inode)) { if (!PIPE_READERS(*inode)) { /* no readers */ send_sig(SIGPIPE,current,0); err = -EPIPE; goto errout; } if (signal_pending(current)) { err = -ERESTARTSYS; goto errout; } if (filp->f_flags & O_NONBLOCK) { err = -EAGAIN; goto errout; } interruptible_sleep_on(&PIPE_WAIT(*inode)); } PIPE_LOCK(*inode)++; while (count>0 && (free = PIPE_FREE(*inode))) { chars = PIPE_MAX_WCHUNK(*inode); if (chars > count) chars = count; if (chars > free) chars = free; pipebuf = PIPE_BASE(*inode)+PIPE_END(*inode); written += chars; PIPE_LEN(*inode) += chars; count -= chars; copy_from_user(pipebuf, buf, chars ); buf += chars; } PIPE_LOCK(*inode)--; wake_up_interruptible(&PIPE_WAIT(*inode)); free = 1; } inode->i_ctime = inode->i_mtime = CURRENT_TIME; mark_inode_dirty(inode); errout: up(&inode->i_atomic_write); down(&inode->i_sem); return written ? written : err; }
int PipeWrite(struct File* file,BYTE* buffer,DWORD size) { DWORD free = 0, chars; int written = 0; int err = 0; /* If we've got no readers on this pipe, let userspace know. */ if (PIPE_READERS(file) == 0) return -EPIPE; if (size <= PIPE_BUFFER_SIZE) free = size; else free = 1; while (size > 0) { while ((PIPE_FREE(file) < free || PIPE_LOCK(file))) { if (!PIPE_READERS(file) == 0) { err = -EPIPE; goto out; } if (file->flags & FILE_NONBLOCK) { goto out; } WAIT_ON(&PIPE_WAIT(file), PIPE_LOCK(file) == 0); } PIPE_LOCK(file)++; while (size > 0 && (free = PIPE_FREE(file))) { char* pipeBuf = PIPE_BUF(file) + PIPE_END(file); chars = PIPE_MAX_WCHUNK(file); if (chars > size) chars = size; if (chars > free) chars = size; /* Update counters. */ written += chars; PIPE_SIZE(file) += chars; size -= chars; memcpy(pipeBuf, buffer, chars); buffer += chars; } PIPE_LOCK(file)--; WakeUp(&PIPE_WAIT(file)); free = 1; } out: return (written > 0) ? (written) : (err); }
static int fifo_open(struct inode *inode, struct file *filp) { int ret; ret = -ERESTARTSYS; lock_kernel(); if (down_interruptible(PIPE_SEM(*inode))) goto err_nolock_nocleanup; if (!inode->i_pipe) { ret = -ENOMEM; if(!pipe_new(inode)) goto err_nocleanup; } filp->f_version = 0; switch (filp->f_mode) { case 1: /* * O_RDONLY * POSIX.1 says that O_NONBLOCK means return with the FIFO * opened, even when there is no process writing the FIFO. */ filp->f_op = &read_fifo_fops; PIPE_RCOUNTER(*inode)++; if (PIPE_READERS(*inode)++ == 0) wake_up_partner(inode); if (!PIPE_WRITERS(*inode)) { if ((filp->f_flags & O_NONBLOCK)) { /* suppress POLLHUP until we have * seen a writer */ filp->f_version = PIPE_WCOUNTER(*inode); } else { wait_for_partner(inode, &PIPE_WCOUNTER(*inode)); if(signal_pending(current)) goto err_rd; } } break; case 2: /* * O_WRONLY * POSIX.1 says that O_NONBLOCK means return -1 with * errno=ENXIO when there is no process reading the FIFO. */ ret = -ENXIO; if ((filp->f_flags & O_NONBLOCK) && !PIPE_READERS(*inode)) goto err; filp->f_op = &write_fifo_fops; PIPE_WCOUNTER(*inode)++; if (!PIPE_WRITERS(*inode)++) wake_up_partner(inode); if (!PIPE_READERS(*inode)) { wait_for_partner(inode, &PIPE_RCOUNTER(*inode)); if (signal_pending(current)) goto err_wr; } break; case 3: /* * O_RDWR * POSIX.1 leaves this case "undefined" when O_NONBLOCK is set. * This implementation will NEVER block on a O_RDWR open, since * the process can at least talk to itself. */ filp->f_op = &rdwr_fifo_fops; PIPE_READERS(*inode)++; PIPE_WRITERS(*inode)++; PIPE_RCOUNTER(*inode)++; PIPE_WCOUNTER(*inode)++; if (PIPE_READERS(*inode) == 1 || PIPE_WRITERS(*inode) == 1) wake_up_partner(inode); break; default: ret = -EINVAL; goto err; } /* Ok! */ up(PIPE_SEM(*inode)); unlock_kernel(); return 0; err_rd: if (!--PIPE_READERS(*inode)) wake_up_interruptible(PIPE_WAIT(*inode)); ret = -ERESTARTSYS; goto err; err_wr: if (!--PIPE_WRITERS(*inode)) wake_up_interruptible(PIPE_WAIT(*inode)); ret = -ERESTARTSYS; goto err; err: 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); } err_nocleanup: up(PIPE_SEM(*inode)); err_nolock_nocleanup: unlock_kernel(); return ret; }
static ssize_t pipe_writev(struct file *filp, const struct iovec *_iov, unsigned long nr_segs, loff_t *ppos) { struct inode *inode = filp->f_dentry->d_inode; struct pipe_inode_info *info; ssize_t ret; int do_wakeup; struct iovec *iov = (struct iovec *)_iov; size_t total_len; ssize_t chars; total_len = iov_length(iov, nr_segs); /* Null write succeeds. */ if (unlikely(total_len == 0)) return 0; do_wakeup = 0; ret = 0; down(PIPE_SEM(*inode)); info = inode->i_pipe; if (!PIPE_READERS(*inode)) { send_sig(SIGPIPE, current, 0); ret = -EPIPE; goto out; } /* We try to merge small writes */ chars = total_len & (PAGE_SIZE-1); /* size of the last buffer */ if (info->nrbufs && chars != 0) { int lastbuf = (info->curbuf + info->nrbufs - 1) & (PIPE_BUFFERS-1); struct pipe_buffer *buf = info->bufs + lastbuf; struct pipe_buf_operations *ops = buf->ops; int offset = buf->offset + buf->len; if (ops->can_merge && offset + chars <= PAGE_SIZE) { void *addr = ops->map(filp, info, buf); int error = pipe_iov_copy_from_user(offset + addr, iov, chars); ops->unmap(info, buf); ret = error; do_wakeup = 1; if (error) goto out; buf->len += chars; total_len -= chars; ret = chars; if (!total_len) goto out; } } for (;;) { int bufs; if (!PIPE_READERS(*inode)) { send_sig(SIGPIPE, current, 0); if (!ret) ret = -EPIPE; break; } bufs = info->nrbufs; if (bufs < PIPE_BUFFERS) { int newbuf = (info->curbuf + bufs) & (PIPE_BUFFERS-1); struct pipe_buffer *buf = info->bufs + newbuf; struct page *page = info->tmp_page; int error; if (!page) { page = alloc_page(GFP_HIGHUSER); if (unlikely(!page)) { ret = ret ? : -ENOMEM; break; } info->tmp_page = page; }