Siyao Meng created HDDS-16865:
---------------------------------

             Summary: OM deletes its pre-install DB backup before the installed 
Ratis checkpoint is synced, so a power loss can leave om.db unopenable
                 Key: HDDS-16865
                 URL: https://issues.apache.org/jira/browse/HDDS-16865
             Project: Apache Ozone
          Issue Type: Bug
            Reporter: Siyao Meng
         Attachments: MC-2-sync-checkpoint-before-replacing-om-db.patch, 
TestBugMC2CheckpointNotDurable.java

h3. Mechanism
A follower OM that installs a Ratis snapshot writes every checkpoint file 
without fsync: {{RDBSnapshotProvider.untarContentsOfTarball}} extracts the 
tarball with Hadoop {{FileUtil.unTar}} (GNU tar), 
{{InodeMetadataRocksDBCheckpoint}} adds hard links, and 
{{OzoneManager.replaceOMDBWithCheckpoint}} renames the old DB items into 
{{om.db.backup.*}} and the checkpoint items into the metadata dir. 
{{OzoneManager.installCheckpoint}} then reloads the DB and deletes the backup 
with {{FileUtils.deleteFully(dbBackup)}}. Nothing on this path syncs the new 
files or the directories; the only syncs are the ones RocksDB issues for its 
own new MANIFEST, OPTIONS and directory when the DB is reopened.

With delayed allocation (ext4 and XFS defaults) the metadata of the new files 
and the renames are forced to the journal by the RocksDB directory fsync on 
reload, and the unlink of the backup follows within seconds (the next journal 
commit, or any later fsync on the file system), while the SST data stays in the 
page cache until writeback, about 30 seconds later with default 
{{vm.dirty_expire_centisecs}}. A power loss or host crash in that window leaves 
the installed SST files that were not yet written back (all 22 in the test) at 
0 bytes, and one such file is enough for RocksDB to refuse to open {{om.db}}. 
There is no backup to fall back to.

h3. Trigger
# A follower OM falls behind the leader's Ratis log purge, so Ratis triggers 
install snapshot (or a new OM bootstraps).
# The follower downloads, untars and installs the checkpoint and logs "Install 
Checkpoint is finished".
# The host loses power, or the kernel crashes, before the installed files are 
written back. A process crash alone does not lose the data.

h3. Impact
On restart RocksDB refuses to open {{om.db}} ("Sst file size mismatch between 
expected N and file system 0"), and the old DB is gone, so that OM cannot start 
until an operator wipes its metadata and lets it install a checkpoint from the 
leader again. The other OMs keep serving, so this costs one OM's availability, 
not cluster data. The full OM startup on the damaged directory was not run; it 
is argued from {{OmMetadataManagerImpl.loadDB}} using the same RocksDB open 
that fails here. All releases with OM HA are affected: the install path dates 
from HDDS-1649 (0.5.0), and the release tags from 0.5.0 to 2.2.1 delete the 
backup without any sync (code reading, only the commit above was run).

SCM's install path ({{HAUtils.replaceDBWithCheckpoint}} and 
{{SCMHAManagerImpl.installCheckpoint}}) has the same gap and is not changed 
here.

h3. Reproduction
Two forms, both on the unmodified commit.

[^TestBugMC2CheckpointNotDurable.java] ({{hadoop-ozone/integration-test}}) 
starts a 3 OM mini cluster with one OM down, writes past the log purge gap and 
starts that OM, so the install runs through the normal Ratis download, untar 
and swap path. Right after the install finishes it checks that the backup is 
gone and runs {{filefrag -v}} on the installed SST files. On XFS it failed with 
"Backup of the old DB is deleted, but 22 of 22 installed SST files have data 
that is not on disk yet". It needs Linux, {{filefrag}} and ext4 or XFS, and a 
{{sync}} by another process right after the install can make it pass.

A real power cut was run separately: the same install with the mini cluster 
data dir on a loop device behind dm-flakey, cutting writes 1 second after the 
install finished (suspend with {{--nolockfs}}, load a {{drop_writes}} table, 
kill the JVM, remount), then opening {{om.db}} with rocksdbjni 10.10.1.1. On 
ext4 (defaults, {{data=ordered}}) and on XFS (defaults) the remounted {{om.db}} 
had 22 of 22 SST files at 0 bytes, no {{om.db.backup.*}} was left, and the open 
failed with "Sst file size mismatch between expected 1562 and file system 0". 
One earlier XFS run kept its data; that run did not record whether the files 
had already been written back before the cut, and the XFS run that did record 
it showed 22 of 22 files still with delayed allocation extents.

h3. Patch
[^MC-2-sync-checkpoint-before-replacing-om-db.patch], against 
a6b7bdb937109ba2893688b41a89470bc95c88cf. It also applies to master at 
b0aa6475b78.

{{installCheckpoint}} now first fsyncs every file and directory of the 
checkpoint (once per inode, so hard links are not synced twice), before it 
stops any service, and {{moveCheckpointFiles}} fsyncs the metadata dir after 
the renames and the marker deletion. Both use Hadoop {{IOUtils.fsync}}, which 
also handles directories. If the checkpoint sync fails, the install fails with 
nothing stopped or moved; if the metadata dir sync fails, the existing rollback 
restores the old DB. The checkpoint sync costs about the data still dirty at 
the end of the untar divided by the disk write bandwidth: 2 GB dirty in 250 
files took 4.5 s on a SATA SSD, and a second pass over the now clean files took 
4 ms. That is bounded by the kernel dirty limit, not by the checkpoint size, so 
expect seconds on NVMe, tens of seconds on SATA SSD and minutes on HDD for a 
large checkpoint. Because it runs before the services are stopped, it does not 
lengthen the time the OM is offline.

Covered by {{testInstallCheckpointSyncsCheckpointBeforeReplacingDb}} in the 
existing {{TestOMRatisSnapshots}}: it fails if the install proceeds when the 
checkpoint sync fails, if the old DB is not restored when the metadata dir sync 
fails, if any checkpoint inode is not synced, or if the metadata dir is not 
synced after the checkpoint {{om.db}} was renamed into it. Without the change 
it fails because the install proceeds when the checkpoint sync fails. With it 
{{TestOMRatisSnapshots}}, {{TestOMRatisSnapshotTransfer}} and 
{{TestOMInstallSnapshotDuringBootstrapping}} (11 tests) pass and checkstyle is 
clean. With the patch the reproduction passes, and the same dm-flakey power cut 
1 second after the install left all 22 SST files intact and {{om.db}} opening 
on both ext4 and XFS.

Found by TLA+ model checking and code review of the OM Ratis snapshot 
(checkpoint) install paths under HDDS-15926, on commit 
a6b7bdb937109ba2893688b41a89470bc95c88cf. Checked against HDDS issues and 
apache/ozone pull requests for duplicates before filing. The attached patch is 
a proposal for review. Generated with Specula (Claude Opus 5.5).



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to