]> git.proxmox.com Git - mirror_ubuntu-hirsute-kernel.git/blobdiff - fs/xfs/xfs_aops.c
Merge tag 'ext4_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso...
[mirror_ubuntu-hirsute-kernel.git] / fs / xfs / xfs_aops.c
index 2b2691b7342890e64e957d616dfb1c4aa2efc8c1..596ec71da00e8d4f005ab264142e927d03ac667d 100644 (file)
@@ -725,6 +725,25 @@ xfs_convert_page(
                        (xfs_off_t)(page->index + 1) << PAGE_CACHE_SHIFT,
                        i_size_read(inode));
 
+       /*
+        * If the current map does not span the entire page we are about to try
+        * to write, then give up. The only way we can write a page that spans
+        * multiple mappings in a single writeback iteration is via the
+        * xfs_vm_writepage() function. Data integrity writeback requires the
+        * entire page to be written in a single attempt, otherwise the part of
+        * the page we don't write here doesn't get written as part of the data
+        * integrity sync.
+        *
+        * For normal writeback, we also don't attempt to write partial pages
+        * here as it simply means that write_cache_pages() will see it under
+        * writeback and ignore the page until some point in the future, at
+        * which time this will be the only page in the file that needs
+        * writeback.  Hence for more optimal IO patterns, we should always
+        * avoid partial page writeback due to multiple mappings on a page here.
+        */
+       if (!xfs_imap_valid(inode, imap, end_offset))
+               goto fail_unlock_page;
+
        len = 1 << inode->i_blkbits;
        p_offset = min_t(unsigned long, end_offset & (PAGE_CACHE_SIZE - 1),
                                        PAGE_CACHE_SIZE);
@@ -824,10 +843,12 @@ xfs_cluster_write(
 STATIC void
 xfs_vm_invalidatepage(
        struct page             *page,
-       unsigned long           offset)
+       unsigned int            offset,
+       unsigned int            length)
 {
-       trace_xfs_invalidatepage(page->mapping->host, page, offset);
-       block_invalidatepage(page, offset);
+       trace_xfs_invalidatepage(page->mapping->host, page, offset,
+                                length);
+       block_invalidatepage(page, offset, length);
 }
 
 /*
@@ -891,7 +912,7 @@ next_buffer:
 
        xfs_iunlock(ip, XFS_ILOCK_EXCL);
 out_invalidate:
-       xfs_vm_invalidatepage(page, 0);
+       xfs_vm_invalidatepage(page, 0, PAGE_CACHE_SIZE);
        return;
 }
 
@@ -921,7 +942,7 @@ xfs_vm_writepage(
        int                     count = 0;
        int                     nonblocking = 0;
 
-       trace_xfs_writepage(inode, page, 0);
+       trace_xfs_writepage(inode, page, 0, 0);
 
        ASSERT(page_has_buffers(page));
 
@@ -1152,7 +1173,7 @@ xfs_vm_releasepage(
 {
        int                     delalloc, unwritten;
 
-       trace_xfs_releasepage(page->mapping->host, page, 0);
+       trace_xfs_releasepage(page->mapping->host, page, 0, 0);
 
        xfs_count_page_state(page, &delalloc, &unwritten);