The tmpfs supports large folio, but there is some configurable options to enable/disable large folio allocation, and for huge=within_size, large folio only allowabled if it fully within i_size, so there is performance issue when perform write without large folio, the issue is similar to commit 4e527d5841e2 ("iomap: fault in smaller chunks for non-large folio mappings"). Fix it by checking whether it allows large folio allocation or not before perform write. Fixes: 9aac777aaf94 ("filemap: Convert generic_perform_write() to support large folios") Signed-off-by: Kefeng Wang <wangkefeng.wang@xxxxxxxxxx> --- v2: - Don't use IOCB flags mm/filemap.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/mm/filemap.c b/mm/filemap.c index 3e46ca45e13d..b33f260fa32f 100644 --- a/mm/filemap.c +++ b/mm/filemap.c @@ -4126,13 +4126,28 @@ generic_file_direct_write(struct kiocb *iocb, struct iov_iter *from) } EXPORT_SYMBOL(generic_file_direct_write); +static size_t generic_mapping_max_folio_size(struct address_space *mapping, + loff_t pos) +{ + struct inode *inode = mapping->host; + pgoff_t index = pos >> PAGE_SHIFT; + + if (!shmem_mapping(mapping)) + goto out; + + if (!shmem_allowable_huge_orders(inode, NULL, index, 0, false)) + return PAGE_SIZE; +out: + return mapping_max_folio_size(mapping); +} + ssize_t generic_perform_write(struct kiocb *iocb, struct iov_iter *i) { struct file *file = iocb->ki_filp; loff_t pos = iocb->ki_pos; struct address_space *mapping = file->f_mapping; const struct address_space_operations *a_ops = mapping->a_ops; - size_t chunk = mapping_max_folio_size(mapping); + size_t chunk = generic_mapping_max_folio_size(mapping, pos); long status = 0; ssize_t written = 0; -- 2.27.0