[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: Arnd Bergmann <arndb@de.ibm.com>
Signed-off-by: Paul Mackerras <paulus@samba.org>
This commit is contained in:
Arnd Bergmann 2006-01-04 20:31:27 +01:00 committed by Paul Mackerras
parent 346f4d3ce9
commit 3f51dd91c8
1 changed files with 43 additions and 40 deletions

View File

@ -134,9 +134,48 @@ 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, *tmp;
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->d_inode, dentry);
spin_unlock(&dcache_lock);
dput(dentry);
} else {
spin_unlock(&dentry->d_lock);
spin_unlock(&dcache_lock);
}
}
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 */
ctx = SPUFS_I(dir_dentry->d_inode)->i_ctx;
spu_forget(ctx);
/* XXX Do we need to hold i_sem here ? */
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; struct dentry *dentry;
int ret; int ret;
@ -154,46 +193,10 @@ spufs_fill_dir(struct dentry *dir, struct tree_descr *files,
} }
return 0; return 0;
out: out:
// FIXME: remove all files that are left spufs_prune_dir(dir);
return ret; return ret;
} }
static int spufs_rmdir(struct inode *root, struct dentry *dir_dentry)
{
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) {
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);
spin_unlock(&dcache_lock);
dput(dentry);
} else {
spin_unlock(&dentry->d_lock);
spin_unlock(&dcache_lock);
}
}
shrink_dcache_parent(dir_dentry);
up(&dir_dentry->d_inode->i_sem);
up(&root->i_sem);
/* We have to give up the mm_struct */
ctx = SPUFS_I(dir_dentry->d_inode)->i_ctx;
spu_forget(ctx);
/* XXX Do we need to hold i_sem here ? */
return simple_rmdir(root, dir_dentry);
}
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;