[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:
parent
346f4d3ce9
commit
3f51dd91c8
|
@ -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;
|
||||||
|
|
Loading…
Reference in New Issue