Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

filemap: Convert generic_perform_write() to support large folios

Modelled after the loop in iomap_write_iter(), copy larger chunks from
userspace if the filesystem has created large folios.

[hch: use mapping_max_folio_size to keep supporting file systems that do
not support large folios]

Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
Signed-off-by: Christoph Hellwig <hch@lst.de>
Tested-by: Shaun Tancheff <shaun.tancheff@hpe.com>
Tested-by: Sagi Grimberg <sagi@grimberg.me>
Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>

authored by

Matthew Wilcox (Oracle) and committed by
Anna Schumaker
9aac777a 146a99ae

+26 -16
+26 -16
mm/filemap.c
··· 3981 3981 loff_t pos = iocb->ki_pos; 3982 3982 struct address_space *mapping = file->f_mapping; 3983 3983 const struct address_space_operations *a_ops = mapping->a_ops; 3984 + size_t chunk = mapping_max_folio_size(mapping); 3984 3985 long status = 0; 3985 3986 ssize_t written = 0; 3986 3987 3987 3988 do { 3988 3989 struct page *page; 3989 - unsigned long offset; /* Offset into pagecache page */ 3990 - unsigned long bytes; /* Bytes to write to page */ 3990 + struct folio *folio; 3991 + size_t offset; /* Offset into folio */ 3992 + size_t bytes; /* Bytes to write to folio */ 3991 3993 size_t copied; /* Bytes copied from user */ 3992 3994 void *fsdata = NULL; 3993 3995 3994 - offset = (pos & (PAGE_SIZE - 1)); 3995 - bytes = min_t(unsigned long, PAGE_SIZE - offset, 3996 - iov_iter_count(i)); 3996 + bytes = iov_iter_count(i); 3997 + retry: 3998 + offset = pos & (chunk - 1); 3999 + bytes = min(chunk - offset, bytes); 4000 + balance_dirty_pages_ratelimited(mapping); 3997 4001 3998 - again: 3999 4002 /* 4000 4003 * Bring in the user page that we will copy from _first_. 4001 4004 * Otherwise there's a nasty deadlock on copying from the ··· 4020 4017 if (unlikely(status < 0)) 4021 4018 break; 4022 4019 4023 - if (mapping_writably_mapped(mapping)) 4024 - flush_dcache_page(page); 4020 + folio = page_folio(page); 4021 + offset = offset_in_folio(folio, pos); 4022 + if (bytes > folio_size(folio) - offset) 4023 + bytes = folio_size(folio) - offset; 4025 4024 4026 - copied = copy_page_from_iter_atomic(page, offset, bytes, i); 4027 - flush_dcache_page(page); 4025 + if (mapping_writably_mapped(mapping)) 4026 + flush_dcache_folio(folio); 4027 + 4028 + copied = copy_folio_from_iter_atomic(folio, offset, bytes, i); 4029 + flush_dcache_folio(folio); 4028 4030 4029 4031 status = a_ops->write_end(file, mapping, pos, bytes, copied, 4030 4032 page, fsdata); ··· 4047 4039 * halfway through, might be a race with munmap, 4048 4040 * might be severe memory pressure. 4049 4041 */ 4050 - if (copied) 4042 + if (chunk > PAGE_SIZE) 4043 + chunk /= 2; 4044 + if (copied) { 4051 4045 bytes = copied; 4052 - goto again; 4046 + goto retry; 4047 + } 4048 + } else { 4049 + pos += status; 4050 + written += status; 4053 4051 } 4054 - pos += status; 4055 - written += status; 4056 - 4057 - balance_dirty_pages_ratelimited(mapping); 4058 4052 } while (iov_iter_count(i)); 4059 4053 4060 4054 if (!written)