]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/commitdiff
[POWERPC] spufs: Fix error handling in spufs_fill_dir()
authorSebastian Siewior <bigeasy@linux.vnet.ibm.com>
Wed, 6 Jun 2007 04:03:58 +0000 (14:03 +1000)
committerPaul Mackerras <paulus@samba.org>
Thu, 7 Jun 2007 01:44:40 +0000 (11:44 +1000)
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>
arch/powerpc/platforms/cell/spufs/inode.c

index 08356813977103e173b76bea7213dcf7f9b8bab7..9807206e02196d479b1ea171ecc754fae9c7a746 100644 (file)
@@ -177,7 +177,7 @@ static int spufs_rmdir(struct inode *parent, struct dentry *dir)
 static int spufs_fill_dir(struct dentry *dir, struct tree_descr *files,
                          int mode, struct spu_context *ctx)
 {
-       struct dentry *dentry;
+       struct dentry *dentry, *tmp;
        int ret;
 
        while (files->name && files->name[0]) {
@@ -193,7 +193,20 @@ static int spufs_fill_dir(struct dentry *dir, struct tree_descr *files,
        }
        return 0;
 out:
-       spufs_prune_dir(dir);
+       /*
+        * remove all children from dir. dir->inode is not set so don't
+        * just simply use spufs_prune_dir() and panic afterwards :)
+        * dput() looks like it will do the right thing:
+        * - dec parent's ref counter
+        * - remove child from parent's child list
+        * - free child's inode if possible
+        * - free child
+        */
+       list_for_each_entry_safe(dentry, tmp, &dir->d_subdirs, d_u.d_child) {
+               dput(dentry);
+       }
+
+       shrink_dcache_parent(dir);
        return ret;
 }