[
https://issues.apache.org/jira/browse/HDDS-17369?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
]
Meng-Shuan Tsai reassigned HDDS-17369:
--------------------------------------
Assignee: Meng-Shuan Tsai
> Mapped chunk read that fails on a later piece releases the quota of earlier
> pieces a second time, raising the effective mmap limit until restart
> ------------------------------------------------------------------------------------------------------------------------------------------------
>
> Key: HDDS-17369
> URL: https://issues.apache.org/jira/browse/HDDS-17369
> Project: Apache Ozone
> Issue Type: Bug
> Affects Versions: 2.0.0, 2.1.0, 2.2.0, 2.1.1, 2.1.2, 2.2.1
> Reporter: Siyao Meng
> Assignee: Meng-Shuan Tsai
> Priority: Major
> Attachments:
> MC-2-release-only-unsettled-quota-on-failed-mapped-read.patch
>
>
> h3. Mechanism
> The mapped branch of {{ChunkUtils.readData}} reserves one permit per piece
> with {{MappedBufferManager.getQuota(bufferNum)}}. Each piece then settles its
> own permit in {{MappedBufferManager.computeIfAbsent}}: a cache hit releases
> it at once, a miss hands it to the new cache entry, which the cleanup in
> {{getQuota}} reclaims after GC has cleared it. When a later piece fails to
> map, the failure handler calls {{releaseQuota(bufferNum)}} and so releases
> the permits of the pieces that already settled a second time. The quota
> {{Semaphore}} has no ceiling, so the extra permits stay.
> h3. Trigger
> # Mapped reads are enabled ({{ozone.chunk.read.mapped.buffer.max.count}} > 0,
> default 0).
> # A read is served from the mapped path, which needs a buffer capacity above
> {{ozone.chunk.read.mapped.buffer.threshold}} (32KB). The default 16KB per
> checksum does not reach it.
> # The read is split into several pieces, and a later piece fails to map after
> an earlier one has settled, for example because the block file on disk is
> shorter than the chunk being read, or because the map call fails.
> h3. Impact
> * Each such failure raises the effective mmap limit of the manager by the
> number of pieces that settled before it, and the limit stays raised until the
> datanode restarts. The configured value of
> {{ozone.chunk.read.mapped.buffer.max.count}} does not change.
> * More mappings can then be live at the same time than {{max.count}} allows:
> at once for pieces that were cache hits, and for newly mapped pieces after GC
> and the cleanup have reclaimed their entries.
> * That limit was added in HDDS-10488 to keep the datanode from running out of
> map areas. What running out would do here is argued from that issue, not run.
> h3. Reproduction
> No standalone reproduction is attached. The regression test in the patch,
> {{TestChunkUtils#testFailedMappedReadReleasesOnlyUnsettledQuota}}, covers it:
> it calls {{ChunkUtils.readData}} directly with a buffer capacity of 64KB,
> above the threshold, on a block file that holds one piece, and checks the
> quota after a failed two piece read in three cases: first piece a cache hit,
> no piece mapped, first piece newly mapped. On unmodified source it fails in
> the cache hit case with {{expected: <3> but was: <4>}}.
> h3. Patch
> [^MC-2-release-only-unsettled-quota-on-failed-mapped-read.patch], against
> 5fed99dab3c3204cd7bf1516074969a38d5eb00d. It also applies to master at
> 76b5c6947a2.
> The list of mapped pieces is declared before the {{try}}, and the failure
> handler releases only {{bufferNum - buffers.size()}} permits. A piece is
> added to that list only after {{computeIfAbsent}} returned it, that is after
> it settled its permit. A failure before the first piece still releases all
> permits, a failure after the last piece releases none, and successful reads
> are unchanged.
> With the patch {{TestMappedBufferManager}} (1 test), {{TestChunkUtils}} (7),
> {{TestFilePerBlockStrategy}} (21), {{TestFilePerChunkStrategy}} (17),
> {{TestChunkManagerDummyImpl}} (2), {{TestKeyValueHandler}} (43) and
> {{TestKeyValueHandlerWithUnhealthyContainer}} (68) pass, 159 tests in total,
> and checkstyle on {{hadoop-hdds/container-service}} is clean. It does not
> conflict with the patches for the two related quota accounting issues in
> {{MappedBufferManager}} found in the same review (HDDS-17368, a replaced
> cleared cache entry, and HDDS-17367, the cache map shared by both chunk
> layouts).
> The defect is in every release from 2.0.0 to 2.2.1. It came in with
> HDDS-10488, which added the mapped read path.
> Found by TLA+ model checking and code review of the datanode memory mapped
> chunk read path under HDDS-15926, on commit
> 5fed99dab3c3204cd7bf1516074969a38d5eb00d. Checked against HDDS issues and
> apache/ozone PRs for duplicates before filing. Related but not duplicates:
> HDDS-10488 (introduced the mapped read path and its limit), HDDS-15357 (other
> quota races in {{MappedBufferManager}}). The attached patch is a proposal for
> review. Generated with Specula (Claude Opus 5.5).
--
This message was sent by Atlassian Jira
(v10.3.26#10030026)
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]