Siyao Meng created HDDS-17019:
---------------------------------
Summary: Failure of a datanode DB volume is not propagated to the
data volumes whose RocksDB it holds, so they stay in service
Key: HDDS-17019
URL: https://issues.apache.org/jira/browse/HDDS-17019
Project: Apache Ozone
Issue Type: Bug
Reporter: Siyao Meng
Attachments: MC-4-fail-data-volumes-of-failed-db-volume.patch,
TestBugMC4DbVolumeFailureNotPropagated.java
h3. Mechanism
With {{hdds.datanode.container.db.dir}} set, the schema V3 RocksDB of each data
volume lives on a separate DB volume. {{OzoneContainer}} registers a failed
volume listener only on the data volume set; the DB volume set has none. When
the periodic check fails a DB volume, {{DbVolume.failVolume}} closes and
uncaches the DB stores below it, but the data volumes that use it are left
NORMAL: they keep their containers, are reported to SCM as healthy and are
still chosen for new containers. {{DatanodeStoreCache.getDB}} reopens a store
that is not cached on its next access, so those data volumes go on using a
RocksDB on the failed DB volume.
{{HddsVolume.check}} only checks that the data volume's own RocksDB files can
be read and opened. It does not look at the DB volume's state, so a DB volume
that fails its own check while those files stay readable (its root directory no
longer writable, as reproduced here, or a file system remounted read only after
errors) leaves the data volumes in service. A DB disk that becomes unreadable
is already caught by each data volume's own check.
h3. Trigger
# A datanode with two or more DB volumes. With a single DB volume the datanode
already shuts down when it fails, because the default
{{hdds.datanode.failed.db.volumes.tolerated}} of -1 requires one healthy DB
volume.
# A DB volume fails its periodic disk check while the RocksDB files on it stay
readable.
No client action is involved.
h3. Impact
* The data volumes whose DB is on the failed DB volume stay in service until
the datanode restarts. SCM is not told and their containers are not
re-replicated.
* New containers are placed on those data volumes and their block metadata is
written to the RocksDB that the cache reopened on the failed DB volume. In the
reproduction the DB files themselves are still writable, so those writes
succeed. On a file system remounted read only the reopen or the writes would
fail instead (argued from the code, not run).
h3. Reproduction
PASS, deterministic, unmodified source, needs a POSIX file system and a non
root user. [^TestBugMC4DbVolumeFailureNotPropagated.java]
({{hadoop-hdds/container-service}}) starts a real {{OzoneContainer}} with two
data volumes and two DB volumes; one data volume has its RocksDB on a DB
volume, the other on itself. The root directory of that DB volume is made read
only and the real {{StorageVolumeChecker}} fails it through
{{MutableVolumeSet.checkAllVolumes}}. The data volume set check that follows
passes, because the RocksDB files stay readable. The data volume stays NORMAL
with its DB loaded, a new container is placed on it with the round robin
policy, its block is committed to a DB file under the failed DB volume, and the
node report shows the data volume as not failed. A passing test means the
defect is present.
h3. Patch
[^MC-4-fail-data-volumes-of-failed-db-volume.patch], against
cce1ca28944886218132f01c0e271c1fd0700078. It also applies to master at
2536fe9cbc3.
{{OzoneContainer}} registers a failed volume listener on the DB volume set. It
collects the active data volumes whose DB volume has failed and passes them to
{{MutableVolumeSet.handleVolumeFailures}} of the data volume set (made public
for this), which is the existing path for a failed data volume: it marks them
failed, closes their DBs, applies
{{hdds.datanode.failed.data.volumes.tolerated}} and runs the data set listener
that removes their containers and sends a full container report. The listener
runs after the DB set has released its lock, so no locks are nested. Checking
the DB volume from {{HddsVolume.check}} instead would only act in the next
periodic check, because data volumes are checked before DB volumes in each
cycle.
This changes behaviour on purpose, on nodes with two or more DB volumes: losing
a DB disk now fails every data volume whose DB is on it, their containers are
re-replicated, and if that exceeds the tolerated number of failed data volumes
the datanode shuts down, as for any other data volume loss.
Not covered: a DB volume that fails {{StorageVolumeUtil.checkVolume}} during
the SCM version handshake at startup. {{VersionEndpointTask}} fails it directly
through {{MutableVolumeSet.failVolume}} while holding the DB set lock, so the
listener does not run there, and the data volumes whose DB was already loaded
on it stay in service. Covering it would need a separate check in that task.
Covered by {{testDbVolumeFailureFailsDataVolumesWithDbOnIt}} in the existing
{{TestOzoneContainer}}, with three data volumes whose RocksDB is on the failing
DB volume, on the other DB volume and on the data volume itself. Without the
change it fails because no data volume is failed; it also fails if every data
volume with a DB volume is failed. With it the {{TestOzoneContainer}}, volume,
DB volume, volume checker and volume health check suites (138 tests) and
{{TestOzoneContainerWithTLS}}, an integration test that starts a real
{{OzoneContainer}} with a DB volume configured, pass, and checkstyle is clean.
With the patch the reproduction fails because the data volume is FAILED.
Found by TLA+ model checking and code review of the datanode volume and
per-disk RocksDB lifecycle paths under HDDS-15926, on commit
cce1ca28944886218132f01c0e271c1fd0700078. Checked against HDDS issues and
apache/ozone pull requests for duplicates before filing. Related but not
duplicates: HDDS-6616 and HDDS-6541, which added the DB volume check and the
separate DB location. 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]