diff options
author | Sebastian Siewior <bigeasy@linux.vnet.ibm.com> | 2007-06-06 00:03:58 -0400 |
---|---|---|
committer | Paul Mackerras <paulus@samba.org> | 2007-06-06 21:44:40 -0400 |
commit | 87873c86802ba7ff9d9550d06459a6e99d72c5eb (patch) | |
tree | c077539fbf5eca8010d4edfa8fd5771a4926101c /arch | |
parent | 5e1e9ba690a2e2135a8f997242f9c46d2b8ac033 (diff) |
[POWERPC] spufs: Fix error handling in spufs_fill_dir()
The error path in spufs_fill_dir() is broken. If d_alloc_name() or
spufs_new_file() fails, spufs_prune_dir() is getting called. At this time
dir->inode is not set and a NULL pointer is dereferenced by mutex_lock().
This bugfix replaces spufs_prune_dir() with a shorter version that does
not touch dir->inode but simply removes all children.
Signed-off-by: Sebastian Siewior <bigeasy@linux.vnet.ibm.com>
Signed-off-by: Jeremy Kerr <jk@ozlabs.org>
Acked-by: Arnd Bergmann <arnd.bergmann@de.ibm.com>
Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/powerpc/platforms/cell/spufs/inode.c | 17 |
1 files changed, 15 insertions, 2 deletions
diff --git a/arch/powerpc/platforms/cell/spufs/inode.c b/arch/powerpc/platforms/cell/spufs/inode.c index 083568139771..9807206e0219 100644 --- a/arch/powerpc/platforms/cell/spufs/inode.c +++ b/arch/powerpc/platforms/cell/spufs/inode.c | |||
@@ -177,7 +177,7 @@ static int spufs_rmdir(struct inode *parent, struct dentry *dir) | |||
177 | static int spufs_fill_dir(struct dentry *dir, struct tree_descr *files, | 177 | static int spufs_fill_dir(struct dentry *dir, struct tree_descr *files, |
178 | int mode, struct spu_context *ctx) | 178 | int mode, struct spu_context *ctx) |
179 | { | 179 | { |
180 | struct dentry *dentry; | 180 | struct dentry *dentry, *tmp; |
181 | int ret; | 181 | int ret; |
182 | 182 | ||
183 | while (files->name && files->name[0]) { | 183 | while (files->name && files->name[0]) { |
@@ -193,7 +193,20 @@ static int spufs_fill_dir(struct dentry *dir, struct tree_descr *files, | |||
193 | } | 193 | } |
194 | return 0; | 194 | return 0; |
195 | out: | 195 | out: |
196 | spufs_prune_dir(dir); | 196 | /* |
197 | * remove all children from dir. dir->inode is not set so don't | ||
198 | * just simply use spufs_prune_dir() and panic afterwards :) | ||
199 | * dput() looks like it will do the right thing: | ||
200 | * - dec parent's ref counter | ||
201 | * - remove child from parent's child list | ||
202 | * - free child's inode if possible | ||
203 | * - free child | ||
204 | */ | ||
205 | list_for_each_entry_safe(dentry, tmp, &dir->d_subdirs, d_u.d_child) { | ||
206 | dput(dentry); | ||
207 | } | ||
208 | |||
209 | shrink_dcache_parent(dir); | ||
197 | return ret; | 210 | return ret; |
198 | } | 211 | } |
199 | 212 | ||