diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2009-08-08 16:52:35 -0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2009-12-16 12:16:42 -0500 |
commit | 2c48b9c45579a9b5e3e74694eebf3d2451f3dbd3 (patch) | |
tree | cecbf786ae0650368a8136bdd90910e05d9b95c3 /fs | |
parent | a95161aaa801c18c52b2e7cf3d6b4b141c00a20a (diff) |
switch alloc_file() to passing struct path
... and have the caller grab both mnt and dentry; kill
leak in infiniband, while we are at it.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/anon_inodes.c | 18 | ||||
-rw-r--r-- | fs/file_table.c | 13 | ||||
-rw-r--r-- | fs/hugetlbfs/inode.c | 15 | ||||
-rw-r--r-- | fs/notify/inotify/inotify_user.c | 8 | ||||
-rw-r--r-- | fs/pipe.c | 17 |
5 files changed, 38 insertions, 33 deletions
diff --git a/fs/anon_inodes.c b/fs/anon_inodes.c index 2ca7a7cafdbf..94f5110c4655 100644 --- a/fs/anon_inodes.c +++ b/fs/anon_inodes.c | |||
@@ -88,7 +88,7 @@ struct file *anon_inode_getfile(const char *name, | |||
88 | void *priv, int flags) | 88 | void *priv, int flags) |
89 | { | 89 | { |
90 | struct qstr this; | 90 | struct qstr this; |
91 | struct dentry *dentry; | 91 | struct path path; |
92 | struct file *file; | 92 | struct file *file; |
93 | int error; | 93 | int error; |
94 | 94 | ||
@@ -106,10 +106,11 @@ struct file *anon_inode_getfile(const char *name, | |||
106 | this.name = name; | 106 | this.name = name; |
107 | this.len = strlen(name); | 107 | this.len = strlen(name); |
108 | this.hash = 0; | 108 | this.hash = 0; |
109 | dentry = d_alloc(anon_inode_mnt->mnt_sb->s_root, &this); | 109 | path.dentry = d_alloc(anon_inode_mnt->mnt_sb->s_root, &this); |
110 | if (!dentry) | 110 | if (!path.dentry) |
111 | goto err_module; | 111 | goto err_module; |
112 | 112 | ||
113 | path.mnt = mntget(anon_inode_mnt); | ||
113 | /* | 114 | /* |
114 | * We know the anon_inode inode count is always greater than zero, | 115 | * We know the anon_inode inode count is always greater than zero, |
115 | * so we can avoid doing an igrab() and we can use an open-coded | 116 | * so we can avoid doing an igrab() and we can use an open-coded |
@@ -117,14 +118,13 @@ struct file *anon_inode_getfile(const char *name, | |||
117 | */ | 118 | */ |
118 | atomic_inc(&anon_inode_inode->i_count); | 119 | atomic_inc(&anon_inode_inode->i_count); |
119 | 120 | ||
120 | dentry->d_op = &anon_inodefs_dentry_operations; | 121 | path.dentry->d_op = &anon_inodefs_dentry_operations; |
121 | /* Do not publish this dentry inside the global dentry hash table */ | 122 | /* Do not publish this dentry inside the global dentry hash table */ |
122 | dentry->d_flags &= ~DCACHE_UNHASHED; | 123 | path.dentry->d_flags &= ~DCACHE_UNHASHED; |
123 | d_instantiate(dentry, anon_inode_inode); | 124 | d_instantiate(path.dentry, anon_inode_inode); |
124 | 125 | ||
125 | error = -ENFILE; | 126 | error = -ENFILE; |
126 | file = alloc_file(anon_inode_mnt, dentry, | 127 | file = alloc_file(&path, FMODE_READ | FMODE_WRITE, fops); |
127 | FMODE_READ | FMODE_WRITE, fops); | ||
128 | if (!file) | 128 | if (!file) |
129 | goto err_dput; | 129 | goto err_dput; |
130 | file->f_mapping = anon_inode_inode->i_mapping; | 130 | file->f_mapping = anon_inode_inode->i_mapping; |
@@ -137,7 +137,7 @@ struct file *anon_inode_getfile(const char *name, | |||
137 | return file; | 137 | return file; |
138 | 138 | ||
139 | err_dput: | 139 | err_dput: |
140 | dput(dentry); | 140 | path_put(&path); |
141 | err_module: | 141 | err_module: |
142 | module_put(fops->owner); | 142 | module_put(fops->owner); |
143 | return ERR_PTR(error); | 143 | return ERR_PTR(error); |
diff --git a/fs/file_table.c b/fs/file_table.c index 602a9ee3023a..163cd28314e0 100644 --- a/fs/file_table.c +++ b/fs/file_table.c | |||
@@ -162,8 +162,8 @@ fail: | |||
162 | * If all the callers of init_file() are eliminated, its | 162 | * If all the callers of init_file() are eliminated, its |
163 | * code should be moved into this function. | 163 | * code should be moved into this function. |
164 | */ | 164 | */ |
165 | struct file *alloc_file(struct vfsmount *mnt, struct dentry *dentry, | 165 | struct file *alloc_file(struct path *path, fmode_t mode, |
166 | fmode_t mode, const struct file_operations *fop) | 166 | const struct file_operations *fop) |
167 | { | 167 | { |
168 | struct file *file; | 168 | struct file *file; |
169 | 169 | ||
@@ -171,9 +171,8 @@ struct file *alloc_file(struct vfsmount *mnt, struct dentry *dentry, | |||
171 | if (!file) | 171 | if (!file) |
172 | return NULL; | 172 | return NULL; |
173 | 173 | ||
174 | file->f_path.dentry = dentry; | 174 | file->f_path = *path; |
175 | file->f_path.mnt = mntget(mnt); | 175 | file->f_mapping = path->dentry->d_inode->i_mapping; |
176 | file->f_mapping = dentry->d_inode->i_mapping; | ||
177 | file->f_mode = mode; | 176 | file->f_mode = mode; |
178 | file->f_op = fop; | 177 | file->f_op = fop; |
179 | 178 | ||
@@ -183,10 +182,10 @@ struct file *alloc_file(struct vfsmount *mnt, struct dentry *dentry, | |||
183 | * visible. We do this for consistency, and so | 182 | * visible. We do this for consistency, and so |
184 | * that we can do debugging checks at __fput() | 183 | * that we can do debugging checks at __fput() |
185 | */ | 184 | */ |
186 | if ((mode & FMODE_WRITE) && !special_file(dentry->d_inode->i_mode)) { | 185 | if ((mode & FMODE_WRITE) && !special_file(path->dentry->d_inode->i_mode)) { |
187 | int error = 0; | 186 | int error = 0; |
188 | file_take_write(file); | 187 | file_take_write(file); |
189 | error = mnt_clone_write(mnt); | 188 | error = mnt_clone_write(path->mnt); |
190 | WARN_ON(error); | 189 | WARN_ON(error); |
191 | } | 190 | } |
192 | return file; | 191 | return file; |
diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c index 87a1258953b8..6bd41525cd71 100644 --- a/fs/hugetlbfs/inode.c +++ b/fs/hugetlbfs/inode.c | |||
@@ -922,7 +922,8 @@ struct file *hugetlb_file_setup(const char *name, size_t size, int acctflag, | |||
922 | int error = -ENOMEM; | 922 | int error = -ENOMEM; |
923 | struct file *file; | 923 | struct file *file; |
924 | struct inode *inode; | 924 | struct inode *inode; |
925 | struct dentry *dentry, *root; | 925 | struct path path; |
926 | struct dentry *root; | ||
926 | struct qstr quick_string; | 927 | struct qstr quick_string; |
927 | 928 | ||
928 | *user = NULL; | 929 | *user = NULL; |
@@ -944,10 +945,11 @@ struct file *hugetlb_file_setup(const char *name, size_t size, int acctflag, | |||
944 | quick_string.name = name; | 945 | quick_string.name = name; |
945 | quick_string.len = strlen(quick_string.name); | 946 | quick_string.len = strlen(quick_string.name); |
946 | quick_string.hash = 0; | 947 | quick_string.hash = 0; |
947 | dentry = d_alloc(root, &quick_string); | 948 | path.dentry = d_alloc(root, &quick_string); |
948 | if (!dentry) | 949 | if (!path.dentry) |
949 | goto out_shm_unlock; | 950 | goto out_shm_unlock; |
950 | 951 | ||
952 | path.mnt = mntget(hugetlbfs_vfsmount); | ||
951 | error = -ENOSPC; | 953 | error = -ENOSPC; |
952 | inode = hugetlbfs_get_inode(root->d_sb, current_fsuid(), | 954 | inode = hugetlbfs_get_inode(root->d_sb, current_fsuid(), |
953 | current_fsgid(), S_IFREG | S_IRWXUGO, 0); | 955 | current_fsgid(), S_IFREG | S_IRWXUGO, 0); |
@@ -960,13 +962,12 @@ struct file *hugetlb_file_setup(const char *name, size_t size, int acctflag, | |||
960 | acctflag)) | 962 | acctflag)) |
961 | goto out_inode; | 963 | goto out_inode; |
962 | 964 | ||
963 | d_instantiate(dentry, inode); | 965 | d_instantiate(path.dentry, inode); |
964 | inode->i_size = size; | 966 | inode->i_size = size; |
965 | inode->i_nlink = 0; | 967 | inode->i_nlink = 0; |
966 | 968 | ||
967 | error = -ENFILE; | 969 | error = -ENFILE; |
968 | file = alloc_file(hugetlbfs_vfsmount, dentry, | 970 | file = alloc_file(&path, FMODE_WRITE | FMODE_READ, |
969 | FMODE_WRITE | FMODE_READ, | ||
970 | &hugetlbfs_file_operations); | 971 | &hugetlbfs_file_operations); |
971 | if (!file) | 972 | if (!file) |
972 | goto out_dentry; /* inode is already attached */ | 973 | goto out_dentry; /* inode is already attached */ |
@@ -977,7 +978,7 @@ struct file *hugetlb_file_setup(const char *name, size_t size, int acctflag, | |||
977 | out_inode: | 978 | out_inode: |
978 | iput(inode); | 979 | iput(inode); |
979 | out_dentry: | 980 | out_dentry: |
980 | dput(dentry); | 981 | path_put(&path); |
981 | out_shm_unlock: | 982 | out_shm_unlock: |
982 | if (*user) { | 983 | if (*user) { |
983 | user_shm_unlock(size, *user); | 984 | user_shm_unlock(size, *user); |
diff --git a/fs/notify/inotify/inotify_user.c b/fs/notify/inotify/inotify_user.c index 9e4f90042eaf..8271cf05c957 100644 --- a/fs/notify/inotify/inotify_user.c +++ b/fs/notify/inotify/inotify_user.c | |||
@@ -646,6 +646,7 @@ SYSCALL_DEFINE1(inotify_init1, int, flags) | |||
646 | struct fsnotify_group *group; | 646 | struct fsnotify_group *group; |
647 | struct user_struct *user; | 647 | struct user_struct *user; |
648 | struct file *filp; | 648 | struct file *filp; |
649 | struct path path; | ||
649 | int fd, ret; | 650 | int fd, ret; |
650 | 651 | ||
651 | /* Check the IN_* constants for consistency. */ | 652 | /* Check the IN_* constants for consistency. */ |
@@ -675,8 +676,10 @@ SYSCALL_DEFINE1(inotify_init1, int, flags) | |||
675 | 676 | ||
676 | atomic_inc(&user->inotify_devs); | 677 | atomic_inc(&user->inotify_devs); |
677 | 678 | ||
678 | filp = alloc_file(inotify_mnt, dget(inotify_mnt->mnt_root), | 679 | path.mnt = inotify_mnt; |
679 | FMODE_READ, &inotify_fops); | 680 | path.dentry = inotify_mnt->mnt_root; |
681 | path_get(&path); | ||
682 | filp = alloc_file(&path, FMODE_READ, &inotify_fops); | ||
680 | if (!filp) | 683 | if (!filp) |
681 | goto Enfile; | 684 | goto Enfile; |
682 | 685 | ||
@@ -689,6 +692,7 @@ SYSCALL_DEFINE1(inotify_init1, int, flags) | |||
689 | 692 | ||
690 | Enfile: | 693 | Enfile: |
691 | ret = -ENFILE; | 694 | ret = -ENFILE; |
695 | path_put(&path); | ||
692 | atomic_dec(&user->inotify_devs); | 696 | atomic_dec(&user->inotify_devs); |
693 | out_free_uid: | 697 | out_free_uid: |
694 | free_uid(user); | 698 | free_uid(user); |
@@ -974,7 +974,7 @@ struct file *create_write_pipe(int flags) | |||
974 | int err; | 974 | int err; |
975 | struct inode *inode; | 975 | struct inode *inode; |
976 | struct file *f; | 976 | struct file *f; |
977 | struct dentry *dentry; | 977 | struct path path; |
978 | struct qstr name = { .name = "" }; | 978 | struct qstr name = { .name = "" }; |
979 | 979 | ||
980 | err = -ENFILE; | 980 | err = -ENFILE; |
@@ -983,21 +983,22 @@ struct file *create_write_pipe(int flags) | |||
983 | goto err; | 983 | goto err; |
984 | 984 | ||
985 | err = -ENOMEM; | 985 | err = -ENOMEM; |
986 | dentry = d_alloc(pipe_mnt->mnt_sb->s_root, &name); | 986 | path.dentry = d_alloc(pipe_mnt->mnt_sb->s_root, &name); |
987 | if (!dentry) | 987 | if (!path.dentry) |
988 | goto err_inode; | 988 | goto err_inode; |
989 | path.mnt = mntget(pipe_mnt); | ||
989 | 990 | ||
990 | dentry->d_op = &pipefs_dentry_operations; | 991 | path.dentry->d_op = &pipefs_dentry_operations; |
991 | /* | 992 | /* |
992 | * We dont want to publish this dentry into global dentry hash table. | 993 | * We dont want to publish this dentry into global dentry hash table. |
993 | * We pretend dentry is already hashed, by unsetting DCACHE_UNHASHED | 994 | * We pretend dentry is already hashed, by unsetting DCACHE_UNHASHED |
994 | * This permits a working /proc/$pid/fd/XXX on pipes | 995 | * This permits a working /proc/$pid/fd/XXX on pipes |
995 | */ | 996 | */ |
996 | dentry->d_flags &= ~DCACHE_UNHASHED; | 997 | path.dentry->d_flags &= ~DCACHE_UNHASHED; |
997 | d_instantiate(dentry, inode); | 998 | d_instantiate(path.dentry, inode); |
998 | 999 | ||
999 | err = -ENFILE; | 1000 | err = -ENFILE; |
1000 | f = alloc_file(pipe_mnt, dentry, FMODE_WRITE, &write_pipefifo_fops); | 1001 | f = alloc_file(&path, FMODE_WRITE, &write_pipefifo_fops); |
1001 | if (!f) | 1002 | if (!f) |
1002 | goto err_dentry; | 1003 | goto err_dentry; |
1003 | f->f_mapping = inode->i_mapping; | 1004 | f->f_mapping = inode->i_mapping; |
@@ -1009,7 +1010,7 @@ struct file *create_write_pipe(int flags) | |||
1009 | 1010 | ||
1010 | err_dentry: | 1011 | err_dentry: |
1011 | free_pipe_info(inode); | 1012 | free_pipe_info(inode); |
1012 | dput(dentry); | 1013 | path_put(&path); |
1013 | return ERR_PTR(err); | 1014 | return ERR_PTR(err); |
1014 | 1015 | ||
1015 | err_inode: | 1016 | err_inode: |