Skip to content

Commit 5d8edfb

Browse files
author
Matthew Wilcox (Oracle)
committed
iomap: Copy larger chunks from userspace
If we have a large folio, we can copy in larger chunks than PAGE_SIZE. Start at the maximum page cache size and shrink by half every time we hit the "we are short on memory" problem. Signed-off-by: Matthew Wilcox (Oracle) <[email protected]> Reviewed-by: Christoph Hellwig <[email protected]> Reviewed-by: Darrick J. Wong <[email protected]>
1 parent d6bb59a commit 5d8edfb

File tree

1 file changed

+17
-15
lines changed

1 file changed

+17
-15
lines changed

fs/iomap/buffered-io.c

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -769,6 +769,7 @@ static size_t iomap_write_end(struct iomap_iter *iter, loff_t pos, size_t len,
769769
static loff_t iomap_write_iter(struct iomap_iter *iter, struct iov_iter *i)
770770
{
771771
loff_t length = iomap_length(iter);
772+
size_t chunk = PAGE_SIZE << MAX_PAGECACHE_ORDER;
772773
loff_t pos = iter->pos;
773774
ssize_t written = 0;
774775
long status = 0;
@@ -777,15 +778,12 @@ static loff_t iomap_write_iter(struct iomap_iter *iter, struct iov_iter *i)
777778

778779
do {
779780
struct folio *folio;
780-
struct page *page;
781-
unsigned long offset; /* Offset into pagecache page */
782-
unsigned long bytes; /* Bytes to write to page */
781+
size_t offset; /* Offset into folio */
782+
size_t bytes; /* Bytes to write to folio */
783783
size_t copied; /* Bytes copied from user */
784784

785-
offset = offset_in_page(pos);
786-
bytes = min_t(unsigned long, PAGE_SIZE - offset,
787-
iov_iter_count(i));
788-
again:
785+
offset = pos & (chunk - 1);
786+
bytes = min(chunk - offset, iov_iter_count(i));
789787
status = balance_dirty_pages_ratelimited_flags(mapping,
790788
bdp_flags);
791789
if (unlikely(status))
@@ -815,12 +813,14 @@ static loff_t iomap_write_iter(struct iomap_iter *iter, struct iov_iter *i)
815813
if (iter->iomap.flags & IOMAP_F_STALE)
816814
break;
817815

818-
page = folio_file_page(folio, pos >> PAGE_SHIFT);
819-
if (mapping_writably_mapped(mapping))
820-
flush_dcache_page(page);
816+
offset = offset_in_folio(folio, pos);
817+
if (bytes > folio_size(folio) - offset)
818+
bytes = folio_size(folio) - offset;
821819

822-
copied = copy_page_from_iter_atomic(page, offset, bytes, i);
820+
if (mapping_writably_mapped(mapping))
821+
flush_dcache_folio(folio);
823822

823+
copied = copy_folio_from_iter_atomic(folio, offset, bytes, i);
824824
status = iomap_write_end(iter, pos, bytes, copied, folio);
825825

826826
if (unlikely(copied != status))
@@ -836,11 +836,13 @@ static loff_t iomap_write_iter(struct iomap_iter *iter, struct iov_iter *i)
836836
*/
837837
if (copied)
838838
bytes = copied;
839-
goto again;
839+
if (chunk > PAGE_SIZE)
840+
chunk /= 2;
841+
} else {
842+
pos += status;
843+
written += status;
844+
length -= status;
840845
}
841-
pos += status;
842-
written += status;
843-
length -= status;
844846
} while (iov_iter_count(i) && length);
845847

846848
if (status == -EAGAIN) {

0 commit comments

Comments
 (0)