spufs raises two exceptions
Subsystems (3)
PATCH 1/1 spufs raises two exceptions
I'm running my test program, it uses all available spus to compute via OpenCL kernel 3.2.5 on a ps3
even on testing spu directly, it crashes
=====================================
[ BUG: bad unlock balance detected! ]
-------------------------------------
test/1067 is trying to release lock (&sb->s_type->i_mutex_key) at:
[<d0000000005828a8>] .do_spu_create+0x90/0xd8 [spufs] but there are no more locks to release!
other info that might help us debug this:
no locks held by test/1067.
stack backtrace: Call Trace: [c00000000e9bfa30] [c0000000000110d0] .show_stack+0x6c/0x16c (unreliable) [c00000000e9bfae0] [c000000000081f90] .print_unlock_inbalance_bug+0xe8/0x110 [c00000000e9bfb70] [c0000000000868cc] .lock_release+0xd8/0x200 [c00000000e9bfc10] [c0000000003efb60] .__mutex_unlock_slowpath+0x11c/0x1d8 [c00000000e9bfcb0] [d0000000005828a8] .do_spu_create+0x90/0xd8 [spufs] [c00000000e9bfd70] [c0000000000346ac] .sys_spu_create+0x164/0x1c0 [c00000000e9bfe30] [c0000000000097d8] syscall_exit+0x0/0x40 ------------[ cut here ]------------ kernel BUG at fs/dcache.c:474! Oops: Exception in kernel mode, sig: 5 [#1] SMP NR_CPUS=2 NUMA PS3 Modules linked in: spufs dm_mod btusb bluetooth usb_storage ohci_hcd snd_ps3 ehci_hcd snd_pcm snd_page_alloc snd_timer sg snd usbcore usb_common ps3flash rtc_ps3 soundcore ps3_lpm ps3vram [last unloaded: scsi_wait_scan] NIP: c000000000109f94 LR: c000000000109f84 CTR: c0000000000a029c REGS: c00000000e9bf930 TRAP: 0700 Not tainted (3.2.5) MSR: 8000000000028032 <EE,CE,IR,DR> CR: 22004822 XER: 00000000
TASK = c0000000062f0ec0[1067] 'test' THREAD: c00000000e9bc000 CPU: 1
GPR00: 0000000000000001 c00000000e9bfbb0 c0000000006812e8 c00000000543b798
GPR04: 0000000000000000 0000000000000000 0000000000000000 0000000000000002
GPR08: 0000000000000000 0000000000000000 c000000000109f84 c0000000062f0ec0
GPR12: 0000000082004824 c000000007ffe280 0000000000000004 00000000f7850688
GPR16: 00000000f7830734 00000000f78517a4 00000000f7852008 00000000f78517a8
GPR20: 00000000ff805dc0 000000000fd958a0 0000000000000000 000000000000000d
GPR24: 000000000fd98240 c00000000e101e10 0000000040000010 c00000000616e080
GPR28: c00000000543b738 c00000000543b798 c0000000006149e8 c00000000543b738 NIP [c000000000109f94] .dput+0x48/0x214
LR [c000000000109f84] .dput+0x38/0x214
Call Trace: [c00000000e9bfbb0] [c000000000109f84] .dput+0x38/0x214 (unreliable) [c00000000e9bfc50] [c0000000000f1740] .fput+0x24c/0x288 [c00000000e9bfd00] [c0000000000ed708] .filp_close+0xbc/0xe4 [c00000000e9bfd90] [c0000000000ed800] .SyS_close+0xd0/0x128 [c00000000e9bfe30] [c0000000000097d8] syscall_exit+0x0/0x40 Instruction dump: fb61ffd8 fb81ffe0 fba1ffe8 f821ff61 418201c8 3bbf0060 7fa3eb78 482e7f31 60000000 813f0058 7d200074 7800d182 <0b000000> 2b890001 409d0010 3809ffff ---[ end trace c337aad05d94532f ]--- ------------[ cut here ]------------ kernel BUG at fs/dcache.c:474! Oops: Exception in kernel mode, sig: 5 [#2] SMP NR_CPUS=2 NUMA PS3 Modules linked in: spufs dm_mod btusb bluetooth usb_storage ohci_hcd snd_ps3 ehci_hcd snd_pcm snd_page_alloc snd_timer sg snd usbcore usb_common ps3flash rtc_ps3 soundcore ps3_lpm ps3vram [last unloaded: scsi_wait_scan] NIP: c000000000109f94 LR: c000000000109f84 CTR: c0000000000a029c REGS: c00000000e9bec20 TRAP: 0700 Tainted: G D (3.2.5) MSR: 8000000000028032 <EE,CE,IR,DR> CR: 22004822 XER: 00000000
TASK = c0000000062f0ec0[1067] 'test' THREAD: c00000000e9bc000 CPU: 1
GPR00: 0000000000000001 c00000000e9beea0 c0000000006812e8 c0000000054361c8
GPR04: 0000000000000000 0000000000000000 0000000000000000 0000000000000002
GPR08: 0000000000000000 0000000000000000 c000000000109f84 c0000000062f0ec0
GPR12: 0000000042004824 c000000007ffe280 0000000000000004 00000000f7850688
GPR16: 00000000f7830734 00000000f78517a4 00000000f7852008 00000000f78517a8
GPR20: 00000000ff805dc0 000000000fd958a0 0000000000000000 0000000000000001
GPR24: 000000000fd98240 c00000000e9b2390 0000000000000008 c0000000062bd010
GPR28: c000000005436168 c0000000054361c8 c0000000006149e8 c000000005436168 NIP [c000000000109f94] .dput+0x48/0x214
LR [c000000000109f84] .dput+0x38/0x214
Call Trace: [c00000000e9beea0] [c000000000109f84] .dput+0x38/0x214 (unreliable) [c00000000e9bef40] [c0000000000f1740] .fput+0x24c/0x288 [c00000000e9beff0] [c0000000000c93a8] .remove_vma+0x68/0xcc [c00000000e9bf080] [c0000000000c951c] .exit_mmap+0x110/0x14c [c00000000e9bf1a0] [c00000000004b4c8] .mmput+0x5c/0x13c [c00000000e9bf230] [d00000000058237c] .spu_forget+0x54/0x7c [spufs] [c00000000e9bf2c0] [d00000000057c294] .spufs_dir_close+0x8c/0xc8 [spufs] [c00000000e9bf370] [c0000000000f166c] .fput+0x178/0x288 [c00000000e9bf420] [c0000000000ed708] .filp_close+0xbc/0xe4 [c00000000e9bf4b0] [c000000000050294] .put_files_struct+0xf4/0x1b8 [c00000000e9bf560] [c0000000000520bc] .do_exit+0x23c/0x6f4 [c00000000e9bf660] [c00000000001922c] .die+0x274/0x2a4 [c00000000e9bf700] [c000000000019640] ._exception+0x88/0x17c [c00000000e9bf8c0] [c000000000005314] program_check_common+0x114/0x180 --- Exception: 700 at .dput+0x48/0x214 LR = .dput+0x38/0x214 [c00000000e9bfc50] [c0000000000f1740] .fput+0x24c/0x288 [c00000000e9bfd00] [c0000000000ed708] .filp_close+0xbc/0xe4 [c00000000e9bfd90] [c0000000000ed800] .SyS_close+0xd0/0x128 [c00000000e9bfe30] [c0000000000097d8] syscall_exit+0x0/0x40 Instruction dump: fb61ffd8 fb81ffe0 fba1ffe8 f821ff61 418201c8 3bbf0060 7fa3eb78 482e7f31 60000000 813f0058 7d200074 7800d182 <0b000000> 2b890001 409d0010 3809ffff ---[ end trace c337aad05d945330 ]---
Fixing recursive fault but reboot is needed!
First time, the mutex gets unlocked in spufs_create_context, then the second time in do_spu_create. It seems that SPU main directory dentry has invalid d_count.
This patch fixes all, OpenCL is running fine, testing spe runs without issues.
powerpc/platforms/cell/spufs/syscalls.c.new renamed from powerpc/platforms/cell/spufs/syscalls.c +2 -2
@@ -70,8 +70,8 @@ ret = PTR_ERR(dentry); if (!IS_ERR(dentry)) { ret = spufs_create(&path, dentry, flags, mode, neighbor); - mutex_unlock(&path.dentry->d_inode->i_mutex); - dput(dentry); + if (ret < 0) + dput(dentry); path_put(&path); }
Quoted 4 lines · masterzorag
I'm running my test program, it uses all available spus to compute via OpenCL
kernel 3.2.5 on a ps3
even on testing spu directly, it crashes
I think the patch is not 100% right yet. Looking at the code, we have a real mess of who gets to clean what up here. This is an attempt at sorting things by having the mutex and dentry dropped in spufs_create() always. Can you give it a spin (untested):
Al, I'm not familiar with the vfs, can you take a quick look ?
Thanks !
Cheers,
Ben.
Quoted 124 lines
=====================================
[ BUG: bad unlock balance detected! ]
-------------------------------------
test/1067 is trying to release lock (&sb->s_type->i_mutex_key) at:
[<d0000000005828a8>] .do_spu_create+0x90/0xd8 [spufs] but there are no more locks to release!
other info that might help us debug this:
no locks held by test/1067.stack backtrace: Call Trace: [c00000000e9bfa30] [c0000000000110d0] .show_stack+0x6c/0x16c (unreliable) [c00000000e9bfae0] [c000000000081f90] .print_unlock_inbalance_bug+0xe8/0x110 [c00000000e9bfb70] [c0000000000868cc] .lock_release+0xd8/0x200 [c00000000e9bfc10] [c0000000003efb60] .__mutex_unlock_slowpath+0x11c/0x1d8 [c00000000e9bfcb0] [d0000000005828a8] .do_spu_create+0x90/0xd8 [spufs] [c00000000e9bfd70] [c0000000000346ac] .sys_spu_create+0x164/0x1c0 [c00000000e9bfe30] [c0000000000097d8] syscall_exit+0x0/0x40 ------------[ cut here ]------------ kernel BUG at fs/dcache.c:474! Oops: Exception in kernel mode, sig: 5 [#1] SMP NR_CPUS=2 NUMA PS3 Modules linked in: spufs dm_mod btusb bluetooth usb_storage ohci_hcd
snd_ps3ehci_hcdsnd_pcmsnd_page_allocsnd_timersg snd usbcoreusb_commonps3flashrtc_ps3soundcoreps3_lpmps3vram [last unloaded:scsi_wait_scan]
NIP:c000000000109f94LR:c000000000109f84CTR:c0000000000a029c
REGS:c00000000e9bf930TRAP: 0700 Not tainted (3.2.5)
MSR: 8000000000028032 <EE,CE,IR,DR> CR: 22004822 XER: 00000000 TASK = c0000000062f0ec0[1067] 'test' THREAD:c00000000e9bc000CPU: 1
GPR00: 0000000000000001c00000000e9bfbb0c0000000006812e8c00000000543b798
GPR04: 0000000000000000 0000000000000000 0000000000000000 0000000000000002
GPR08: 0000000000000000 0000000000000000c000000000109f84c0000000062f0ec0
GPR12: 0000000082004824c000000007ffe280000000000000000400000000f7850688
GPR16:00000000f783073400000000f78517a400000000f785200800000000f78517a8
GPR20:00000000ff805dc0000000000fd958a00000000000000000000000000000000d
GPR24:000000000fd98240c00000000e101e100000000040000010c00000000616e080
GPR28:c00000000543b738c00000000543b798c0000000006149e8c00000000543b738NIP [c000000000109f94] .dput+0x48/0x214
LR [c000000000109f84] .dput+0x38/0x214Call Trace: [c00000000e9bfbb0] [c000000000109f84] .dput+0x38/0x214 (unreliable) [c00000000e9bfc50] [c0000000000f1740] .fput+0x24c/0x288 [c00000000e9bfd00] [c0000000000ed708] .filp_close+0xbc/0xe4 [c00000000e9bfd90] [c0000000000ed800] .SyS_close+0xd0/0x128 [c00000000e9bfe30] [c0000000000097d8] syscall_exit+0x0/0x40 Instruction dump: fb61ffd8 fb81ffe0 fba1ffe8 f821ff61 418201c8 3bbf0060 7fa3eb78 482e7f31 60000000 813f0058 7d200074 7800d182 <0b000000> 2b890001 409d0010 3809ffff ---[ end trace c337aad05d94532f ]--- ------------[ cut here ]------------ kernel BUG at fs/dcache.c:474! Oops: Exception in kernel mode, sig: 5 [#2] SMP NR_CPUS=2 NUMA PS3 Modules linked in: spufs dm_mod btusb bluetooth usb_storage ohci_hcd
snd_ps3ehci_hcdsnd_pcmsnd_page_allocsnd_timersg snd usbcoreusb_commonps3flashrtc_ps3soundcoreps3_lpmps3vram [last unloaded:scsi_wait_scan]
NIP:c000000000109f94LR:c000000000109f84CTR:c0000000000a029c
REGS:c00000000e9bec20TRAP: 0700 Tainted: G D (3.2.5)
MSR: 8000000000028032 <EE,CE,IR,DR> CR: 22004822 XER: 00000000 TASK = c0000000062f0ec0[1067] 'test' THREAD:c00000000e9bc000CPU: 1
GPR00: 0000000000000001c00000000e9beea0c0000000006812e8c0000000054361c8
GPR04: 0000000000000000 0000000000000000 0000000000000000 0000000000000002
GPR08: 0000000000000000 0000000000000000c000000000109f84c0000000062f0ec0
GPR12: 0000000042004824c000000007ffe280000000000000000400000000f7850688
GPR16:00000000f783073400000000f78517a400000000f785200800000000f78517a8
GPR20:00000000ff805dc0000000000fd958a00000000000000000 0000000000000001
GPR24:000000000fd98240c00000000e9b23900000000000000008c0000000062bd010
GPR28:c000000005436168c0000000054361c8c0000000006149e8c000000005436168NIP [c000000000109f94] .dput+0x48/0x214
LR [c000000000109f84] .dput+0x38/0x214Call Trace: [c00000000e9beea0] [c000000000109f84] .dput+0x38/0x214 (unreliable) [c00000000e9bef40] [c0000000000f1740] .fput+0x24c/0x288 [c00000000e9beff0] [c0000000000c93a8] .remove_vma+0x68/0xcc [c00000000e9bf080] [c0000000000c951c] .exit_mmap+0x110/0x14c [c00000000e9bf1a0] [c00000000004b4c8] .mmput+0x5c/0x13c [c00000000e9bf230] [d00000000058237c] .spu_forget+0x54/0x7c [spufs] [c00000000e9bf2c0] [d00000000057c294] .spufs_dir_close+0x8c/0xc8 [spufs] [c00000000e9bf370] [c0000000000f166c] .fput+0x178/0x288 [c00000000e9bf420] [c0000000000ed708] .filp_close+0xbc/0xe4 [c00000000e9bf4b0] [c000000000050294] .put_files_struct+0xf4/0x1b8 [c00000000e9bf560] [c0000000000520bc] .do_exit+0x23c/0x6f4 [c00000000e9bf660] [c00000000001922c] .die+0x274/0x2a4 [c00000000e9bf700] [c000000000019640] ._exception+0x88/0x17c [c00000000e9bf8c0] [c000000000005314] program_check_common+0x114/0x180 --- Exception: 700 at .dput+0x48/0x214 LR = .dput+0x38/0x214 [c00000000e9bfc50] [c0000000000f1740] .fput+0x24c/0x288 [c00000000e9bfd00] [c0000000000ed708] .filp_close+0xbc/0xe4 [c00000000e9bfd90] [c0000000000ed800] .SyS_close+0xd0/0x128 [c00000000e9bfe30] [c0000000000097d8] syscall_exit+0x0/0x40 Instruction dump: fb61ffd8 fb81ffe0 fba1ffe8 f821ff61 418201c8 3bbf0060 7fa3eb78 482e7f31 60000000 813f0058 7d200074 7800d182 <0b000000> 2b890001 409d0010 3809ffff ---[ end trace c337aad05d945330 ]---Fixing recursive fault but reboot is needed!
First time, the mutex gets unlocked in
spufs_create_context, then the second time indo_spu_create.
It seems that SPU main directory dentry has invalidd_count.This patch fixes all, OpenCL is running fine, testing spe runs without issues.
powerpc/platforms/cell/spufs/syscalls.c.new renamed from powerpc/platforms/cell/spufs/syscalls.c +2
-2@@ -70,8 +70,8 @@ ret = PTR_ERR(dentry); if (!IS_ERR(dentry)) { ret = spufs_create(&path, dentry, flags, mode, neighbor); - mutex_unlock(&path.dentry->d_inode->i_mutex); - dput(dentry); + if (ret < 0) + dput(dentry); path_put(&path); }_______________________________________________
Linuxppc-dev mailing list
[email protected]
https://lists.ozlabs.org/listinfo/linuxppc-dev
Quoted 6 lines · Benjamin Herrenschmidt
Quoted 4 lines · masterzorag
I'm running my test program, it uses all available spus to compute via OpenCL
kernel 3.2.5 on a ps3
even on testing spu directly, it crashes
Quoted 6 lines
I think the patch is not 100% right yet. Looking at the code, we have a real mess of who gets to clean what up here. This is an attempt at sorting things by having the mutex and dentry dropped in
spufs_create()always. Can you give it a spin (untested):Al, I'm not familiar with the vfs, can you take a quick look ?
Better with the actual patch :-)
powerpc/cell: Fix locking in spufs_create()
The error path in spufs_create() could cause double unlocks among other horrors. Clean it up.
arch/powerpc/platforms/cell/spufs/inode.c +19 -28
@@ -454,19 +454,16 @@ spufs_create_context(struct inode *inode, struct dentry *dentry,struct spu_gang *gang;struct spu_context *neighbor; - ret = -EPERM ;if ((flags &SPU_CREATE_NOSCHED ) && - !capable (CAP_SYS_NICE )) - goto out_unlock; + !capable (CAP_SYa_NICE)) +return -EPERM ; - ret = -EINVAL ;if ((flags & (SPU_CREATE_NOSCHED |SPU_CREATE_ISOLATE )) ==SPU_CREATE_ISOLATE ) - goto out_unlock; +return -EINVAL ; - ret = -ENODEV ;if ((flags &SPU_CREATE_ISOLATE ) && !isolated_loader) - goto out_unlock; +return -ENODEV ; gang =NULL ; neighbor =NULL ;
@@ -512,10 +509,6 @@ spufs_create_context(struct inode *inode, struct dentry *dentry, out_aff_unlock:if (affinity)mutex_unlock (&gang->aff_mutex); -out_unlock: -mutex_unlock (&inode->i_mutex); -out: -dput (dentry);return ret; }
@@ -585,11 +578,9 @@ static int spufs_create_gang(struct inode *inode,struct dentry *dentry, struct vfsmount *mnt, umode_t mode) { - int ret; - - ret =spufs_mkgang (inode, dentry, mode &S_IRWXUGO ); + int ret = spufs_mkgang(inode, dentry, mode & S_IRWXUGO);if (ret) - goto out; +return ret;/* * get references for dget and mntget, will be released
@@ -600,10 +591,6 @@ static int spufs_create_gang(struct inode *inode,int err =simple_rmdir (inode, dentry);WARN_ON (err); } - -out: -mutex_unlock (&inode->i_mutex); -dput (dentry);return ret; }
@@ -613,22 +600,21 @@ static struct file_system_type spufs_type;long spufs_create (struct path *path,struct dentry *dentry,unsigned int flags,umode_t mode,struct file *filp) { -int ret; +int ret = -EINVAL ; - ret = -EINVAL ;/* check if we are on spufs */ if (path->dentry->d_sb->s_type != &spufs_type) - goto out; + goto fail;/* don't accept undefined flags */ if (flags & (~SPU_CREATE_FLAG_ALL )) - goto out; + goto fail;/* only threads can be underneath a gang */ if (path->dentry != path->dentry->d_sb->s_root) {if ((flags &SPU_CREATE_GANG ) || !SPUFS_I (path->dentry->d_inode)->i_gang) - goto out; + goto fail; } mode &= ~current_umask ();
@@ -640,12 +626,17 @@ long spufs_create(struct path *path, struct dentry *dentry, ret =spufs_create_context (path->dentry->d_inode, dentry, path->mnt, flags, mode, filp); -if (ret >=0 ) +if (ret >=0 ) { +/* We drop these before fsnotify */ +mutex_unlock (&inode->i_mutex); +dput (dentry);fsnotify_mkdir (path->dentry->d_inode, dentry); -return ret; -out: -mutex_unlock (&path->dentry->d_inode->i_mutex); +return ret; + } + fail: +mutex_unlock (&inode->i_mutex); +dput (dentry);return ret; }
arch/powerpc/platforms/cell/spufs/syscalls.c +0 -3
@@ -70,11 +70,8 @@ static long do_spu_create(const char __user *pathname, unsigned int flags, ret =PTR_ERR (dentry);if (!IS_ERR (dentry)) { ret =spufs_create (&path, dentry, flags, mode, neighbor); -mutex_unlock (&path.dentry->d_inode->i_mutex); -dput (dentry);path_put (&path); } -return ret; }
Quoted 29 lines · Benjamin Herrenschmidt
Quoted 6 lines · Benjamin Herrenschmidt
Quoted 4 lines · masterzorag
I'm running my test program, it uses all available spus to compute via OpenCL
kernel 3.2.5 on a ps3
even on testing spu directly, it crashesQuoted 6 lines
I think the patch is not 100% right yet. Looking at the code, we have a real mess of who gets to clean what up here. This is an attempt at sorting things by having the mutex and dentry dropped in
spufs_create()always. Can you give it a spin (untested):Al, I'm not familiar with the vfs, can you take a quick look ?
Better with the actual patch :-)
powerpc/cell: Fix locking in
spufs_create()The error path in
spufs_create()could cause double unlocks among other horrors. Clean it up.Signed-off-by Benjamin Herrenschmidt <[email protected]>Reported-by [email protected]arch/powerpc/platforms/cell/spufs/inode.c +0
-0
arch/powerpc/platforms/cell/spufs/inode.c spufs_create_context(struct inode *inode, struct dentry *dentry, · line 458
Quoted 8 lines
arch/powerpc/platforms/cell/spufs/inode.c +1
-3@@ -454,19 +454,16 @@ spufs_create_context(struct inode *inode, struct dentry *dentry,struct spu_gang *gang;struct spu_context *neighbor; - ret = -EPERM ;if ((flags &SPU_CREATE_NOSCHED ) && - !capable (CAP_SYS_NICE )) - goto out_unlock; + !capable (CAP_SYa_NICE))
^typo
Quoted 5 lines
arch/powerpc/platforms/cell/spufs/inode.c +1
-1+return -EPERM ; - ret = -EINVAL ;if ((flags & (SPU_CREATE_NOSCHED |SPU_CREATE_ISOLATE )) ==SPU_CREATE_ISOLATE )
arch/powerpc/platforms/cell/spufs/inode.c spufs_create_context(struct inode *inode, struct dentry *dentry, · line 469
Quoted 10 lines
arch/powerpc/platforms/cell/spufs/inode.c +2
-3- goto out_unlock; +return -EINVAL ; - ret = -ENODEV ;if ((flags &SPU_CREATE_ISOLATE ) && !isolated_loader) - goto out_unlock; +return -ENODEV ; gang =NULL ; neighbor =NULL ;
This mostly changes coding style, pointlessly.
arch/powerpc/platforms/cell/spufs/inode.c spufs_create_context(struct inode *inode, struct dentry *dentry, · line 513
Quoted 10 lines
arch/powerpc/platforms/cell/spufs/inode.c +0
-4@@ -512,10 +509,6 @@ spufs_create_context(struct inode *inode, struct dentry *dentry, out_aff_unlock:if (affinity)mutex_unlock (&gang->aff_mutex); -out_unlock: -mutex_unlock (&inode->i_mutex); -out: -dput (dentry);return ret; }
The original intention of this was to always unlock in the error case. It seems that Al changed this in 1ba10681 "switch do_spufs_create() to user_path_create(), fix double-unlock" to never unlock early but always unlock in do_spu_create, fixing a different bug, but it looks like he forgot this one in the process.
The reason why we originally had the unlock in the leaf functions is to avoid a problem with spu_forget(), which had to be called without the i_mutex held to avoid deadlocks.
arch/powerpc/platforms/cell/spufs/inode.c static int spufs_create_gang(struct inode *inode, · line 595
Quoted 10 lines
arch/powerpc/platforms/cell/spufs/inode.c +0
-4@@ -600,10 +591,6 @@ static int spufs_create_gang(struct inode *inode,int err =simple_rmdir (inode, dentry);WARN_ON (err); } - -out: -mutex_unlock (&inode->i_mutex); -dput (dentry);return ret; }
Right, this obviously goes together with the one above,
Quoted 17 lines
arch/powerpc/platforms/cell/spufs/inode.c +3
-4@@ -613,22 +600,21 @@ static struct file_system_type spufs_type;long spufs_create (struct path *path,struct dentry *dentry,unsigned int flags,umode_t mode,struct file *filp) { -int ret; +int ret = -EINVAL ; - ret = -EINVAL ;/* check if we are on spufs */ if (path->dentry->d_sb->s_type != &spufs_type) - goto out; + goto fail;/* don't accept undefined flags */ if (flags & (~SPU_CREATE_FLAG_ALL )) - goto out; + goto fail;
arch/powerpc/platforms/cell/spufs/inode.c static struct file_system_type spufs_type; · line 620
Quoted 10 lines
arch/powerpc/platforms/cell/spufs/inode.c +1
-1/* only threads can be underneath a gang */ if (path->dentry != path->dentry->d_sb->s_root) {if ((flags &SPU_CREATE_GANG ) || !SPUFS_I (path->dentry->d_inode)->i_gang) - goto out; + goto fail; } mode &= ~current_umask ();
These just change coding style, and not in a helpful way.
Quoted 27 lines
arch/powerpc/platforms/cell/spufs/inode.c +9
-4@@ -640,12 +626,17 @@ long spufs_create(struct path *path, struct dentry *dentry, ret =spufs_create_context (path->dentry->d_inode, dentry, path->mnt, flags, mode, filp); -if (ret >=0 ) +if (ret >=0 ) { +/* We drop these before fsnotify */ +mutex_unlock (&inode->i_mutex); +dput (dentry);fsnotify_mkdir (path->dentry->d_inode, dentry); -return ret; -out: -mutex_unlock (&path->dentry->d_inode->i_mutex); +return ret; + } + fail: +mutex_unlock (&inode->i_mutex); +dput (dentry);return ret; }arch/powerpc/platforms/cell/spufs/syscalls.c +0
-0
arch/powerpc/platforms/cell/spufs/syscalls.c static long do_spu_create(const char __user *pathname, unsigned int flags, · line 76
Quoted 10 lines
arch/powerpc/platforms/cell/spufs/syscalls.c +0
-3@@ -70,11 +70,8 @@ static long do_spu_create(const char __user *pathname, unsigned int flags, ret =PTR_ERR (dentry);if (!IS_ERR (dentry)) { ret =spufs_create (&path, dentry, flags, mode, neighbor); -mutex_unlock (&path.dentry->d_inode->i_mutex); -dput (dentry);path_put (&path); } -return ret; }
This moves the unlock in front of the fsnotify_mkdir, where it was before Al's change. This seems independent of the other change.
Arnd
Quoted 9 lines
Quoted 9 lines
arch/powerpc/platforms/cell/spufs/inode.c +0
-0@@ -454,19 +454,16 @@ spufs_create_context(struct inode *inode, struct dentry *dentry,struct spu_gang *gang;struct spu_context *neighbor;
Quoted 7 lines
arch/powerpc/platforms/cell/spufs/inode.c spufs_create_context(struct inode *inode, struct dentry *dentry, · line 458
Quoted 5 lines
arch/powerpc/platforms/cell/spufs/inode.c +1
-3- ret = -EPERM ;if ((flags &SPU_CREATE_NOSCHED ) && - !capable (CAP_SYS_NICE )) - goto out_unlock; + !capable (CAP_SYa_NICE))^typo
Odd, probably an emacs fart
Quoted 13 lines
Quoted 13 lines
arch/powerpc/platforms/cell/spufs/inode.c +3
-4+return -EPERM ; - ret = -EINVAL ;if ((flags & (SPU_CREATE_NOSCHED |SPU_CREATE_ISOLATE )) ==SPU_CREATE_ISOLATE ) - goto out_unlock; +return -EINVAL ; - ret = -ENODEV ;if ((flags &SPU_CREATE_ISOLATE ) && !isolated_loader) - goto out_unlock; +return -ENODEV ;
Quoted 4 lines
arch/powerpc/platforms/cell/spufs/inode.c spufs_create_context(struct inode *inode, struct dentry *dentry, · line 469
Quoted 2 lines
arch/powerpc/platforms/cell/spufs/inode.c +0
-0gang =NULL ; neighbor =NULL ;This mostly changes coding style, pointlessly.
How so ? it's no longer necessary to store ret and goto out since there is no cleanup at all, which makes things smaller/simpler. I wouldn't call that 'pointlessly'.
I tend to dislike the use of "goto xxxx" when the xxx: label does no cleanup whatsoever.
Quoted 17 lines
arch/powerpc/platforms/cell/spufs/inode.c spufs_create_context(struct inode *inode, struct dentry *dentry, · line 513
Quoted 10 lines
arch/powerpc/platforms/cell/spufs/inode.c +0
-4@@ -512,10 +509,6 @@ spufs_create_context(struct inode *inode, struct dentry *dentry, out_aff_unlock:if (affinity)mutex_unlock (&gang->aff_mutex); -out_unlock: -mutex_unlock (&inode->i_mutex); -out: -dput (dentry);return ret; }The original intention of this was to always unlock in the error case. It seems that Al changed this in
1ba10681"switchdo_spufs_create()touser_path_create(), fix double-unlock" to never unlock early but always unlock indo_spu_create, fixing a different bug, but it looks like he forgot this one in the process.
Quoted 3 lines
The reason why we originally had the unlock in the leaf functions is to avoid a problem with
spu_forget(), which had to be called without thei_mutexheld to avoid deadlocks.
Ok. I assumed it was fnotify that was the problem...
Quoted 4 lines
Quoted 4 lines
arch/powerpc/platforms/cell/spufs/inode.c +0
-0@@ -600,10 +591,6 @@ static int spufs_create_gang(struct inode *inode,int err =simple_rmdir (inode, dentry);WARN_ON (err); }
Quoted 8 lines
arch/powerpc/platforms/cell/spufs/inode.c static int spufs_create_gang(struct inode *inode, · line 595
Quoted 6 lines
arch/powerpc/platforms/cell/spufs/inode.c +0
-4- -out: -mutex_unlock (&inode->i_mutex); -dput (dentry);return ret; }Right, this obviously goes together with the one above,
Yes, whatever they do they should do the same thing.
Quoted 26 lines
Quoted 26 lines
arch/powerpc/platforms/cell/spufs/inode.c +4
-5@@ -613,22 +600,21 @@ static struct file_system_type spufs_type; long spufs_create(struct path *path, struct dentry *dentry unsigned int flags, umode_t mode, struct file *filp) { - int ret; + int ret = -EINVAL; - ret = -EINVAL ;/* check if we are on spufs */ if (path->dentry->d_sb->s_type != &spufs_type) - goto out; + goto fail;/* don't accept undefined flags */ if (flags & (~SPU_CREATE_FLAG_ALL )) - goto out; + goto fail;/* only threads can be underneath a gang */ if (path->dentry != path->dentry->d_sb->s_root) {if ((flags &SPU_CREATE_GANG ) || !SPUFS_I (path->dentry->d_inode)->i_gang) - goto out; + goto fail; }
Quoted 3 lines
arch/powerpc/platforms/cell/spufs/inode.c static struct file_system_type spufs_type; · line 620
Quoted 1 line
arch/powerpc/platforms/cell/spufs/inode.c +0
-0mode &= ~current_umask ();These just change coding style, and not in a helpful way.
Oh I just renamed the label, it's helpful because the label is specifically only for the fail case, not the general exit path, hence "fail" is a better naming than "out". It's about code clarity.
Quoted 32 lines
Quoted 32 lines
arch/powerpc/platforms/cell/spufs/inode.c +9
-4@@ -640,12 +626,17 @@ long spufs_create(struct path *path, struct dentry *dentry, ret =spufs_create_context (path->dentry->d_inode, dentry, path->mnt, flags, mode, filp); -if (ret >=0 ) +if (ret >=0 ) { +/* We drop these before fsnotify */ +mutex_unlock (&inode->i_mutex); +dput (dentry);fsnotify_mkdir (path->dentry->d_inode, dentry); -return ret; -out: -mutex_unlock (&path->dentry->d_inode->i_mutex); +return ret; + } + fail: +mutex_unlock (&inode->i_mutex); +dput (dentry);return ret; }arch/powerpc/platforms/cell/spufs/syscalls.c +0
-2@@ -70,11 +70,8 @@ static long do_spu_create(const char __user *pathname, unsigned int flags, ret =PTR_ERR (dentry);if (!IS_ERR (dentry)) { ret =spufs_create (&path, dentry, flags, mode, neighbor); -mutex_unlock (&path.dentry->d_inode->i_mutex); -dput (dentry);
Quoted 8 lines
arch/powerpc/platforms/cell/spufs/syscalls.c static long do_spu_create(const char __user *pathname, unsigned int flags, · line 76
Quoted 5 lines
arch/powerpc/platforms/cell/spufs/syscalls.c +0
-1path_put (&path); } -return ret; }This moves the unlock in front of the
fsnotify_mkdir, where it was before Al's change. This seems independent of the other change.
No it's not, it all goes together. spufs_create_context() always unlocked & dropped the dentry before returning, so I assumed the lock had to be dropped before fsnotify.
Note that if the problem is that the lock has to be dropped before spu_forget(), then we should indeed move it back into the leaf functions and just remove all the unlock path from the top ones. It's a bit nasty how we drop the mutex first, then do spu_forget, then drop the dentry but we could go back to doing that.
What I want is consistent semantics. It's just silly to have 3 different stacking levels which all 3 may or may not be responsible to dropping the lock & dentry depending on circumstances.
In any case, what about this instead then:
arch/powerpc/platforms/cell/spufs/inode.c +1 -0
@@ -646,6 +646,7 @@ long spufs_create(struct path *path, struct dentry *dentry, out:mutex_unlock (&path->dentry->d_inode->i_mutex); +dput (dentry);return ret; }
arch/powerpc/platforms/cell/spufs/syscalls.c +0 -2
@@ -70,8 +70,6 @@ static long do_spu_create(const char __user *pathname, unsigned int flags, ret =PTR_ERR (dentry);if (!IS_ERR (dentry)) { ret =spufs_create (&path, dentry, flags, mode, neighbor); -mutex_unlock (&path.dentry->d_inode->i_mutex); -dput (dentry);path_put (&path); }
Cheers,
Ben.
Quoted 11 lines
No it's not, it all goes together.
spufs_create_context()always unlocked & dropped the dentry before returning, so I assumed the lock had to be dropped before fsnotify.Note that if the problem is that the lock has to be dropped before
spu_forget(), then we should indeed move it back into the leaf functions and just remove all the unlock path from the top ones. It's a bit nasty how we drop the mutex first, then dospu_forget, then drop the dentry but we could go back to doing that.
Quoted 3 lines
What I want is consistent semantics. It's just silly to have 3 different stacking levels which all 3 may or may not be responsible to dropping the lock & dentry depending on circumstances.
Why not leave unlock/dput to the caller? Details of deadlocks caused by that approach, please...
Quoted 10 lines · Al Viro
Quoted 10 lines
No it's not, it all goes together.
spufs_create_context()always unlocked & dropped the dentry before returning, so I assumed the lock had to be dropped before fsnotify.Note that if the problem is that the lock has to be dropped before
spu_forget(), then we should indeed move it back into the leaf functions and just remove all the unlock path from the top ones. It's a bit nasty how we drop the mutex first, then dospu_forget, then drop the dentry but we could go back to doing that.
Quoted 6 lines
Quoted 3 lines
What I want is consistent semantics. It's just silly to have 3 different stacking levels which all 3 may or may not be responsible to dropping the lock & dentry depending on circumstances.
Why not leave unlock/dput to the caller? Details of deadlocks caused by that approach, please...
If only I could remember that part exactly. I think I was remembering 0309f02d8 "spufs: fix deadlock in spu_create error path", which had a double lock problem in this path. Please bear with me here because it's been six years since I debugged that particular problem.
A lot of the nastyness of spu_forget() is about the problem of having to give up a reference on current->mm that is held by an spu context, while the mm contains a vma that maps this context and holds a refence on the inode, in particular in case of calling exit().
However, I don't see now how either of these two issues requires that we call spu_forget without the i_mutex held during a context creation failure.
Arnd