Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3f51dd91 authored by Arnd Bergmann's avatar Arnd Bergmann Committed by Paul Mackerras
Browse files

[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: default avatarArnd Bergmann <arndb@de.ibm.com>
Signed-off-by: default avatarPaul Mackerras <paulus@samba.org>
parent 346f4d3c
Loading
Loading
Loading
Loading
+38 −35
Original line number Diff line number Diff line
@@ -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;