diff options
Diffstat (limited to 'fs/anon_inodes.c')
-rw-r--r-- | fs/anon_inodes.c | 25 |
1 files changed, 12 insertions, 13 deletions
diff --git a/fs/anon_inodes.c b/fs/anon_inodes.c index b4a75880f6fd..23321889d9b0 100644 --- a/fs/anon_inodes.c +++ b/fs/anon_inodes.c | |||
@@ -76,7 +76,6 @@ int anon_inode_getfd(int *pfd, struct inode **pinode, struct file **pfile, | |||
76 | { | 76 | { |
77 | struct qstr this; | 77 | struct qstr this; |
78 | struct dentry *dentry; | 78 | struct dentry *dentry; |
79 | struct inode *inode; | ||
80 | struct file *file; | 79 | struct file *file; |
81 | int error, fd; | 80 | int error, fd; |
82 | 81 | ||
@@ -86,15 +85,9 @@ int anon_inode_getfd(int *pfd, struct inode **pinode, struct file **pfile, | |||
86 | if (!file) | 85 | if (!file) |
87 | return -ENFILE; | 86 | return -ENFILE; |
88 | 87 | ||
89 | inode = igrab(anon_inode_inode); | ||
90 | if (IS_ERR(inode)) { | ||
91 | error = PTR_ERR(inode); | ||
92 | goto err_put_filp; | ||
93 | } | ||
94 | |||
95 | error = get_unused_fd(); | 88 | error = get_unused_fd(); |
96 | if (error < 0) | 89 | if (error < 0) |
97 | goto err_iput; | 90 | goto err_put_filp; |
98 | fd = error; | 91 | fd = error; |
99 | 92 | ||
100 | /* | 93 | /* |
@@ -108,14 +101,22 @@ int anon_inode_getfd(int *pfd, struct inode **pinode, struct file **pfile, | |||
108 | dentry = d_alloc(anon_inode_mnt->mnt_sb->s_root, &this); | 101 | dentry = d_alloc(anon_inode_mnt->mnt_sb->s_root, &this); |
109 | if (!dentry) | 102 | if (!dentry) |
110 | goto err_put_unused_fd; | 103 | goto err_put_unused_fd; |
104 | |||
105 | /* | ||
106 | * We know the anon_inode inode count is always greater than zero, | ||
107 | * so we can avoid doing an igrab() and we can use an open-coded | ||
108 | * atomic_inc(). | ||
109 | */ | ||
110 | atomic_inc(&anon_inode_inode->i_count); | ||
111 | |||
111 | dentry->d_op = &anon_inodefs_dentry_operations; | 112 | dentry->d_op = &anon_inodefs_dentry_operations; |
112 | /* Do not publish this dentry inside the global dentry hash table */ | 113 | /* Do not publish this dentry inside the global dentry hash table */ |
113 | dentry->d_flags &= ~DCACHE_UNHASHED; | 114 | dentry->d_flags &= ~DCACHE_UNHASHED; |
114 | d_instantiate(dentry, inode); | 115 | d_instantiate(dentry, anon_inode_inode); |
115 | 116 | ||
116 | file->f_path.mnt = mntget(anon_inode_mnt); | 117 | file->f_path.mnt = mntget(anon_inode_mnt); |
117 | file->f_path.dentry = dentry; | 118 | file->f_path.dentry = dentry; |
118 | file->f_mapping = inode->i_mapping; | 119 | file->f_mapping = anon_inode_inode->i_mapping; |
119 | 120 | ||
120 | file->f_pos = 0; | 121 | file->f_pos = 0; |
121 | file->f_flags = O_RDWR; | 122 | file->f_flags = O_RDWR; |
@@ -127,14 +128,12 @@ int anon_inode_getfd(int *pfd, struct inode **pinode, struct file **pfile, | |||
127 | fd_install(fd, file); | 128 | fd_install(fd, file); |
128 | 129 | ||
129 | *pfd = fd; | 130 | *pfd = fd; |
130 | *pinode = inode; | 131 | *pinode = anon_inode_inode; |
131 | *pfile = file; | 132 | *pfile = file; |
132 | return 0; | 133 | return 0; |
133 | 134 | ||
134 | err_put_unused_fd: | 135 | err_put_unused_fd: |
135 | put_unused_fd(fd); | 136 | put_unused_fd(fd); |
136 | err_iput: | ||
137 | iput(inode); | ||
138 | err_put_filp: | 137 | err_put_filp: |
139 | put_filp(file); | 138 | put_filp(file); |
140 | return error; | 139 | return error; |