To be able to calculate folio order based on the file size when allocation occurs on the write path. Use of length 0 for non write paths and PAGE_SIZE for pagecache read and vm fault. Signed-off-by: Daniel Gomez <da.gomez@xxxxxxxxxxx> --- include/linux/shmem_fs.h | 2 +- mm/khugepaged.c | 2 +- mm/shmem.c | 32 ++++++++++++++++++-------------- 3 files changed, 20 insertions(+), 16 deletions(-) diff --git a/include/linux/shmem_fs.h b/include/linux/shmem_fs.h index 6b0c626620f5..b3509e7f1054 100644 --- a/include/linux/shmem_fs.h +++ b/include/linux/shmem_fs.h @@ -133,7 +133,7 @@ enum sgp_type { }; int shmem_get_folio(struct inode *inode, pgoff_t index, struct folio **foliop, - enum sgp_type sgp); + enum sgp_type sgp, size_t len); struct folio *shmem_read_folio_gfp(struct address_space *mapping, pgoff_t index, gfp_t gfp); diff --git a/mm/khugepaged.c b/mm/khugepaged.c index 88433cc25d8a..e5d3feff6de6 100644 --- a/mm/khugepaged.c +++ b/mm/khugepaged.c @@ -1856,7 +1856,7 @@ static int collapse_file(struct mm_struct *mm, unsigned long addr, xas_unlock_irq(&xas); /* swap in or instantiate fallocated page */ if (shmem_get_folio(mapping->host, index, - &folio, SGP_NOALLOC)) { + &folio, SGP_NOALLOC, 0)) { result = SCAN_FAIL; goto xa_unlocked; } diff --git a/mm/shmem.c b/mm/shmem.c index 66d94207b40c..38aafa0b0845 100644 --- a/mm/shmem.c +++ b/mm/shmem.c @@ -971,7 +971,7 @@ static struct folio *shmem_get_partial_folio(struct inode *inode, pgoff_t index) * (although in some cases this is just a waste of time). */ folio = NULL; - shmem_get_folio(inode, index, &folio, SGP_READ); + shmem_get_folio(inode, index, &folio, SGP_READ, 0); return folio; } @@ -1948,7 +1948,7 @@ static int shmem_swapin_folio(struct inode *inode, pgoff_t index, static int shmem_get_folio_gfp(struct inode *inode, pgoff_t index, struct folio **foliop, enum sgp_type sgp, gfp_t gfp, struct vm_area_struct *vma, struct vm_fault *vmf, - vm_fault_t *fault_type) + vm_fault_t *fault_type, size_t len) { struct address_space *mapping = inode->i_mapping; struct shmem_inode_info *info = SHMEM_I(inode); @@ -2162,10 +2162,11 @@ static int shmem_get_folio_gfp(struct inode *inode, pgoff_t index, } int shmem_get_folio(struct inode *inode, pgoff_t index, struct folio **foliop, - enum sgp_type sgp) + enum sgp_type sgp, size_t len) { return shmem_get_folio_gfp(inode, index, foliop, sgp, - mapping_gfp_mask(inode->i_mapping), NULL, NULL, NULL); + mapping_gfp_mask(inode->i_mapping), + NULL, NULL, NULL, len); } /* @@ -2248,8 +2249,8 @@ static vm_fault_t shmem_fault(struct vm_fault *vmf) spin_unlock(&inode->i_lock); } - err = shmem_get_folio_gfp(inode, vmf->pgoff, &folio, SGP_CACHE, - gfp, vma, vmf, &ret); + err = shmem_get_folio_gfp(inode, vmf->pgoff, &folio, SGP_CACHE, gfp, + vma, vmf, &ret, PAGE_SIZE); if (err) return vmf_error(err); if (folio) @@ -2700,6 +2701,9 @@ shmem_write_begin(struct file *file, struct address_space *mapping, struct folio *folio; int ret = 0; + if (!mapping_large_folio_support(mapping)) + len = min_t(size_t, len, PAGE_SIZE - offset_in_page(pos)); + /* i_rwsem is held by caller */ if (unlikely(info->seals & (F_SEAL_GROW | F_SEAL_WRITE | F_SEAL_FUTURE_WRITE))) { @@ -2709,7 +2713,7 @@ shmem_write_begin(struct file *file, struct address_space *mapping, return -EPERM; } - ret = shmem_get_folio(inode, index, &folio, SGP_WRITE); + ret = shmem_get_folio(inode, index, &folio, SGP_WRITE, len); if (ret) return ret; @@ -2781,7 +2785,7 @@ static ssize_t shmem_file_read_iter(struct kiocb *iocb, struct iov_iter *to) break; } - error = shmem_get_folio(inode, index, &folio, SGP_READ); + error = shmem_get_folio(inode, index, &folio, SGP_READ, 0); if (error) { if (error == -EINVAL) error = 0; @@ -2958,7 +2962,7 @@ static ssize_t shmem_file_splice_read(struct file *in, loff_t *ppos, break; error = shmem_get_folio(inode, *ppos / PAGE_SIZE, &folio, - SGP_READ); + SGP_READ, 0); if (error) { if (error == -EINVAL) error = 0; @@ -3145,7 +3149,7 @@ static long shmem_fallocate(struct file *file, int mode, loff_t offset, error = -ENOMEM; else error = shmem_get_folio(inode, index, &folio, - SGP_FALLOC); + SGP_FALLOC, 0); if (error) { info->fallocend = undo_fallocend; /* Remove the !uptodate folios we added */ @@ -3500,7 +3504,7 @@ static int shmem_symlink(struct mnt_idmap *idmap, struct inode *dir, inode->i_op = &shmem_short_symlink_operations; } else { inode_nohighmem(inode); - error = shmem_get_folio(inode, 0, &folio, SGP_WRITE); + error = shmem_get_folio(inode, 0, &folio, SGP_WRITE, 0); if (error) goto out_remove_offset; inode->i_mapping->a_ops = &shmem_aops; @@ -3548,7 +3552,7 @@ static const char *shmem_get_link(struct dentry *dentry, return ERR_PTR(-ECHILD); } } else { - error = shmem_get_folio(inode, 0, &folio, SGP_READ); + error = shmem_get_folio(inode, 0, &folio, SGP_READ, 0); if (error) return ERR_PTR(error); if (!folio) @@ -4916,8 +4920,8 @@ struct folio *shmem_read_folio_gfp(struct address_space *mapping, int error; BUG_ON(!shmem_mapping(mapping)); - error = shmem_get_folio_gfp(inode, index, &folio, SGP_CACHE, - gfp, NULL, NULL, NULL); + error = shmem_get_folio_gfp(inode, index, &folio, SGP_CACHE, gfp, NULL, + NULL, NULL, PAGE_SIZE); if (error) return ERR_PTR(error); -- 2.39.2