diff options
author | Jiri Kosina <jkosina@suse.cz> | 2017-11-15 13:04:13 +0300 |
---|---|---|
committer | Jiri Kosina <jkosina@suse.cz> | 2017-11-15 13:04:13 +0300 |
commit | 5cc619db5c34146ee821acd08382b9d78579b52e (patch) | |
tree | ee28e3cefdb35d56e33887f05db0a50589aa5883 /fs/btrfs/send.c | |
parent | 83fd5ddc19931d5a5b884c43ee3c9d69c673bc96 (diff) | |
parent | 287b8e11972f934052f4ed0751df465a5e84b69c (diff) | |
download | linux-5cc619db5c34146ee821acd08382b9d78579b52e.tar.xz |
Merge branch 'for-4.15/alps' into for-linus
- New ALPS touchpad (T4, found currently on HP EliteBook 1000, Zbook Stduio
and HP Elite book x360) support from Masaki Ota
Diffstat (limited to 'fs/btrfs/send.c')
-rw-r--r-- | fs/btrfs/send.c | 41 |
1 files changed, 25 insertions, 16 deletions
diff --git a/fs/btrfs/send.c b/fs/btrfs/send.c index b082210df9c8..8fd195cfe81b 100644 --- a/fs/btrfs/send.c +++ b/fs/btrfs/send.c @@ -539,33 +539,23 @@ static struct btrfs_path *alloc_path_for_send(void) static int write_buf(struct file *filp, const void *buf, u32 len, loff_t *off) { int ret; - mm_segment_t old_fs; u32 pos = 0; - old_fs = get_fs(); - set_fs(KERNEL_DS); - while (pos < len) { - ret = vfs_write(filp, (__force const char __user *)buf + pos, - len - pos, off); + ret = kernel_write(filp, buf + pos, len - pos, off); /* TODO handle that correctly */ /*if (ret == -ERESTARTSYS) { continue; }*/ if (ret < 0) - goto out; + return ret; if (ret == 0) { - ret = -EIO; - goto out; + return -EIO; } pos += ret; } - ret = 0; - -out: - set_fs(old_fs); - return ret; + return 0; } static int tlv_put(struct send_ctx *sctx, u16 attr, const void *data, int len) @@ -2640,7 +2630,7 @@ static int send_create_inode(struct send_ctx *sctx, u64 ino) } else { btrfs_warn(sctx->send_root->fs_info, "unexpected inode type %o", (int)(mode & S_IFMT)); - ret = -ENOTSUPP; + ret = -EOPNOTSUPP; goto out; } @@ -4733,7 +4723,7 @@ static ssize_t fill_read_buf(struct send_ctx *sctx, u64 offset, u32 len) /* initial readahead */ memset(&sctx->ra, 0, sizeof(struct file_ra_state)); file_ra_state_init(&sctx->ra, inode->i_mapping); - btrfs_force_ra(inode->i_mapping, &sctx->ra, NULL, index, + page_cache_sync_readahead(inode->i_mapping, &sctx->ra, NULL, index, last_index - index + 1); while (index <= last_index) { @@ -4992,6 +4982,25 @@ static int clone_range(struct send_ctx *sctx, struct btrfs_key key; int ret; + /* + * Prevent cloning from a zero offset with a length matching the sector + * size because in some scenarios this will make the receiver fail. + * + * For example, if in the source filesystem the extent at offset 0 + * has a length of sectorsize and it was written using direct IO, then + * it can never be an inline extent (even if compression is enabled). + * Then this extent can be cloned in the original filesystem to a non + * zero file offset, but it may not be possible to clone in the + * destination filesystem because it can be inlined due to compression + * on the destination filesystem (as the receiver's write operations are + * always done using buffered IO). The same happens when the original + * filesystem does not have compression enabled but the destination + * filesystem has. + */ + if (clone_root->offset == 0 && + len == sctx->send_root->fs_info->sectorsize) + return send_extent_data(sctx, offset, len); + path = alloc_path_for_send(); if (!path) return -ENOMEM; |