Re: [PATCH 09/16] mm/shmem: preserve data in clean folios when splitting fails
From: David Hildenbrand (Arm)
Date: Tue Oct 27 2026 - 06:48:41 EST
On 10/26/26 18:12, Kiryl Shutsemau wrote:
> On Mon, Oct 26, 2026 at 10:40:42AM +0100, David Hildenbrand (Arm) wrote:
>> From: Chris Mason <mason@xxxxxxxxxx>
>>
>> A shared writable mapping can have dirty PTEs while its shmem folio is
>> still clean. A read fault can install a writable PTE, and a later store
>> sets the PTE's dirty bit without marking the folio dirty.
>>
>> After shmem_undo_range() has handled the boundary folios, a concurrent
>> read fault into a hole below the new EOF can allocate a large folio.
>> For example, on a tmpfs mount with huge=always, the fault's offset must
>> be within the file, but the allocated folio can extend beyond i_size.
>> The final scan then finds this folio and calls
>> truncate_inode_partial_folio() without marking it dirty.
>
> This is hard to follow. I asked LLM for a diagram. I think it would be
> helpful for the commit message:
>
> CPU0: ftruncate(fd, 3M) CPU1: MAP_SHARED, tmpfs huge=always
> ───────────────────────────────────── ──────────────────────────────────
> i_size = 3M
> shmem_undo_range(3M, -1)
> first pass: hole, nothing to do
> boundary folio at 3M: hole, none
> read fault at 2M+x (below EOF)
> PMD folio [2M,4M), crosses EOF
> writable PTE, folio clean
> store to 2M+x
> PTE dirty, folio still clean
> vmsplice(2M+x)
> extra folio reference
> whole_folios: finds [2M,4M) folio
> truncate_inode_partial_folio()
> zero [3M,4M)
> folio_split()
> unmap_folio(): extra ref
> → -EAGAIN, PTE dirty bit
> never reaches the folio
> folio clean
> → truncate_inode_folio(whole)
> [2M,3M) dropped
> read 2M+x → refault → zeroes
>
I'll add it, thanks!
--
Cheers,
David