]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - fs/btrfs/send.c
Merge tag 'sound-fix-4.12-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai...
[karo-tx-linux.git] / fs / btrfs / send.c
index a60d5bfb8a49e2bfc3faef10f4ea353a9da5f8b8..fc496a6f842a87d3544e80b3b9e063d57417f788 100644 (file)
@@ -5184,13 +5184,19 @@ static int is_extent_unchanged(struct send_ctx *sctx,
        while (key.offset < ekey->offset + left_len) {
                ei = btrfs_item_ptr(eb, slot, struct btrfs_file_extent_item);
                right_type = btrfs_file_extent_type(eb, ei);
-               if (right_type != BTRFS_FILE_EXTENT_REG) {
+               if (right_type != BTRFS_FILE_EXTENT_REG &&
+                   right_type != BTRFS_FILE_EXTENT_INLINE) {
                        ret = 0;
                        goto out;
                }
 
                right_disknr = btrfs_file_extent_disk_bytenr(eb, ei);
-               right_len = btrfs_file_extent_num_bytes(eb, ei);
+               if (right_type == BTRFS_FILE_EXTENT_INLINE) {
+                       right_len = btrfs_file_extent_inline_len(eb, slot, ei);
+                       right_len = PAGE_ALIGN(right_len);
+               } else {
+                       right_len = btrfs_file_extent_num_bytes(eb, ei);
+               }
                right_offset = btrfs_file_extent_offset(eb, ei);
                right_gen = btrfs_file_extent_generation(eb, ei);
 
@@ -5204,6 +5210,19 @@ static int is_extent_unchanged(struct send_ctx *sctx,
                        goto out;
                }
 
+               /*
+                * We just wanted to see if when we have an inline extent, what
+                * follows it is a regular extent (wanted to check the above
+                * condition for inline extents too). This should normally not
+                * happen but it's possible for example when we have an inline
+                * compressed extent representing data with a size matching
+                * the page size (currently the same as sector size).
+                */
+               if (right_type == BTRFS_FILE_EXTENT_INLINE) {
+                       ret = 0;
+                       goto out;
+               }
+
                left_offset_fixed = left_offset;
                if (key.offset < ekey->offset) {
                        /* Fix the right offset for 2a and 7. */
@@ -6360,22 +6379,16 @@ long btrfs_ioctl_send(struct file *mnt_file, void __user *arg_)
        sctx->clone_roots_cnt = arg->clone_sources_count;
 
        sctx->send_max_size = BTRFS_SEND_BUF_SIZE;
-       sctx->send_buf = kmalloc(sctx->send_max_size, GFP_KERNEL | __GFP_NOWARN);
+       sctx->send_buf = kvmalloc(sctx->send_max_size, GFP_KERNEL);
        if (!sctx->send_buf) {
-               sctx->send_buf = vmalloc(sctx->send_max_size);
-               if (!sctx->send_buf) {
-                       ret = -ENOMEM;
-                       goto out;
-               }
+               ret = -ENOMEM;
+               goto out;
        }
 
-       sctx->read_buf = kmalloc(BTRFS_SEND_READ_SIZE, GFP_KERNEL | __GFP_NOWARN);
+       sctx->read_buf = kvmalloc(BTRFS_SEND_READ_SIZE, GFP_KERNEL);
        if (!sctx->read_buf) {
-               sctx->read_buf = vmalloc(BTRFS_SEND_READ_SIZE);
-               if (!sctx->read_buf) {
-                       ret = -ENOMEM;
-                       goto out;
-               }
+               ret = -ENOMEM;
+               goto out;
        }
 
        sctx->pending_dir_moves = RB_ROOT;
@@ -6396,13 +6409,10 @@ long btrfs_ioctl_send(struct file *mnt_file, void __user *arg_)
        alloc_size = arg->clone_sources_count * sizeof(*arg->clone_sources);
 
        if (arg->clone_sources_count) {
-               clone_sources_tmp = kmalloc(alloc_size, GFP_KERNEL | __GFP_NOWARN);
+               clone_sources_tmp = kvmalloc(alloc_size, GFP_KERNEL);
                if (!clone_sources_tmp) {
-                       clone_sources_tmp = vmalloc(alloc_size);
-                       if (!clone_sources_tmp) {
-                               ret = -ENOMEM;
-                               goto out;
-                       }
+                       ret = -ENOMEM;
+                       goto out;
                }
 
                ret = copy_from_user(clone_sources_tmp, arg->clone_sources,