Siyao Meng created HDDS-16823:
---------------------------------

             Summary: OMRecoverLeaseRequest calls SCM and generates block 
tokens in validateAndUpdateCache, so applying RecoverLease depends on SCM
                 Key: HDDS-16823
                 URL: https://issues.apache.org/jira/browse/HDDS-16823
             Project: Apache Ozone
          Issue Type: Bug
            Reporter: Siyao Meng
         Attachments: CR-1-move-recover-lease-scm-call-out-of-apply.patch

h3. Mechanism
{{OMRecoverLeaseRequest.validateAndUpdateCache}} runs on the OM state machine 
apply thread of every OM. Through {{doWork}} and {{updateBlockInfo}} it calls 
{{getContainerWithPipeline}} on SCM, up to three times (last block of the file, 
last two blocks of the open file), while holding the bucket write lock. The 
pipelines, and the block tokens generated next to them, are only put into the 
reply for the recovering client. They are never written to the OM DB.

An {{IOException}} from the SCM call is not an {{OMException}}, so 
{{OzoneManagerRatisUtils.exceptionToResponseStatus}} turns it into 
{{INTERNAL_ERROR}}, which {{OzoneManagerStateMachine.processResponse}} treats 
as an unrecoverable error of the OM. The request is a replicated log entry, so 
every OM that applies it makes the same call. {{RecoverLease}} is the only OM 
write request that calls SCM from {{validateAndUpdateCache}}. Block allocation 
and upgrade finalization call it from {{preExecute}} on the leader.

HDDS-10626 was an earlier OM shutdown from the same method (block token 
generation while a {{RecoverLease}} entry was applied) and was fixed by 
changing the startup order, which left both calls in the apply path.

h3. Trigger
A {{RecoverLease}} entry is applied while {{getContainerWithPipeline}} fails 
with an exception that is not an {{OMException}}.

h3. Impact
* The entry is answered with {{INTERNAL_ERROR}} and the state machine 
terminates the OM, on each OM that applies it. The status is shown by the 
regression test below. What the state machine does with that status is from 
reading {{processResponse}}.
* Without any failure, each OM's single apply thread waits for up to three SCM 
calls with the bucket write lock held, so no other write is applied on that OM 
in the meantime.

h3. Reproduction
There is no standalone reproduction for this issue. The regression test in the 
attached patch covers it: on unmodified source the apply level part of 
{{TestOMRecoverLeaseRequest.testScmFailureDoesNotFailApply}} (a mocked SCM 
client that throws {{IOException}}) fails with "expected: <OK> but was: 
<INTERNAL_ERROR>".

h3. Patch
[^CR-1-move-recover-lease-scm-call-out-of-apply.patch], against 
ea69b4a7d9abd040e5259dbcbb7c6ce52eb5d199. It also applies to master at 
84f5594a6a2.

{{validateAndUpdateCache}} no longer talks to SCM or generates block tokens. 
The leader adds both to the reply in 
{{OzoneManagerProtocolServerSideTranslatorPB.internalProcessRequest}}, after 
the request has been applied and outside any OM lock, in the same place where 
the S3 derived key is already added to a {{CreateKey}} reply. If the SCM call 
fails there, the caller gets {{SCM_GET_PIPELINE_EXCEPTION}} (the code 
{{KeyManagerImpl}} already uses for a failed pipeline refresh). The file is 
then already marked as under recovery, and a later {{recoverLease}} call 
continues from there, as a second recovery of the same file does today.

There is no wire or protocol change, and entries already in the log are applied 
as before, without the SCM call. Two side effects. The block token is now 
issued for the calling user, as it is for block allocation, instead of the OM's 
own user (the apply thread has no RPC caller). And the SCM call still blocks 
its caller for as long as the SCM client takes, but on the RPC handler thread 
of the leader only, not on the apply thread and not under the bucket lock.

Covered by {{testPipelinesAreAddedAfterApply}} and 
{{testScmFailureDoesNotFailApply}} in the existing 
{{TestOMRecoverLeaseRequest}}. With the patch {{TestOMRecoverLeaseRequest}}, 
{{TestOpenKeyCleanupService}} and {{TestOMKeyCommitRequestWithFSO}} (48 tests) 
pass and checkstyle is clean. On a mini cluster {{TestHSync}} (42), 
{{TestSecureOzoneRpcClient}} (241, block tokens enabled) and {{TestOFSWithFSO}} 
(73, 9 skipped) pass.

Found by code review of the lease recovery paths for hsynced files, as part of 
the TLA+ verification effort under HDDS-15926, on commit 
ea69b4a7d9abd040e5259dbcbb7c6ce52eb5d199. Checked against HDDS issues and 
apache/ozone pull requests for duplicates before filing. Related but not 
duplicates: HDDS-10626 (earlier shutdown from the same method), HDDS-16767 
(wall clock read while the same request is applied). 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