diff options
author | Paolo Bonzini <pbonzini@redhat.com> | 2024-09-02 10:55:27 -0400 |
---|---|---|
committer | Paolo Bonzini <pbonzini@redhat.com> | 2024-09-02 10:55:27 -0400 |
commit | 1ae99594fb7a7e78de7b1adf0feb4f681937a28e (patch) | |
tree | eb243e1ba67336a21605b23265eb6259a2a9201b /fs/btrfs/send.c | |
parent | 66155de93bcf4f2967e602a4b3bf7ebe58f34b11 (diff) | |
parent | 5fa9f0480c7985e44e6ec32def0a395b768599cc (diff) |
Merge tag 'kvm-x86-fixes-6.11-rcN' of https://github.com/kvm-x86/linux into kvm-master
KVM x86 fixes for 6.11
- Fixup missed comments from the REMOVED_SPTE=>FROZEN_SPTE rename.
- Ensure a root is successfully loaded when pre-faulting SPTEs.
- Grab kvm->srcu when handling KVM_SET_VCPU_EVENTS to guard against accessing
memslots if toggling SMM happens to force a VM-Exit.
- Emulate MSR_{FS,GS}_BASE on SVM even though interception is always disabled,
so that KVM does the right thing if KVM's emulator encounters {RD,WR}MSR.
- Explicitly clear BUS_LOCK_DETECT from KVM's caps on AMD, as KVM doesn't yet
virtualize BUS_LOCK_DETECT on AMD.
- Cleanup the help message for CONFIG_KVM_AMD_SEV, and call out that KVM now
supports SEV-SNP too.
Diffstat (limited to 'fs/btrfs/send.c')
-rw-r--r-- | fs/btrfs/send.c | 54 |
1 files changed, 40 insertions, 14 deletions
diff --git a/fs/btrfs/send.c b/fs/btrfs/send.c index 4ca711a773ef..619fa0b8b3f6 100644 --- a/fs/btrfs/send.c +++ b/fs/btrfs/send.c @@ -347,7 +347,7 @@ struct name_cache_entry { int ret; int need_later_update; int name_len; - char name[]; + char name[] __counted_by(name_len); }; /* See the comment at lru_cache.h about struct btrfs_lru_cache_entry. */ @@ -6157,25 +6157,51 @@ static int send_write_or_clone(struct send_ctx *sctx, u64 offset = key->offset; u64 end; u64 bs = sctx->send_root->fs_info->sectorsize; + struct btrfs_file_extent_item *ei; + u64 disk_byte; + u64 data_offset; + u64 num_bytes; + struct btrfs_inode_info info = { 0 }; end = min_t(u64, btrfs_file_extent_end(path), sctx->cur_inode_size); if (offset >= end) return 0; - if (clone_root && IS_ALIGNED(end, bs)) { - struct btrfs_file_extent_item *ei; - u64 disk_byte; - u64 data_offset; + num_bytes = end - offset; - ei = btrfs_item_ptr(path->nodes[0], path->slots[0], - struct btrfs_file_extent_item); - disk_byte = btrfs_file_extent_disk_bytenr(path->nodes[0], ei); - data_offset = btrfs_file_extent_offset(path->nodes[0], ei); - ret = clone_range(sctx, path, clone_root, disk_byte, - data_offset, offset, end - offset); - } else { - ret = send_extent_data(sctx, path, offset, end - offset); - } + if (!clone_root) + goto write_data; + + if (IS_ALIGNED(end, bs)) + goto clone_data; + + /* + * If the extent end is not aligned, we can clone if the extent ends at + * the i_size of the inode and the clone range ends at the i_size of the + * source inode, otherwise the clone operation fails with -EINVAL. + */ + if (end != sctx->cur_inode_size) + goto write_data; + + ret = get_inode_info(clone_root->root, clone_root->ino, &info); + if (ret < 0) + return ret; + + if (clone_root->offset + num_bytes == info.size) + goto clone_data; + +write_data: + ret = send_extent_data(sctx, path, offset, num_bytes); + sctx->cur_inode_next_write_offset = end; + return ret; + +clone_data: + ei = btrfs_item_ptr(path->nodes[0], path->slots[0], + struct btrfs_file_extent_item); + disk_byte = btrfs_file_extent_disk_bytenr(path->nodes[0], ei); + data_offset = btrfs_file_extent_offset(path->nodes[0], ei); + ret = clone_range(sctx, path, clone_root, disk_byte, data_offset, offset, + num_bytes); sctx->cur_inode_next_write_offset = end; return ret; } |