diff options
author | Arnd Bergmann <arnd@arndb.de> | 2006-01-04 14:31:27 -0500 |
---|---|---|
committer | Paul Mackerras <paulus@samba.org> | 2006-01-08 23:44:42 -0500 |
commit | 3f51dd91c80746a5cf76f8c4a77bfc88aa82bb9e (patch) | |
tree | f92d9867e51a10b73a3f48fa3d65413f186ac733 | |
parent | 346f4d3ce948a381a559dcaefb141d79f492335c (diff) |
[PATCH] spufs: fix spufs_fill_dir error path
If creating one entry failed in spufs_fill_dir,
we never cleaned up the freshly created entries.
Fix this by calling the cleanup function on error.
Noticed by Al Viro.
Signed-off-by: Arnd Bergmann <arndb@de.ibm.com>
Signed-off-by: Paul Mackerras <paulus@samba.org>
-rw-r--r-- | arch/powerpc/platforms/cell/spufs/inode.c | 73 |
1 files changed, 38 insertions, 35 deletions
diff --git a/arch/powerpc/platforms/cell/spufs/inode.c b/arch/powerpc/platforms/cell/spufs/inode.c index d9a39fb63a8a..687f80d09f41 100644 --- a/arch/powerpc/platforms/cell/spufs/inode.c +++ b/arch/powerpc/platforms/cell/spufs/inode.c | |||
@@ -134,47 +134,18 @@ spufs_delete_inode(struct inode *inode) | |||
134 | clear_inode(inode); | 134 | clear_inode(inode); |
135 | } | 135 | } |
136 | 136 | ||
137 | static int | 137 | static void spufs_prune_dir(struct dentry *dir) |
138 | spufs_fill_dir(struct dentry *dir, struct tree_descr *files, | ||
139 | int mode, struct spu_context *ctx) | ||
140 | { | ||
141 | struct dentry *dentry; | ||
142 | int ret; | ||
143 | |||
144 | while (files->name && files->name[0]) { | ||
145 | ret = -ENOMEM; | ||
146 | dentry = d_alloc_name(dir, files->name); | ||
147 | if (!dentry) | ||
148 | goto out; | ||
149 | ret = spufs_new_file(dir->d_sb, dentry, files->ops, | ||
150 | files->mode & mode, ctx); | ||
151 | if (ret) | ||
152 | goto out; | ||
153 | files++; | ||
154 | } | ||
155 | return 0; | ||
156 | out: | ||
157 | // FIXME: remove all files that are left | ||
158 | |||
159 | return ret; | ||
160 | } | ||
161 | |||
162 | static int spufs_rmdir(struct inode *root, struct dentry *dir_dentry) | ||
163 | { | 138 | { |
164 | struct dentry *dentry, *tmp; | 139 | struct dentry *dentry, *tmp; |
165 | struct spu_context *ctx; | 140 | down(&dir->d_inode->i_sem); |
166 | 141 | list_for_each_entry_safe(dentry, tmp, &dir->d_subdirs, d_child) { | |
167 | /* remove all entries */ | ||
168 | down(&root->i_sem); | ||
169 | down(&dir_dentry->d_inode->i_sem); | ||
170 | list_for_each_entry_safe(dentry, tmp, &dir_dentry->d_subdirs, d_child) { | ||
171 | spin_lock(&dcache_lock); | 142 | spin_lock(&dcache_lock); |
172 | spin_lock(&dentry->d_lock); | 143 | spin_lock(&dentry->d_lock); |
173 | if (!(d_unhashed(dentry)) && dentry->d_inode) { | 144 | if (!(d_unhashed(dentry)) && dentry->d_inode) { |
174 | dget_locked(dentry); | 145 | dget_locked(dentry); |
175 | __d_drop(dentry); | 146 | __d_drop(dentry); |
176 | spin_unlock(&dentry->d_lock); | 147 | spin_unlock(&dentry->d_lock); |
177 | simple_unlink(dir_dentry->d_inode, dentry); | 148 | simple_unlink(dir->d_inode, dentry); |
178 | spin_unlock(&dcache_lock); | 149 | spin_unlock(&dcache_lock); |
179 | dput(dentry); | 150 | dput(dentry); |
180 | } else { | 151 | } else { |
@@ -182,8 +153,17 @@ static int spufs_rmdir(struct inode *root, struct dentry *dir_dentry) | |||
182 | spin_unlock(&dcache_lock); | 153 | spin_unlock(&dcache_lock); |
183 | } | 154 | } |
184 | } | 155 | } |
185 | shrink_dcache_parent(dir_dentry); | 156 | shrink_dcache_parent(dir); |
186 | up(&dir_dentry->d_inode->i_sem); | 157 | up(&dir->d_inode->i_sem); |
158 | } | ||
159 | |||
160 | static int spufs_rmdir(struct inode *root, struct dentry *dir_dentry) | ||
161 | { | ||
162 | struct spu_context *ctx; | ||
163 | |||
164 | /* remove all entries */ | ||
165 | down(&root->i_sem); | ||
166 | spufs_prune_dir(dir_dentry); | ||
187 | up(&root->i_sem); | 167 | up(&root->i_sem); |
188 | 168 | ||
189 | /* We have to give up the mm_struct */ | 169 | /* We have to give up the mm_struct */ |
@@ -194,6 +174,29 @@ static int spufs_rmdir(struct inode *root, struct dentry *dir_dentry) | |||
194 | return simple_rmdir(root, dir_dentry); | 174 | return simple_rmdir(root, dir_dentry); |
195 | } | 175 | } |
196 | 176 | ||
177 | static int spufs_fill_dir(struct dentry *dir, struct tree_descr *files, | ||
178 | int mode, struct spu_context *ctx) | ||
179 | { | ||
180 | struct dentry *dentry; | ||
181 | int ret; | ||
182 | |||
183 | while (files->name && files->name[0]) { | ||
184 | ret = -ENOMEM; | ||
185 | dentry = d_alloc_name(dir, files->name); | ||
186 | if (!dentry) | ||
187 | goto out; | ||
188 | ret = spufs_new_file(dir->d_sb, dentry, files->ops, | ||
189 | files->mode & mode, ctx); | ||
190 | if (ret) | ||
191 | goto out; | ||
192 | files++; | ||
193 | } | ||
194 | return 0; | ||
195 | out: | ||
196 | spufs_prune_dir(dir); | ||
197 | return ret; | ||
198 | } | ||
199 | |||
197 | static int spufs_dir_close(struct inode *inode, struct file *file) | 200 | static int spufs_dir_close(struct inode *inode, struct file *file) |
198 | { | 201 | { |
199 | struct inode *dir; | 202 | struct inode *dir; |