]> asedeno.scripts.mit.edu Git - linux.git/blobdiff - fs/btrfs/ioctl.c
Merge tag 'block-5.6-2020-02-05' of git://git.kernel.dk/linux-block
[linux.git] / fs / btrfs / ioctl.c
index 18e328ce4b54964a6dbbddbf36450e24bf77460d..4f4b13830b258cbb7f860e9e9d3dd68035c4c810 100644 (file)
@@ -1128,7 +1128,7 @@ static struct extent_map *defrag_lookup_extent(struct inode *inode, u64 start)
 
                /* get the big lock and read metadata off disk */
                lock_extent_bits(io_tree, start, end, &cached);
-               em = btrfs_get_extent(BTRFS_I(inode), NULL, 0, start, len, 0);
+               em = btrfs_get_extent(BTRFS_I(inode), NULL, 0, start, len);
                unlock_extent_cached(io_tree, start, end, &cached);
 
                if (IS_ERR(em))
@@ -3243,6 +3243,7 @@ static void btrfs_double_extent_lock(struct inode *inode1, u64 loff1,
 static int btrfs_extent_same_range(struct inode *src, u64 loff, u64 len,
                                   struct inode *dst, u64 dst_loff)
 {
+       const u64 bs = BTRFS_I(src)->root->fs_info->sb->s_blocksize;
        int ret;
 
        /*
@@ -3250,7 +3251,7 @@ static int btrfs_extent_same_range(struct inode *src, u64 loff, u64 len,
         * source range to serialize with relocation.
         */
        btrfs_double_extent_lock(src, loff, dst, dst_loff, len);
-       ret = btrfs_clone(src, dst, loff, len, len, dst_loff, 1);
+       ret = btrfs_clone(src, dst, loff, len, ALIGN(len, bs), dst_loff, 1);
        btrfs_double_extent_unlock(src, loff, dst, dst_loff, len);
 
        return ret;
@@ -4252,7 +4253,19 @@ static long btrfs_ioctl_scrub(struct file *file, void __user *arg)
                              &sa->progress, sa->flags & BTRFS_SCRUB_READONLY,
                              0);
 
-       if (ret == 0 && copy_to_user(arg, sa, sizeof(*sa)))
+       /*
+        * Copy scrub args to user space even if btrfs_scrub_dev() returned an
+        * error. This is important as it allows user space to know how much
+        * progress scrub has done. For example, if scrub is canceled we get
+        * -ECANCELED from btrfs_scrub_dev() and return that error back to user
+        * space. Later user space can inspect the progress from the structure
+        * btrfs_ioctl_scrub_args and resume scrub from where it left off
+        * previously (btrfs-progs does this).
+        * If we fail to copy the btrfs_ioctl_scrub_args structure to user space
+        * then return -EFAULT to signal the structure was not copied or it may
+        * be corrupt and unreliable due to a partial copy.
+        */
+       if (copy_to_user(arg, sa, sizeof(*sa)))
                ret = -EFAULT;
 
        if (!(sa->flags & BTRFS_SCRUB_READONLY))