diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2018-06-09 09:40:05 -0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2018-07-12 10:04:23 -0400 |
commit | d93aa9d82aea80b80f225dbf9c7986df444d8106 (patch) | |
tree | 887b5626f375e6745e034e227eb0c583fbefad99 | |
parent | dbae8f2ca2f0586f4b80201c78ff0aed2a012ab5 (diff) |
new wrapper: alloc_file_pseudo()
takes inode, vfsmount, name, O_... flags and file_operations and
either returns a new struct file (in which case inode reference we
held is consumed) or returns ERR_PTR(), in which case no refcounts
are altered.
converted aio_private_file() and sock_alloc_file() to it
Acked-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
-rw-r--r-- | fs/aio.c | 20 | ||||
-rw-r--r-- | fs/file_table.c | 27 | ||||
-rw-r--r-- | include/linux/file.h | 3 | ||||
-rw-r--r-- | net/socket.c | 28 |
4 files changed, 39 insertions, 39 deletions
@@ -215,9 +215,7 @@ static const struct address_space_operations aio_ctx_aops; | |||
215 | 215 | ||
216 | static struct file *aio_private_file(struct kioctx *ctx, loff_t nr_pages) | 216 | static struct file *aio_private_file(struct kioctx *ctx, loff_t nr_pages) |
217 | { | 217 | { |
218 | struct qstr this = QSTR_INIT("[aio]", 5); | ||
219 | struct file *file; | 218 | struct file *file; |
220 | struct path path; | ||
221 | struct inode *inode = alloc_anon_inode(aio_mnt->mnt_sb); | 219 | struct inode *inode = alloc_anon_inode(aio_mnt->mnt_sb); |
222 | if (IS_ERR(inode)) | 220 | if (IS_ERR(inode)) |
223 | return ERR_CAST(inode); | 221 | return ERR_CAST(inode); |
@@ -226,27 +224,17 @@ static struct file *aio_private_file(struct kioctx *ctx, loff_t nr_pages) | |||
226 | inode->i_mapping->private_data = ctx; | 224 | inode->i_mapping->private_data = ctx; |
227 | inode->i_size = PAGE_SIZE * nr_pages; | 225 | inode->i_size = PAGE_SIZE * nr_pages; |
228 | 226 | ||
229 | path.dentry = d_alloc_pseudo(aio_mnt->mnt_sb, &this); | 227 | file = alloc_file_pseudo(inode, aio_mnt, "[aio]", |
230 | if (!path.dentry) { | 228 | O_RDWR, &aio_ring_fops); |
231 | iput(inode); | ||
232 | return ERR_PTR(-ENOMEM); | ||
233 | } | ||
234 | path.mnt = mntget(aio_mnt); | ||
235 | |||
236 | d_instantiate(path.dentry, inode); | ||
237 | file = alloc_file(&path, O_RDWR, &aio_ring_fops); | ||
238 | if (IS_ERR(file)) | 229 | if (IS_ERR(file)) |
239 | path_put(&path); | 230 | iput(inode); |
240 | return file; | 231 | return file; |
241 | } | 232 | } |
242 | 233 | ||
243 | static struct dentry *aio_mount(struct file_system_type *fs_type, | 234 | static struct dentry *aio_mount(struct file_system_type *fs_type, |
244 | int flags, const char *dev_name, void *data) | 235 | int flags, const char *dev_name, void *data) |
245 | { | 236 | { |
246 | static const struct dentry_operations ops = { | 237 | struct dentry *root = mount_pseudo(fs_type, "aio:", NULL, NULL, |
247 | .d_dname = simple_dname, | ||
248 | }; | ||
249 | struct dentry *root = mount_pseudo(fs_type, "aio:", NULL, &ops, | ||
250 | AIO_RING_MAGIC); | 238 | AIO_RING_MAGIC); |
251 | 239 | ||
252 | if (!IS_ERR(root)) | 240 | if (!IS_ERR(root)) |
diff --git a/fs/file_table.c b/fs/file_table.c index 9b70ed2bbc4e..6b3723909342 100644 --- a/fs/file_table.c +++ b/fs/file_table.c | |||
@@ -184,6 +184,33 @@ struct file *alloc_file(const struct path *path, int flags, | |||
184 | } | 184 | } |
185 | EXPORT_SYMBOL(alloc_file); | 185 | EXPORT_SYMBOL(alloc_file); |
186 | 186 | ||
187 | struct file *alloc_file_pseudo(struct inode *inode, struct vfsmount *mnt, | ||
188 | const char *name, int flags, | ||
189 | const struct file_operations *fops) | ||
190 | { | ||
191 | static const struct dentry_operations anon_ops = { | ||
192 | .d_dname = simple_dname | ||
193 | }; | ||
194 | struct qstr this = QSTR_INIT(name, strlen(name)); | ||
195 | struct path path; | ||
196 | struct file *file; | ||
197 | |||
198 | path.dentry = d_alloc_pseudo(mnt->mnt_sb, &this); | ||
199 | if (!path.dentry) | ||
200 | return ERR_PTR(-ENOMEM); | ||
201 | if (!mnt->mnt_sb->s_d_op) | ||
202 | d_set_d_op(path.dentry, &anon_ops); | ||
203 | path.mnt = mntget(mnt); | ||
204 | d_instantiate(path.dentry, inode); | ||
205 | file = alloc_file(&path, flags, fops); | ||
206 | if (IS_ERR(file)) { | ||
207 | ihold(inode); | ||
208 | path_put(&path); | ||
209 | } | ||
210 | return file; | ||
211 | } | ||
212 | EXPORT_SYMBOL(alloc_file_pseudo); | ||
213 | |||
187 | /* the real guts of fput() - releasing the last reference to file | 214 | /* the real guts of fput() - releasing the last reference to file |
188 | */ | 215 | */ |
189 | static void __fput(struct file *file) | 216 | static void __fput(struct file *file) |
diff --git a/include/linux/file.h b/include/linux/file.h index aed45d69811e..5b25388f2f79 100644 --- a/include/linux/file.h +++ b/include/linux/file.h | |||
@@ -17,9 +17,12 @@ extern void fput(struct file *); | |||
17 | struct file_operations; | 17 | struct file_operations; |
18 | struct vfsmount; | 18 | struct vfsmount; |
19 | struct dentry; | 19 | struct dentry; |
20 | struct inode; | ||
20 | struct path; | 21 | struct path; |
21 | extern struct file *alloc_file(const struct path *, int flags, | 22 | extern struct file *alloc_file(const struct path *, int flags, |
22 | const struct file_operations *fop); | 23 | const struct file_operations *fop); |
24 | extern struct file *alloc_file_pseudo(struct inode *, struct vfsmount *, | ||
25 | const char *, int flags, const struct file_operations *); | ||
23 | 26 | ||
24 | static inline void fput_light(struct file *file, int fput_needed) | 27 | static inline void fput_light(struct file *file, int fput_needed) |
25 | { | 28 | { |
diff --git a/net/socket.c b/net/socket.c index 2cdbe8f71b7f..4cf3568caf9f 100644 --- a/net/socket.c +++ b/net/socket.c | |||
@@ -391,33 +391,15 @@ static struct file_system_type sock_fs_type = { | |||
391 | 391 | ||
392 | struct file *sock_alloc_file(struct socket *sock, int flags, const char *dname) | 392 | struct file *sock_alloc_file(struct socket *sock, int flags, const char *dname) |
393 | { | 393 | { |
394 | struct qstr name = { .name = "" }; | ||
395 | struct path path; | ||
396 | struct file *file; | 394 | struct file *file; |
397 | 395 | ||
398 | if (dname) { | 396 | if (!dname) |
399 | name.name = dname; | 397 | dname = sock->sk ? sock->sk->sk_prot_creator->name : ""; |
400 | name.len = strlen(name.name); | ||
401 | } else if (sock->sk) { | ||
402 | name.name = sock->sk->sk_prot_creator->name; | ||
403 | name.len = strlen(name.name); | ||
404 | } | ||
405 | path.dentry = d_alloc_pseudo(sock_mnt->mnt_sb, &name); | ||
406 | if (unlikely(!path.dentry)) { | ||
407 | sock_release(sock); | ||
408 | return ERR_PTR(-ENOMEM); | ||
409 | } | ||
410 | path.mnt = mntget(sock_mnt); | ||
411 | |||
412 | d_instantiate(path.dentry, SOCK_INODE(sock)); | ||
413 | 398 | ||
414 | file = alloc_file(&path, O_RDWR | (flags & O_NONBLOCK), | 399 | file = alloc_file_pseudo(SOCK_INODE(sock), sock_mnt, dname, |
415 | &socket_file_ops); | 400 | O_RDWR | (flags & O_NONBLOCK), |
401 | &socket_file_ops); | ||
416 | if (IS_ERR(file)) { | 402 | if (IS_ERR(file)) { |
417 | /* drop dentry, keep inode for a bit */ | ||
418 | ihold(d_inode(path.dentry)); | ||
419 | path_put(&path); | ||
420 | /* ... and now kill it properly */ | ||
421 | sock_release(sock); | 403 | sock_release(sock); |
422 | return file; | 404 | return file; |
423 | } | 405 | } |