DAOS-18690 vos: fix engine abort in DTX commit blob fallback on ENOSPC#18612
Open
hgichon wants to merge 1 commit into
Open
DAOS-18690 vos: fix engine abort in DTX commit blob fallback on ENOSPC#18612hgichon wants to merge 1 commit into
hgichon wants to merge 1 commit into
Conversation
|
Ticket title is 'Aurora daos_user: SCM single target ran out of space (min:0 B) and not able to finish GC. ' |
f395915 to
8e83c8f
Compare
When the pool is physically full, vos_dtx_extend_cmt_table() fails to
allocate a new commit blob and falls back to vos_dtx_reuse_cmt_blob()
inside the same transaction. The failing allocation is a plain
(non-NO_ABORT) alloc inside the regular object modification transaction
started by vos_tx_begin(), whose failure behavior is left at the
default, so the allocator aborts the whole TX on failure. The fallback
then calls umem_tx_add_ptr() on the aborted TX, which is a fatal usage
error in the allocator:
CRIT pmdk tx.c:1403 pmemobj_tx_add_range_direct() called in invalid stage 3
*** Process (daos_engine) received signal 6 (Aborted) ***
vos_dtx_commit_internal <- vos_dtx_prepared <- vos_tx_end
<- vos_obj_punch <- ds_obj_punch_handler
The reuse fallback introduced by daos-stack#18141 is only exercised in tests via
the DAOS_DTX_NOSPACE_NOREFRESH fail-check, which skips the allocation
entirely and therefore never reproduces the TX abort of a real ENOSPC.
Fix: add a UMEM_FLAG_NO_ABORT alloc flag (1 << 3, distinct from
UMEM_XADD_NO_SNAPSHOT), map it to POBJ_XALLOC_NO_ABORT /
DAV_XALLOC_NO_ABORT in the pmem/dav/dav_v2 backends, and use it for
the commit blob allocation so the transaction survives the failure and
the reuse fallback can run as designed.
Add a umem regression test (UMEM010): a failed NO_ABORT allocation must
leave the TX alive so a subsequent alloc/tx_add_ptr/commit succeeds.
Verified on a 400 MB tmpfs-SCM pool: fill the pool to ENOSPC, then run
a create/unlink storm. Before the fix the engine aborts within seconds
with the backtrace above; after the fix it stays up and the operations
fail cleanly with -DER_NOSPACE.
Signed-off-by: hgichon <hgichon@gmail.com>
8e83c8f to
6c4dd32
Compare
Author
|
Note on backport scope: the Jira bot above shows DAOS-18690 is So this fix should ride along with the #18141 backport to 2.8.1 (and any other target branches), not just land on master. Happy to prepare the 2.8-based patch as well if useful. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Regression introduced by PR #18141 (DAOS-18690 "vos: handle DTX commit under space pressure", commit b36dd7b, 2026-05-14) — master only. Release branches (2.6.x/2.8) are not affected: their
vos_dtx_commit_internal()returns-DER_NOSPACEdirectly on blob allocation failure without touching the aborted TX.When the pool is physically full (ENOSPC), extending the DTX committed table during a punch/update commit crashes the whole engine with SIGABRT.
vos_dtx_extend_cmt_table()allocates a new commit blob withumem_zalloc(). On allocation failure it falls back tovos_dtx_reuse_cmt_blob()inside the same transaction. However, all three allocator backends (pmemobj, dav, dav_v2) abort the transaction automatically when a tx alloc fails (no*_NO_ABORTflag is passed by the umem wrappers). The fallback then callsumem_tx_add_ptr()/dbtree_delete()on the aborted TX, which is a fatal usage error in the allocator:Backtrace (master, commit ~f6b827e3e):
Why CI doesn't catch it
The reuse-blob fallback is exercised in tests via the
DAOS_DTX_NOSPACE_NOREFRESHfail-check, which skips the allocation entirely — the TX stays alive, so the fallback works. A real ENOSPC allocation failure aborts the TX first, which the fail-check path never reproduces.Reproduction
vos_dtx_extend_cmt_table()while the pool is full.invalid stage 3+ SIGABRT). A pool-full production system can be taken down by any client issuing unlinks.Suggested fix (verified)
Add a
UMEM_FLAG_NO_ABORTalloc flag, map it toPOBJ_XALLOC_NO_ABORT/DAV_XALLOC_NO_ABORTin the pmem/dav/dav_v2 backends, and use it for the commit-blob allocation invos_dtx_extend_cmt_table()so the TX survives the failure and the reuse fallback can run as designed:src/include/daos/mem.h:#define UMEM_FLAG_NO_ABORT (((uint64_t)1) << 2)src/common/mem.c:pmem_tx_alloc()→POBJ_XALLOC_NO_ABORT,bmem_tx_alloc()/bmem_tx_alloc_v2()→DAV_XALLOC_NO_ABORTsrc/vos/vos_dtx.cvos_dtx_extend_cmt_table():umem_zalloc(umm, DTX_CMT_BLOB_SIZE)→umem_alloc_verb(umm, UMEM_FLAG_ZERO | UMEM_FLAG_NO_ABORT, DTX_CMT_BLOB_SIZE, UMEM_DEFAULT_MBKT_ID)With this patch the same reproduction survives: unlink storms on a full pool return
-DER_NOSPACEcleanly and the engine stays up (verified on tmpfs SCM/pmemobj backend; dav paths compile-verified only).Note: filed as a PR because GitHub issues are disabled on this repo; happy to file a Jira ticket as well if preferred.
Update (2026-07-04):
UMEM_FLAG_NO_ABORTmoved to1 << 3to avoid sharing a bit withUMEM_XADD_NO_SNAPSHOT(1 << 2) in the same flags namespace.UMEM_FLAG_NO_ABORTallocation must leave the TX alive so a subsequent alloc/umem_tx_add_ptr()/commit succeeds — this covers the TX-abort path that theDAOS_DTX_NOSPACE_NOREFRESHfail-check cannot reproduce. Passes 10/10 locally (pmem backend on tmpfs needsPMEMOBJ_CONF=sds.at_create=0).vos_tx_begin()object transaction, whose failure behavior is left at the default (abort) rather thanTX_FAILURE_RETURN.