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

[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
...@@ -134,47 +134,18 @@ spufs_delete_inode(struct inode *inode) ...@@ -134,47 +134,18 @@ spufs_delete_inode(struct inode *inode)
clear_inode(inode); clear_inode(inode);
} }
static int static void spufs_prune_dir(struct dentry *dir)
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)
{ {
struct dentry *dentry, *tmp; struct dentry *dentry, *tmp;
struct spu_context *ctx; down(&dir->d_inode->i_sem);
list_for_each_entry_safe(dentry, tmp, &dir->d_subdirs, d_child) {
/* 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) {
spin_lock(&dcache_lock); spin_lock(&dcache_lock);
spin_lock(&dentry->d_lock); spin_lock(&dentry->d_lock);
if (!(d_unhashed(dentry)) && dentry->d_inode) { if (!(d_unhashed(dentry)) && dentry->d_inode) {
dget_locked(dentry); dget_locked(dentry);
__d_drop(dentry); __d_drop(dentry);
spin_unlock(&dentry->d_lock); spin_unlock(&dentry->d_lock);
simple_unlink(dir_dentry->d_inode, dentry); simple_unlink(dir->d_inode, dentry);
spin_unlock(&dcache_lock); spin_unlock(&dcache_lock);
dput(dentry); dput(dentry);
} else { } else {
...@@ -182,8 +153,17 @@ static int spufs_rmdir(struct inode *root, struct dentry *dir_dentry) ...@@ -182,8 +153,17 @@ static int spufs_rmdir(struct inode *root, struct dentry *dir_dentry)
spin_unlock(&dcache_lock); spin_unlock(&dcache_lock);
} }
} }
shrink_dcache_parent(dir_dentry); shrink_dcache_parent(dir);
up(&dir_dentry->d_inode->i_sem); 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); up(&root->i_sem);
/* We have to give up the mm_struct */ /* We have to give up the mm_struct */
...@@ -194,6 +174,29 @@ static int spufs_rmdir(struct inode *root, struct dentry *dir_dentry) ...@@ -194,6 +174,29 @@ static int spufs_rmdir(struct inode *root, struct dentry *dir_dentry)
return simple_rmdir(root, 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) static int spufs_dir_close(struct inode *inode, struct file *file)
{ {
struct inode *dir; struct inode *dir;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment