Commit 7944c724 authored by Kefeng Wang's avatar Kefeng Wang Committed by Liu Shixin
Browse files

tmpfs: fault in smaller chunks if large folio allocation not allowed

hulk inclusion
category: performance
bugzilla: https://gitee.com/openeuler/kernel/issues/IAO6NS



--------------------------------

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, it is very
similar with 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: default avatarKefeng Wang <wangkefeng.wang@huawei.com>
Signed-off-by: default avatarLiu Shixin <liushixin2@huawei.com>
parent 898fad02
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -372,6 +372,8 @@ enum rw_hint {
#define IOCB_DIO_CALLER_COMP	(1 << 22)
/* kiocb is a read or write operation submitted by fs/aio.c. */
#define IOCB_AIO_RW		(1 << 23)
/* fault int small chunks(PAGE_SIZE) from userspace */
#define IOCB_NO_LARGE_CHUNK	(1 << 24)

/* for use in trace events */
#define TRACE_IOCB_STRINGS \
+6 −1
Original line number Diff line number Diff line
@@ -4043,9 +4043,14 @@ ssize_t generic_perform_write(struct kiocb *iocb, struct iov_iter *i)
	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);
	long status = 0;
	ssize_t written = 0;
	size_t chunk;

	if (iocb->ki_flags & IOCB_NO_LARGE_CHUNK)
		chunk = PAGE_SIZE;
	else
		chunk = mapping_max_folio_size(mapping);

	do {
		struct page *page;
+5 −0
Original line number Diff line number Diff line
@@ -3042,6 +3042,7 @@ static ssize_t shmem_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
{
	struct file *file = iocb->ki_filp;
	struct inode *inode = file->f_mapping->host;
	pgoff_t index = iocb->ki_pos >> PAGE_SHIFT;
	ssize_t ret;

	inode_lock(inode);
@@ -3054,6 +3055,10 @@ static ssize_t shmem_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
	ret = file_update_time(file);
	if (ret)
		goto unlock;

	if (!shmem_allowable_huge_orders(inode, NULL, index, 0, false))
		iocb->ki_flags |= IOCB_NO_LARGE_CHUNK;

	ret = generic_perform_write(iocb, from);
unlock:
	inode_unlock(inode);