[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:
Arnd Bergmann 2006-01-04 20:31:22 +01:00 committed by Paul Mackerras
parent 762cf6dac2
commit c8ca0633e5

View file

@ -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);
} }