diff mbox series

[v4,67/68] btrfs: reflink: do full page writeback for reflink prepare

Message ID 20201021062554.68132-68-wqu@suse.com
State New, archived
Headers show
Series btrfs: add basic rw support for subpage sector size | expand

Commit Message

Qu Wenruo Oct. 21, 2020, 6:25 a.m. UTC
Since we don't support subpage writeback yet, let
btrfs_remap_file_range_prep() to do full page writeback.

This only affects subpage support, as the regular sectorsize support
already has its sectorsize == PAGE_SIZE.

Signed-off-by: Qu Wenruo <wqu@suse.com>
---
 fs/btrfs/reflink.c | 36 ++++++++++++++++++++++++++----------
 1 file changed, 26 insertions(+), 10 deletions(-)
diff mbox series

Patch

diff --git a/fs/btrfs/reflink.c b/fs/btrfs/reflink.c
index 5cd02514cf4d..e8023c1dcb5d 100644
--- a/fs/btrfs/reflink.c
+++ b/fs/btrfs/reflink.c
@@ -700,9 +700,15 @@  static int btrfs_remap_file_range_prep(struct file *file_in, loff_t pos_in,
 {
 	struct inode *inode_in = file_inode(file_in);
 	struct inode *inode_out = file_inode(file_out);
-	u64 bs = BTRFS_I(inode_out)->root->fs_info->sb->s_blocksize;
+	/*
+	 * We don't support subpage write yet, thus for data writeback we
+	 * must use PAGE_SIZE here. But for reflink we still support proper
+	 * sector alignment.
+	 */
+	u32 wb_bs = PAGE_SIZE;
 	bool same_inode = inode_out == inode_in;
-	u64 wb_len;
+	u64 in_wb_len;
+	u64 out_wb_len;
 	int ret;
 
 	if (!(remap_flags & REMAP_FILE_DEDUP)) {
@@ -735,11 +741,21 @@  static int btrfs_remap_file_range_prep(struct file *file_in, loff_t pos_in,
 	 *    waits for the writeback to complete, i.e. for IO to be done, and
 	 *    not for the ordered extents to complete. We need to wait for them
 	 *    to complete so that new file extent items are in the fs tree.
+	 *
+	 * Also for subpage case, since at different offset the same length can
+	 * cover different number of pages, we have to calculate the wb_len for
+	 * each file.
 	 */
-	if (*len == 0 && !(remap_flags & REMAP_FILE_DEDUP))
-		wb_len = ALIGN(inode_in->i_size, bs) - ALIGN_DOWN(pos_in, bs);
-	else
-		wb_len = ALIGN(*len, bs);
+	if (*len == 0 && !(remap_flags & REMAP_FILE_DEDUP)) {
+		in_wb_len = round_up(inode_in->i_size, wb_bs) -
+			    round_down(pos_in, wb_bs);
+		out_wb_len = in_wb_len;
+	} else {
+		in_wb_len = round_up(pos_in + *len, wb_bs) -
+			    round_down(pos_in, wb_bs);
+		out_wb_len = round_up(pos_out + *len, wb_bs) -
+			     round_down(pos_out, wb_bs);
+	}
 
 	/*
 	 * Since we don't lock ranges, wait for ongoing lockless dio writes (as
@@ -771,12 +787,12 @@  static int btrfs_remap_file_range_prep(struct file *file_in, loff_t pos_in,
 	if (ret < 0)
 		return ret;
 
-	ret = btrfs_wait_ordered_range(inode_in, ALIGN_DOWN(pos_in, bs),
-				       wb_len);
+	ret = btrfs_wait_ordered_range(inode_in, round_down(pos_in, wb_bs),
+				       in_wb_len);
 	if (ret < 0)
 		return ret;
-	ret = btrfs_wait_ordered_range(inode_out, ALIGN_DOWN(pos_out, bs),
-				       wb_len);
+	ret = btrfs_wait_ordered_range(inode_out, round_down(pos_out, wb_bs),
+				       out_wb_len);
 	if (ret < 0)
 		return ret;