aboutsummaryrefslogtreecommitdiffstats
path: root/fs/anon_inodes.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/anon_inodes.c')
-rw-r--r--fs/anon_inodes.c35
1 files changed, 16 insertions, 19 deletions
diff --git a/fs/anon_inodes.c b/fs/anon_inodes.c
index 2ca7a7cafdbf..9f0bf13291e5 100644
--- a/fs/anon_inodes.c
+++ b/fs/anon_inodes.c
@@ -35,14 +35,13 @@ static int anon_inodefs_get_sb(struct file_system_type *fs_type, int flags,
35 mnt); 35 mnt);
36} 36}
37 37
38static int anon_inodefs_delete_dentry(struct dentry *dentry) 38/*
39 * anon_inodefs_dname() is called from d_path().
40 */
41static char *anon_inodefs_dname(struct dentry *dentry, char *buffer, int buflen)
39{ 42{
40 /* 43 return dynamic_dname(dentry, buffer, buflen, "anon_inode:%s",
41 * We faked vfs to believe the dentry was hashed when we created it. 44 dentry->d_name.name);
42 * Now we restore the flag so that dput() will work correctly.
43 */
44 dentry->d_flags |= DCACHE_UNHASHED;
45 return 1;
46} 45}
47 46
48static struct file_system_type anon_inode_fs_type = { 47static struct file_system_type anon_inode_fs_type = {
@@ -51,7 +50,7 @@ static struct file_system_type anon_inode_fs_type = {
51 .kill_sb = kill_anon_super, 50 .kill_sb = kill_anon_super,
52}; 51};
53static const struct dentry_operations anon_inodefs_dentry_operations = { 52static const struct dentry_operations anon_inodefs_dentry_operations = {
54 .d_delete = anon_inodefs_delete_dentry, 53 .d_dname = anon_inodefs_dname,
55}; 54};
56 55
57/* 56/*
@@ -88,7 +87,7 @@ struct file *anon_inode_getfile(const char *name,
88 void *priv, int flags) 87 void *priv, int flags)
89{ 88{
90 struct qstr this; 89 struct qstr this;
91 struct dentry *dentry; 90 struct path path;
92 struct file *file; 91 struct file *file;
93 int error; 92 int error;
94 93
@@ -106,10 +105,11 @@ struct file *anon_inode_getfile(const char *name,
106 this.name = name; 105 this.name = name;
107 this.len = strlen(name); 106 this.len = strlen(name);
108 this.hash = 0; 107 this.hash = 0;
109 dentry = d_alloc(anon_inode_mnt->mnt_sb->s_root, &this); 108 path.dentry = d_alloc(anon_inode_mnt->mnt_sb->s_root, &this);
110 if (!dentry) 109 if (!path.dentry)
111 goto err_module; 110 goto err_module;
112 111
112 path.mnt = mntget(anon_inode_mnt);
113 /* 113 /*
114 * We know the anon_inode inode count is always greater than zero, 114 * 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 115 * so we can avoid doing an igrab() and we can use an open-coded
@@ -117,27 +117,24 @@ struct file *anon_inode_getfile(const char *name,
117 */ 117 */
118 atomic_inc(&anon_inode_inode->i_count); 118 atomic_inc(&anon_inode_inode->i_count);
119 119
120 dentry->d_op = &anon_inodefs_dentry_operations; 120 path.dentry->d_op = &anon_inodefs_dentry_operations;
121 /* Do not publish this dentry inside the global dentry hash table */ 121 d_instantiate(path.dentry, anon_inode_inode);
122 dentry->d_flags &= ~DCACHE_UNHASHED;
123 d_instantiate(dentry, anon_inode_inode);
124 122
125 error = -ENFILE; 123 error = -ENFILE;
126 file = alloc_file(anon_inode_mnt, dentry, 124 file = alloc_file(&path, OPEN_FMODE(flags), fops);
127 FMODE_READ | FMODE_WRITE, fops);
128 if (!file) 125 if (!file)
129 goto err_dput; 126 goto err_dput;
130 file->f_mapping = anon_inode_inode->i_mapping; 127 file->f_mapping = anon_inode_inode->i_mapping;
131 128
132 file->f_pos = 0; 129 file->f_pos = 0;
133 file->f_flags = O_RDWR | (flags & O_NONBLOCK); 130 file->f_flags = flags & (O_ACCMODE | O_NONBLOCK);
134 file->f_version = 0; 131 file->f_version = 0;
135 file->private_data = priv; 132 file->private_data = priv;
136 133
137 return file; 134 return file;
138 135
139err_dput: 136err_dput:
140 dput(dentry); 137 path_put(&path);
141err_module: 138err_module:
142 module_put(fops->owner); 139 module_put(fops->owner);
143 return ERR_PTR(error); 140 return ERR_PTR(error);