mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2026-08-05 02:19:16 +00:00
The relocate-on-write path in update_cluster_addr() pushes the old L2 table cluster onto unref_clusters before allocating the relocation target. When that allocation fails at allocator exhaustion, the error unwinds with the still-referenced table on the free list, its deferred refcount update dropped, the L1 entry unchanged and the cached table still clean. The next metadata flush publishes the cluster to the allocator, and a later allocation hands the live L2 table to a new writer, which overwrites it with a refcount block, another L2 table or guest data. Retried writes against the same L1 slot re-enter the clean-table branch and push further duplicates, so one cluster can also be handed out to two writers at once. Images holding compressed clusters reach this constantly: writing to a compressed cluster always takes the decompress -> append_data_cluster -> update_cluster_addr path, so every such write relocates its L2 table. Allocate the relocation target first and release the old table only once the allocation has succeeded. A failed relocation now leaves the old table referenced, off the free lists and intact. Add deterministic regression coverage for both entry points: a plain write that exhausts the allocator at the L2 relocation step, and a compressed-cluster write that triggers the same relocation. Signed-off-by: doge <me@crackerben.com>