diff options
Diffstat (limited to 'fs/pipe.c')
-rw-r--r-- | fs/pipe.c | 76 |
1 files changed, 48 insertions, 28 deletions
@@ -44,7 +44,8 @@ void pipe_wait(struct pipe_inode_info *pipe) | |||
44 | * Pipes are system-local resources, so sleeping on them | 44 | * Pipes are system-local resources, so sleeping on them |
45 | * is considered a noninteractive wait: | 45 | * is considered a noninteractive wait: |
46 | */ | 46 | */ |
47 | prepare_to_wait(&pipe->wait, &wait, TASK_INTERRUPTIBLE|TASK_NONINTERACTIVE); | 47 | prepare_to_wait(&pipe->wait, &wait, |
48 | TASK_INTERRUPTIBLE | TASK_NONINTERACTIVE); | ||
48 | if (pipe->inode) | 49 | if (pipe->inode) |
49 | mutex_unlock(&pipe->inode->i_mutex); | 50 | mutex_unlock(&pipe->inode->i_mutex); |
50 | schedule(); | 51 | schedule(); |
@@ -93,7 +94,8 @@ pipe_iov_copy_to_user(struct iovec *iov, const void *from, unsigned long len) | |||
93 | return 0; | 94 | return 0; |
94 | } | 95 | } |
95 | 96 | ||
96 | static void anon_pipe_buf_release(struct pipe_inode_info *pipe, struct pipe_buffer *buf) | 97 | static void anon_pipe_buf_release(struct pipe_inode_info *pipe, |
98 | struct pipe_buffer *buf) | ||
97 | { | 99 | { |
98 | struct page *page = buf->page; | 100 | struct page *page = buf->page; |
99 | 101 | ||
@@ -102,25 +104,22 @@ static void anon_pipe_buf_release(struct pipe_inode_info *pipe, struct pipe_buff | |||
102 | /* | 104 | /* |
103 | * If nobody else uses this page, and we don't already have a | 105 | * If nobody else uses this page, and we don't already have a |
104 | * temporary page, let's keep track of it as a one-deep | 106 | * temporary page, let's keep track of it as a one-deep |
105 | * allocation cache | 107 | * allocation cache. (Otherwise just release our reference to it) |
106 | */ | 108 | */ |
107 | if (page_count(page) == 1 && !pipe->tmp_page) { | 109 | if (page_count(page) == 1 && !pipe->tmp_page) |
108 | pipe->tmp_page = page; | 110 | pipe->tmp_page = page; |
109 | return; | 111 | else |
110 | } | 112 | page_cache_release(page); |
111 | |||
112 | /* | ||
113 | * Otherwise just release our reference to it | ||
114 | */ | ||
115 | page_cache_release(page); | ||
116 | } | 113 | } |
117 | 114 | ||
118 | static void *anon_pipe_buf_map(struct file *file, struct pipe_inode_info *pipe, struct pipe_buffer *buf) | 115 | static void * anon_pipe_buf_map(struct file *file, struct pipe_inode_info *pipe, |
116 | struct pipe_buffer *buf) | ||
119 | { | 117 | { |
120 | return kmap(buf->page); | 118 | return kmap(buf->page); |
121 | } | 119 | } |
122 | 120 | ||
123 | static void anon_pipe_buf_unmap(struct pipe_inode_info *pipe, struct pipe_buffer *buf) | 121 | static void anon_pipe_buf_unmap(struct pipe_inode_info *pipe, |
122 | struct pipe_buffer *buf) | ||
124 | { | 123 | { |
125 | kunmap(buf->page); | 124 | kunmap(buf->page); |
126 | } | 125 | } |
@@ -182,7 +181,8 @@ pipe_readv(struct file *filp, const struct iovec *_iov, | |||
182 | error = pipe_iov_copy_to_user(iov, addr + buf->offset, chars); | 181 | error = pipe_iov_copy_to_user(iov, addr + buf->offset, chars); |
183 | ops->unmap(pipe, buf); | 182 | ops->unmap(pipe, buf); |
184 | if (unlikely(error)) { | 183 | if (unlikely(error)) { |
185 | if (!ret) ret = -EFAULT; | 184 | if (!ret) |
185 | ret = -EFAULT; | ||
186 | break; | 186 | break; |
187 | } | 187 | } |
188 | ret += chars; | 188 | ret += chars; |
@@ -218,7 +218,8 @@ pipe_readv(struct file *filp, const struct iovec *_iov, | |||
218 | } | 218 | } |
219 | } | 219 | } |
220 | if (signal_pending(current)) { | 220 | if (signal_pending(current)) { |
221 | if (!ret) ret = -ERESTARTSYS; | 221 | if (!ret) |
222 | ret = -ERESTARTSYS; | ||
222 | break; | 223 | break; |
223 | } | 224 | } |
224 | if (do_wakeup) { | 225 | if (do_wakeup) { |
@@ -228,7 +229,8 @@ pipe_readv(struct file *filp, const struct iovec *_iov, | |||
228 | pipe_wait(pipe); | 229 | pipe_wait(pipe); |
229 | } | 230 | } |
230 | mutex_unlock(&inode->i_mutex); | 231 | mutex_unlock(&inode->i_mutex); |
231 | /* Signal writers asynchronously that there is more room. */ | 232 | |
233 | /* Signal writers asynchronously that there is more room. */ | ||
232 | if (do_wakeup) { | 234 | if (do_wakeup) { |
233 | wake_up_interruptible(&pipe->wait); | 235 | wake_up_interruptible(&pipe->wait); |
234 | kill_fasync(&pipe->fasync_writers, SIGIO, POLL_OUT); | 236 | kill_fasync(&pipe->fasync_writers, SIGIO, POLL_OUT); |
@@ -242,6 +244,7 @@ static ssize_t | |||
242 | pipe_read(struct file *filp, char __user *buf, size_t count, loff_t *ppos) | 244 | pipe_read(struct file *filp, char __user *buf, size_t count, loff_t *ppos) |
243 | { | 245 | { |
244 | struct iovec iov = { .iov_base = buf, .iov_len = count }; | 246 | struct iovec iov = { .iov_base = buf, .iov_len = count }; |
247 | |||
245 | return pipe_readv(filp, &iov, 1, ppos); | 248 | return pipe_readv(filp, &iov, 1, ppos); |
246 | } | 249 | } |
247 | 250 | ||
@@ -276,10 +279,12 @@ pipe_writev(struct file *filp, const struct iovec *_iov, | |||
276 | /* We try to merge small writes */ | 279 | /* We try to merge small writes */ |
277 | chars = total_len & (PAGE_SIZE-1); /* size of the last buffer */ | 280 | chars = total_len & (PAGE_SIZE-1); /* size of the last buffer */ |
278 | if (pipe->nrbufs && chars != 0) { | 281 | if (pipe->nrbufs && chars != 0) { |
279 | int lastbuf = (pipe->curbuf + pipe->nrbufs - 1) & (PIPE_BUFFERS-1); | 282 | int lastbuf = (pipe->curbuf + pipe->nrbufs - 1) & |
283 | (PIPE_BUFFERS-1); | ||
280 | struct pipe_buffer *buf = pipe->bufs + lastbuf; | 284 | struct pipe_buffer *buf = pipe->bufs + lastbuf; |
281 | struct pipe_buf_operations *ops = buf->ops; | 285 | struct pipe_buf_operations *ops = buf->ops; |
282 | int offset = buf->offset + buf->len; | 286 | int offset = buf->offset + buf->len; |
287 | |||
283 | if (ops->can_merge && offset + chars <= PAGE_SIZE) { | 288 | if (ops->can_merge && offset + chars <= PAGE_SIZE) { |
284 | void *addr; | 289 | void *addr; |
285 | int error; | 290 | int error; |
@@ -306,9 +311,11 @@ pipe_writev(struct file *filp, const struct iovec *_iov, | |||
306 | 311 | ||
307 | for (;;) { | 312 | for (;;) { |
308 | int bufs; | 313 | int bufs; |
314 | |||
309 | if (!pipe->readers) { | 315 | if (!pipe->readers) { |
310 | send_sig(SIGPIPE, current, 0); | 316 | send_sig(SIGPIPE, current, 0); |
311 | if (!ret) ret = -EPIPE; | 317 | if (!ret) |
318 | ret = -EPIPE; | ||
312 | break; | 319 | break; |
313 | } | 320 | } |
314 | bufs = pipe->nrbufs; | 321 | bufs = pipe->nrbufs; |
@@ -326,7 +333,7 @@ pipe_writev(struct file *filp, const struct iovec *_iov, | |||
326 | } | 333 | } |
327 | pipe->tmp_page = page; | 334 | pipe->tmp_page = page; |
328 | } | 335 | } |
329 | /* Always wakeup, even if the copy fails. Otherwise | 336 | /* Always wake up, even if the copy fails. Otherwise |
330 | * we lock up (O_NONBLOCK-)readers that sleep due to | 337 | * we lock up (O_NONBLOCK-)readers that sleep due to |
331 | * syscall merging. | 338 | * syscall merging. |
332 | * FIXME! Is this really true? | 339 | * FIXME! Is this really true? |
@@ -339,7 +346,8 @@ pipe_writev(struct file *filp, const struct iovec *_iov, | |||
339 | error = pipe_iov_copy_from_user(kmap(page), iov, chars); | 346 | error = pipe_iov_copy_from_user(kmap(page), iov, chars); |
340 | kunmap(page); | 347 | kunmap(page); |
341 | if (unlikely(error)) { | 348 | if (unlikely(error)) { |
342 | if (!ret) ret = -EFAULT; | 349 | if (!ret) |
350 | ret = -EFAULT; | ||
343 | break; | 351 | break; |
344 | } | 352 | } |
345 | ret += chars; | 353 | ret += chars; |
@@ -359,11 +367,13 @@ pipe_writev(struct file *filp, const struct iovec *_iov, | |||
359 | if (bufs < PIPE_BUFFERS) | 367 | if (bufs < PIPE_BUFFERS) |
360 | continue; | 368 | continue; |
361 | if (filp->f_flags & O_NONBLOCK) { | 369 | if (filp->f_flags & O_NONBLOCK) { |
362 | if (!ret) ret = -EAGAIN; | 370 | if (!ret) |
371 | ret = -EAGAIN; | ||
363 | break; | 372 | break; |
364 | } | 373 | } |
365 | if (signal_pending(current)) { | 374 | if (signal_pending(current)) { |
366 | if (!ret) ret = -ERESTARTSYS; | 375 | if (!ret) |
376 | ret = -ERESTARTSYS; | ||
367 | break; | 377 | break; |
368 | } | 378 | } |
369 | if (do_wakeup) { | 379 | if (do_wakeup) { |
@@ -391,6 +401,7 @@ pipe_write(struct file *filp, const char __user *buf, | |||
391 | size_t count, loff_t *ppos) | 401 | size_t count, loff_t *ppos) |
392 | { | 402 | { |
393 | struct iovec iov = { .iov_base = (void __user *)buf, .iov_len = count }; | 403 | struct iovec iov = { .iov_base = (void __user *)buf, .iov_len = count }; |
404 | |||
394 | return pipe_writev(filp, &iov, 1, ppos); | 405 | return pipe_writev(filp, &iov, 1, ppos); |
395 | } | 406 | } |
396 | 407 | ||
@@ -401,7 +412,8 @@ bad_pipe_r(struct file *filp, char __user *buf, size_t count, loff_t *ppos) | |||
401 | } | 412 | } |
402 | 413 | ||
403 | static ssize_t | 414 | static ssize_t |
404 | bad_pipe_w(struct file *filp, const char __user *buf, size_t count, loff_t *ppos) | 415 | bad_pipe_w(struct file *filp, const char __user *buf, size_t count, |
416 | loff_t *ppos) | ||
405 | { | 417 | { |
406 | return -EBADF; | 418 | return -EBADF; |
407 | } | 419 | } |
@@ -475,6 +487,7 @@ pipe_release(struct inode *inode, int decr, int decw) | |||
475 | pipe = inode->i_pipe; | 487 | pipe = inode->i_pipe; |
476 | pipe->readers -= decr; | 488 | pipe->readers -= decr; |
477 | pipe->writers -= decw; | 489 | pipe->writers -= decw; |
490 | |||
478 | if (!pipe->readers && !pipe->writers) { | 491 | if (!pipe->readers && !pipe->writers) { |
479 | free_pipe_info(inode); | 492 | free_pipe_info(inode); |
480 | } else { | 493 | } else { |
@@ -525,14 +538,15 @@ static int | |||
525 | pipe_rdwr_fasync(int fd, struct file *filp, int on) | 538 | pipe_rdwr_fasync(int fd, struct file *filp, int on) |
526 | { | 539 | { |
527 | struct inode *inode = filp->f_dentry->d_inode; | 540 | struct inode *inode = filp->f_dentry->d_inode; |
541 | struct pipe_inode_info *pipe = inode->i_pipe; | ||
528 | int retval; | 542 | int retval; |
529 | 543 | ||
530 | mutex_lock(&inode->i_mutex); | 544 | mutex_lock(&inode->i_mutex); |
531 | 545 | ||
532 | retval = fasync_helper(fd, filp, on, &inode->i_pipe->fasync_readers); | 546 | retval = fasync_helper(fd, filp, on, &pipe->fasync_readers); |
533 | 547 | ||
534 | if (retval >= 0) | 548 | if (retval >= 0) |
535 | retval = fasync_helper(fd, filp, on, &inode->i_pipe->fasync_writers); | 549 | retval = fasync_helper(fd, filp, on, &pipe->fasync_writers); |
536 | 550 | ||
537 | mutex_unlock(&inode->i_mutex); | 551 | mutex_unlock(&inode->i_mutex); |
538 | 552 | ||
@@ -720,6 +734,7 @@ static int pipefs_delete_dentry(struct dentry *dentry) | |||
720 | { | 734 | { |
721 | return 1; | 735 | return 1; |
722 | } | 736 | } |
737 | |||
723 | static struct dentry_operations pipefs_dentry_operations = { | 738 | static struct dentry_operations pipefs_dentry_operations = { |
724 | .d_delete = pipefs_delete_dentry, | 739 | .d_delete = pipefs_delete_dentry, |
725 | }; | 740 | }; |
@@ -757,6 +772,7 @@ static struct inode * get_pipe_inode(void) | |||
757 | 772 | ||
758 | fail_iput: | 773 | fail_iput: |
759 | iput(inode); | 774 | iput(inode); |
775 | |||
760 | fail_inode: | 776 | fail_inode: |
761 | return NULL; | 777 | return NULL; |
762 | } | 778 | } |
@@ -769,7 +785,7 @@ int do_pipe(int *fd) | |||
769 | struct inode * inode; | 785 | struct inode * inode; |
770 | struct file *f1, *f2; | 786 | struct file *f1, *f2; |
771 | int error; | 787 | int error; |
772 | int i,j; | 788 | int i, j; |
773 | 789 | ||
774 | error = -ENFILE; | 790 | error = -ENFILE; |
775 | f1 = get_empty_filp(); | 791 | f1 = get_empty_filp(); |
@@ -802,6 +818,7 @@ int do_pipe(int *fd) | |||
802 | dentry = d_alloc(pipe_mnt->mnt_sb->s_root, &this); | 818 | dentry = d_alloc(pipe_mnt->mnt_sb->s_root, &this); |
803 | if (!dentry) | 819 | if (!dentry) |
804 | goto close_f12_inode_i_j; | 820 | goto close_f12_inode_i_j; |
821 | |||
805 | dentry->d_op = &pipefs_dentry_operations; | 822 | dentry->d_op = &pipefs_dentry_operations; |
806 | d_add(dentry, inode); | 823 | d_add(dentry, inode); |
807 | f1->f_vfsmnt = f2->f_vfsmnt = mntget(mntget(pipe_mnt)); | 824 | f1->f_vfsmnt = f2->f_vfsmnt = mntget(mntget(pipe_mnt)); |
@@ -825,6 +842,7 @@ int do_pipe(int *fd) | |||
825 | fd_install(j, f2); | 842 | fd_install(j, f2); |
826 | fd[0] = i; | 843 | fd[0] = i; |
827 | fd[1] = j; | 844 | fd[1] = j; |
845 | |||
828 | return 0; | 846 | return 0; |
829 | 847 | ||
830 | close_f12_inode_i_j: | 848 | close_f12_inode_i_j: |
@@ -849,8 +867,9 @@ no_files: | |||
849 | * d_name - pipe: will go nicely and kill the special-casing in procfs. | 867 | * d_name - pipe: will go nicely and kill the special-casing in procfs. |
850 | */ | 868 | */ |
851 | 869 | ||
852 | static struct super_block *pipefs_get_sb(struct file_system_type *fs_type, | 870 | static struct super_block * |
853 | int flags, const char *dev_name, void *data) | 871 | pipefs_get_sb(struct file_system_type *fs_type, int flags, |
872 | const char *dev_name, void *data) | ||
854 | { | 873 | { |
855 | return get_sb_pseudo(fs_type, "pipe:", NULL, PIPEFS_MAGIC); | 874 | return get_sb_pseudo(fs_type, "pipe:", NULL, PIPEFS_MAGIC); |
856 | } | 875 | } |
@@ -864,6 +883,7 @@ static struct file_system_type pipe_fs_type = { | |||
864 | static int __init init_pipe_fs(void) | 883 | static int __init init_pipe_fs(void) |
865 | { | 884 | { |
866 | int err = register_filesystem(&pipe_fs_type); | 885 | int err = register_filesystem(&pipe_fs_type); |
886 | |||
867 | if (!err) { | 887 | if (!err) { |
868 | pipe_mnt = kern_mount(&pipe_fs_type); | 888 | pipe_mnt = kern_mount(&pipe_fs_type); |
869 | if (IS_ERR(pipe_mnt)) { | 889 | if (IS_ERR(pipe_mnt)) { |