[V16,16/18] Btrfs: btrfs_clone: Flush dirty blocks of a page that do not map the clone range
diff mbox

Message ID 1460622775-20723-17-git-send-email-chandan@linux.vnet.ibm.com
State New
Headers show

Commit Message

Chandan Rajendra April 14, 2016, 8:32 a.m. UTC
After cloning the required extents, we truncate all the pages that map
the file range being cloned. In subpage-blocksize scenario, we could
have dirty blocks before and/or after the clone range in the
leading/trailing pages. Truncating these pages would lead to data
loss. Hence this commit forces such dirty blocks to be flushed to disk
before performing the clone operation.

Signed-off-by: Chandan Rajendra <chandan@linux.vnet.ibm.com>
---
 fs/btrfs/ioctl.c | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)

Comments

kbuild test robot April 14, 2016, 9:36 a.m. UTC | #1
Hi Chandan,

[auto build test ERROR on tip/perf/core]
[also build test ERROR on v4.6-rc3 next-20160414]
[cannot apply to btrfs/next]
[if your patch is applied to the wrong git tree, please drop us a note to help improving the system]

url:    https://github.com/0day-ci/linux/commits/Chandan-Rajendra/Allow-I-O-on-blocks-whose-size-is-less-than-page-size/20160414-163922
config: x86_64-randconfig-x006-201615 (attached as .config)
reproduce:
        # save the attached .config to linux build tree
        make ARCH=x86_64 

Note: the linux-review/Chandan-Rajendra/Allow-I-O-on-blocks-whose-size-is-less-than-page-size/20160414-163922 HEAD 753cfebe561d4ba706b6095f0df83e345888dd92 builds fine.
      It only hurts bisectibility.

All error/warnings (new ones prefixed by >>):

   In file included from include/linux/linkage.h:4:0,
                    from include/linux/kernel.h:6,
                    from fs/btrfs/ioctl.c:19:
   fs/btrfs/ioctl.c: In function 'btrfs_clone_files':
>> fs/btrfs/ioctl.c:3913:27: error: 'PAGE_CACHE_SIZE' undeclared (first use in this function)
     if ((round_down(destoff, PAGE_CACHE_SIZE) < inode->i_size) &&
                              ^
   include/linux/compiler.h:151:30: note: in definition of macro '__trace_if'
     if (__builtin_constant_p(!!(cond)) ? !!(cond) :   \
                                 ^
>> fs/btrfs/ioctl.c:3913:2: note: in expansion of macro 'if'
     if ((round_down(destoff, PAGE_CACHE_SIZE) < inode->i_size) &&
     ^
>> include/linux/kernel.h:64:34: note: in expansion of macro '__round_mask'
    #define round_down(x, y) ((x) & ~__round_mask(x, y))
                                     ^
>> fs/btrfs/ioctl.c:3913:7: note: in expansion of macro 'round_down'
     if ((round_down(destoff, PAGE_CACHE_SIZE) < inode->i_size) &&
          ^
   fs/btrfs/ioctl.c:3913:27: note: each undeclared identifier is reported only once for each function it appears in
     if ((round_down(destoff, PAGE_CACHE_SIZE) < inode->i_size) &&
                              ^
   include/linux/compiler.h:151:30: note: in definition of macro '__trace_if'
     if (__builtin_constant_p(!!(cond)) ? !!(cond) :   \
                                 ^
>> fs/btrfs/ioctl.c:3913:2: note: in expansion of macro 'if'
     if ((round_down(destoff, PAGE_CACHE_SIZE) < inode->i_size) &&
     ^
>> include/linux/kernel.h:64:34: note: in expansion of macro '__round_mask'
    #define round_down(x, y) ((x) & ~__round_mask(x, y))
                                     ^
>> fs/btrfs/ioctl.c:3913:7: note: in expansion of macro 'round_down'
     if ((round_down(destoff, PAGE_CACHE_SIZE) < inode->i_size) &&
          ^

vim +/PAGE_CACHE_SIZE +3913 fs/btrfs/ioctl.c

  3907		/* verify if ranges are overlapped within the same file */
  3908		if (same_inode) {
  3909			if (destoff + len > off && destoff < off + len)
  3910				goto out_unlock;
  3911		}
  3912	
> 3913		if ((round_down(destoff, PAGE_CACHE_SIZE) < inode->i_size) &&
  3914			!IS_ALIGNED(destoff, PAGE_CACHE_SIZE)) {
  3915			ret = filemap_write_and_wait_range(inode->i_mapping,
  3916						round_down(destoff, PAGE_CACHE_SIZE),

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

Patch
diff mbox

diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
index 4ff7cf8..3038589 100644
--- a/fs/btrfs/ioctl.c
+++ b/fs/btrfs/ioctl.c
@@ -3849,6 +3849,7 @@  static noinline int btrfs_clone_files(struct file *file, struct file *file_src,
 	int ret;
 	u64 len = olen;
 	u64 bs = root->fs_info->sb->s_blocksize;
+	u64 dest_end;
 	int same_inode = src == inode;
 
 	/*
@@ -3909,6 +3910,21 @@  static noinline int btrfs_clone_files(struct file *file, struct file *file_src,
 			goto out_unlock;
 	}
 
+	if ((round_down(destoff, PAGE_CACHE_SIZE) < inode->i_size) &&
+		!IS_ALIGNED(destoff, PAGE_CACHE_SIZE)) {
+		ret = filemap_write_and_wait_range(inode->i_mapping,
+					round_down(destoff, PAGE_CACHE_SIZE),
+					destoff - 1);
+	}
+
+	dest_end = destoff + len - 1;
+	if ((dest_end < inode->i_size) &&
+		!IS_ALIGNED(dest_end + 1, PAGE_CACHE_SIZE)) {
+		ret = filemap_write_and_wait_range(inode->i_mapping,
+					dest_end + 1,
+					round_up(dest_end, PAGE_CACHE_SIZE));
+	}
+
 	if (destoff > inode->i_size) {
 		ret = btrfs_cont_expand(inode, inode->i_size, destoff);
 		if (ret)