summaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorArnd Bergmann <arnd@arndb.de>2006-01-04 20:31:22 +0100
committerPaul Mackerras <paulus@samba.org>2006-01-09 15:44:37 +1100
commitc8ca0633e5f2bceab7b4eba4475820fd7674dece (patch)
tree6801e179da8f4cebf09d19446f9ce6fcaab54d8e /arch
parent762cf6dac2623473e83bb271f2bbe97d2355c64d (diff)
downloadlinux-c8ca0633e5f2bceab7b4eba4475820fd7674dece.tar.bz2
[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>
Diffstat (limited to 'arch')
-rw-r--r--arch/powerpc/platforms/cell/spufs/inode.c20
1 files changed, 10 insertions, 10 deletions
diff --git a/arch/powerpc/platforms/cell/spufs/inode.c b/arch/powerpc/platforms/cell/spufs/inode.c
index 2c3ba4eb41cb..45944012b06a 100644
--- a/arch/powerpc/platforms/cell/spufs/inode.c
+++ b/arch/powerpc/platforms/cell/spufs/inode.c
@@ -162,10 +162,10 @@ static int spufs_rmdir(struct inode *root, struct dentry *dir_dentry)
{
struct dentry *dentry, *tmp;
struct spu_context *ctx;
- int err;
/* 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) {
spin_lock(&dcache_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);
}
}
+ 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);
- if (!err) {
- shrink_dcache_parent(dir_dentry);
- err = simple_rmdir(root, dir_dentry);
- }
- return err;
+ /* 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)
@@ -201,10 +201,10 @@ static int spufs_dir_close(struct inode *inode, struct file *file)
dentry = file->f_dentry;
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);
- up(&dir->i_sem);
+
return dcache_dir_close(inode, file);
}