Re: [PATCH 17/30] mm: prefer vma_[start,end]_pgoff() to vma->vm_pgoff in kernel/
Lorenzo Stoakes <[email protected]> Thu, 2 Jul 2026 12:30:59 +0100
| Newsgroups | org.kernel.vger.linux-sgx,dev.linux.lists.damon,dev.linux.lists.iommu,dev.linux.lists.nvdimm,org.freedesktop.lists.dri-devel,org.kernel.vger.kvm,org.kernel.vger.linux-arm-msm,org.kernel.vger.linux-fsdevel,org.kernel.vger.linux-kernel,org.kernel.vger.linux-parisc,org.kernel.vger.linux-perf-users,org.kernel.vger.linux-tegra,org.kernel.vger.linux-trace-kernel |
|---|---|
| Message-ID | <akZGqclqQ6gS12Vv@lucifer> |
On Thu, Jul 02, 2026 at 12:01:37PM +0100, Pedro Falcato wrote: > On Mon, Jun 29, 2026 at 01:23:28PM +0100, Lorenzo Stoakes wrote: > > Be consistent in using vma_start_pgoff() and vma_end_pgoff(), which clearly > > indicates which part of the VMA the page offset refers to and aids > > greppability. > > > > This is part of a broader series laying the ground to provide a virtual > > page offset for MAP_PRIVATE-file backed anon folios. > > > > No functional change intended. > > > > Signed-off-by: Lorenzo Stoakes <[email protected]> > > --- > > kernel/dma/coherent.c | 7 ++++--- > > kernel/dma/direct.c | 6 ++++-- > > kernel/dma/mapping.c | 8 +++++--- > > kernel/dma/ops_helpers.c | 4 ++-- > > kernel/events/core.c | 20 +++++++++++--------- > > kernel/events/uprobes.c | 11 +++++++---- > > kernel/kcov.c | 2 +- > > kernel/trace/ring_buffer.c | 3 ++- > > 8 files changed, 36 insertions(+), 25 deletions(-) > > > > diff --git a/kernel/dma/coherent.c b/kernel/dma/coherent.c > > index bcdc0f76d2e8..2d3195eb7e83 100644 > > --- a/kernel/dma/coherent.c > > +++ b/kernel/dma/coherent.c > > @@ -236,14 +236,15 @@ static int __dma_mmap_from_coherent(struct dma_coherent_mem *mem, > > { > > if (mem && vaddr >= mem->virt_base && vaddr + size <= > > (mem->virt_base + ((dma_addr_t)mem->size << PAGE_SHIFT))) { > > - unsigned long off = vma->vm_pgoff; > > + const pgoff_t pgoff_start = vma_start_pgoff(vma); > > + const pgoff_t pgoff_end = vma_end_pgoff(vma); > > int start = (vaddr - mem->virt_base) >> PAGE_SHIFT; > > unsigned long user_count = vma_pages(vma); > > int count = PAGE_ALIGN(size) >> PAGE_SHIFT; > > > > *ret = -ENXIO; > > - if (off < count && user_count <= count - off) { > > - unsigned long pfn = mem->pfn_base + start + off; > > + if (pgoff_start < count && pgoff_end <= count) { > > + unsigned long pfn = mem->pfn_base + start + pgoff_start; > > *ret = remap_pfn_range(vma, vma->vm_start, pfn, > > user_count << PAGE_SHIFT, > > vma->vm_page_prot); > > diff --git a/kernel/dma/direct.c b/kernel/dma/direct.c > > index 4391b797d4db..436310d6e4a2 100644 > > --- a/kernel/dma/direct.c > > +++ b/kernel/dma/direct.c > > @@ -534,6 +534,8 @@ int dma_direct_mmap(struct device *dev, struct vm_area_struct *vma, > > unsigned long user_count = vma_pages(vma); > > unsigned long count = PAGE_ALIGN(size) >> PAGE_SHIFT; > > unsigned long pfn = PHYS_PFN(dma_to_phys(dev, dma_addr)); > > + const pgoff_t pgoff_start = vma_start_pgoff(vma); > > + const pgoff_t pgoff_end = vma_end_pgoff(vma); > > int ret = -ENXIO; > > > > vma->vm_page_prot = dma_pgprot(dev, vma->vm_page_prot, attrs); > > @@ -545,9 +547,9 @@ int dma_direct_mmap(struct device *dev, struct vm_area_struct *vma, > > if (dma_mmap_from_global_coherent(vma, cpu_addr, size, &ret)) > > return ret; > > > > - if (vma->vm_pgoff >= count || user_count > count - vma->vm_pgoff) > > + if (pgoff_start >= count || pgoff_end > count) > > return -ENXIO; > > - return remap_pfn_range(vma, vma->vm_start, pfn + vma->vm_pgoff, > > + return remap_pfn_range(vma, vma->vm_start, pfn + pgoff_start, > > user_count << PAGE_SHIFT, vma->vm_page_prot); > > } > > > > diff --git a/kernel/dma/mapping.c b/kernel/dma/mapping.c > > index 4fe04669e5e6..c986639044e9 100644 > > --- a/kernel/dma/mapping.c > > +++ b/kernel/dma/mapping.c > > @@ -761,12 +761,14 @@ EXPORT_SYMBOL_GPL(dma_free_pages); > > int dma_mmap_pages(struct device *dev, struct vm_area_struct *vma, > > size_t size, struct page *page) > > { > > - unsigned long count = PAGE_ALIGN(size) >> PAGE_SHIFT; > > + const pgoff_t pgoff_start = vma_start_pgoff(vma); > > + const pgoff_t pgoff_end = vma_end_pgoff(vma); > > + const unsigned long count = PAGE_ALIGN(size) >> PAGE_SHIFT; > > > > - if (vma->vm_pgoff >= count || vma_pages(vma) > count - vma->vm_pgoff) > > + if (pgoff_start >= count || pgoff_end > count) > > return -ENXIO; > > return remap_pfn_range(vma, vma->vm_start, > > - page_to_pfn(page) + vma->vm_pgoff, > > + page_to_pfn(page) + pgoff_start, > > vma_pages(vma) << PAGE_SHIFT, vma->vm_page_prot); > > } > > EXPORT_SYMBOL_GPL(dma_mmap_pages); > > diff --git a/kernel/dma/ops_helpers.c b/kernel/dma/ops_helpers.c > > index 20caf9cabf69..6b5f9208d31c 100644 > > --- a/kernel/dma/ops_helpers.c > > +++ b/kernel/dma/ops_helpers.c > > @@ -39,7 +39,7 @@ int dma_common_mmap(struct device *dev, struct vm_area_struct *vma, > > #ifdef CONFIG_MMU > > unsigned long user_count = vma_pages(vma); > > unsigned long count = PAGE_ALIGN(size) >> PAGE_SHIFT; > > - unsigned long off = vma->vm_pgoff; > > + unsigned long off = vma_start_pgoff(vma); > > struct page *page = dma_common_vaddr_to_page(cpu_addr); > > int ret = -ENXIO; > > > > @@ -52,7 +52,7 @@ int dma_common_mmap(struct device *dev, struct vm_area_struct *vma, > > return -ENXIO; > > > > return remap_pfn_range(vma, vma->vm_start, > > - page_to_pfn(page) + vma->vm_pgoff, > > + page_to_pfn(page) + vma_start_pgoff(vma), > > user_count << PAGE_SHIFT, vma->vm_page_prot); > > #else > > return -ENXIO; > > diff --git a/kernel/events/core.c b/kernel/events/core.c > > index 954c36e28101..d6d2d557ccb8 100644 > > --- a/kernel/events/core.c > > +++ b/kernel/events/core.c > > @@ -6998,7 +6998,7 @@ static void perf_mmap_open(struct vm_area_struct *vma) > > refcount_inc(&event->mmap_count); > > refcount_inc(&event->rb->mmap_count); > > > > - if (vma->vm_pgoff) > > + if (vma_start_pgoff(vma)) > > refcount_inc(&event->rb->aux_mmap_count); > > > > if (mapped) > > @@ -7032,7 +7032,7 @@ static void perf_mmap_close(struct vm_area_struct *vma) > > * The AUX buffer is strictly a sub-buffer, serialize using aux_mutex > > * to avoid complications. > > */ > > - if (rb_has_aux(rb) && vma->vm_pgoff == rb->aux_pgoff && > > + if (rb_has_aux(rb) && vma_start_pgoff(vma) == rb->aux_pgoff && > > refcount_dec_and_mutex_lock(&rb->aux_mmap_count, &rb->aux_mutex)) { > > /* > > * Stop all AUX events that are writing to this buffer, > > @@ -7190,7 +7190,8 @@ static int map_range(struct perf_buffer *rb, struct vm_area_struct *vma) > > */ > > for (pagenum = 0; pagenum < nr_pages; pagenum++) { > > unsigned long va = vma->vm_start + PAGE_SIZE * pagenum; > > - struct page *page = perf_mmap_to_page(rb, vma->vm_pgoff + pagenum); > > + struct page *page = perf_mmap_to_page(rb, > > + vma_start_pgoff(vma) + pagenum); > > > > if (page == NULL) { > > err = -EINVAL; > > @@ -7348,6 +7349,7 @@ static int perf_mmap_aux(struct vm_area_struct *vma, struct perf_event *event, > > u64 aux_offset, aux_size; > > struct perf_buffer *rb; > > int ret, rb_flags = 0; > > + const pgoff_t pgoff_start = vma_start_pgoff(vma); > > Variable decs here seem to be in reverse christmas tree order, so perhaps > move this to the top. Ack will change on respin. > > > > > rb = event->rb; > > if (!rb) > > @@ -7366,11 +7368,11 @@ static int perf_mmap_aux(struct vm_area_struct *vma, struct perf_event *event, > > if (aux_offset < perf_data_size(rb) + PAGE_SIZE) > > return -EINVAL; > > > > - if (aux_offset != vma->vm_pgoff << PAGE_SHIFT) > > + if (aux_offset != pgoff_start << PAGE_SHIFT) > > return -EINVAL; > > > > /* already mapped with a different offset */ > > - if (rb_has_aux(rb) && rb->aux_pgoff != vma->vm_pgoff) > > + if (rb_has_aux(rb) && rb->aux_pgoff != pgoff_start) > > return -EINVAL; > > > > if (aux_size != nr_pages * PAGE_SIZE) > > @@ -7400,7 +7402,7 @@ static int perf_mmap_aux(struct vm_area_struct *vma, struct perf_event *event, > > if (vma->vm_flags & VM_WRITE) > > rb_flags |= RING_BUFFER_WRITABLE; > > > > - ret = rb_alloc_aux(rb, event, vma->vm_pgoff, nr_pages, > > + ret = rb_alloc_aux(rb, event, pgoff_start, nr_pages, > > event->attr.aux_watermark, rb_flags); > > if (ret) { > > refcount_dec(&rb->mmap_count); > > @@ -7457,7 +7459,7 @@ static int perf_mmap(struct file *file, struct vm_area_struct *vma) > > if (event->state <= PERF_EVENT_STATE_REVOKED) > > return -ENODEV; > > > > - if (vma->vm_pgoff == 0) > > + if (!vma_start_pgoff(vma)) > > ret = perf_mmap_rb(vma, event, nr_pages); > > else > > ret = perf_mmap_aux(vma, event, nr_pages); > > @@ -9884,7 +9886,7 @@ static bool perf_addr_filter_vma_adjust(struct perf_addr_filter *filter, > > struct perf_addr_filter_range *fr) > > { > > unsigned long vma_size = vma->vm_end - vma->vm_start; > > - unsigned long off = vma->vm_pgoff << PAGE_SHIFT; > > + unsigned long off = vma_start_pgoff(vma) << PAGE_SHIFT; > > struct file *file = vma->vm_file; > > > > if (!perf_addr_filter_match(filter, file, off, vma_size)) > > @@ -9974,7 +9976,7 @@ void perf_event_mmap(struct vm_area_struct *vma) > > /* .tid */ > > .start = vma->vm_start, > > .len = vma->vm_end - vma->vm_start, > > - .pgoff = (u64)vma->vm_pgoff << PAGE_SHIFT, > > + .pgoff = (u64)vma_start_pgoff(vma) << PAGE_SHIFT, > > }, > > /* .maj (attr_mmap2 only) */ > > /* .min (attr_mmap2 only) */ > > diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c > > index f23cebacbc6d..244651380ca1 100644 > > --- a/kernel/events/uprobes.c > > +++ b/kernel/events/uprobes.c > > @@ -144,12 +144,14 @@ static bool valid_vma(struct vm_area_struct *vma, bool is_register) > > > > static unsigned long offset_to_vaddr(struct vm_area_struct *vma, loff_t offset) > > { > > - return vma->vm_start + offset - ((loff_t)vma->vm_pgoff << PAGE_SHIFT); > > + return vma->vm_start + offset - > > + ((loff_t)vma_start_pgoff(vma) << PAGE_SHIFT); > > } > > > > static loff_t vaddr_to_offset(struct vm_area_struct *vma, unsigned long vaddr) > > { > > - return ((loff_t)vma->vm_pgoff << PAGE_SHIFT) + (vaddr - vma->vm_start); > > + return ((loff_t)vma_start_pgoff(vma) << PAGE_SHIFT) + > > + (vaddr - vma->vm_start); > > } > > Something we've seen in this series is that perhaps something like > > static inline loff_t vma_start_off(vma) > { > return ((loff_t) vma_start_pgoff(vma)) << PAGE_SHIFT; > } > > could be worth it. Yeah I already thought about this kind of thing, but in the end decided against it at least for now, maybe I could revisit with something like that added though... But given this series is being held off on already for acceptance, I'm not sure adding _yet more_ changes will be welcomed. Plus I worry people will get confused. There's 2 forms I noticed: 1. effectively: linear_page_index(vma, address) << PAGE_SHIFT I wanted to rewrite this as such, but you can't, because of course vaddr might have non-page aligned bits (or tags) that you lose by doing that. So ugh. You'd then need to write a slightly nuanced version like: static inline unsigned long vma_offset(const struct vm_area_struct *vma, const unsigned long address) { /* Retains page offset and tags. */ return address - vma->vm_start; } static inline unsigned long linear_page_offset(const struct vm_area_struct *vma, const unsigned long address) { const unsigned long addr = vma_start_pgoff(vma) << PAGE_SHIFT; addr += linear_delta(vma, address); return addr; } (Could also do:) static inline pgoff_t linear_page_delta(const struct vm_area_struct *vma, const unsigned long address) { return vma_offset(vma, address) >> PAGE_SHIFT; } BUT. I think this will confuse people. I already in a previous version of this series named linear_page_delta() as linear_page_offset() and then changed it to avoid confusion. And I'm not sure it's really all that useful. Perhaps retaining vma_offset() would be though. 2. This is a much more useful form I noticed, effectively drivers doing the inverse of a linear_page_index() to get the address: static inline unsigned long linear_page_address(const struct vm_area_struct *vma, const pgoff_t pgoff) { const pgoff_t page_delta = pgoff - vma_start_pgoff(vma); const unsigned long offset = page_delta << PAGE_SHIFT; return vma->vm_start + offset; } This is one that I think makes more sense. But in general, I'd rather hold off from yet more churn here. I'm making these changes to establish a basis for virtual page offsets introduced in [0], rather than just cleaning up in general. These changes are really to make it such that we more consistently use these forms, so when I introduce the virt pgoff versions, it fits canonically into that. And also beacuse I may as well improve kernel code as I go :) But I think adding yet more doesn't really serve the same purpose. But it's food for a follow up perhaps? > > > > > /** > > @@ -1482,7 +1484,7 @@ static int unapply_uprobe(struct uprobe *uprobe, struct mm_struct *mm) > > file_inode(vma->vm_file) != uprobe->inode) > > continue; > > > > - offset = (loff_t)vma->vm_pgoff << PAGE_SHIFT; > > + offset = (loff_t)vma_start_pgoff(vma) << PAGE_SHIFT; > > if (uprobe->offset < offset || > > uprobe->offset >= offset + vma->vm_end - vma->vm_start) > > continue; > > @@ -2453,7 +2455,8 @@ static struct uprobe *find_active_uprobe_speculative(unsigned long bp_vaddr) > > if (!vm_file) > > return NULL; > > > > - offset = (loff_t)(vma->vm_pgoff << PAGE_SHIFT) + (bp_vaddr - vma->vm_start); > > + offset = (loff_t)(vma_start_pgoff(vma) << PAGE_SHIFT) + > > + (bp_vaddr - vma->vm_start); > > This is more extremely contrived logic that could be better expressed as > > loff_t vma_linear_off(vma, bp_vaddr); See above. > > > uprobe = find_uprobe_rcu(vm_file->f_inode, offset); > > if (!uprobe) > > return NULL; > > diff --git a/kernel/kcov.c b/kernel/kcov.c > > index 1df373fb562b..b19b473c366a 100644 > > --- a/kernel/kcov.c > > +++ b/kernel/kcov.c > > @@ -512,7 +512,7 @@ static int kcov_mmap(struct file *filep, struct vm_area_struct *vma) > > > > spin_lock_irqsave(&kcov->lock, flags); > > size = kcov->size * sizeof(unsigned long); > > - if (kcov->area == NULL || vma->vm_pgoff != 0 || > > + if (kcov->area == NULL || vma_start_pgoff(vma) || > > as a nit, perhaps vma_start_pgoff(vma) > 0 > would be a little more idiomatic. I felt the if (<val>) form was more idiomatic? > > > vma->vm_end - vma->vm_start != size) { > > res = -EINVAL; > > goto exit; > > diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c > > index 56a328e94395..dfa493d54ef9 100644 > > --- a/kernel/trace/ring_buffer.c > > +++ b/kernel/trace/ring_buffer.c > > @@ -7613,7 +7613,8 @@ static int __rb_inc_dec_mapped(struct ring_buffer_per_cpu *cpu_buffer, > > static int __rb_map_vma(struct ring_buffer_per_cpu *cpu_buffer, > > struct vm_area_struct *vma) > > { > > - unsigned long nr_subbufs, nr_pages, nr_vma_pages, pgoff = vma->vm_pgoff; > > + unsigned long nr_subbufs, nr_pages, nr_vma_pages; > > + pgoff_t pgoff = vma_start_pgoff(vma); > > unsigned int subbuf_pages, subbuf_order; > > struct page **pages __free(kfree) = NULL; > > int p = 0, s = 0; > > Anyway, in general: > > Acked-by: Pedro Falcato <[email protected]> Thanks! > > -- > Pedro [0]:https://lore.kernel.org/linux-mm/[email protected]/