> This patch establishes fields within the vm_area_struct type to store the > virtual page offset of VMAs. > > The virtual page offset of a VMA is equal to vma->vm_start >> PAGE_SHIFT if > they are unfaulted or were not remapped, otherwise it is equal to this > value at the point of first fault. > > Currently, anonymous folios belonging to CoW'd MAP_PRIVATE-mapped > file-backed VMAs are tracked by their file offset. By adding virtual offset > as a property of VMAs, we can now track them by their virtual page offset > instead. > > By tracking this, we provide the means by which to eliminate this > inconsistency, and more importantly lay the foundations for future work for > the scalable CoW anonymous rmap rework. > > This patch simply adds the fields and some simple helpers. Subsequent > patches will update mm code to make use of these fields correctly. > > The fields chosen are packed in the VMA such that, for 64-bit kernel > builds, no additional space is taken up.
It is not necessarily true that no additional memory will be consumed, as it depends on whether the baseline kernel has CONFIG_PER_VMA_LOCK enabled. Moreover, in the future evolution of mm, maintaining this benefit would require that the layout of struct vm_area_struct before __vm_virt_pgoff_lo remains unchanged, which seems impractical. My personal suggestion is: maybe we could simply add an unsigned long field, say vm_virt_pgoff, without worrying about the increased memory footprint for now. Additionally, it would be helpful to add some comments clarifying the difference between this new field and the existing vm_pgoff, to aid understanding. Thanks, Xu Xin > > The first field is present on cacheline 0 containing key VMA fields, and > the second on cacheline 3, which contains file-backed reverse mapping > fields. > > > Signed-off-by: Lorenzo Stoakes (ARM) <[email protected]> > --- > include/linux/mm.h | 59 > +++++++++++++++++++++++++++++++++++++++++ > include/linux/mm_types.h | 4 +++ > mm/vma.h | 14 ++++++++++ > mm/vma_init.c | 1 + > tools/testing/vma/include/dup.h | 26 ++++++++++++++++++ > 5 files changed, 104 insertions(+) > > +static inline pgoff_t vma_last_virt_pgoff(const struct vm_area_struct *vma) > +{ > + return vma_end_virt_pgoff(vma) - 1; > +} > + > static inline unsigned long vma_desc_size(const struct vm_area_desc *desc) > { > return desc->end - desc->start; > diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h > index 939b5ea8c9e0..2710628059b1 100644 > --- a/include/linux/mm_types.h > +++ b/include/linux/mm_types.h > @@ -967,6 +967,7 @@ struct vm_area_struct { > */ > unsigned int vm_lock_seq; > #endif > + unsigned int __vm_virt_pgoff_lo; /* Low 32-bits of virtual pgoff. */ > /* > * A file's MAP_PRIVATE vma can be in both i_mmap tree and anon_vma > * list, after a COW of one of the file pages. A MAP_SHARED vma > @@ -1041,6 +1042,9 @@ struct vm_area_struct { > #ifdef CONFIG_DEBUG_LOCK_ALLOC > struct lockdep_map vmlock_dep_map; > #endif > +#endif > +#ifdef CONFIG_64BIT > + unsigned int __vm_virt_pgoff_hi; /* High 32-bits of virtual pgoff. */ > #endif >

