diff options
Diffstat (limited to 'fs/btrfs/send.c')
-rw-r--r-- | fs/btrfs/send.c | 197 |
1 files changed, 82 insertions, 115 deletions
diff --git a/fs/btrfs/send.c b/fs/btrfs/send.c index e46e0ed74925..945d1db98f26 100644 --- a/fs/btrfs/send.c +++ b/fs/btrfs/send.c | |||
@@ -121,7 +121,6 @@ struct send_ctx { | |||
121 | struct list_head name_cache_list; | 121 | struct list_head name_cache_list; |
122 | int name_cache_size; | 122 | int name_cache_size; |
123 | 123 | ||
124 | struct file *cur_inode_filp; | ||
125 | char *read_buf; | 124 | char *read_buf; |
126 | }; | 125 | }; |
127 | 126 | ||
@@ -565,10 +564,8 @@ static int begin_cmd(struct send_ctx *sctx, int cmd) | |||
565 | { | 564 | { |
566 | struct btrfs_cmd_header *hdr; | 565 | struct btrfs_cmd_header *hdr; |
567 | 566 | ||
568 | if (!sctx->send_buf) { | 567 | if (WARN_ON(!sctx->send_buf)) |
569 | WARN_ON(1); | ||
570 | return -EINVAL; | 568 | return -EINVAL; |
571 | } | ||
572 | 569 | ||
573 | BUG_ON(sctx->send_size); | 570 | BUG_ON(sctx->send_size); |
574 | 571 | ||
@@ -791,7 +788,7 @@ static int iterate_inode_ref(struct btrfs_root *root, struct btrfs_path *path, | |||
791 | if (found_key->type == BTRFS_INODE_REF_KEY) { | 788 | if (found_key->type == BTRFS_INODE_REF_KEY) { |
792 | ptr = (unsigned long)btrfs_item_ptr(eb, slot, | 789 | ptr = (unsigned long)btrfs_item_ptr(eb, slot, |
793 | struct btrfs_inode_ref); | 790 | struct btrfs_inode_ref); |
794 | item = btrfs_item_nr(eb, slot); | 791 | item = btrfs_item_nr(slot); |
795 | total = btrfs_item_size(eb, item); | 792 | total = btrfs_item_size(eb, item); |
796 | elem_size = sizeof(*iref); | 793 | elem_size = sizeof(*iref); |
797 | } else { | 794 | } else { |
@@ -905,7 +902,7 @@ static int iterate_dir_item(struct btrfs_root *root, struct btrfs_path *path, | |||
905 | 902 | ||
906 | eb = path->nodes[0]; | 903 | eb = path->nodes[0]; |
907 | slot = path->slots[0]; | 904 | slot = path->slots[0]; |
908 | item = btrfs_item_nr(eb, slot); | 905 | item = btrfs_item_nr(slot); |
909 | di = btrfs_item_ptr(eb, slot, struct btrfs_dir_item); | 906 | di = btrfs_item_ptr(eb, slot, struct btrfs_dir_item); |
910 | cur = 0; | 907 | cur = 0; |
911 | len = 0; | 908 | len = 0; |
@@ -2120,77 +2117,6 @@ out: | |||
2120 | } | 2117 | } |
2121 | 2118 | ||
2122 | /* | 2119 | /* |
2123 | * Called for regular files when sending extents data. Opens a struct file | ||
2124 | * to read from the file. | ||
2125 | */ | ||
2126 | static int open_cur_inode_file(struct send_ctx *sctx) | ||
2127 | { | ||
2128 | int ret = 0; | ||
2129 | struct btrfs_key key; | ||
2130 | struct path path; | ||
2131 | struct inode *inode; | ||
2132 | struct dentry *dentry; | ||
2133 | struct file *filp; | ||
2134 | int new = 0; | ||
2135 | |||
2136 | if (sctx->cur_inode_filp) | ||
2137 | goto out; | ||
2138 | |||
2139 | key.objectid = sctx->cur_ino; | ||
2140 | key.type = BTRFS_INODE_ITEM_KEY; | ||
2141 | key.offset = 0; | ||
2142 | |||
2143 | inode = btrfs_iget(sctx->send_root->fs_info->sb, &key, sctx->send_root, | ||
2144 | &new); | ||
2145 | if (IS_ERR(inode)) { | ||
2146 | ret = PTR_ERR(inode); | ||
2147 | goto out; | ||
2148 | } | ||
2149 | |||
2150 | dentry = d_obtain_alias(inode); | ||
2151 | inode = NULL; | ||
2152 | if (IS_ERR(dentry)) { | ||
2153 | ret = PTR_ERR(dentry); | ||
2154 | goto out; | ||
2155 | } | ||
2156 | |||
2157 | path.mnt = sctx->mnt; | ||
2158 | path.dentry = dentry; | ||
2159 | filp = dentry_open(&path, O_RDONLY | O_LARGEFILE, current_cred()); | ||
2160 | dput(dentry); | ||
2161 | dentry = NULL; | ||
2162 | if (IS_ERR(filp)) { | ||
2163 | ret = PTR_ERR(filp); | ||
2164 | goto out; | ||
2165 | } | ||
2166 | sctx->cur_inode_filp = filp; | ||
2167 | |||
2168 | out: | ||
2169 | /* | ||
2170 | * no xxxput required here as every vfs op | ||
2171 | * does it by itself on failure | ||
2172 | */ | ||
2173 | return ret; | ||
2174 | } | ||
2175 | |||
2176 | /* | ||
2177 | * Closes the struct file that was created in open_cur_inode_file | ||
2178 | */ | ||
2179 | static int close_cur_inode_file(struct send_ctx *sctx) | ||
2180 | { | ||
2181 | int ret = 0; | ||
2182 | |||
2183 | if (!sctx->cur_inode_filp) | ||
2184 | goto out; | ||
2185 | |||
2186 | ret = filp_close(sctx->cur_inode_filp, NULL); | ||
2187 | sctx->cur_inode_filp = NULL; | ||
2188 | |||
2189 | out: | ||
2190 | return ret; | ||
2191 | } | ||
2192 | |||
2193 | /* | ||
2194 | * Sends a BTRFS_SEND_C_SUBVOL command/item to userspace | 2120 | * Sends a BTRFS_SEND_C_SUBVOL command/item to userspace |
2195 | */ | 2121 | */ |
2196 | static int send_subvol_begin(struct send_ctx *sctx) | 2122 | static int send_subvol_begin(struct send_ctx *sctx) |
@@ -3622,6 +3548,72 @@ out: | |||
3622 | return ret; | 3548 | return ret; |
3623 | } | 3549 | } |
3624 | 3550 | ||
3551 | static ssize_t fill_read_buf(struct send_ctx *sctx, u64 offset, u32 len) | ||
3552 | { | ||
3553 | struct btrfs_root *root = sctx->send_root; | ||
3554 | struct btrfs_fs_info *fs_info = root->fs_info; | ||
3555 | struct inode *inode; | ||
3556 | struct page *page; | ||
3557 | char *addr; | ||
3558 | struct btrfs_key key; | ||
3559 | pgoff_t index = offset >> PAGE_CACHE_SHIFT; | ||
3560 | pgoff_t last_index; | ||
3561 | unsigned pg_offset = offset & ~PAGE_CACHE_MASK; | ||
3562 | ssize_t ret = 0; | ||
3563 | |||
3564 | key.objectid = sctx->cur_ino; | ||
3565 | key.type = BTRFS_INODE_ITEM_KEY; | ||
3566 | key.offset = 0; | ||
3567 | |||
3568 | inode = btrfs_iget(fs_info->sb, &key, root, NULL); | ||
3569 | if (IS_ERR(inode)) | ||
3570 | return PTR_ERR(inode); | ||
3571 | |||
3572 | if (offset + len > i_size_read(inode)) { | ||
3573 | if (offset > i_size_read(inode)) | ||
3574 | len = 0; | ||
3575 | else | ||
3576 | len = offset - i_size_read(inode); | ||
3577 | } | ||
3578 | if (len == 0) | ||
3579 | goto out; | ||
3580 | |||
3581 | last_index = (offset + len - 1) >> PAGE_CACHE_SHIFT; | ||
3582 | while (index <= last_index) { | ||
3583 | unsigned cur_len = min_t(unsigned, len, | ||
3584 | PAGE_CACHE_SIZE - pg_offset); | ||
3585 | page = find_or_create_page(inode->i_mapping, index, GFP_NOFS); | ||
3586 | if (!page) { | ||
3587 | ret = -ENOMEM; | ||
3588 | break; | ||
3589 | } | ||
3590 | |||
3591 | if (!PageUptodate(page)) { | ||
3592 | btrfs_readpage(NULL, page); | ||
3593 | lock_page(page); | ||
3594 | if (!PageUptodate(page)) { | ||
3595 | unlock_page(page); | ||
3596 | page_cache_release(page); | ||
3597 | ret = -EIO; | ||
3598 | break; | ||
3599 | } | ||
3600 | } | ||
3601 | |||
3602 | addr = kmap(page); | ||
3603 | memcpy(sctx->read_buf + ret, addr + pg_offset, cur_len); | ||
3604 | kunmap(page); | ||
3605 | unlock_page(page); | ||
3606 | page_cache_release(page); | ||
3607 | index++; | ||
3608 | pg_offset = 0; | ||
3609 | len -= cur_len; | ||
3610 | ret += cur_len; | ||
3611 | } | ||
3612 | out: | ||
3613 | iput(inode); | ||
3614 | return ret; | ||
3615 | } | ||
3616 | |||
3625 | /* | 3617 | /* |
3626 | * Read some bytes from the current inode/file and send a write command to | 3618 | * Read some bytes from the current inode/file and send a write command to |
3627 | * user space. | 3619 | * user space. |
@@ -3630,35 +3622,20 @@ static int send_write(struct send_ctx *sctx, u64 offset, u32 len) | |||
3630 | { | 3622 | { |
3631 | int ret = 0; | 3623 | int ret = 0; |
3632 | struct fs_path *p; | 3624 | struct fs_path *p; |
3633 | loff_t pos = offset; | 3625 | ssize_t num_read = 0; |
3634 | int num_read = 0; | ||
3635 | mm_segment_t old_fs; | ||
3636 | 3626 | ||
3637 | p = fs_path_alloc(); | 3627 | p = fs_path_alloc(); |
3638 | if (!p) | 3628 | if (!p) |
3639 | return -ENOMEM; | 3629 | return -ENOMEM; |
3640 | 3630 | ||
3641 | /* | ||
3642 | * vfs normally only accepts user space buffers for security reasons. | ||
3643 | * we only read from the file and also only provide the read_buf buffer | ||
3644 | * to vfs. As this buffer does not come from a user space call, it's | ||
3645 | * ok to temporary allow kernel space buffers. | ||
3646 | */ | ||
3647 | old_fs = get_fs(); | ||
3648 | set_fs(KERNEL_DS); | ||
3649 | |||
3650 | verbose_printk("btrfs: send_write offset=%llu, len=%d\n", offset, len); | 3631 | verbose_printk("btrfs: send_write offset=%llu, len=%d\n", offset, len); |
3651 | 3632 | ||
3652 | ret = open_cur_inode_file(sctx); | 3633 | num_read = fill_read_buf(sctx, offset, len); |
3653 | if (ret < 0) | 3634 | if (num_read <= 0) { |
3654 | goto out; | 3635 | if (num_read < 0) |
3655 | 3636 | ret = num_read; | |
3656 | ret = vfs_read(sctx->cur_inode_filp, sctx->read_buf, len, &pos); | ||
3657 | if (ret < 0) | ||
3658 | goto out; | ||
3659 | num_read = ret; | ||
3660 | if (!num_read) | ||
3661 | goto out; | 3637 | goto out; |
3638 | } | ||
3662 | 3639 | ||
3663 | ret = begin_cmd(sctx, BTRFS_SEND_C_WRITE); | 3640 | ret = begin_cmd(sctx, BTRFS_SEND_C_WRITE); |
3664 | if (ret < 0) | 3641 | if (ret < 0) |
@@ -3677,7 +3654,6 @@ verbose_printk("btrfs: send_write offset=%llu, len=%d\n", offset, len); | |||
3677 | tlv_put_failure: | 3654 | tlv_put_failure: |
3678 | out: | 3655 | out: |
3679 | fs_path_free(p); | 3656 | fs_path_free(p); |
3680 | set_fs(old_fs); | ||
3681 | if (ret < 0) | 3657 | if (ret < 0) |
3682 | return ret; | 3658 | return ret; |
3683 | return num_read; | 3659 | return num_read; |
@@ -3926,16 +3902,16 @@ static int is_extent_unchanged(struct send_ctx *sctx, | |||
3926 | while (key.offset < ekey->offset + left_len) { | 3902 | while (key.offset < ekey->offset + left_len) { |
3927 | ei = btrfs_item_ptr(eb, slot, struct btrfs_file_extent_item); | 3903 | ei = btrfs_item_ptr(eb, slot, struct btrfs_file_extent_item); |
3928 | right_type = btrfs_file_extent_type(eb, ei); | 3904 | right_type = btrfs_file_extent_type(eb, ei); |
3929 | right_disknr = btrfs_file_extent_disk_bytenr(eb, ei); | ||
3930 | right_len = btrfs_file_extent_num_bytes(eb, ei); | ||
3931 | right_offset = btrfs_file_extent_offset(eb, ei); | ||
3932 | right_gen = btrfs_file_extent_generation(eb, ei); | ||
3933 | |||
3934 | if (right_type != BTRFS_FILE_EXTENT_REG) { | 3905 | if (right_type != BTRFS_FILE_EXTENT_REG) { |
3935 | ret = 0; | 3906 | ret = 0; |
3936 | goto out; | 3907 | goto out; |
3937 | } | 3908 | } |
3938 | 3909 | ||
3910 | right_disknr = btrfs_file_extent_disk_bytenr(eb, ei); | ||
3911 | right_len = btrfs_file_extent_num_bytes(eb, ei); | ||
3912 | right_offset = btrfs_file_extent_offset(eb, ei); | ||
3913 | right_gen = btrfs_file_extent_generation(eb, ei); | ||
3914 | |||
3939 | /* | 3915 | /* |
3940 | * Are we at extent 8? If yes, we know the extent is changed. | 3916 | * Are we at extent 8? If yes, we know the extent is changed. |
3941 | * This may only happen on the first iteration. | 3917 | * This may only happen on the first iteration. |
@@ -4222,10 +4198,6 @@ static int changed_inode(struct send_ctx *sctx, | |||
4222 | u64 left_gen = 0; | 4198 | u64 left_gen = 0; |
4223 | u64 right_gen = 0; | 4199 | u64 right_gen = 0; |
4224 | 4200 | ||
4225 | ret = close_cur_inode_file(sctx); | ||
4226 | if (ret < 0) | ||
4227 | goto out; | ||
4228 | |||
4229 | sctx->cur_ino = key->objectid; | 4201 | sctx->cur_ino = key->objectid; |
4230 | sctx->cur_inode_new_gen = 0; | 4202 | sctx->cur_inode_new_gen = 0; |
4231 | 4203 | ||
@@ -4686,11 +4658,6 @@ static int send_subvol(struct send_ctx *sctx) | |||
4686 | } | 4658 | } |
4687 | 4659 | ||
4688 | out: | 4660 | out: |
4689 | if (!ret) | ||
4690 | ret = close_cur_inode_file(sctx); | ||
4691 | else | ||
4692 | close_cur_inode_file(sctx); | ||
4693 | |||
4694 | free_recorded_refs(sctx); | 4661 | free_recorded_refs(sctx); |
4695 | return ret; | 4662 | return ret; |
4696 | } | 4663 | } |
@@ -4756,8 +4723,8 @@ long btrfs_ioctl_send(struct file *mnt_file, void __user *arg_) | |||
4756 | } | 4723 | } |
4757 | 4724 | ||
4758 | if (!access_ok(VERIFY_READ, arg->clone_sources, | 4725 | if (!access_ok(VERIFY_READ, arg->clone_sources, |
4759 | sizeof(*arg->clone_sources * | 4726 | sizeof(*arg->clone_sources) * |
4760 | arg->clone_sources_count))) { | 4727 | arg->clone_sources_count)) { |
4761 | ret = -EFAULT; | 4728 | ret = -EFAULT; |
4762 | goto out; | 4729 | goto out; |
4763 | } | 4730 | } |