]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commit
crimson/seastore: fix LogNode overflow from unsigned underflow in expect_overflow
authorMatan Breizman <mbreizma@redhat.com>
Sun, 19 Jul 2026 12:07:10 +0000 (12:07 +0000)
committerMatan Breizman <mbreizma@redhat.com>
Sun, 19 Jul 2026 13:29:04 +0000 (13:29 +0000)
commit271817bbb8bd52ee74490a9ea12f4a4d4bdac2f7
tree3e00e63b6d52a628afdb1b6f5920ac205b3cb302
parent32e28b9a70313455fd2c5108ef147ca9f2ba6ec9
crimson/seastore: fix LogNode overflow from unsigned underflow in expect_overflow

The can_ow branch of LogManager's expect_overflow computed:
```
remain = capacity() - get_last_pos() - reserved_len
```
all uint32 operands, once the log leaf node is near full
(get_last_pos() + reserved_len >= capacity()) this subtraction underflows.

The node never rolls to a new leaf, instead it overflows the
16 KB block at commit-time delta replay.

Captured at the replay overflow point (per-collection batching, 4K randwrite):

```
  LogNode OVERFLOW at replay: pos=16641 size=58 reserved_len=3098
                              reserved_size=6 capacity=16328 LIMIT=16384

  log_node.h : In function 'void LogKVNodeLayout::set_last_pos(uint32_t)',
               ceph_assert(pos <= LOG_NODE_BLOCK_SIZE)
```

Here reserved_len (3098) is accurate: ~13543 committed + 3098 pending =
16641 = pos, i.e. the node was already ~13.5 KB full and the predictor
should have rolled over. Instead capacity - get_last_pos - reserved_len
went negative (16328 - ~13273 - 3098 < 0), wrapped in uint32, and the
check passed; pos reached 16641 > 16384 and set_last_pos asserted.

This was exposed by the per-coll batching where many overwrites append in
a single txn.

Signed-off-by: Matan Breizman <mbreizma@redhat.com>
src/crimson/os/seastore/omap_manager/log/log_node.cc