diff options
author | Ralf Baechle <ralf@linux-mips.org> | 2000-02-04 07:40:19 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2000-02-04 07:40:19 +0000 |
commit | 33263fc5f9ac8e8cb2b22d06af3ce5ac1dd815e4 (patch) | |
tree | 2d1b86a40bef0958a68cf1a2eafbeb0667a70543 /fs/pipe.c | |
parent | 216f5f51aa02f8b113aa620ebc14a9631a217a00 (diff) |
Merge with Linux 2.3.32.
Diffstat (limited to 'fs/pipe.c')
-rw-r--r-- | fs/pipe.c | 70 |
1 files changed, 41 insertions, 29 deletions
@@ -51,6 +51,7 @@ pipe_read(struct file *filp, char *buf, size_t count, loff_t *ppos) /* Seeks are not allowed on pipes. */ ret = -ESPIPE; + read = 0; if (ppos != &filp->f_pos) goto out_nolock; @@ -65,6 +66,7 @@ pipe_read(struct file *filp, char *buf, size_t count, loff_t *ppos) goto out_nolock; if (PIPE_EMPTY(*inode)) { +do_more_read: ret = 0; if (!PIPE_WRITERS(*inode)) goto out; @@ -74,7 +76,9 @@ pipe_read(struct file *filp, char *buf, size_t count, loff_t *ppos) goto out; for (;;) { + PIPE_WAITING_READERS(*inode)++; pipe_wait(inode); + PIPE_WAITING_READERS(*inode)--; ret = -ERESTARTSYS; if (signal_pending(current)) goto out_nolock; @@ -90,7 +94,6 @@ pipe_read(struct file *filp, char *buf, size_t count, loff_t *ppos) /* 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); @@ -115,16 +118,26 @@ pipe_read(struct file *filp, char *buf, size_t count, loff_t *ppos) if (!PIPE_LEN(*inode)) PIPE_START(*inode) = 0; - /* Signal writers there is more room. */ + if (count && PIPE_WAITING_WRITERS(*inode) && !(filp->f_flags & O_NONBLOCK)) { + /* + * We know that we are going to sleep: signal + * writers synchronously that there is more + * room. + */ + wake_up_interruptible_sync(PIPE_WAIT(*inode)); + if (!PIPE_EMPTY(*inode)) + BUG(); + goto do_more_read; + } + /* Signal writers asynchronously that there is more room. */ wake_up_interruptible(PIPE_WAIT(*inode)); - if (read) - UPDATE_ATIME(inode); ret = read; - out: up(PIPE_SEM(*inode)); out_nolock: + if (read) + ret = read; return ret; } @@ -136,6 +149,7 @@ pipe_write(struct file *filp, const char *buf, size_t count, loff_t *ppos) /* Seeks are not allowed on pipes. */ ret = -ESPIPE; + written = 0; if (ppos != &filp->f_pos) goto out_nolock; @@ -148,13 +162,13 @@ pipe_write(struct file *filp, const char *buf, size_t count, loff_t *ppos) if (down_interruptible(PIPE_SEM(*inode))) goto out_nolock; +do_more_write: /* 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) { @@ -163,7 +177,9 @@ pipe_write(struct file *filp, const char *buf, size_t count, loff_t *ppos) 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_nolock; @@ -204,9 +220,15 @@ pipe_write(struct file *filp, const char *buf, size_t count, loff_t *ppos) break; do { - /* This should be a synchronous wake-up: don't do idle reschedules! */ - wake_up_interruptible(PIPE_WAIT(*inode)); + /* + * Synchronous wake-up: it knows that this process + * is going to give up this CPU, so it doesnt 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_nolock; if (down_interruptible(PIPE_SEM(*inode))) @@ -217,19 +239,27 @@ pipe_write(struct file *filp, const char *buf, size_t count, loff_t *ppos) ret = -EFAULT; } - /* Signal readers there is more data. */ + if (count && PIPE_WAITING_READERS(*inode) && + !(filp->f_flags & O_NONBLOCK)) { + wake_up_interruptible_sync(PIPE_WAIT(*inode)); + goto do_more_write; + } + /* Signal readers asynchronously that 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: + if (written) + ret = written; return ret; sigpipe: + if (written) + goto out; up(PIPE_SEM(*inode)); send_sig(SIGPIPE, current, 0); return -EPIPE; @@ -552,6 +582,7 @@ static struct inode * get_pipe_inode(void) PIPE_BASE(*inode) = (char *) page; PIPE_START(*inode) = PIPE_LEN(*inode) = 0; PIPE_READERS(*inode) = PIPE_WRITERS(*inode) = 1; + PIPE_WAITING_READERS(*inode) = PIPE_WAITING_WRITERS(*inode) = 0; /* * Mark the inode dirty from the very beginning, @@ -577,25 +608,6 @@ fail_inode: 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) |