Research notes / Persistent memory
Persistent memory: DAX is not a durable commit
13 October 2026 / Primary-source review and logical model
A store can be visible to another thread before it survives power loss. DAX, a persistence fence and a transaction solve different problems. Start by identifying which parts of the machine are protected, then prove that recovery never accepts metadata whose data is missing.
Where does a store become persistent?
Byte addressability describes how locations are selected. Load/store access describes an interface. Neither alone promises survival after a crash. A persistence domain is the set of components whose contents are protected against a specified failure. It can include volatile buffers with a guaranteed power-fail drain, not only nonvolatile cells. Intel's ADR example protects the memory-controller write-pending queue, but not dirty processor caches. [1]
These are platform contracts for persistent-memory mappings, not promises about all RAM or every machine carrying a particular processor.
| Contract | Protected boundary | Software obligation |
|---|---|---|
| ADR | Persistent media and covered controller buffers; CPU caches remain outside | Move dirty data out of unprotected caches and complete the required ordering |
| eADR | Protection extends to CPU caches on a correctly enabled platform | Preserve ordering and the application's recovery protocol |
Intel's eADR description removes the need for explicit cache flushes when supported and detected, but still requires SFENCE. The platform also needs adequate stored energy. Treat eADR as a verified system property, not an inference from an instruction being available. It does not turn ordinary volatile DRAM into persistent storage. [2]
DAX and MAP_SYNC live at another boundary
Filesystem DAX avoids the kernel page-cache copy for suitable memory-like storage; mapped file data can be accessed directly. This does not mean the processor caches are bypassed. Linux distinguishes the persistent FS_XFLAG_DAX preference from the active per-file S_DAX state reported through STATX_ATTR_DAX. A configured preference is not proof of the effective access mode. [3]
MAP_SYNC is a mapping contract, not an instruction that flushes each store. Linux requires MAP_SHARED_VALIDATE; using MAP_SHARED can silently ignore the flag. Unsupported files return EOPNOTSUPP. For supported DAX files, MAP_SYNC gives the file-offset persistence guarantee needed to use appropriate CPU persistence instructions. The instructions are still part of the protocol. [4, MAP_SYNC]
PMDK's mapping-specific API distinguishes page, cache-line and byte persistence granularity. That classification selects the required persistence mechanism; it does not specify an application's transaction size. Use the function associated with the actual mapping instead of assuming every mmap target is PMem. The reference here is pinned to PMDK 1.13.1, not advertised as the newest release. [5]
Data may persist earlier than the flush
The function returned by pmem2_get_persist_fn ensures durability by completion, but it is not atomic or transactional. Cache replacement may persist writes before that call. A flush is therefore not a gate that keeps unfinished updates away from recovery. The API combines flushing and draining; completing one range says nothing about the consistency of unrelated ranges. [6]
Concurrency adds another route to trouble: on a system without eADR, a reader may act on a value that is already visible but not persistent, then durably publish a dependent change. PMDK documents this counterexample and a persist-on-read approach for its stated scenario. It is not a general recipe for every lock-free structure. [7]
One final persist is not all-or-nothing
Hesela's synthetic example uses two initially zero cells on separate cache lines: payload and commit. Each individual cell update is assumed atomic. There is one writer, no reuse, no tearing and no other failures. Recovery accepts the record only if commit is one; its invariant is commit = 1 implies payload = 1.
We enumerate early persistence of issued stores under three declared protocols. In the first, the writer stores payload then commit without persistence ordering. The second adds a single persist of both at the end. The third persists payload completely before issuing the commit store, then persists commit.
All reachable states during each protocol, including before completion. Yes means allowed by this logical model, not equally likely or observed on hardware. Cell values are zero or one; counts are not failure rates.
| Payload / commit | No ordering | One final persist | Payload before commit | Recovery meaning |
|---|---|---|---|---|
| 0 / 0 | Yes | Yes | Yes | No published record |
| 1 / 0 | Yes | Yes | Yes | Unpublished payload; recovery ignores it |
| 0 / 1 | Yes | Yes | No | Invalid: commit names missing payload |
| 1 / 1 | Yes | Yes | Yes | Published payload present |
Both protocols with a final successful persist finish at 1 / 1. Their intermediate recovery states differ. Only the payload-before-commit protocol excludes 0 / 1. It still allows 1 / 0: ordering plus a recovery rule makes that state safe, rather than making the two writes physically indivisible.
This is a bounded illustration, not a CPU emulator or proof for arbitrary programs. It does not model compilers, concurrent publication, cache-line sharing, large payloads, memory reclamation or repeated updates. In particular, the unordered model is not a claim that every eADR execution admits all four states.
Inspect the generated states, assumptions and operation traces or run the dependency-free enumeration module. The page's values are generated from that module, not hand-entered results.
The Yat lesson: test recovery during recovery
Lantz and colleagues' Yat (ATC 2014) recorded PMFS operations and replayed allowed persistent states, then ran recovery and a consistency checker. One reported bug involved a shared truncate list; fixing its transaction boundary exposed another failure when recovery itself was interrupted. Recovery had to be idempotent. [8, section 5]
The study used a proposed historical architecture, including pm_wbarrier, not a specification of today's eADR. It captured the observed thread schedule rather than exploring all software schedules. Large state sets were sampled, and adjacent writes could be coalesced at a stated coverage cost. This is evidence for disciplined fault modeling and recovery checks, not an exhaustive guarantee for current PMem applications. [8, sections 2-4]
What to record before claiming durability
- Identify the real mapping, backing storage, active DAX state and supported MAP_SYNC behavior. A device name or a successful ordinary mmap is insufficient.
- Record the enabled persistence domain, protected failure class and platform requirements. Keep power-loss survival separate from media-error tolerance.
- Name the durable dependency: which payload must survive before which marker, pointer or index entry can be accepted after restart?
- Test interrupted updates and interrupted recovery against an independent oracle. Retain the workload, platform details and excluded states with the result.
These are engineering implications of the cited contracts, not measurements by Hesela. No hardware power-cut test, benchmark or reproduction of Yat was performed. Related: crash-testing oracles and atomic rename versus durable commit.
Corpus: persistent memory, persistence domain, ADR, eADR, DAX, MAP_SYNC, byte-addressable storage.
Primary sources
- Intel. Second Generation Xeon Processor Scalable Family Technical Overview: The Persistence Domain.
- Intel. Third Generation Xeon Processor Scalable Family on Two Socket Platforms: eADR.
- Linux kernel documentation. Direct Access for files: motivation and S_DAX state.
- Linux man-pages. mmap(2), MAP_SYNC and MAP_SHARED_VALIDATE.
- PMDK 1.13.1. libpmem2(7), GRANULARITY (pinned source documentation).
- PMDK 1.13.1. pmem2_get_persist_fn(3): early persistence and non-transactional semantics.
- PMDK project. Concurrency considerations in libpmemobj-cpp, 17 September 2021.
- Philip Lantz, Subramanya Dulloor, Sanjay Kumar, Rajesh Sankaran and Jeff Jackson. Yat: A Validation Framework for Persistent Memory Software. USENIX ATC 2014, pp. 433-438, sections 2-5.
Reviewed 13 October 2026. Version-pinned software documentation and historical research retain their original scope and rights.