aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>2008-07-24 00:29:40 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2008-07-24 13:47:29 -0400
commitbe61a86d7237dd80510615f38ae21d6e1e98660c (patch)
tree3dfe6c8275c724533f88525970a4065ae795f6e3
parent6b1ef0e60d42f2fdaec26baee8327eb156347b4f (diff)
flag parameters: NONBLOCK in pipe
This patch adds O_NONBLOCK support to pipe2. It is minimally more involved than the patches for eventfd et.al but still trivial. The interfaces of the create_write_pipe and create_read_pipe helper functions were changed and the one other caller as well. The following test must be adjusted for architectures other than x86 and x86-64 and in case the syscall numbers changed. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ #include <fcntl.h> #include <stdio.h> #include <unistd.h> #include <sys/syscall.h> #ifndef __NR_pipe2 # ifdef __x86_64__ # define __NR_pipe2 293 # elif defined __i386__ # define __NR_pipe2 331 # else # error "need __NR_pipe2" # endif #endif int main (void) { int fds[2]; if (syscall (__NR_pipe2, fds, 0) == -1) { puts ("pipe2(0) failed"); return 1; } for (int i = 0; i < 2; ++i) { int fl = fcntl (fds[i], F_GETFL); if (fl == -1) { puts ("fcntl failed"); return 1; } if (fl & O_NONBLOCK) { printf ("pipe2(0) set non-blocking mode for fds[%d]\n", i); return 1; } close (fds[i]); } if (syscall (__NR_pipe2, fds, O_NONBLOCK) == -1) { puts ("pipe2(O_NONBLOCK) failed"); return 1; } for (int i = 0; i < 2; ++i) { int fl = fcntl (fds[i], F_GETFL); if (fl == -1) { puts ("fcntl failed"); return 1; } if ((fl & O_NONBLOCK) == 0) { printf ("pipe2(O_NONBLOCK) does not set non-blocking mode for fds[%d]\n", i); return 1; } close (fds[i]); } puts ("OK"); return 0; } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Signed-off-by: Ulrich Drepper <drepper@redhat.com> Acked-by: Davide Libenzi <davidel@xmailserver.org> Cc: Michael Kerrisk <mtk.manpages@googlemail.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--fs/pipe.c14
-rw-r--r--include/linux/fs.h4
-rw-r--r--kernel/kmod.c4
3 files changed, 11 insertions, 11 deletions
diff --git a/fs/pipe.c b/fs/pipe.c
index 68e82061070c..10c4e9aa5c49 100644
--- a/fs/pipe.c
+++ b/fs/pipe.c
@@ -950,7 +950,7 @@ fail_inode:
950 return NULL; 950 return NULL;
951} 951}
952 952
953struct file *create_write_pipe(void) 953struct file *create_write_pipe(int flags)
954{ 954{
955 int err; 955 int err;
956 struct inode *inode; 956 struct inode *inode;
@@ -983,7 +983,7 @@ struct file *create_write_pipe(void)
983 goto err_dentry; 983 goto err_dentry;
984 f->f_mapping = inode->i_mapping; 984 f->f_mapping = inode->i_mapping;
985 985
986 f->f_flags = O_WRONLY; 986 f->f_flags = O_WRONLY | (flags & O_NONBLOCK);
987 f->f_version = 0; 987 f->f_version = 0;
988 988
989 return f; 989 return f;
@@ -1007,7 +1007,7 @@ void free_write_pipe(struct file *f)
1007 put_filp(f); 1007 put_filp(f);
1008} 1008}
1009 1009
1010struct file *create_read_pipe(struct file *wrf) 1010struct file *create_read_pipe(struct file *wrf, int flags)
1011{ 1011{
1012 struct file *f = get_empty_filp(); 1012 struct file *f = get_empty_filp();
1013 if (!f) 1013 if (!f)
@@ -1019,7 +1019,7 @@ struct file *create_read_pipe(struct file *wrf)
1019 f->f_mapping = wrf->f_path.dentry->d_inode->i_mapping; 1019 f->f_mapping = wrf->f_path.dentry->d_inode->i_mapping;
1020 1020
1021 f->f_pos = 0; 1021 f->f_pos = 0;
1022 f->f_flags = O_RDONLY; 1022 f->f_flags = O_RDONLY | (flags & O_NONBLOCK);
1023 f->f_op = &read_pipe_fops; 1023 f->f_op = &read_pipe_fops;
1024 f->f_mode = FMODE_READ; 1024 f->f_mode = FMODE_READ;
1025 f->f_version = 0; 1025 f->f_version = 0;
@@ -1033,13 +1033,13 @@ int do_pipe_flags(int *fd, int flags)
1033 int error; 1033 int error;
1034 int fdw, fdr; 1034 int fdw, fdr;
1035 1035
1036 if (flags & ~O_CLOEXEC) 1036 if (flags & ~(O_CLOEXEC | O_NONBLOCK))
1037 return -EINVAL; 1037 return -EINVAL;
1038 1038
1039 fw = create_write_pipe(); 1039 fw = create_write_pipe(flags);
1040 if (IS_ERR(fw)) 1040 if (IS_ERR(fw))
1041 return PTR_ERR(fw); 1041 return PTR_ERR(fw);
1042 fr = create_read_pipe(fw); 1042 fr = create_read_pipe(fw, flags);
1043 error = PTR_ERR(fr); 1043 error = PTR_ERR(fr);
1044 if (IS_ERR(fr)) 1044 if (IS_ERR(fr))
1045 goto err_write_pipe; 1045 goto err_write_pipe;
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 0e80cd717d32..4b86f806014c 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -1778,8 +1778,8 @@ static inline void allow_write_access(struct file *file)
1778} 1778}
1779extern int do_pipe(int *); 1779extern int do_pipe(int *);
1780extern int do_pipe_flags(int *, int); 1780extern int do_pipe_flags(int *, int);
1781extern struct file *create_read_pipe(struct file *f); 1781extern struct file *create_read_pipe(struct file *f, int flags);
1782extern struct file *create_write_pipe(void); 1782extern struct file *create_write_pipe(int flags);
1783extern void free_write_pipe(struct file *); 1783extern void free_write_pipe(struct file *);
1784 1784
1785extern struct file *do_filp_open(int dfd, const char *pathname, 1785extern struct file *do_filp_open(int dfd, const char *pathname,
diff --git a/kernel/kmod.c b/kernel/kmod.c
index 90d7af1c1655..2989f67c4446 100644
--- a/kernel/kmod.c
+++ b/kernel/kmod.c
@@ -417,12 +417,12 @@ int call_usermodehelper_stdinpipe(struct subprocess_info *sub_info,
417{ 417{
418 struct file *f; 418 struct file *f;
419 419
420 f = create_write_pipe(); 420 f = create_write_pipe(0);
421 if (IS_ERR(f)) 421 if (IS_ERR(f))
422 return PTR_ERR(f); 422 return PTR_ERR(f);
423 *filp = f; 423 *filp = f;
424 424
425 f = create_read_pipe(f); 425 f = create_read_pipe(f, 0);
426 if (IS_ERR(f)) { 426 if (IS_ERR(f)) {
427 free_write_pipe(*filp); 427 free_write_pipe(*filp);
428 return PTR_ERR(f); 428 return PTR_ERR(f);