[
https://issues.apache.org/jira/browse/HDDS-16921?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
]
Siyao Meng updated HDDS-16921:
------------------------------
Attachment: TestBugMC6RollbackKeepsCheckpointStore.java
> SCM checkpoint install rollback restores the old DB without closing the open
> checkpoint DB, so it reloads the rejected checkpoint
> ---------------------------------------------------------------------------------------------------------------------------------
>
> Key: HDDS-16921
> URL: https://issues.apache.org/jira/browse/HDDS-16921
> Project: Apache Ozone
> Issue Type: Bug
> Reporter: Siyao Meng
> Priority: Minor
> Attachments: MC-6-close-scm-db-before-rollback-restore.patch,
> TestBugMC6RollbackKeepsCheckpointStore.java
>
>
> h3. Mechanism
> {{SCMHAManagerImpl.installCheckpoint}} closes the metadata store, swaps the
> checkpoint into {{scm.db}} and calls {{reloadSCMState}}. If that fails, the
> rollback calls {{HAUtils.replaceDBWithCheckpoint}} with the backup of the old
> DB and then {{reloadSCMState}} again, before {{exitSystem}}. When the first
> reload failed after {{SCMMetadataStoreImpl.start}} had opened the checkpoint
> (a later service rejected it), that store is still open during the rollback:
> * the directory of the open RocksDB is renamed to a second
> {{scm.db.backup.*}} and the old DB is copied back to {{scm.db}};
> * {{SCMMetadataStoreImpl.start}} does nothing while its store is set, so the
> rollback's {{reloadSCMState}} rebinds every service to the rejected
> checkpoint again instead of the restored old DB. With a deterministic failure
> it fails again with the same error.
> h3. Trigger
> # A follower SCM installs a checkpoint that RocksDB opens but a service
> rejects in {{startServices}}. Examples: a damaged data block in a table that
> a service reads by key, a failed precondition in a service's
> {{reinitialize}}, or (as in the reproduction) an apparent layout version this
> software does not know.
> # The rollback runs.
> h3. Impact
> * In production {{exitSystem(1)}} in the {{finally}} block terminates the
> process right after the rollback, so nothing serves the wrong state, and on
> restart {{scm.db}} holds the old DB. What remains is that the rollback
> reload, which is meant to check the old DB before terminating, checks the
> wrong DB, and that the open DB's directory is renamed under it: new RocksDB
> files of the open store would be created in the restored {{scm.db}} before
> the exit (argued, not observed).
> * Only with a test exit manager, which returns instead of terminating, does
> the SCM go on serving the rejected checkpoint, whose directory has been
> renamed, while {{scm.db}} on disk holds the old DB.
> h3. Reproduction
> PASS on the unmodified source. [^TestBugMC6RollbackKeepsCheckpointStore.java]
> ({{hadoop-ozone/integration-test}}) runs a one SCM mini cluster, takes a
> checkpoint of its DB, sets the checkpoint's apparent layout version one above
> the software version and its transaction info above the applied index,
> allocates a container and writes a marker key that only the current DB has,
> and installs the checkpoint through {{SCMStateMachine.pause}},
> {{setInstallingSnapshotData}} and {{reinitialize}}, with a counting exit
> manager. Output: {{exitSystem(1, Failed to reload SCM state and instantiate
> services.)}}; after the rollback {{the live store reads apparent version 101
> (checkpoint value 101), marker null, ContainerManager has #1: false}}, while
> {{restored DB on disk at scm.db has marker old and #1: true}}. A passing test
> means the defect is present.
> h3. Patch
> [^MC-6-close-scm-db-before-rollback-restore.patch], against
> b0aa6475b7856d2c7f467dd3db12b9a1dd116f63. It also applies to master at
> 52812559dad.
> The patch calls {{stopServices()}} (close the metadata store) in the rollback
> before the old DB is restored, so the rollback's reload opens the restored
> old DB. It is a no op when the failed reload never opened the store. The
> process still exits as before. With the patch the reproduction fails because
> after the rollback the live store and ContainerManager read the restored old
> DB (marker present, container #1 present).
> Covered by {{testRollbackAfterReloadFailureRestoresOldDB}} in the existing
> {{TestSCMInstallSnapshotWithHA}}. Without the change the rollback's own
> {{reloadSCMState}} throws "Initialization failed. Disk contains unknown
> apparent version 101 for software version ZDU (100)", because it reloaded the
> rejected checkpoint. With it {{TestSCMInstallSnapshotWithHA}} and
> {{TestSCMInstallSnapshot}} (6 tests), {{TestSCMHAManagerImpl}} and
> {{TestSCMStateMachine}} (18 tests) pass and checkstyle is clean.
> Found by TLA+ model checking and code review of the SCM Ratis snapshot and
> checkpoint install paths under HDDS-15926, on commit
> b0aa6475b7856d2c7f467dd3db12b9a1dd116f63. 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]