Subject: Fix deadlock in spu_create error path From: Michael Ellerman spufs_rmdir tries to acquire the spufs root i_mutex, which is already held by spufs_create_thread. This was tracked as Bug #H9512. Signed-off-by: Arnd Bergmann --- On Tue, 2006-05-09 at 11:06 +0200, Arnd Bergmann wrote: > Hmm, you were right about which mutex this is, I actually > thought it > was the one for the directory being removed, not for the > root. > > Al Viro asked be to call spu_forget without that mutex > held, > so it's probably more complicated than your suggestion. I > think > the cleanup path in spufs_create_thread() should just do > the > stuff from spufs_rmdir() open coded. Gah this stuff is complicated. Do you know why Al asked you to call spu_forget() without the mutex? I'm sure he knows what he's talking about, it just seems strange because it makes the locking not nest right. It'd be nice to understand what's going on there. I thought I had a nice solution, but it didn't work, so I've coded up this messy patch, which might work. I think we want to do the dput after spufs_rmdir(), otherwise we'd have no reference to it. Do you know if there's a test case I can use to verify it works? Index: linus-2.6/arch/powerpc/platforms/cell/spufs/inode.c =================================================================== --- linus-2.6.orig/arch/powerpc/platforms/cell/spufs/inode.c +++ linus-2.6/arch/powerpc/platforms/cell/spufs/inode.c @@ -324,8 +324,12 @@ long spufs_create_thread(struct nameidat * in error path of *_open(). */ ret = spufs_context_open(dget(dentry), mntget(nd->mnt)); - if (ret < 0) + if (ret < 0) { + mutex_unlock(&nd->dentry->d_inode->i_mutex); spufs_rmdir(nd->dentry->d_inode, dentry); + dput(dentry); + goto out; + } out_dput: dput(dentry);