[PATCH v2 03/13] filemap: align the index to mapping_min_order in the page cache

From: Pankaj Raghav (Samsung)
Date: Fri Mar 01 2024 - 11:52:22 EST


From: Luis Chamberlain <mcgrof@xxxxxxxxxx>

Supporting mapping_min_order implies that we guarantee each folio in the
page cache has at least an order of mapping_min_order. So when adding new
folios to the page cache we must ensure the index used is aligned to the
mapping_min_order as the page cache requires the index to be aligned to
the order of the folio.

A higher order folio than min_order by definition is a multiple of the
min_order. If an index is aligned to an order higher than a min_order, it
will also be aligned to the min order.

This effectively introduces no new functional changes when min order is
not set other than a few rounding computations that should result in the
same value.

Signed-off-by: Luis Chamberlain <mcgrof@xxxxxxxxxx>
Signed-off-by: Pankaj Raghav <p.raghav@xxxxxxxxxxx>
---
include/linux/pagemap.h | 10 +++++++++-
mm/filemap.c | 16 ++++++++++------
2 files changed, 19 insertions(+), 7 deletions(-)

diff --git a/include/linux/pagemap.h b/include/linux/pagemap.h
index fc8eb9c94e9c..b3cf8ef89826 100644
--- a/include/linux/pagemap.h
+++ b/include/linux/pagemap.h
@@ -1328,6 +1328,14 @@ struct readahead_control {
._index = i, \
}

+#define DEFINE_READAHEAD_ALIGNED(ractl, f, r, m, i) \
+ struct readahead_control ractl = { \
+ .file = f, \
+ .mapping = m, \
+ .ra = r, \
+ ._index = mapping_align_start_index(m, i), \
+ }
+
#define VM_READAHEAD_PAGES (SZ_128K / PAGE_SIZE)

void page_cache_ra_unbounded(struct readahead_control *,
@@ -1356,7 +1364,7 @@ void page_cache_sync_readahead(struct address_space *mapping,
struct file_ra_state *ra, struct file *file, pgoff_t index,
unsigned long req_count)
{
- DEFINE_READAHEAD(ractl, file, ra, mapping, index);
+ DEFINE_READAHEAD_ALIGNED(ractl, file, ra, mapping, index);
page_cache_sync_ra(&ractl, req_count);
}

diff --git a/mm/filemap.c b/mm/filemap.c
index 2b00442b9d19..96fe5c7fe094 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -2416,11 +2416,13 @@ static int filemap_update_page(struct kiocb *iocb,
}

static int filemap_create_folio(struct file *file,
- struct address_space *mapping, pgoff_t index,
+ struct address_space *mapping, loff_t pos,
struct folio_batch *fbatch)
{
struct folio *folio;
int error;
+ unsigned int min_order = mapping_min_folio_order(mapping);
+ pgoff_t index;

folio = filemap_alloc_folio(mapping_gfp_mask(mapping), 0);
if (!folio)
@@ -2440,6 +2442,8 @@ static int filemap_create_folio(struct file *file,
* well to keep locking rules simple.
*/
filemap_invalidate_lock_shared(mapping);
+ /* index in PAGE units but aligned to min_order number of pages. */
+ index = (pos >> (PAGE_SHIFT + min_order)) << min_order;
error = filemap_add_folio(mapping, folio, index,
mapping_gfp_constraint(mapping, GFP_KERNEL));
if (error == -EEXIST)
@@ -2500,8 +2504,7 @@ static int filemap_get_pages(struct kiocb *iocb, size_t count,
if (!folio_batch_count(fbatch)) {
if (iocb->ki_flags & (IOCB_NOWAIT | IOCB_WAITQ))
return -EAGAIN;
- err = filemap_create_folio(filp, mapping,
- iocb->ki_pos >> PAGE_SHIFT, fbatch);
+ err = filemap_create_folio(filp, mapping, iocb->ki_pos, fbatch);
if (err == AOP_TRUNCATED_PAGE)
goto retry;
return err;
@@ -3093,7 +3096,7 @@ static struct file *do_sync_mmap_readahead(struct vm_fault *vmf)
struct file *file = vmf->vma->vm_file;
struct file_ra_state *ra = &file->f_ra;
struct address_space *mapping = file->f_mapping;
- DEFINE_READAHEAD(ractl, file, ra, mapping, vmf->pgoff);
+ DEFINE_READAHEAD_ALIGNED(ractl, file, ra, mapping, vmf->pgoff);
struct file *fpin = NULL;
unsigned long vm_flags = vmf->vma->vm_flags;
unsigned int mmap_miss;
@@ -3147,7 +3150,7 @@ static struct file *do_sync_mmap_readahead(struct vm_fault *vmf)
ra->start = max_t(long, 0, vmf->pgoff - ra->ra_pages / 2);
ra->size = ra->ra_pages;
ra->async_size = ra->ra_pages / 4;
- ractl._index = ra->start;
+ ractl._index = mapping_align_start_index(mapping, ra->start);
page_cache_ra_order(&ractl, ra, 0);
return fpin;
}
@@ -3162,7 +3165,7 @@ static struct file *do_async_mmap_readahead(struct vm_fault *vmf,
{
struct file *file = vmf->vma->vm_file;
struct file_ra_state *ra = &file->f_ra;
- DEFINE_READAHEAD(ractl, file, ra, file->f_mapping, vmf->pgoff);
+ DEFINE_READAHEAD_ALIGNED(ractl, file, ra, file->f_mapping, vmf->pgoff);
struct file *fpin = NULL;
unsigned int mmap_miss;

@@ -3657,6 +3660,7 @@ static struct folio *do_read_cache_folio(struct address_space *mapping,
struct folio *folio;
int err;

+ index = mapping_align_start_index(mapping, index);
if (!filler)
filler = mapping->a_ops->read_folio;
repeat:
--
2.43.0