[PATCH 07/13] spufs: fix spufs_fill_dir error path

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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 <[email protected]>

Index: linux-2.6.15-rc/arch/powerpc/platforms/cell/spufs/inode.c
===================================================================
--- linux-2.6.15-rc.orig/arch/powerpc/platforms/cell/spufs/inode.c
+++ linux-2.6.15-rc/arch/powerpc/platforms/cell/spufs/inode.c
@@ -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 *roo
 			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 *roo
 	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;

--

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[Index of Archives]     [Kernel Newbies]     [Netfilter]     [Bugtraq]     [Photo]     [Stuff]     [Gimp]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Video 4 Linux]     [Linux for the blind]     [Linux Resources]
  Powered by Linux