Re: [PATCH 1/3] rwsem: Remove the list_head from struct rw_semaphore

From: Mark Brown

Date: Wed Mar 18 2026 - 15:08:35 EST


On Thu, Mar 05, 2026 at 07:55:41PM +0000, Matthew Wilcox (Oracle) wrote:
> Instead of embedding a list_head in struct rw_semaphore, store a pointer
> to the first waiter. The list of waiters remains a doubly linked list
> so we can efficiently add to the tail of the list, remove from the front
> (or middle) of the list.

> Some of the list manipulation becomes more complicated, but it's a
> reasonable tradeoff on the slow paths to shrink some core data structures
> like struct inode.

In the past few days we've started seeing lockups when running LTP on
-next on a range of arm64 platforms which bisect to this patch. It
looks like corruption of some kind, the exact trigger varies but it's
very predictable that something goes wrong and we get lots of rwsem
related backtraces which do seem relevant to this commmit. This one
seems reasonably typical:

<0>[ 79.522930] Internal error: Oops: 0000000096000004 [#2] SMP
<6>[ 79.522932] note: cve-2017-17052[653] exited with preempt_count 2

...

<4>[ 79.839721] Call trace:
<4>[ 79.842417] rwsem_mark_wake (kernel/locking/rwsem.c:442) (P)
<4>[ 79.846854] rwsem_down_write_slowpath (kernel/locking/rwsem.c:609 kernel/locking/rwsem.c:1230)
<4>[ 79.851896] down_write_killable (kernel/locking/rwsem.c:1343 (discriminator 2) kernel/locking/rwsem.c:1357 (discriminator 2) kernel/locking/rwsem.c:1629 (discriminator 2))
<4>[ 79.856242] vm_mmap_pgoff (include/linux/mmap_lock.h:555 mm/util.c:579)
<4>[ 79.860158] ksys_mmap_pgoff (mm/mmap.c:605)
<4>[ 79.864246] __arm64_sys_mmap (arch/arm64/kernel/sys.c:21)
<4>[ 79.868333] invoke_syscall (arch/arm64/include/asm/current.h:19 arch/arm64/kernel/syscall.c:54)
<4>[ 79.872332] el0_svc_common.constprop.0 (include/linux/thread_info.h:142 (discriminator 2) arch/arm64/kernel/syscall.c:140 (discriminator 2))
<4>[ 79.877285] do_el0_svc (arch/arm64/kernel/syscall.c:152)
<4>[ 79.880850] el0_svc (arch/arm64/include/asm/irqflags.h:55 arch/arm64/include/asm/irqflags.h:76 arch/arm64/kernel/entry-common.c:80 arch/arm64/kernel/entry-common.c:725)
<4>[ 79.884242] el0t_64_sync_handler (arch/arm64/kernel/entry-common.c:744)
<4>[ 79.888676] el0t_64_sync (arch/arm64/kernel/entry.S:596)

It's one particular subset of LTP tests that's being run when triggering
the issue which makes me suspect that there's some preexisting bug
that's being exposed, I've enclosed the full list below but it's
generally relatively early that things go south.

Bisect log, I confirmed that yesterday's -next also has the issue:

git bisect start
# status: waiting for both good and bad commits
# bad: [95c541ddfb0815a0ea8477af778bb13bb075079a] Add linux-next specific files for 20260316
git bisect bad 95c541ddfb0815a0ea8477af778bb13bb075079a
# status: waiting for good commit(s), bad commit known
# good: [ead394bf2919868802fdf6da887f485866893b12] Merge branch 'tip/urgent' of https://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git
git bisect good ead394bf2919868802fdf6da887f485866893b12
# good: [cf610899a17faed2e78af3336854572033243dbd] Merge branch 'master' of https://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth-next.git
git bisect good cf610899a17faed2e78af3336854572033243dbd
# good: [828588f80831be0e7d40c1602d17a71f1810474c] Merge branch 'next' of https://git.kernel.org/pub/scm/linux/kernel/git/ulfh/mmc.git
git bisect good 828588f80831be0e7d40c1602d17a71f1810474c
# bad: [acf2f4ef88e001a943f651aa1095a2337550c9a9] Merge branch 'usb-next' of https://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb.git
git bisect bad acf2f4ef88e001a943f651aa1095a2337550c9a9
# bad: [bd35dc8f24e87f856e7d5462b0e70a08fcfd13fc] Merge branch 'master' of https://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git
git bisect bad bd35dc8f24e87f856e7d5462b0e70a08fcfd13fc
# bad: [fb3ed409f83bac4cdc38e2f2a35ce059a36bc24f] Merge branch into tip/master: 'timers/vdso'
git bisect bad fb3ed409f83bac4cdc38e2f2a35ce059a36bc24f
# bad: [35a4a178818d30d3802253651ad4e430686dce13] Merge branch into tip/master: 'objtool/core'
git bisect bad 35a4a178818d30d3802253651ad4e430686dce13
# good: [bcf081a44cb86c9f48479915fccffcd0ea8f6309] Merge branch into tip/master: 'irq/core'
git bisect good bcf081a44cb86c9f48479915fccffcd0ea8f6309
# bad: [739690915ce1f017223ef4e6f3cc966ccfa3c861] locking/rwsem: Add context analysis
git bisect bad 739690915ce1f017223ef4e6f3cc966ccfa3c861
# good: [553c02fb588d4310193eba80f75b43b20befd1d2] rust: sync: atomic: Clarify the need of CONFIG_ARCH_SUPPORTS_ATOMIC_RMW
git bisect good 553c02fb588d4310193eba80f75b43b20befd1d2
# good: [b91d5d4bcf1266257a9e0199e1b4ad7fa8771baa] rust: atomic: Update a safety comment in impl of `fetch_add()`
git bisect good b91d5d4bcf1266257a9e0199e1b4ad7fa8771baa
# bad: [25500ba7e77ce9d3d9b5a1929d41a2ee2e23f6fe] locking/mutex: Remove the list_head from struct mutex
git bisect bad 25500ba7e77ce9d3d9b5a1929d41a2ee2e23f6fe
# bad: [b9bdd4b6840454ef87f61b6506c9635c57a81650] locking/semaphore: Remove the list_head from struct semaphore
git bisect bad b9bdd4b6840454ef87f61b6506c9635c57a81650
# bad: [1ea4b473504b6dc6a0d21c298519aff2d52433c9] locking/rwsem: Remove the list_head from struct rw_semaphore
git bisect bad 1ea4b473504b6dc6a0d21c298519aff2d52433c9
# first bad commit: [1ea4b473504b6dc6a0d21c298519aff2d52433c9] locking/rwsem: Remove the list_head from struct rw_semaphore

The LTP test list:

cve-2016-9604 keyctl08
cve-2016-9793 setsockopt04
cve-2017-1000111 setsockopt07
cve-2017-1000112 setsockopt05
cve-2017-1000364 stack_clash
cve-2017-1000380 snd_timer01
cve-2017-1000405 thp04
cve-2017-10661 timerfd_settime02
cve-2017-12192 keyctl07
cve-2017-12193 add_key04
cve-2017-15274 add_key02
cve-2017-15299 request_key03 -b cve-2017-15299
cve-2017-15951 request_key03 -b cve-2017-15951
cve-2017-17052 cve-2017-17052
cve-2017-17712 sendmsg03
cve-2017-17807 request_key04
cve-2017-2618 cve-2017-2618
cve-2017-2671 cve-2017-2671
cve-2017-6951 request_key05
cve-2017-7308 setsockopt02
cve-2017-7472 keyctl04
cve-2018-1000001 realpath01
cve-2018-12896 timer_settime03
cve-2018-9568 connect02
cve-2020-14386 sendto03
data_space data_space
delete_module02 delete_module02
df01_sh df01.sh
dirtyc0w dirtyc0w
du01_sh du01.sh
dup01 dup01
dup02 dup02
dup03 dup03
dup04 dup04
dup05 dup05
dup06 dup06
dup07 dup07
dup201 dup201
dup202 dup202
dup203 dup203
dup204 dup204
dup205 dup205
dup3_01 dup3_01
dup3_02 dup3_02
epoll01 epoll-ltp
epoll_create1_01 epoll_create1_01
epoll_ctl01 epoll_ctl01
epoll_ctl02 epoll_ctl02
epoll_pwait01 epoll_pwait01
epoll_wait01 epoll_wait01
epoll_wait02 epoll_wait02
epoll_wait03 epoll_wait03
eventfd2_01 eventfd2_01
eventfd2_02 eventfd2_02
eventfd2_03 eventfd2_03
execl01 execl01
execle01 execle01
execlp01 execlp01
execv01 execv01
execve01 execve01
execve02 execve02
execve03 execve03
execve05 execve05 -i 5 -n 32
execveat01 execveat01
execveat02 execveat02
execveat03 execveat03
execvp01 execvp01
exit01 exit01
exit02 exit02
exit_group01 exit_group01
faccessat01 faccessat01
fallocate01 fallocate01
fallocate02 fallocate02
fallocate03 fallocate03
fallocate04 fallocate04
fallocate05 fallocate05
fallocate06 fallocate06
fanotify01 fanotify01
fanotify02 fanotify02
fanotify03 fanotify03
fanotify04 fanotify04
fanotify05 fanotify05
fanotify06 fanotify06
fanotify07 fanotify07
fanotify08 fanotify08
fanotify09 fanotify09
fanotify10 fanotify10
fanotify11 fanotify11
fanotify12 fanotify12
fanotify13 fanotify13
fanotify14 fanotify14
fanotify15 fanotify15
fanotify16 fanotify16
fchdir01 fchdir01
fchdir02 fchdir02
fchdir03 fchdir03
fchmod01 fchmod01
fchmod02 fchmod02
fchmod03 fchmod03
fchmod04 fchmod04
fchmod05 fchmod05
fchmod06 fchmod06
fchmodat01 fchmodat01
fchown01 fchown01
fchown02 fchown02
fchown03 fchown03
fchown04 fchown04
fchown05 fchown05
fchownat01 fchownat01
fchownat02 fchownat02
fcntl01 fcntl01
fcntl01_64 fcntl01_64
fcntl02 fcntl02
fcntl02_64 fcntl02_64
fcntl03 fcntl03
fcntl03_64 fcntl03_64
fcntl04 fcntl04
fcntl04_64 fcntl04_64
fcntl05 fcntl05
fcntl05_64 fcntl05_64
fcntl07 fcntl07
fcntl07_64 fcntl07_64
fcntl08 fcntl08
fcntl08_64 fcntl08_64
fcntl09 fcntl09
fcntl09_64 fcntl09_64
fcntl10 fcntl10
fcntl10_64 fcntl10_64
fcntl11 fcntl11
fcntl11_64 fcntl11_64
fcntl12 fcntl12
fcntl12_64 fcntl12_64
fcntl13 fcntl13
fcntl13_64 fcntl13_64
fcntl14 fcntl14
fcntl14_64 fcntl14_64
fcntl15 fcntl15
fcntl15_64 fcntl15_64
fcntl16 fcntl16
fcntl16_64 fcntl16_64
fcntl17 fcntl17
fcntl17_64 fcntl17_64
fcntl18 fcntl18
fcntl18_64 fcntl18_64
fcntl19 fcntl19
fcntl19_64 fcntl19_64
fcntl20 fcntl20
fcntl20_64 fcntl20_64
fcntl21 fcntl21
fcntl21_64 fcntl21_64
fcntl22 fcntl22
fcntl22_64 fcntl22_64
fcntl23 fcntl23
fcntl23_64 fcntl23_64
fcntl27 fcntl27
fcntl27_64 fcntl27_64
fcntl29 fcntl29
fcntl29_64 fcntl29_64
fcntl30 fcntl30
fcntl30_64 fcntl30_64
fcntl31 fcntl31
fcntl31_64 fcntl31_64
fcntl34 fcntl34
fcntl34_64 fcntl34_64
fcntl35 fcntl35
fcntl35_64 fcntl35_64
fcntl36 fcntl36
fcntl36_64 fcntl36_64
fcntl37 fcntl37
fcntl37_64 fcntl37_64
fcntl38 fcntl38
fcntl38_64 fcntl38_64
FCNTL_LOCKTESTS locktests -n 100 -f /tmp/fcntl_locktest_testfile
fdatasync01 fdatasync01
fdatasync02 fdatasync02
fdatasync03 fdatasync03
fgetxattr01 fgetxattr01
file01_sh file01.sh
float_bessel cd $LTPROOT/testcases/bin; float_bessel -v
float_exp_log cd $LTPROOT/testcases/bin; float_exp_log -v
float_iperb cd $LTPROOT/testcases/bin; float_iperb -v
float_power cd $LTPROOT/testcases/bin; float_power -v
float_trigo cd $LTPROOT/testcases/bin; float_trigo -v
flock01 flock01
flock02 flock02
flock03 flock03
flock04 flock04
flock06 flock06
fmtmsg01 fmtmsg01
fork01 fork01
fork03 fork03
fork04 fork04
fork05 fork05
fork07 fork07
fork08 fork08
fork09 fork09
fork10 fork10
fork14 fork14
fpathconf01 fpathconf01
fptest01 fptest01
fptest02 fptest02
fremovexattr01 fremovexattr01
fremovexattr02 fremovexattr02
fs_bind01_sh fs_bind01.sh
fs_bind02_sh fs_bind02.sh
fs_bind03_sh fs_bind03.sh
fs_bind04_sh fs_bind04.sh
fs_bind05_sh fs_bind05.sh
fs_bind06_sh fs_bind06.sh
fs_bind07_sh fs_bind07.sh
fs_bind07-2_sh fs_bind07-2.sh
fs_bind08_sh fs_bind08.sh
fs_bind09_sh fs_bind09.sh
fs_bind10_sh fs_bind10.sh
fs_bind11_sh fs_bind11.sh
fs_bind12_sh fs_bind12.sh
fs_bind13_sh fs_bind13.sh
fs_bind14_sh fs_bind14.sh
fs_bind15_sh fs_bind15.sh
fs_bind16_sh fs_bind16.sh
fs_bind17_sh fs_bind17.sh
fs_bind18_sh fs_bind18.sh
fs_bind19_sh fs_bind19.sh
fs_bind20_sh fs_bind20.sh
fs_bind21_sh fs_bind21.sh
fs_bind22_sh fs_bind22.sh
fs_bind23_sh fs_bind23.sh
fs_bind24_sh fs_bind24.sh
fs_bind_move01_sh fs_bind_move01.sh
fs_bind_move02_sh fs_bind_move02.sh
fs_bind_move03_sh fs_bind_move03.sh
fs_bind_move04_sh fs_bind_move04.sh
fs_bind_move05_sh fs_bind_move05.sh
fs_bind_move06_sh fs_bind_move06.sh
fs_bind_move07_sh fs_bind_move07.sh
fs_bind_move08_sh fs_bind_move08.sh
fs_bind_move09_sh fs_bind_move09.sh
fs_bind_move10_sh fs_bind_move10.sh
fs_bind_move11_sh fs_bind_move11.sh
fs_bind_move12_sh fs_bind_move12.sh
fs_bind_move13_sh fs_bind_move13.sh
fs_bind_move14_sh fs_bind_move14.sh
fs_bind_move15_sh fs_bind_move15.sh
fs_bind_move16_sh fs_bind_move16.sh
fs_bind_move17_sh fs_bind_move17.sh
fs_bind_move18_sh fs_bind_move18.sh
fs_bind_move19_sh fs_bind_move19.sh
fs_bind_move20_sh fs_bind_move20.sh
fs_bind_move21_sh fs_bind_move21.sh
fs_bind_move22_sh fs_bind_move22.sh
fs_bind_rbind01_sh fs_bind_rbind01.sh
fs_bind_rbind02_sh fs_bind_rbind02.sh
fs_bind_rbind03_sh fs_bind_rbind03.sh
fs_bind_rbind04_sh fs_bind_rbind04.sh
fs_bind_rbind05_sh fs_bind_rbind05.sh
fs_bind_rbind06_sh fs_bind_rbind06.sh
fs_bind_rbind07-2_sh fs_bind_rbind07-2.sh
fs_bind_rbind07_sh fs_bind_rbind07.sh
fs_bind_rbind08_sh fs_bind_rbind08.sh
fs_bind_rbind09_sh fs_bind_rbind09.sh
fs_bind_rbind10_sh fs_bind_rbind10.sh
fs_bind_rbind11_sh fs_bind_rbind11.sh
fs_bind_rbind12_sh fs_bind_rbind12.sh
fs_bind_rbind13_sh fs_bind_rbind13.sh
fs_bind_rbind14_sh fs_bind_rbind14.sh
fs_bind_rbind15_sh fs_bind_rbind15.sh
fs_bind_rbind16_sh fs_bind_rbind16.sh
fs_bind_rbind17_sh fs_bind_rbind17.sh
fs_bind_rbind18_sh fs_bind_rbind18.sh
fs_bind_rbind19_sh fs_bind_rbind19.sh
fs_bind_rbind20_sh fs_bind_rbind20.sh
fs_bind_rbind21_sh fs_bind_rbind21.sh
fs_bind_rbind22_sh fs_bind_rbind22.sh
fs_bind_rbind23_sh fs_bind_rbind23.sh
fs_bind_rbind24_sh fs_bind_rbind24.sh
fs_bind_rbind25_sh fs_bind_rbind25.sh
fs_bind_rbind26_sh fs_bind_rbind26.sh
fs_bind_rbind27_sh fs_bind_rbind27.sh
fs_bind_rbind28_sh fs_bind_rbind28.sh
fs_bind_rbind29_sh fs_bind_rbind29.sh
fs_bind_rbind30_sh fs_bind_rbind30.sh
fs_bind_rbind31_sh fs_bind_rbind31.sh
fs_bind_rbind32_sh fs_bind_rbind32.sh
fs_bind_rbind33_sh fs_bind_rbind33.sh
fs_bind_rbind34_sh fs_bind_rbind34.sh
fs_bind_rbind35_sh fs_bind_rbind35.sh
fs_bind_rbind36_sh fs_bind_rbind36.sh
fs_bind_rbind37_sh fs_bind_rbind37.sh
fs_bind_rbind38_sh fs_bind_rbind38.sh
fs_bind_rbind39_sh fs_bind_rbind39.sh
fs_bind_regression_sh fs_bind_regression.sh
fs_di fs_di -d $TMPDIR
fs_fill fs_fill
fs_inod01 fs_inod $TMPDIR 10 10 10
fs_perms01 fs_perms 005 99 99 12 100 x 0
fs_perms02 fs_perms 050 99 99 200 99 x 0
fs_perms03 fs_perms 500 99 99 99 500 x 0
fs_perms04 fs_perms 002 99 99 12 100 w 0
fs_perms05 fs_perms 020 99 99 200 99 w 0
fs_perms06 fs_perms 200 99 99 99 500 w 0
fs_perms07 fs_perms 004 99 99 12 100 r 0
fs_perms08 fs_perms 040 99 99 200 99 r 0
fs_perms09 fs_perms 400 99 99 99 500 r 0
fs_perms10 fs_perms 000 99 99 99 99 r 1
fs_perms11 fs_perms 000 99 99 99 99 w 1
fs_perms12 fs_perms 000 99 99 99 99 x 1
fs_perms13 fs_perms 010 99 99 99 500 x 1
fs_perms14 fs_perms 100 99 99 200 99 x 1
fs_perms15 fs_perms 020 99 99 99 500 w 1
fs_perms16 fs_perms 200 99 99 200 99 w 1
fs_perms17 fs_perms 040 99 99 99 500 r 1
fs_perms18 fs_perms 400 99 99 200 99 r 1
fs_racer fs_racer.sh -t 5
fsconfig01 fsconfig01
fsconfig02 fsconfig02
fsetxattr01 fsetxattr01
fsmount01 fsmount01
fsmount02 fsmount02
fsopen01 fsopen01
fsopen02 fsopen02
fspick01 fspick01
fspick02 fspick02
fstat02 fstat02
fstat02_64 fstat02_64
fstat03 fstat03
fstat03_64 fstat03_64
fstatat01 fstatat01
fstatfs01 fstatfs01
fstatfs01_64 fstatfs01_64
fstatfs02 fstatfs02
fstatfs02_64 fstatfs02_64
fsx02 fsx-linux -l 500000 -r 4096 -t 2048 -w 2048 -N 10000
fsync01 fsync01
fsync02 fsync02
fsync03 fsync03
fsync04 fsync04
ftest01 ftest01
ftest02 ftest02
ftest03 ftest03
ftest04 ftest04
ftest05 ftest05
ftest06 ftest06
ftest07 ftest07
ftest08 ftest08
ftruncate01 ftruncate01
ftruncate01_64 ftruncate01_64
ftruncate03 ftruncate03
ftruncate03_64 ftruncate03_64
ftruncate04 ftruncate04
ftruncate04_64 ftruncate04_64
futex_cmp_requeue01 futex_cmp_requeue01
futex_cmp_requeue02 futex_cmp_requeue02
futex_wait01 futex_wait01
futex_wait02 futex_wait02
futex_wait03 futex_wait03
futex_wait04 futex_wait04
futex_wait05 futex_wait05
futex_wait_bitset01 futex_wait_bitset01
futex_wake01 futex_wake01
futex_wake02 futex_wake02
futex_wake03 futex_wake03
futex_wake04 futex_wake04
get_robust_list01 get_robust_list01
getaddrinfo_01 getaddrinfo_01
getcontext01 getcontext01
getcpu01 getcpu01
getcwd01 getcwd01
getcwd02 getcwd02
getcwd03 getcwd03
getcwd04 getcwd04
getdents01 getdents01
getdents02 getdents02
getdomainname01 getdomainname01
getegid01 getegid01
getegid02 getegid02
geteuid01 geteuid01
geteuid02 geteuid02
getgid01 getgid01
getgid03 getgid03
getgroups01 getgroups01
getgroups03 getgroups03
gethostbyname_r01 gethostbyname_r01
gethostid01 gethostid01
gethostname01 gethostname01
getitimer01 getitimer01
getitimer02 getitimer02
getpagesize01 getpagesize01
getpeername01 getpeername01
getpgid01 getpgid01
getpgid02 getpgid02
getpgrp01 getpgrp01
getpid01 getpid01
getpid02 getpid02
getppid01 getppid01
getppid02 getppid02
getpriority01 getpriority01
getpriority02 getpriority02
getrandom01 getrandom01
getrandom02 getrandom02
getrandom03 getrandom03
getrandom04 getrandom04
getresgid01 getresgid01
getresgid02 getresgid02
getresgid03 getresgid03
getresuid01 getresuid01
getresuid02 getresuid02
getresuid03 getresuid03
getrlimit01 getrlimit01
getrlimit02 getrlimit02
getrlimit03 getrlimit03
getrusage01 getrusage01
getrusage02 getrusage02
getrusage03 getrusage03
getrusage04 getrusage04
getsid01 getsid01
getsid02 getsid02
getsockname01 getsockname01
getsockopt01 getsockopt01
getsockopt02 getsockopt02
gettid01 gettid01
gettimeofday01 gettimeofday01
gettimeofday02 gettimeofday02
getuid01 getuid01
getuid03 getuid03
gzip01_sh gzip_tests.sh
hackbench01 hackbench 50 process 1000
hackbench02 hackbench 20 thread 1000
hangup01 hangup01
hugemmap01 hugemmap01
hugemmap02 hugemmap02
hugemmap04 hugemmap04
hugemmap05 hugemmap05
hugemmap05_1 hugemmap05 -m
hugemmap05_2 hugemmap05 -s

Attachment: signature.asc
Description: PGP signature