diff options
author | Arnd Bergmann <arnd@arndb.de> | 2006-01-04 14:31:22 -0500 |
---|---|---|
committer | Paul Mackerras <paulus@samba.org> | 2006-01-08 23:44:37 -0500 |
commit | c8ca0633e5f2bceab7b4eba4475820fd7674dece (patch) | |
tree | 6801e179da8f4cebf09d19446f9ce6fcaab54d8e | |
parent | 762cf6dac2623473e83bb271f2bbe97d2355c64d (diff) |
[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>
-rw-r--r-- | arch/powerpc/platforms/cell/spufs/inode.c | 20 |
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) | |||
162 | { | 162 | { |
163 | struct dentry *dentry, *tmp; | 163 | struct dentry *dentry, *tmp; |
164 | struct spu_context *ctx; | 164 | struct spu_context *ctx; |
165 | int err; | ||
166 | 165 | ||
167 | /* remove all entries */ | 166 | /* remove all entries */ |
168 | err = 0; | 167 | down(&root->i_sem); |
168 | down(&dir_dentry->d_inode->i_sem); | ||
169 | list_for_each_entry_safe(dentry, tmp, &dir_dentry->d_subdirs, d_child) { | 169 | list_for_each_entry_safe(dentry, tmp, &dir_dentry->d_subdirs, d_child) { |
170 | spin_lock(&dcache_lock); | 170 | spin_lock(&dcache_lock); |
171 | spin_lock(&dentry->d_lock); | 171 | spin_lock(&dentry->d_lock); |
@@ -181,16 +181,16 @@ static int spufs_rmdir(struct inode *root, struct dentry *dir_dentry) | |||
181 | spin_unlock(&dcache_lock); | 181 | spin_unlock(&dcache_lock); |
182 | } | 182 | } |
183 | } | 183 | } |
184 | shrink_dcache_parent(dir_dentry); | ||
185 | up(&dir_dentry->d_inode->i_sem); | ||
186 | up(&root->i_sem); | ||
184 | 187 | ||
185 | /* We have to give up the mm_struct */ | 188 | /* We have to give up the mm_struct */ |
186 | ctx = SPUFS_I(dir_dentry->d_inode)->i_ctx; | 189 | ctx = SPUFS_I(dir_dentry->d_inode)->i_ctx; |
187 | spu_forget(ctx); | 190 | spu_forget(ctx); |
188 | 191 | ||
189 | if (!err) { | 192 | /* XXX Do we need to hold i_sem here ? */ |
190 | shrink_dcache_parent(dir_dentry); | 193 | return simple_rmdir(root, dir_dentry); |
191 | err = simple_rmdir(root, dir_dentry); | ||
192 | } | ||
193 | return err; | ||
194 | } | 194 | } |
195 | 195 | ||
196 | static int spufs_dir_close(struct inode *inode, struct file *file) | 196 | 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) | |||
201 | 201 | ||
202 | dentry = file->f_dentry; | 202 | dentry = file->f_dentry; |
203 | dir = dentry->d_parent->d_inode; | 203 | dir = dentry->d_parent->d_inode; |
204 | down(&dir->i_sem); | 204 | |
205 | ret = spufs_rmdir(dir, file->f_dentry); | 205 | ret = spufs_rmdir(dir, dentry); |
206 | WARN_ON(ret); | 206 | WARN_ON(ret); |
207 | up(&dir->i_sem); | 207 | |
208 | return dcache_dir_close(inode, file); | 208 | return dcache_dir_close(inode, file); |
209 | } | 209 | } |
210 | 210 | ||