Skip to content

Commit 8c0e092

Browse files
author
Al Viro
committed
spufs: switch to locked_recursive_removal()
... and fix an old deadlock on spufs_mkdir() failures to populate subdirectory - spufs_rmdir() had always been taking lock on the victim, so doing it while the victim is locked is a bad idea. Reviewed-by: Christian Brauner <brauner@kernel.org> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
1 parent 9fd4523 commit 8c0e092

1 file changed

Lines changed: 9 additions & 40 deletions

File tree

  • arch/powerpc/platforms/cell/spufs

arch/powerpc/platforms/cell/spufs/inode.c

Lines changed: 9 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -143,42 +143,13 @@ spufs_evict_inode(struct inode *inode)
143143
put_spu_gang(ei->i_gang);
144144
}
145145

146-
static void spufs_prune_dir(struct dentry *dir)
147-
{
148-
struct dentry *dentry;
149-
struct hlist_node *n;
150-
151-
inode_lock(d_inode(dir));
152-
hlist_for_each_entry_safe(dentry, n, &dir->d_children, d_sib) {
153-
spin_lock(&dentry->d_lock);
154-
if (simple_positive(dentry)) {
155-
dget_dlock(dentry);
156-
__d_drop(dentry);
157-
spin_unlock(&dentry->d_lock);
158-
simple_unlink(d_inode(dir), dentry);
159-
/* XXX: what was dcache_lock protecting here? Other
160-
* filesystems (IB, configfs) release dcache_lock
161-
* before unlink */
162-
dput(dentry);
163-
} else {
164-
spin_unlock(&dentry->d_lock);
165-
}
166-
}
167-
shrink_dcache_parent(dir);
168-
inode_unlock(d_inode(dir));
169-
}
170-
171146
/* Caller must hold parent->i_mutex */
172-
static int spufs_rmdir(struct inode *parent, struct dentry *dir)
147+
static void spufs_rmdir(struct inode *parent, struct dentry *dir)
173148
{
174-
/* remove all entries */
175-
int res;
176-
spufs_prune_dir(dir);
177-
d_drop(dir);
178-
res = simple_rmdir(parent, dir);
179-
/* We have to give up the mm_struct */
180-
spu_forget(SPUFS_I(d_inode(dir))->i_ctx);
181-
return res;
149+
struct spu_context *ctx = SPUFS_I(d_inode(dir))->i_ctx;
150+
151+
locked_recursive_removal(dir, NULL);
152+
spu_forget(ctx);
182153
}
183154

184155
static int spufs_fill_dir(struct dentry *dir,
@@ -222,15 +193,13 @@ static int spufs_dir_close(struct inode *inode, struct file *file)
222193
{
223194
struct inode *parent;
224195
struct dentry *dir;
225-
int ret;
226196

227197
dir = file->f_path.dentry;
228198
parent = d_inode(dir->d_parent);
229199

230200
inode_lock_nested(parent, I_MUTEX_PARENT);
231-
ret = spufs_rmdir(parent, dir);
201+
spufs_rmdir(parent, dir);
232202
inode_unlock(parent);
233-
WARN_ON(ret);
234203

235204
unuse_gang(dir->d_parent);
236205
return dcache_dir_close(inode, file);
@@ -288,11 +257,11 @@ spufs_mkdir(struct inode *dir, struct dentry *dentry, unsigned int flags,
288257
ret = spufs_fill_dir(dentry, spufs_dir_debug_contents,
289258
mode, ctx);
290259

260+
inode_unlock(inode);
261+
291262
if (ret)
292263
spufs_rmdir(dir, dentry);
293264

294-
inode_unlock(inode);
295-
296265
return ret;
297266
}
298267

@@ -475,7 +444,7 @@ spufs_create_context(struct inode *inode, struct dentry *dentry,
475444

476445
ret = spufs_context_open(&path);
477446
if (ret < 0)
478-
WARN_ON(spufs_rmdir(inode, dentry));
447+
spufs_rmdir(inode, dentry);
479448

480449
out_aff_unlock:
481450
if (affinity)

0 commit comments

Comments
 (0)