Skip to content

Commit 32a38a4

Browse files
Christoph Hellwigdjwong
authored andcommitted
iomap: use write_begin to read pages to unshare
Use the existing iomap write_begin code to read the pages unshared by iomap_file_unshare. That avoids the extra ->readpage call and extent tree lookup currently done by read_mapping_page. Signed-off-by: Christoph Hellwig <[email protected]> Reviewed-by: Darrick J. Wong <[email protected]> Signed-off-by: Darrick J. Wong <[email protected]>
1 parent d3b4043 commit 32a38a4

File tree

1 file changed

+16
-33
lines changed

1 file changed

+16
-33
lines changed

fs/iomap/buffered-io.c

Lines changed: 16 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -548,6 +548,10 @@ iomap_migrate_page(struct address_space *mapping, struct page *newpage,
548548
EXPORT_SYMBOL_GPL(iomap_migrate_page);
549549
#endif /* CONFIG_MIGRATION */
550550

551+
enum {
552+
IOMAP_WRITE_F_UNSHARE = (1 << 0),
553+
};
554+
551555
static void
552556
iomap_write_failed(struct inode *inode, loff_t pos, unsigned len)
553557
{
@@ -577,7 +581,7 @@ iomap_read_page_sync(loff_t block_start, struct page *page, unsigned poff,
577581
}
578582

579583
static int
580-
__iomap_write_begin(struct inode *inode, loff_t pos, unsigned len,
584+
__iomap_write_begin(struct inode *inode, loff_t pos, unsigned len, int flags,
581585
struct page *page, struct iomap *iomap)
582586
{
583587
struct iomap_page *iop = iomap_page_create(inode, page);
@@ -596,11 +600,14 @@ __iomap_write_begin(struct inode *inode, loff_t pos, unsigned len,
596600
if (plen == 0)
597601
break;
598602

599-
if ((from <= poff || from >= poff + plen) &&
603+
if (!(flags & IOMAP_WRITE_F_UNSHARE) &&
604+
(from <= poff || from >= poff + plen) &&
600605
(to <= poff || to >= poff + plen))
601606
continue;
602607

603608
if (iomap_block_needs_zeroing(inode, iomap, block_start)) {
609+
if (WARN_ON_ONCE(flags & IOMAP_WRITE_F_UNSHARE))
610+
return -EIO;
604611
zero_user_segments(page, poff, from, to, poff + plen);
605612
iomap_set_range_uptodate(page, poff, plen);
606613
continue;
@@ -646,7 +653,8 @@ iomap_write_begin(struct inode *inode, loff_t pos, unsigned len, unsigned flags,
646653
else if (iomap->flags & IOMAP_F_BUFFER_HEAD)
647654
status = __block_write_begin_int(page, pos, len, NULL, iomap);
648655
else
649-
status = __iomap_write_begin(inode, pos, len, page, iomap);
656+
status = __iomap_write_begin(inode, pos, len, flags, page,
657+
iomap);
650658

651659
if (unlikely(status))
652660
goto out_unlock;
@@ -869,22 +877,6 @@ iomap_file_buffered_write(struct kiocb *iocb, struct iov_iter *iter,
869877
}
870878
EXPORT_SYMBOL_GPL(iomap_file_buffered_write);
871879

872-
static struct page *
873-
__iomap_read_page(struct inode *inode, loff_t offset)
874-
{
875-
struct address_space *mapping = inode->i_mapping;
876-
struct page *page;
877-
878-
page = read_mapping_page(mapping, offset >> PAGE_SHIFT, NULL);
879-
if (IS_ERR(page))
880-
return page;
881-
if (!PageUptodate(page)) {
882-
put_page(page);
883-
return ERR_PTR(-EIO);
884-
}
885-
return page;
886-
}
887-
888880
static loff_t
889881
iomap_unshare_actor(struct inode *inode, loff_t pos, loff_t length, void *data,
890882
struct iomap *iomap)
@@ -900,24 +892,15 @@ iomap_unshare_actor(struct inode *inode, loff_t pos, loff_t length, void *data,
900892
return length;
901893

902894
do {
903-
struct page *page, *rpage;
904-
unsigned long offset; /* Offset into pagecache page */
905-
unsigned long bytes; /* Bytes to write to page */
906-
907-
offset = offset_in_page(pos);
908-
bytes = min_t(loff_t, PAGE_SIZE - offset, length);
909-
910-
rpage = __iomap_read_page(inode, pos);
911-
if (IS_ERR(rpage))
912-
return PTR_ERR(rpage);
895+
unsigned long offset = offset_in_page(pos);
896+
unsigned long bytes = min_t(loff_t, PAGE_SIZE - offset, length);
897+
struct page *page;
913898

914-
status = iomap_write_begin(inode, pos, bytes, 0, &page, iomap);
915-
put_page(rpage);
899+
status = iomap_write_begin(inode, pos, bytes,
900+
IOMAP_WRITE_F_UNSHARE, &page, iomap);
916901
if (unlikely(status))
917902
return status;
918903

919-
WARN_ON_ONCE(!PageUptodate(page));
920-
921904
status = iomap_write_end(inode, pos, bytes, bytes, page, iomap);
922905
if (unlikely(status <= 0)) {
923906
if (WARN_ON_ONCE(status == 0))

0 commit comments

Comments
 (0)