From: Goldwyn Rodrigues <rgold...@suse.com>

In case of a IOMAP_COW, read a page from the srcmap before
performing a write on the page.

Signed-off-by: Goldwyn Rodrigues <rgold...@suse.com>
---
 fs/iomap/buffered-io.c | 14 ++++++++------
 1 file changed, 8 insertions(+), 6 deletions(-)

diff --git a/fs/iomap/buffered-io.c b/fs/iomap/buffered-io.c
index f27756c0b31c..a96cc26eec92 100644
--- a/fs/iomap/buffered-io.c
+++ b/fs/iomap/buffered-io.c
@@ -581,7 +581,7 @@ __iomap_write_begin(struct inode *inode, loff_t pos, 
unsigned len,
 
 static int
 iomap_write_begin(struct inode *inode, loff_t pos, unsigned len, unsigned 
flags,
-               struct page **pagep, struct iomap *iomap)
+               struct page **pagep, struct iomap *iomap, struct iomap *srcmap)
 {
        const struct iomap_page_ops *page_ops = iomap->page_ops;
        pgoff_t index = pos >> PAGE_SHIFT;
@@ -607,6 +607,8 @@ iomap_write_begin(struct inode *inode, loff_t pos, unsigned 
len, unsigned flags,
 
        if (iomap->type == IOMAP_INLINE)
                iomap_read_inline_data(inode, page, iomap);
+       else if (iomap->type == IOMAP_COW)
+               status = __iomap_write_begin(inode, pos, len, page, srcmap);
        else if (iomap->flags & IOMAP_F_BUFFER_HEAD)
                status = __block_write_begin_int(page, pos, len, NULL, iomap);
        else
@@ -772,7 +774,7 @@ iomap_write_actor(struct inode *inode, loff_t pos, loff_t 
length, void *data,
                }
 
                status = iomap_write_begin(inode, pos, bytes, flags, &page,
-                               iomap);
+                               iomap, srcmap);
                if (unlikely(status))
                        break;
 
@@ -871,7 +873,7 @@ iomap_dirty_actor(struct inode *inode, loff_t pos, loff_t 
length, void *data,
                        return PTR_ERR(rpage);
 
                status = iomap_write_begin(inode, pos, bytes,
-                                          AOP_FLAG_NOFS, &page, iomap);
+                                          AOP_FLAG_NOFS, &page, iomap, srcmap);
                put_page(rpage);
                if (unlikely(status))
                        return status;
@@ -917,13 +919,13 @@ iomap_file_dirty(struct inode *inode, loff_t pos, loff_t 
len,
 EXPORT_SYMBOL_GPL(iomap_file_dirty);
 
 static int iomap_zero(struct inode *inode, loff_t pos, unsigned offset,
-               unsigned bytes, struct iomap *iomap)
+               unsigned bytes, struct iomap *iomap, struct iomap *srcmap)
 {
        struct page *page;
        int status;
 
        status = iomap_write_begin(inode, pos, bytes, AOP_FLAG_NOFS, &page,
-                                  iomap);
+                                  iomap, srcmap);
        if (status)
                return status;
 
@@ -961,7 +963,7 @@ iomap_zero_range_actor(struct inode *inode, loff_t pos, 
loff_t count,
                if (IS_DAX(inode))
                        status = iomap_dax_zero(pos, offset, bytes, iomap);
                else
-                       status = iomap_zero(inode, pos, offset, bytes, iomap);
+                       status = iomap_zero(inode, pos, offset, bytes, iomap, 
srcmap);
                if (status < 0)
                        return status;
 
-- 
2.16.4

Reply via email to