The implementation review of this round's public fixes found one gap in
the code and four in the tests.
- A refused expiry was traced with its reason but without its error,
so the trace did not say what refused it. It now carries the error, as
a failed one does.
- The restore MRF test replaced the live MRF channel, which the heal
routines of the test servers read: a race, and a consumer could take
the entry under test. addPartialOp now offers an atomic hook that
receives the operation in place of the queue. Production never sets
it.
- Two fixtures restored the storage class with Update, which marks an
uninitialized configuration initialized and so changes the default
parity (-1) into an explicit 0 for later tests.
setTestStandardParity restores the whole saved value under
storageclass.ConfigLock.
- The v3 metric test built its own descriptor map, so dropping the
counter from the registered ILM collector still passed. It gathers
through the collector the handler registers.
- The audit test read one extra entry or waited 500 ms. It drains every
entry of the bucket up to the removal audited last, and checks one
failure audit, one removal audit and no refusal audit per object.
Each corrected test fails with the corresponding mutation.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Feng Ruohang <rh@vonng.com>
Earlier tests can leave a storage class of parity 0 behind (newTestConfig
on a single drive), and a version written without parity cannot be
rebuilt on the drive the tests heal. Set the parity of the test pools'
sets for the duration of each drive heal test, as other tests that
depend on parity do.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Feng Ruohang <rh@vonng.com>
Drive healing evaluates lifecycle on the versions of one pool. For a
version it found due it enqueued the expiry and skipped the heal. The
expiry is decided again under the object lock, with the versions in all
pools and the Object Lock state it reads then, and can be refused: a
newer version in another pool, an unreadable history, a changed rule,
or a delete-all the exact-key purge refuses. Such a version was never
healed onto the replaced drive and kept reduced redundancy for as long
as the refusal lasted. The scanner heals only versions without a due
action, so it did not repair it either.
Keep the enqueue and heal the version. A version that the expiry then
removes costs one heal. Heal and expiry exclude each other through the
object lock in the writers' lock domain, which the single-pool lock
domain change provides; a version removed first reads as not found and
is skipped, and heal rebuilds only from read-quorum metadata, so it does
not bring back a version deleted on a write quorum.
Tests: a version refused across pools is healed onto the replaced drive
and survives the expiry; an unversioned object due is healed and then
removed from every drive; a versioned latest version due is healed and
hidden by a marker; a stale minority is not recreated. The first three
fail without the change.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Feng Ruohang <rh@vonng.com>