mirror of
https://github.com/Fishwaldo/Star64_linux.git
synced 2025-06-07 07:08:07 +00:00
[PATCH] another round of fs/pipe.c cleanups
make pipe.c a bit more readable and hackable. Signed-off-by: Ingo Molnar <mingo@elte.hu> Signed-off-by: Jens Axboe <axboe@suse.de>
This commit is contained in:
parent
73d62d83ec
commit
341b446bc5
1 changed files with 48 additions and 28 deletions
76
fs/pipe.c
76
fs/pipe.c
|
@ -44,7 +44,8 @@ void pipe_wait(struct pipe_inode_info *pipe)
|
||||||
* Pipes are system-local resources, so sleeping on them
|
* Pipes are system-local resources, so sleeping on them
|
||||||
* is considered a noninteractive wait:
|
* is considered a noninteractive wait:
|
||||||
*/
|
*/
|
||||||
prepare_to_wait(&pipe->wait, &wait, TASK_INTERRUPTIBLE|TASK_NONINTERACTIVE);
|
prepare_to_wait(&pipe->wait, &wait,
|
||||||
|
TASK_INTERRUPTIBLE | TASK_NONINTERACTIVE);
|
||||||
if (pipe->inode)
|
if (pipe->inode)
|
||||||
mutex_unlock(&pipe->inode->i_mutex);
|
mutex_unlock(&pipe->inode->i_mutex);
|
||||||
schedule();
|
schedule();
|
||||||
|
@ -93,7 +94,8 @@ pipe_iov_copy_to_user(struct iovec *iov, const void *from, unsigned long len)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void anon_pipe_buf_release(struct pipe_inode_info *pipe, struct pipe_buffer *buf)
|
static void anon_pipe_buf_release(struct pipe_inode_info *pipe,
|
||||||
|
struct pipe_buffer *buf)
|
||||||
{
|
{
|
||||||
struct page *page = buf->page;
|
struct page *page = buf->page;
|
||||||
|
|
||||||
|
@ -102,25 +104,22 @@ static void anon_pipe_buf_release(struct pipe_inode_info *pipe, struct pipe_buff
|
||||||
/*
|
/*
|
||||||
* If nobody else uses this page, and we don't already have a
|
* If nobody else uses this page, and we don't already have a
|
||||||
* temporary page, let's keep track of it as a one-deep
|
* temporary page, let's keep track of it as a one-deep
|
||||||
* allocation cache
|
* allocation cache. (Otherwise just release our reference to it)
|
||||||
*/
|
*/
|
||||||
if (page_count(page) == 1 && !pipe->tmp_page) {
|
if (page_count(page) == 1 && !pipe->tmp_page)
|
||||||
pipe->tmp_page = page;
|
pipe->tmp_page = page;
|
||||||
return;
|
else
|
||||||
}
|
page_cache_release(page);
|
||||||
|
|
||||||
/*
|
|
||||||
* Otherwise just release our reference to it
|
|
||||||
*/
|
|
||||||
page_cache_release(page);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void *anon_pipe_buf_map(struct file *file, struct pipe_inode_info *pipe, struct pipe_buffer *buf)
|
static void * anon_pipe_buf_map(struct file *file, struct pipe_inode_info *pipe,
|
||||||
|
struct pipe_buffer *buf)
|
||||||
{
|
{
|
||||||
return kmap(buf->page);
|
return kmap(buf->page);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void anon_pipe_buf_unmap(struct pipe_inode_info *pipe, struct pipe_buffer *buf)
|
static void anon_pipe_buf_unmap(struct pipe_inode_info *pipe,
|
||||||
|
struct pipe_buffer *buf)
|
||||||
{
|
{
|
||||||
kunmap(buf->page);
|
kunmap(buf->page);
|
||||||
}
|
}
|
||||||
|
@ -182,7 +181,8 @@ pipe_readv(struct file *filp, const struct iovec *_iov,
|
||||||
error = pipe_iov_copy_to_user(iov, addr + buf->offset, chars);
|
error = pipe_iov_copy_to_user(iov, addr + buf->offset, chars);
|
||||||
ops->unmap(pipe, buf);
|
ops->unmap(pipe, buf);
|
||||||
if (unlikely(error)) {
|
if (unlikely(error)) {
|
||||||
if (!ret) ret = -EFAULT;
|
if (!ret)
|
||||||
|
ret = -EFAULT;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
ret += chars;
|
ret += chars;
|
||||||
|
@ -218,7 +218,8 @@ pipe_readv(struct file *filp, const struct iovec *_iov,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (signal_pending(current)) {
|
if (signal_pending(current)) {
|
||||||
if (!ret) ret = -ERESTARTSYS;
|
if (!ret)
|
||||||
|
ret = -ERESTARTSYS;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (do_wakeup) {
|
if (do_wakeup) {
|
||||||
|
@ -228,7 +229,8 @@ pipe_readv(struct file *filp, const struct iovec *_iov,
|
||||||
pipe_wait(pipe);
|
pipe_wait(pipe);
|
||||||
}
|
}
|
||||||
mutex_unlock(&inode->i_mutex);
|
mutex_unlock(&inode->i_mutex);
|
||||||
/* Signal writers asynchronously that there is more room. */
|
|
||||||
|
/* Signal writers asynchronously that there is more room. */
|
||||||
if (do_wakeup) {
|
if (do_wakeup) {
|
||||||
wake_up_interruptible(&pipe->wait);
|
wake_up_interruptible(&pipe->wait);
|
||||||
kill_fasync(&pipe->fasync_writers, SIGIO, POLL_OUT);
|
kill_fasync(&pipe->fasync_writers, SIGIO, POLL_OUT);
|
||||||
|
@ -242,6 +244,7 @@ static ssize_t
|
||||||
pipe_read(struct file *filp, char __user *buf, size_t count, loff_t *ppos)
|
pipe_read(struct file *filp, char __user *buf, size_t count, loff_t *ppos)
|
||||||
{
|
{
|
||||||
struct iovec iov = { .iov_base = buf, .iov_len = count };
|
struct iovec iov = { .iov_base = buf, .iov_len = count };
|
||||||
|
|
||||||
return pipe_readv(filp, &iov, 1, ppos);
|
return pipe_readv(filp, &iov, 1, ppos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -276,10 +279,12 @@ pipe_writev(struct file *filp, const struct iovec *_iov,
|
||||||
/* We try to merge small writes */
|
/* We try to merge small writes */
|
||||||
chars = total_len & (PAGE_SIZE-1); /* size of the last buffer */
|
chars = total_len & (PAGE_SIZE-1); /* size of the last buffer */
|
||||||
if (pipe->nrbufs && chars != 0) {
|
if (pipe->nrbufs && chars != 0) {
|
||||||
int lastbuf = (pipe->curbuf + pipe->nrbufs - 1) & (PIPE_BUFFERS-1);
|
int lastbuf = (pipe->curbuf + pipe->nrbufs - 1) &
|
||||||
|
(PIPE_BUFFERS-1);
|
||||||
struct pipe_buffer *buf = pipe->bufs + lastbuf;
|
struct pipe_buffer *buf = pipe->bufs + lastbuf;
|
||||||
struct pipe_buf_operations *ops = buf->ops;
|
struct pipe_buf_operations *ops = buf->ops;
|
||||||
int offset = buf->offset + buf->len;
|
int offset = buf->offset + buf->len;
|
||||||
|
|
||||||
if (ops->can_merge && offset + chars <= PAGE_SIZE) {
|
if (ops->can_merge && offset + chars <= PAGE_SIZE) {
|
||||||
void *addr;
|
void *addr;
|
||||||
int error;
|
int error;
|
||||||
|
@ -306,9 +311,11 @@ pipe_writev(struct file *filp, const struct iovec *_iov,
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
int bufs;
|
int bufs;
|
||||||
|
|
||||||
if (!pipe->readers) {
|
if (!pipe->readers) {
|
||||||
send_sig(SIGPIPE, current, 0);
|
send_sig(SIGPIPE, current, 0);
|
||||||
if (!ret) ret = -EPIPE;
|
if (!ret)
|
||||||
|
ret = -EPIPE;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
bufs = pipe->nrbufs;
|
bufs = pipe->nrbufs;
|
||||||
|
@ -326,7 +333,7 @@ pipe_writev(struct file *filp, const struct iovec *_iov,
|
||||||
}
|
}
|
||||||
pipe->tmp_page = page;
|
pipe->tmp_page = page;
|
||||||
}
|
}
|
||||||
/* Always wakeup, even if the copy fails. Otherwise
|
/* Always wake up, even if the copy fails. Otherwise
|
||||||
* we lock up (O_NONBLOCK-)readers that sleep due to
|
* we lock up (O_NONBLOCK-)readers that sleep due to
|
||||||
* syscall merging.
|
* syscall merging.
|
||||||
* FIXME! Is this really true?
|
* FIXME! Is this really true?
|
||||||
|
@ -339,7 +346,8 @@ pipe_writev(struct file *filp, const struct iovec *_iov,
|
||||||
error = pipe_iov_copy_from_user(kmap(page), iov, chars);
|
error = pipe_iov_copy_from_user(kmap(page), iov, chars);
|
||||||
kunmap(page);
|
kunmap(page);
|
||||||
if (unlikely(error)) {
|
if (unlikely(error)) {
|
||||||
if (!ret) ret = -EFAULT;
|
if (!ret)
|
||||||
|
ret = -EFAULT;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
ret += chars;
|
ret += chars;
|
||||||
|
@ -359,11 +367,13 @@ pipe_writev(struct file *filp, const struct iovec *_iov,
|
||||||
if (bufs < PIPE_BUFFERS)
|
if (bufs < PIPE_BUFFERS)
|
||||||
continue;
|
continue;
|
||||||
if (filp->f_flags & O_NONBLOCK) {
|
if (filp->f_flags & O_NONBLOCK) {
|
||||||
if (!ret) ret = -EAGAIN;
|
if (!ret)
|
||||||
|
ret = -EAGAIN;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (signal_pending(current)) {
|
if (signal_pending(current)) {
|
||||||
if (!ret) ret = -ERESTARTSYS;
|
if (!ret)
|
||||||
|
ret = -ERESTARTSYS;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (do_wakeup) {
|
if (do_wakeup) {
|
||||||
|
@ -391,6 +401,7 @@ pipe_write(struct file *filp, const char __user *buf,
|
||||||
size_t count, loff_t *ppos)
|
size_t count, loff_t *ppos)
|
||||||
{
|
{
|
||||||
struct iovec iov = { .iov_base = (void __user *)buf, .iov_len = count };
|
struct iovec iov = { .iov_base = (void __user *)buf, .iov_len = count };
|
||||||
|
|
||||||
return pipe_writev(filp, &iov, 1, ppos);
|
return pipe_writev(filp, &iov, 1, ppos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -401,7 +412,8 @@ bad_pipe_r(struct file *filp, char __user *buf, size_t count, loff_t *ppos)
|
||||||
}
|
}
|
||||||
|
|
||||||
static ssize_t
|
static ssize_t
|
||||||
bad_pipe_w(struct file *filp, const char __user *buf, size_t count, loff_t *ppos)
|
bad_pipe_w(struct file *filp, const char __user *buf, size_t count,
|
||||||
|
loff_t *ppos)
|
||||||
{
|
{
|
||||||
return -EBADF;
|
return -EBADF;
|
||||||
}
|
}
|
||||||
|
@ -475,6 +487,7 @@ pipe_release(struct inode *inode, int decr, int decw)
|
||||||
pipe = inode->i_pipe;
|
pipe = inode->i_pipe;
|
||||||
pipe->readers -= decr;
|
pipe->readers -= decr;
|
||||||
pipe->writers -= decw;
|
pipe->writers -= decw;
|
||||||
|
|
||||||
if (!pipe->readers && !pipe->writers) {
|
if (!pipe->readers && !pipe->writers) {
|
||||||
free_pipe_info(inode);
|
free_pipe_info(inode);
|
||||||
} else {
|
} else {
|
||||||
|
@ -525,14 +538,15 @@ static int
|
||||||
pipe_rdwr_fasync(int fd, struct file *filp, int on)
|
pipe_rdwr_fasync(int fd, struct file *filp, int on)
|
||||||
{
|
{
|
||||||
struct inode *inode = filp->f_dentry->d_inode;
|
struct inode *inode = filp->f_dentry->d_inode;
|
||||||
|
struct pipe_inode_info *pipe = inode->i_pipe;
|
||||||
int retval;
|
int retval;
|
||||||
|
|
||||||
mutex_lock(&inode->i_mutex);
|
mutex_lock(&inode->i_mutex);
|
||||||
|
|
||||||
retval = fasync_helper(fd, filp, on, &inode->i_pipe->fasync_readers);
|
retval = fasync_helper(fd, filp, on, &pipe->fasync_readers);
|
||||||
|
|
||||||
if (retval >= 0)
|
if (retval >= 0)
|
||||||
retval = fasync_helper(fd, filp, on, &inode->i_pipe->fasync_writers);
|
retval = fasync_helper(fd, filp, on, &pipe->fasync_writers);
|
||||||
|
|
||||||
mutex_unlock(&inode->i_mutex);
|
mutex_unlock(&inode->i_mutex);
|
||||||
|
|
||||||
|
@ -720,6 +734,7 @@ static int pipefs_delete_dentry(struct dentry *dentry)
|
||||||
{
|
{
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct dentry_operations pipefs_dentry_operations = {
|
static struct dentry_operations pipefs_dentry_operations = {
|
||||||
.d_delete = pipefs_delete_dentry,
|
.d_delete = pipefs_delete_dentry,
|
||||||
};
|
};
|
||||||
|
@ -757,6 +772,7 @@ static struct inode * get_pipe_inode(void)
|
||||||
|
|
||||||
fail_iput:
|
fail_iput:
|
||||||
iput(inode);
|
iput(inode);
|
||||||
|
|
||||||
fail_inode:
|
fail_inode:
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -769,7 +785,7 @@ int do_pipe(int *fd)
|
||||||
struct inode * inode;
|
struct inode * inode;
|
||||||
struct file *f1, *f2;
|
struct file *f1, *f2;
|
||||||
int error;
|
int error;
|
||||||
int i,j;
|
int i, j;
|
||||||
|
|
||||||
error = -ENFILE;
|
error = -ENFILE;
|
||||||
f1 = get_empty_filp();
|
f1 = get_empty_filp();
|
||||||
|
@ -802,6 +818,7 @@ int do_pipe(int *fd)
|
||||||
dentry = d_alloc(pipe_mnt->mnt_sb->s_root, &this);
|
dentry = d_alloc(pipe_mnt->mnt_sb->s_root, &this);
|
||||||
if (!dentry)
|
if (!dentry)
|
||||||
goto close_f12_inode_i_j;
|
goto close_f12_inode_i_j;
|
||||||
|
|
||||||
dentry->d_op = &pipefs_dentry_operations;
|
dentry->d_op = &pipefs_dentry_operations;
|
||||||
d_add(dentry, inode);
|
d_add(dentry, inode);
|
||||||
f1->f_vfsmnt = f2->f_vfsmnt = mntget(mntget(pipe_mnt));
|
f1->f_vfsmnt = f2->f_vfsmnt = mntget(mntget(pipe_mnt));
|
||||||
|
@ -825,6 +842,7 @@ int do_pipe(int *fd)
|
||||||
fd_install(j, f2);
|
fd_install(j, f2);
|
||||||
fd[0] = i;
|
fd[0] = i;
|
||||||
fd[1] = j;
|
fd[1] = j;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
close_f12_inode_i_j:
|
close_f12_inode_i_j:
|
||||||
|
@ -849,8 +867,9 @@ no_files:
|
||||||
* d_name - pipe: will go nicely and kill the special-casing in procfs.
|
* d_name - pipe: will go nicely and kill the special-casing in procfs.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static struct super_block *pipefs_get_sb(struct file_system_type *fs_type,
|
static struct super_block *
|
||||||
int flags, const char *dev_name, void *data)
|
pipefs_get_sb(struct file_system_type *fs_type, int flags,
|
||||||
|
const char *dev_name, void *data)
|
||||||
{
|
{
|
||||||
return get_sb_pseudo(fs_type, "pipe:", NULL, PIPEFS_MAGIC);
|
return get_sb_pseudo(fs_type, "pipe:", NULL, PIPEFS_MAGIC);
|
||||||
}
|
}
|
||||||
|
@ -864,6 +883,7 @@ static struct file_system_type pipe_fs_type = {
|
||||||
static int __init init_pipe_fs(void)
|
static int __init init_pipe_fs(void)
|
||||||
{
|
{
|
||||||
int err = register_filesystem(&pipe_fs_type);
|
int err = register_filesystem(&pipe_fs_type);
|
||||||
|
|
||||||
if (!err) {
|
if (!err) {
|
||||||
pipe_mnt = kern_mount(&pipe_fs_type);
|
pipe_mnt = kern_mount(&pipe_fs_type);
|
||||||
if (IS_ERR(pipe_mnt)) {
|
if (IS_ERR(pipe_mnt)) {
|
||||||
|
|
Loading…
Add table
Reference in a new issue