[PATCH] spufs: fix spufs_fill_dir error path
authorArnd Bergmann <arnd@arndb.de>
Wed, 4 Jan 2006 19:31:27 +0000 (20:31 +0100)
committerPaul Mackerras <paulus@samba.org>
Mon, 9 Jan 2006 04:44:42 +0000 (15:44 +1100)
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>
arch/powerpc/platforms/cell/spufs/inode.c

index d9a39fb..687f80d 100644 (file)
@@ -134,47 +134,18 @@ spufs_delete_inode(struct inode *inode)
        clear_inode(inode);
 }
 
-static int
-spufs_fill_dir(struct dentry *dir, struct tree_descr *files,
-               int mode, struct spu_context *ctx)
-{
-       struct dentry *dentry;
-       int ret;
-
-       while (files->name && files->name[0]) {
-               ret = -ENOMEM;
-               dentry = d_alloc_name(dir, files->name);
-               if (!dentry)
-                       goto out;
-               ret = spufs_new_file(dir->d_sb, dentry, files->ops,
-                                       files->mode & mode, ctx);
-               if (ret)
-                       goto out;
-               files++;
-       }
-       return 0;
-out:
-       // FIXME: remove all files that are left
-
-       return ret;
-}
-
-static int spufs_rmdir(struct inode *root, struct dentry *dir_dentry)
+static void spufs_prune_dir(struct dentry *dir)
 {
        struct dentry *dentry, *tmp;
-       struct spu_context *ctx;
-
-       /* remove all entries */
-       down(&root->i_sem);
-       down(&dir_dentry->d_inode->i_sem);
-       list_for_each_entry_safe(dentry, tmp, &dir_dentry->d_subdirs, d_child) {
+       down(&dir->d_inode->i_sem);
+       list_for_each_entry_safe(dentry, tmp, &dir->d_subdirs, d_child) {
                spin_lock(&dcache_lock);
                spin_lock(&dentry->d_lock);
                if (!(d_unhashed(dentry)) && dentry->d_inode) {
                        dget_locked(dentry);
                        __d_drop(dentry);
                        spin_unlock(&dentry->d_lock);
-                       simple_unlink(dir_dentry->d_inode, dentry);
+                       simple_unlink(dir->d_inode, dentry);
                        spin_unlock(&dcache_lock);
                        dput(dentry);
                } else {
@@ -182,8 +153,17 @@ static int spufs_rmdir(struct inode *root, struct dentry *dir_dentry)
                        spin_unlock(&dcache_lock);
                }
        }
-       shrink_dcache_parent(dir_dentry);
-       up(&dir_dentry->d_inode->i_sem);
+       shrink_dcache_parent(dir);
+       up(&dir->d_inode->i_sem);
+}
+
+static int spufs_rmdir(struct inode *root, struct dentry *dir_dentry)
+{
+       struct spu_context *ctx;
+
+       /* remove all entries */
+       down(&root->i_sem);
+       spufs_prune_dir(dir_dentry);
        up(&root->i_sem);
 
        /* We have to give up the mm_struct */
@@ -194,6 +174,29 @@ static int spufs_rmdir(struct inode *root, struct dentry *dir_dentry)
        return simple_rmdir(root, dir_dentry);
 }
 
+static int spufs_fill_dir(struct dentry *dir, struct tree_descr *files,
+                         int mode, struct spu_context *ctx)
+{
+       struct dentry *dentry;
+       int ret;
+
+       while (files->name && files->name[0]) {
+               ret = -ENOMEM;
+               dentry = d_alloc_name(dir, files->name);
+               if (!dentry)
+                       goto out;
+               ret = spufs_new_file(dir->d_sb, dentry, files->ops,
+                                       files->mode & mode, ctx);
+               if (ret)
+                       goto out;
+               files++;
+       }
+       return 0;
+out:
+       spufs_prune_dir(dir);
+       return ret;
+}
+
 static int spufs_dir_close(struct inode *inode, struct file *file)
 {
        struct inode *dir;