diff options
author | Andi Kleen <ak@suse.de> | 2006-10-01 02:29:26 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-10-01 03:39:33 -0400 |
commit | d6cbd281d189977b38eac7eb2a4678de19b6b483 (patch) | |
tree | f853d303687275cd4328bfac53780b7c7c2c67ef | |
parent | 65da4d81f48e092f71feaf04bf2ccd096b5a5171 (diff) |
[PATCH] Some cleanup in the pipe code
Split the big and hard to read do_pipe function into smaller pieces.
This creates new create_write_pipe/free_write_pipe/create_read_pipe
functions. These functions are made global so that they can be used by
other parts of the kernel.
The resulting code is more generic and easier to read and has cleaner error
handling and less gotos.
[akpm@osdl.org: cleanup]
Signed-off-by: Andi Kleen <ak@suse.de>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r-- | fs/pipe.c | 155 | ||||
-rw-r--r-- | include/linux/fs.h | 3 |
2 files changed, 96 insertions, 62 deletions
@@ -874,87 +874,118 @@ fail_inode: | |||
874 | return NULL; | 874 | return NULL; |
875 | } | 875 | } |
876 | 876 | ||
877 | int do_pipe(int *fd) | 877 | struct file *create_write_pipe(void) |
878 | { | 878 | { |
879 | struct qstr this; | 879 | int err; |
880 | char name[32]; | 880 | struct inode *inode; |
881 | struct file *f; | ||
881 | struct dentry *dentry; | 882 | struct dentry *dentry; |
882 | struct inode * inode; | 883 | char name[32]; |
883 | struct file *f1, *f2; | 884 | struct qstr this; |
884 | int error; | ||
885 | int i, j; | ||
886 | |||
887 | error = -ENFILE; | ||
888 | f1 = get_empty_filp(); | ||
889 | if (!f1) | ||
890 | goto no_files; | ||
891 | |||
892 | f2 = get_empty_filp(); | ||
893 | if (!f2) | ||
894 | goto close_f1; | ||
895 | 885 | ||
886 | f = get_empty_filp(); | ||
887 | if (!f) | ||
888 | return ERR_PTR(-ENFILE); | ||
889 | err = -ENFILE; | ||
896 | inode = get_pipe_inode(); | 890 | inode = get_pipe_inode(); |
897 | if (!inode) | 891 | if (!inode) |
898 | goto close_f12; | 892 | goto err_file; |
899 | 893 | ||
900 | error = get_unused_fd(); | ||
901 | if (error < 0) | ||
902 | goto close_f12_inode; | ||
903 | i = error; | ||
904 | |||
905 | error = get_unused_fd(); | ||
906 | if (error < 0) | ||
907 | goto close_f12_inode_i; | ||
908 | j = error; | ||
909 | |||
910 | error = -ENOMEM; | ||
911 | sprintf(name, "[%lu]", inode->i_ino); | 894 | sprintf(name, "[%lu]", inode->i_ino); |
912 | this.name = name; | 895 | this.name = name; |
913 | this.len = strlen(name); | 896 | this.len = strlen(name); |
914 | this.hash = inode->i_ino; /* will go */ | 897 | this.hash = inode->i_ino; /* will go */ |
898 | err = -ENOMEM; | ||
915 | dentry = d_alloc(pipe_mnt->mnt_sb->s_root, &this); | 899 | dentry = d_alloc(pipe_mnt->mnt_sb->s_root, &this); |
916 | if (!dentry) | 900 | if (!dentry) |
917 | goto close_f12_inode_i_j; | 901 | goto err_inode; |
918 | 902 | ||
919 | dentry->d_op = &pipefs_dentry_operations; | 903 | dentry->d_op = &pipefs_dentry_operations; |
920 | d_add(dentry, inode); | 904 | d_add(dentry, inode); |
921 | f1->f_vfsmnt = f2->f_vfsmnt = mntget(mntget(pipe_mnt)); | 905 | f->f_vfsmnt = mntget(pipe_mnt); |
922 | f1->f_dentry = f2->f_dentry = dget(dentry); | 906 | f->f_dentry = dentry; |
923 | f1->f_mapping = f2->f_mapping = inode->i_mapping; | 907 | f->f_mapping = inode->i_mapping; |
924 | |||
925 | /* read file */ | ||
926 | f1->f_pos = f2->f_pos = 0; | ||
927 | f1->f_flags = O_RDONLY; | ||
928 | f1->f_op = &read_pipe_fops; | ||
929 | f1->f_mode = FMODE_READ; | ||
930 | f1->f_version = 0; | ||
931 | |||
932 | /* write file */ | ||
933 | f2->f_flags = O_WRONLY; | ||
934 | f2->f_op = &write_pipe_fops; | ||
935 | f2->f_mode = FMODE_WRITE; | ||
936 | f2->f_version = 0; | ||
937 | |||
938 | fd_install(i, f1); | ||
939 | fd_install(j, f2); | ||
940 | fd[0] = i; | ||
941 | fd[1] = j; | ||
942 | 908 | ||
943 | return 0; | 909 | f->f_flags = O_WRONLY; |
910 | f->f_op = &write_pipe_fops; | ||
911 | f->f_mode = FMODE_WRITE; | ||
912 | f->f_version = 0; | ||
944 | 913 | ||
945 | close_f12_inode_i_j: | 914 | return f; |
946 | put_unused_fd(j); | 915 | |
947 | close_f12_inode_i: | 916 | err_inode: |
948 | put_unused_fd(i); | ||
949 | close_f12_inode: | ||
950 | free_pipe_info(inode); | 917 | free_pipe_info(inode); |
951 | iput(inode); | 918 | iput(inode); |
952 | close_f12: | 919 | err_file: |
953 | put_filp(f2); | 920 | put_filp(f); |
954 | close_f1: | 921 | return ERR_PTR(err); |
955 | put_filp(f1); | 922 | } |
956 | no_files: | 923 | |
957 | return error; | 924 | void free_write_pipe(struct file *f) |
925 | { | ||
926 | mntput(f->f_vfsmnt); | ||
927 | dput(f->f_dentry); | ||
928 | put_filp(f); | ||
929 | } | ||
930 | |||
931 | struct file *create_read_pipe(struct file *wrf) | ||
932 | { | ||
933 | struct file *f = get_empty_filp(); | ||
934 | if (!f) | ||
935 | return ERR_PTR(-ENFILE); | ||
936 | |||
937 | /* Grab pipe from the writer */ | ||
938 | f->f_vfsmnt = mntget(wrf->f_vfsmnt); | ||
939 | f->f_dentry = dget(wrf->f_dentry); | ||
940 | f->f_mapping = wrf->f_dentry->d_inode->i_mapping; | ||
941 | |||
942 | f->f_pos = 0; | ||
943 | f->f_flags = O_RDONLY; | ||
944 | f->f_op = &read_pipe_fops; | ||
945 | f->f_mode = FMODE_READ; | ||
946 | f->f_version = 0; | ||
947 | |||
948 | return f; | ||
949 | } | ||
950 | |||
951 | int do_pipe(int *fd) | ||
952 | { | ||
953 | struct file *fw, *fr; | ||
954 | int error; | ||
955 | int fdw, fdr; | ||
956 | |||
957 | fw = create_write_pipe(); | ||
958 | if (IS_ERR(fw)) | ||
959 | return PTR_ERR(fw); | ||
960 | fr = create_read_pipe(fw); | ||
961 | error = PTR_ERR(fr); | ||
962 | if (IS_ERR(fr)) | ||
963 | goto err_write_pipe; | ||
964 | |||
965 | error = get_unused_fd(); | ||
966 | if (error < 0) | ||
967 | goto err_read_pipe; | ||
968 | fdr = error; | ||
969 | |||
970 | error = get_unused_fd(); | ||
971 | if (error < 0) | ||
972 | goto err_fdr; | ||
973 | fdw = error; | ||
974 | |||
975 | fd_install(fdr, fr); | ||
976 | fd_install(fdw, fw); | ||
977 | fd[0] = fdr; | ||
978 | fd[1] = fdw; | ||
979 | |||
980 | return 0; | ||
981 | |||
982 | err_fdr: | ||
983 | put_unused_fd(fdr); | ||
984 | err_read_pipe: | ||
985 | put_filp(fr); | ||
986 | err_write_pipe: | ||
987 | free_write_pipe(fw); | ||
988 | return error; | ||
958 | } | 989 | } |
959 | 990 | ||
960 | /* | 991 | /* |
diff --git a/include/linux/fs.h b/include/linux/fs.h index 3493d2828f7d..2e29a2edaeec 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h | |||
@@ -1641,6 +1641,9 @@ static inline void allow_write_access(struct file *file) | |||
1641 | atomic_inc(&file->f_dentry->d_inode->i_writecount); | 1641 | atomic_inc(&file->f_dentry->d_inode->i_writecount); |
1642 | } | 1642 | } |
1643 | extern int do_pipe(int *); | 1643 | extern int do_pipe(int *); |
1644 | extern struct file *create_read_pipe(struct file *f); | ||
1645 | extern struct file *create_write_pipe(void); | ||
1646 | extern void free_write_pipe(struct file *); | ||
1644 | 1647 | ||
1645 | extern int open_namei(int dfd, const char *, int, int, struct nameidata *); | 1648 | extern int open_namei(int dfd, const char *, int, int, struct nameidata *); |
1646 | extern int may_open(struct nameidata *, int, int); | 1649 | extern int may_open(struct nameidata *, int, int); |