btrfs: reflink: make copy_inline_to_page() to be subpage compatible
authorQu Wenruo <wqu@suse.com>
Mon, 31 May 2021 08:50:53 +0000 (16:50 +0800)
committerDavid Sterba <dsterba@suse.com>
Mon, 21 Jun 2021 13:19:10 +0000 (15:19 +0200)
The modifications are:

- Page copy destination
  For subpage case, one page can contain multiple sectors, thus we can
  no longer expect the memcpy_to_page()/btrfs_decompress() to copy
  data into page offset 0.
  The correct offset is offset_in_page(file_offset) now, which should
  handle both regular sectorsize and subpage cases well.

- Page status update
  Now we need to use subpage helper to handle the page status update.

Tested-by: Ritesh Harjani <riteshh@linux.ibm.com> # [ppc64]
Tested-by: Anand Jain <anand.jain@oracle.com> # [aarch64]
Signed-off-by: Qu Wenruo <wqu@suse.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
fs/btrfs/reflink.c

index 9178da07cc9c91a7f5f1a294afb1e53ed539686d..9b0814318e72642a8ec5e69e106e2cb7a66d0822 100644 (file)
@@ -7,6 +7,7 @@
 #include "delalloc-space.h"
 #include "reflink.h"
 #include "transaction.h"
+#include "subpage.h"
 
 #define BTRFS_MAX_DEDUPE_LEN   SZ_16M
 
@@ -52,7 +53,8 @@ static int copy_inline_to_page(struct btrfs_inode *inode,
                               const u64 datal,
                               const u8 comp_type)
 {
-       const u64 block_size = btrfs_inode_sectorsize(inode);
+       struct btrfs_fs_info *fs_info = inode->root->fs_info;
+       const u32 block_size = fs_info->sectorsize;
        const u64 range_end = file_offset + block_size - 1;
        const size_t inline_size = size - btrfs_file_extent_calc_inline_size(0);
        char *data_start = inline_data + btrfs_file_extent_calc_inline_size(0);
@@ -106,10 +108,12 @@ static int copy_inline_to_page(struct btrfs_inode *inode,
        set_bit(BTRFS_INODE_NO_DELALLOC_FLUSH, &inode->runtime_flags);
 
        if (comp_type == BTRFS_COMPRESS_NONE) {
-               memcpy_to_page(page, 0, data_start, datal);
+               memcpy_to_page(page, offset_in_page(file_offset), data_start,
+                              datal);
                flush_dcache_page(page);
        } else {
-               ret = btrfs_decompress(comp_type, data_start, page, 0,
+               ret = btrfs_decompress(comp_type, data_start, page,
+                                      offset_in_page(file_offset),
                                       inline_size, datal);
                if (ret)
                        goto out_unlock;
@@ -133,9 +137,9 @@ static int copy_inline_to_page(struct btrfs_inode *inode,
                flush_dcache_page(page);
        }
 
-       SetPageUptodate(page);
+       btrfs_page_set_uptodate(fs_info, page, file_offset, block_size);
        ClearPageChecked(page);
-       set_page_dirty(page);
+       btrfs_page_set_dirty(fs_info, page, file_offset, block_size);
 out_unlock:
        if (page) {
                unlock_page(page);