[PATCH] spufs: dont hold root->isem in spu_forget
spu_forget will do mmput on the DMA address space, which can lead to lots of other stuff getting triggered. We better not hold a semaphore here that we might need in the process. 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
762cf6dac2
commit
c8ca0633e5
1 changed files with 10 additions and 10 deletions
|
@ -162,10 +162,10 @@ static int spufs_rmdir(struct inode *root, struct dentry *dir_dentry)
|
||||||
{
|
{
|
||||||
struct dentry *dentry, *tmp;
|
struct dentry *dentry, *tmp;
|
||||||
struct spu_context *ctx;
|
struct spu_context *ctx;
|
||||||
int err;
|
|
||||||
|
|
||||||
/* remove all entries */
|
/* remove all entries */
|
||||||
err = 0;
|
down(&root->i_sem);
|
||||||
|
down(&dir_dentry->d_inode->i_sem);
|
||||||
list_for_each_entry_safe(dentry, tmp, &dir_dentry->d_subdirs, d_child) {
|
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);
|
||||||
|
@ -181,16 +181,16 @@ static int spufs_rmdir(struct inode *root, struct dentry *dir_dentry)
|
||||||
spin_unlock(&dcache_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 */
|
/* We have to give up the mm_struct */
|
||||||
ctx = SPUFS_I(dir_dentry->d_inode)->i_ctx;
|
ctx = SPUFS_I(dir_dentry->d_inode)->i_ctx;
|
||||||
spu_forget(ctx);
|
spu_forget(ctx);
|
||||||
|
|
||||||
if (!err) {
|
/* XXX Do we need to hold i_sem here ? */
|
||||||
shrink_dcache_parent(dir_dentry);
|
return simple_rmdir(root, dir_dentry);
|
||||||
err = simple_rmdir(root, dir_dentry);
|
|
||||||
}
|
|
||||||
return err;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int spufs_dir_close(struct inode *inode, struct file *file)
|
static int spufs_dir_close(struct inode *inode, struct file *file)
|
||||||
|
@ -201,10 +201,10 @@ static int spufs_dir_close(struct inode *inode, struct file *file)
|
||||||
|
|
||||||
dentry = file->f_dentry;
|
dentry = file->f_dentry;
|
||||||
dir = dentry->d_parent->d_inode;
|
dir = dentry->d_parent->d_inode;
|
||||||
down(&dir->i_sem);
|
|
||||||
ret = spufs_rmdir(dir, file->f_dentry);
|
ret = spufs_rmdir(dir, dentry);
|
||||||
WARN_ON(ret);
|
WARN_ON(ret);
|
||||||
up(&dir->i_sem);
|
|
||||||
return dcache_dir_close(inode, file);
|
return dcache_dir_close(inode, file);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue