Siyao Meng created HDDS-17367:
---------------------------------

             Summary: MappedBufferManager cleanup returns quota of the other 
chunk layout's cached mappings because the mapping map is static
                 Key: HDDS-17367
                 URL: https://issues.apache.org/jira/browse/HDDS-17367
             Project: Apache Ozone
          Issue Type: Bug
            Reporter: Siyao Meng
         Attachments: MC-3-per-instance-mapped-buffer-map.patch, 
TestBugMC3CleanupCreditsOtherManager.java

h3. Mechanism
{{MappedBufferManager.mappedBuffers}} is a static field, while the quota 
{{Semaphore}} belongs to each instance. Each datanode builds two instances, one 
in {{FilePerChunkStrategy}} and one in {{FilePerBlockStrategy}}, each with the 
full {{ozone.chunk.read.mapped.buffer.max.count}}. The cleanup in 
{{MappedBufferManager.getQuota}} walks the shared map and returns the permit of 
every cleared entry to the instance that ran it, including entries the other 
instance created. The two strategies read different files, so the shared map 
gives no cache reuse.

h3. Trigger
A datanode with mmap reads enabled 
({{ozone.chunk.read.mapped.buffer.max.count}} > 0, default 0) that serves 
memory mapped reads for both FILE_PER_CHUNK and FILE_PER_BLOCK containers. 
Reads are memory mapped only when the read buffer capacity is above 
{{ozone.chunk.read.mapped.buffer.threshold}} (32KB), so data written with the 
default 16KB per checksum is never mapped; chunks written with checksum type 
NONE or with more than 32KB per checksum, and reads into a single buffer, are. 
FILE_PER_BLOCK is the default container layout, so this needs a datanode that 
still holds FILE_PER_CHUNK containers. A mapping of one strategy is cleared by 
GC, and the other strategy runs out of quota and runs its cleanup.

h3. Impact
The strategy that ran the cleanup can hold more live mappings than its limit, 
while the other can be left with neither quota nor mappings and serves its 
reads from heap buffers until permits move back. The total over both instances 
stays within twice {{max.count}}, which the datanode already allows today, so 
the limit is not exceeded for the datanode as a whole. The effect is on 
performance only. The static map is also shared by all datanodes in one JVM, 
for example in mini cluster tests.

h3. Reproduction
PASS on unmodified source, which means the defect is present. 
[^TestBugMC3CleanupCreditsOtherManager.java] 
({{hadoop-hdds/container-service}}) builds two managers of capacity 1, one per 
strategy, and reads through {{ChunkUtils.readData}}: after the chunk manager's 
mapping is cleared, the block manager's cleanup reclaims its permit, the block 
manager then holds 2 live mappings with limit 1, and the chunk manager has 
quota 0 with no live mapping. With the patch the block manager's cleanup 
reclaims nothing and the test fails ({{expected: 1 but was: 0}}).

h3. Patch
[^MC-3-per-instance-mapped-buffer-map.patch], against 
5fed99dab3c3204cd7bf1516074969a38d5eb00d. It also applies to master at 
76b5c6947a2.

{{mappedBuffers}} becomes an instance field, so each cleanup reclaims only the 
entries of its own manager. Datanodes that serve one layout behave as before. 
One shared manager per datanode would match the description of {{max.count}} 
("allowed for a DN") but would halve the effective limit for datanodes that 
serve both layouts, so it is left as a separate question.

Covered by {{TestMappedBufferManager#testCleanupReturnsOnlyOwnQuota}}, which 
fails without the change ({{expected: <1> but was: <2>}}). With it, 
{{TestMappedBufferManager}}, {{TestChunkUtils}}, {{TestFilePerBlockStrategy}}, 
{{TestFilePerChunkStrategy}}, {{TestChunkManagerDummyImpl}} and the 
{{TestKeyValueHandler}} suites pass (159 tests), checkstyle is clean.

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 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
(v10.3.26#10030026)

---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to