aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2018-06-09 09:40:05 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2018-07-12 10:04:23 -0400
commitd93aa9d82aea80b80f225dbf9c7986df444d8106 (patch)
tree887b5626f375e6745e034e227eb0c583fbefad99
parentdbae8f2ca2f0586f4b80201c78ff0aed2a012ab5 (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.c20
-rw-r--r--fs/file_table.c27
-rw-r--r--include/linux/file.h3
-rw-r--r--net/socket.c28
4 files changed, 39 insertions, 39 deletions
diff --git a/fs/aio.c b/fs/aio.c
index 9eea53887d6c..c3a8bac16374 100644
--- a/fs/aio.c
+++ b/fs/aio.c
@@ -215,9 +215,7 @@ static const struct address_space_operations aio_ctx_aops;
215 215
216static struct file *aio_private_file(struct kioctx *ctx, loff_t nr_pages) 216static 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
243static struct dentry *aio_mount(struct file_system_type *fs_type, 234static 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}
185EXPORT_SYMBOL(alloc_file); 185EXPORT_SYMBOL(alloc_file);
186 186
187struct 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}
212EXPORT_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 */
189static void __fput(struct file *file) 216static 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 *);
17struct file_operations; 17struct file_operations;
18struct vfsmount; 18struct vfsmount;
19struct dentry; 19struct dentry;
20struct inode;
20struct path; 21struct path;
21extern struct file *alloc_file(const struct path *, int flags, 22extern struct file *alloc_file(const struct path *, int flags,
22 const struct file_operations *fop); 23 const struct file_operations *fop);
24extern struct file *alloc_file_pseudo(struct inode *, struct vfsmount *,
25 const char *, int flags, const struct file_operations *);
23 26
24static inline void fput_light(struct file *file, int fput_needed) 27static 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
392struct file *sock_alloc_file(struct socket *sock, int flags, const char *dname) 392struct 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 }