spufs_create_context() takes a reference on the gang with gang->alive++
and is meant to hold it until the context directory is closed, at which
point spufs_dir_close() -> unuse_gang() drops it again.

The error epilogue instead reads:

        ret = spufs_context_open(&path);
        ...
        if (ret && gang)
                gang->alive--; // can't reach 0

spufs_context_open() returns a non-negative file descriptor on success,
which is non-zero whenever the caller already holds an open fd. The
condition therefore fires on the success path too, dropping the
reference immediately; unuse_gang() then decrements it a second time at
close. The unbalanced double decrement can drive gang->alive to zero
prematurely, while contexts still reference the gang, triggering
simple_recursive_removal() of the gang directory too early.

Test the sign of the return value instead, so the reference is only
released on actual failure -- matching the idiom already used by
spufs_create_gang(), which calls unuse_gang() only on ret < 0.

Fixes: c134deabf478 ("spufs: fix gang directory lifetimes")
Reported-by: Yuhao Jiang <[email protected]>
Assisted-by: Claude:claude-opus-5
Cc: [email protected]
Signed-off-by: Zhenhao Wan <[email protected]>
---
 arch/powerpc/platforms/cell/spufs/inode.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/powerpc/platforms/cell/spufs/inode.c 
b/arch/powerpc/platforms/cell/spufs/inode.c
index 2b54afb31529..23619fbe0bd9 100644
--- a/arch/powerpc/platforms/cell/spufs/inode.c
+++ b/arch/powerpc/platforms/cell/spufs/inode.c
@@ -436,7 +436,7 @@ spufs_create_context(struct inode *inode, struct dentry 
*dentry,
 out_aff_unlock:
        if (affinity)
                mutex_unlock(&gang->aff_mutex);
-       if (ret && gang)
+       if (ret < 0 && gang)
                gang->alive--; // can't reach 0
        return ret;
 }

-- 
2.34.1


Reply via email to