Summary
We are seeing repeatable kernel crashes with Open CAS Linux 26.03.2 on Linux 6.18.33 under a high-throughput nginx fileserver workload.
The crash is always inside the CAS kernel module, in:
cas_cache/src/ocf/utils/utils_alock.c:319
cas_cache/src/ocf/utils/utils_alock.c:368
Both crashes happen from the cached read-hit completion path:
_ocf_read_generic_hit_complete
ocf_req_unlock
ocf_alock_unlock_one_rd
The machine reboots via kdump. This does not look like mdraid, XFS, nginx, NIC, or userspace failure. The direct failure appears to be an OCF alock state invariant violation: CAS is trying to unlock/transfer a read lock while the cache-line access state is already WR (0xff).
Environment
- OS/userland: RHEL 9 based
- Kernel: Linux
6.18.33
- Open CAS Linux:
26.03.2.0000.release
- CAS kernel module:
26.03.2.0000.release
- OCF submodule in release:
d54f2fc9938cc9aa57f69c06cb26084a5322248c
- Kernel config:
CONFIG_PREEMPT_NONE=y
CONFIG_PREEMPT_NONE_BUILD=y
CONFIG_HZ_1000=y
CONFIG_HZ=1000
CONFIG_NO_HZ_IDLE=y
- Workload:
- nginx fileserver
- heavy read traffic
- direct/AIO reads
- high network throughput
- Storage:
- HDD mdraid6 core device
- NVMe CAS cache device
- XFS on exported CAS core
- CAS mode:
- write-around
- cache line size: 64 KiB
- promotion policy:
nhit
- sequential cutoff policy:
always
- sequential cutoff threshold:
16384 KiB
- CAS module parameters:
max_writeback_queue_size=65536
writeback_queue_unblock_size=60000
use_io_scheduler=1
unaligned_io=1
seq_cut_off_mb=1
Actual Result
The server crashed multiple times with the same CAS BUG signature.
Example 1:
kernel BUG at cas_cache/src/ocf/utils/utils_alock.c:368!
Oops: invalid opcode: 0000 [#1] SMP NOPTI
CPU: 58 PID: 0 Comm: swapper/58 Kdump: loaded Tainted: G OE 6.18.33 #2
RIP: 0010:ocf_alock_unlock_one_rd+0x2af/0x2c0 [cas_cache]
RAX: 00000000000000ff
...
Call Trace:
<IRQ>
ocf_req_unlock+0x62/0x100 [cas_cache]
_ocf_read_generic_hit_complete+0x3c/0x60 [cas_cache]
cas_bd_forward_end_callback+0x11/0x20 [cas_cache]
md_end_clone_io+0x45/0x100
blk_mq_end_request_batch+0xf1/0x4e0
nvme_irq+0x86/0xa0 [nvme]
Example 2:
kernel BUG at cas_cache/src/ocf/utils/utils_alock.c:319!
Oops: invalid opcode: 0000 [#1] SMP NOPTI
CPU: 48 UID: 65534 PID: 67341 Comm: nginx Kdump: loaded Tainted: G OE 6.18.33 #2
RIP: 0010:ocf_alock_unlock_one_rd+0x2b7/0x2c0 [cas_cache]
RAX: 00000000000000ff
...
Call Trace:
<IRQ>
ocf_req_unlock+0x62/0x100 [cas_cache]
_ocf_read_generic_hit_complete+0x3c/0x60 [cas_cache]
cas_bd_forward_end_callback+0x11/0x20 [cas_cache]
md_end_clone_io+0x45/0x100
blk_mq_end_request_batch+0xf1/0x4e0
nvme_irq+0x86/0xa0 [nvme]
<TASK>
xfs_file_dio_read+0xa1/0xf0 [xfs]
xfs_file_read_iter+0xb3/0xd0 [xfs]
aio_read+0xeb/0x1b0
io_submit_one+0xce/0x360
__x64_sys_io_submit+0x82/0x170
Why This Looks Like CAS/OCF Lock State Corruption
In OCF utils_alock.c from the 26.03.2 OCF submodule:
#define OCF_CACHE_LINE_ACCESS_WR ((unsigned char)(-1))
#define OCF_CACHE_LINE_ACCESS_IDLE 0
#define OCF_CACHE_LINE_ACCESS_ONE_RD 1
Crash registers show:
That matches OCF_CACHE_LINE_ACCESS_WR.
The failing assertions are:
ENV_BUG_ON(v == OCF_CACHE_LINE_ACCESS_WR);
in the read unlock/read-to-read transfer path.
So CAS appears to be completing a read-hit request and trying to release a read lock, but the alock entry is already in write-lock state.
Reproduction Pattern
The issue appeared after running Open CAS 26.03.2 on Linux 6.18.33 under production read load.
Observed crashes:
- First crash after long uptime under load
- Subsequent crashes within around 20 minutes after reboot under resumed load
- Same BUG signature each time
No manual reboot/shutdown command triggered these events; kdump captured vmcores.
Relevant Upstream Observation
Open CAS Linux v26.03.2 pins OCF:
d54f2fc9938cc9aa57f69c06cb26084a5322248c
OCF master currently contains later metadata/concurrency-related commits.
This one looks especially relevant:
7a524fe53f49dc2f1444834552cf9b170b73e0f8
metadata: Make collision updates atomic
Commit message:
Allow to accessing collision metadata for read without acquiring hash bucket lock.
It changes collision metadata next/prev updates from separate bitfield accesses to an atomic 64-bit entry update/read.
utils_alock.c itself appears unchanged between OCF d54f2fc and current OCF master, so the alock BUG may be a symptom of earlier metadata/collision state corruption rather than a bug directly inside the alock function.
v26.03.2 already includes:
50b7ee24fa4702bb70435563fd7002907cadc975
metadata: Prevent read hoisting in hash bucket lock
but does not include the later atomic collision metadata update commit.
Expected Result
CAS should not hit ENV_BUG_ON() in ocf_alock_unlock_one_rd() during normal cached read-hit completion under read-heavy production load.
Questions
- Is this a known issue in Open CAS
26.03.2 / OCF d54f2fc?
- Is
7a524fe5 metadata: Make collision updates atomic expected to fix this class of alock state corruption?
- Are there other OCF/Open CAS commits after
26.03.2 that should be backported for Linux 6.18.x and high-concurrency read workloads?
- Would you recommend testing current Open CAS master, or backporting only the metadata/collision fixes onto
26.03.2?
Additional Notes
- The kernel is built with
CONFIG_PREEMPT_NONE=y, so this is not a PREEMPT_DYNAMIC/full-preempt runtime issue.
- The crash happens in IRQ completion from NVMe/mdraid completion path.
- The workload uses nginx AIO/direct reads, which may increase concurrency on cached read-hit completion.
- CAS reported no user-visible CAS errors before the BUG.
Summary
We are seeing repeatable kernel crashes with Open CAS Linux
26.03.2on Linux6.18.33under a high-throughput nginx fileserver workload.The crash is always inside the CAS kernel module, in:
cas_cache/src/ocf/utils/utils_alock.c:319cas_cache/src/ocf/utils/utils_alock.c:368Both crashes happen from the cached read-hit completion path:
The machine reboots via kdump. This does not look like mdraid, XFS, nginx, NIC, or userspace failure. The direct failure appears to be an OCF alock state invariant violation: CAS is trying to unlock/transfer a read lock while the cache-line access state is already
WR(0xff).Environment
6.18.3326.03.2.0000.release26.03.2.0000.released54f2fc9938cc9aa57f69c06cb26084a5322248cCONFIG_PREEMPT_NONE=yCONFIG_PREEMPT_NONE_BUILD=yCONFIG_HZ_1000=yCONFIG_HZ=1000CONFIG_NO_HZ_IDLE=ynhitalways16384 KiBmax_writeback_queue_size=65536writeback_queue_unblock_size=60000use_io_scheduler=1unaligned_io=1seq_cut_off_mb=1Actual Result
The server crashed multiple times with the same CAS BUG signature.
Example 1:
Example 2:
Why This Looks Like CAS/OCF Lock State Corruption
In OCF
utils_alock.cfrom the26.03.2OCF submodule:Crash registers show:
That matches
OCF_CACHE_LINE_ACCESS_WR.The failing assertions are:
in the read unlock/read-to-read transfer path.
So CAS appears to be completing a read-hit request and trying to release a read lock, but the alock entry is already in write-lock state.
Reproduction Pattern
The issue appeared after running Open CAS
26.03.2on Linux6.18.33under production read load.Observed crashes:
No manual reboot/shutdown command triggered these events; kdump captured vmcores.
Relevant Upstream Observation
Open CAS Linux
v26.03.2pins OCF:OCF master currently contains later metadata/concurrency-related commits.
This one looks especially relevant:
Commit message:
It changes collision metadata next/prev updates from separate bitfield accesses to an atomic 64-bit entry update/read.
utils_alock.citself appears unchanged between OCFd54f2fcand current OCF master, so the alock BUG may be a symptom of earlier metadata/collision state corruption rather than a bug directly inside the alock function.v26.03.2already includes:but does not include the later atomic collision metadata update commit.
Expected Result
CAS should not hit
ENV_BUG_ON()inocf_alock_unlock_one_rd()during normal cached read-hit completion under read-heavy production load.Questions
26.03.2/ OCFd54f2fc?7a524fe5 metadata: Make collision updates atomicexpected to fix this class of alock state corruption?26.03.2that should be backported for Linux6.18.xand high-concurrency read workloads?26.03.2?Additional Notes
CONFIG_PREEMPT_NONE=y, so this is not a PREEMPT_DYNAMIC/full-preempt runtime issue.