^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Copyright (C) 2007 Oracle. All rights reserved.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) #include <linux/bio.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/pagemap.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/highmem.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/sched/mm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <crypto/hash.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include "ctree.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include "disk-io.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include "transaction.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include "volumes.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include "print-tree.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include "compression.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #define __MAX_CSUM_ITEMS(r, size) ((unsigned long)(((BTRFS_LEAF_DATA_SIZE(r) - \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) sizeof(struct btrfs_item) * 2) / \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) size) - 1))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #define MAX_CSUM_ITEMS(r, size) (min_t(u32, __MAX_CSUM_ITEMS(r, size), \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) PAGE_SIZE))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) * @inode - the inode we want to update the disk_i_size for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) * @new_i_size - the i_size we want to set to, 0 if we use i_size
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) * With NO_HOLES set this simply sets the disk_is_size to whatever i_size_read()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) * returns as it is perfectly fine with a file that has holes without hole file
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) * extent items.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) * However without NO_HOLES we need to only return the area that is contiguous
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) * from the 0 offset of the file. Otherwise we could end up adjust i_size up
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) * to an extent that has a gap in between.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) * Finally new_i_size should only be set in the case of truncate where we're not
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) * ready to use i_size_read() as the limiter yet.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) void btrfs_inode_safe_disk_i_size_write(struct inode *inode, u64 new_i_size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) struct btrfs_fs_info *fs_info = BTRFS_I(inode)->root->fs_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) u64 start, end, i_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) i_size = new_i_size ?: i_size_read(inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) if (btrfs_fs_incompat(fs_info, NO_HOLES)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) BTRFS_I(inode)->disk_i_size = i_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) spin_lock(&BTRFS_I(inode)->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) ret = find_contiguous_extent_bit(&BTRFS_I(inode)->file_extent_tree, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) &start, &end, EXTENT_DIRTY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) if (!ret && start == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) i_size = min(i_size, end + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) i_size = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) BTRFS_I(inode)->disk_i_size = i_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) spin_unlock(&BTRFS_I(inode)->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) * @inode - the inode we're modifying
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) * @start - the start file offset of the file extent we've inserted
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) * @len - the logical length of the file extent item
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) * Call when we are inserting a new file extent where there was none before.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) * Does not need to call this in the case where we're replacing an existing file
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) * extent, however if not sure it's fine to call this multiple times.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) * The start and len must match the file extent item, so thus must be sectorsize
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) * aligned.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) int btrfs_inode_set_file_extent_range(struct btrfs_inode *inode, u64 start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) u64 len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) if (len == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) ASSERT(IS_ALIGNED(start + len, inode->root->fs_info->sectorsize));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) if (btrfs_fs_incompat(inode->root->fs_info, NO_HOLES))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) return set_extent_bits(&inode->file_extent_tree, start, start + len - 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) EXTENT_DIRTY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) * @inode - the inode we're modifying
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) * @start - the start file offset of the file extent we've inserted
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) * @len - the logical length of the file extent item
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) * Called when we drop a file extent, for example when we truncate. Doesn't
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) * need to be called for cases where we're replacing a file extent, like when
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) * we've COWed a file extent.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) * The start and len must match the file extent item, so thus must be sectorsize
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) * aligned.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) int btrfs_inode_clear_file_extent_range(struct btrfs_inode *inode, u64 start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) u64 len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) if (len == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) ASSERT(IS_ALIGNED(start + len, inode->root->fs_info->sectorsize) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) len == (u64)-1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) if (btrfs_fs_incompat(inode->root->fs_info, NO_HOLES))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) return clear_extent_bit(&inode->file_extent_tree, start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) start + len - 1, EXTENT_DIRTY, 0, 0, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) static inline u32 max_ordered_sum_bytes(struct btrfs_fs_info *fs_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) u16 csum_size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) u32 ncsums = (PAGE_SIZE - sizeof(struct btrfs_ordered_sum)) / csum_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) return ncsums * fs_info->sectorsize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) int btrfs_insert_file_extent(struct btrfs_trans_handle *trans,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) struct btrfs_root *root,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) u64 objectid, u64 pos,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) u64 disk_offset, u64 disk_num_bytes,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) u64 num_bytes, u64 offset, u64 ram_bytes,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) u8 compression, u8 encryption, u16 other_encoding)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) struct btrfs_file_extent_item *item;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) struct btrfs_key file_key;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) struct btrfs_path *path;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) struct extent_buffer *leaf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) path = btrfs_alloc_path();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) if (!path)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) file_key.objectid = objectid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) file_key.offset = pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) file_key.type = BTRFS_EXTENT_DATA_KEY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) path->leave_spinning = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) ret = btrfs_insert_empty_item(trans, root, path, &file_key,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) sizeof(*item));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) BUG_ON(ret); /* Can't happen */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) leaf = path->nodes[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) item = btrfs_item_ptr(leaf, path->slots[0],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) struct btrfs_file_extent_item);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) btrfs_set_file_extent_disk_bytenr(leaf, item, disk_offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) btrfs_set_file_extent_disk_num_bytes(leaf, item, disk_num_bytes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) btrfs_set_file_extent_offset(leaf, item, offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) btrfs_set_file_extent_num_bytes(leaf, item, num_bytes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) btrfs_set_file_extent_ram_bytes(leaf, item, ram_bytes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) btrfs_set_file_extent_generation(leaf, item, trans->transid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) btrfs_set_file_extent_type(leaf, item, BTRFS_FILE_EXTENT_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) btrfs_set_file_extent_compression(leaf, item, compression);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) btrfs_set_file_extent_encryption(leaf, item, encryption);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) btrfs_set_file_extent_other_encoding(leaf, item, other_encoding);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) btrfs_mark_buffer_dirty(leaf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) btrfs_free_path(path);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) static struct btrfs_csum_item *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) btrfs_lookup_csum(struct btrfs_trans_handle *trans,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) struct btrfs_root *root,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) struct btrfs_path *path,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) u64 bytenr, int cow)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) struct btrfs_fs_info *fs_info = root->fs_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) struct btrfs_key file_key;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) struct btrfs_key found_key;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) struct btrfs_csum_item *item;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) struct extent_buffer *leaf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) u64 csum_offset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) u16 csum_size = btrfs_super_csum_size(fs_info->super_copy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) int csums_in_item;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) file_key.objectid = BTRFS_EXTENT_CSUM_OBJECTID;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) file_key.offset = bytenr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) file_key.type = BTRFS_EXTENT_CSUM_KEY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) ret = btrfs_search_slot(trans, root, &file_key, path, 0, cow);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) leaf = path->nodes[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) if (ret > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) ret = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) if (path->slots[0] == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) path->slots[0]--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) if (found_key.type != BTRFS_EXTENT_CSUM_KEY)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) csum_offset = (bytenr - found_key.offset) >>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) fs_info->sb->s_blocksize_bits;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) csums_in_item = btrfs_item_size_nr(leaf, path->slots[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) csums_in_item /= csum_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) if (csum_offset == csums_in_item) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) ret = -EFBIG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) } else if (csum_offset > csums_in_item) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) item = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_csum_item);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) item = (struct btrfs_csum_item *)((unsigned char *)item +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) csum_offset * csum_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) return item;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) fail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) if (ret > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) ret = -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) return ERR_PTR(ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) int btrfs_lookup_file_extent(struct btrfs_trans_handle *trans,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) struct btrfs_root *root,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) struct btrfs_path *path, u64 objectid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) u64 offset, int mod)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) struct btrfs_key file_key;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) int ins_len = mod < 0 ? -1 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) int cow = mod != 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) file_key.objectid = objectid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) file_key.offset = offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) file_key.type = BTRFS_EXTENT_DATA_KEY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) ret = btrfs_search_slot(trans, root, &file_key, path, ins_len, cow);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) * btrfs_lookup_bio_sums - Look up checksums for a bio.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) * @inode: inode that the bio is for.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) * @bio: bio to look up.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) * @offset: Unless (u64)-1, look up checksums for this offset in the file.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) * If (u64)-1, use the page offsets from the bio instead.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) * @dst: Buffer of size nblocks * btrfs_super_csum_size() used to return
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) * checksum (nblocks = bio->bi_iter.bi_size / fs_info->sectorsize). If
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) * NULL, the checksum buffer is allocated and returned in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) * btrfs_io_bio(bio)->csum instead.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) * Return: BLK_STS_RESOURCE if allocating memory fails, BLK_STS_OK otherwise.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) blk_status_t btrfs_lookup_bio_sums(struct inode *inode, struct bio *bio,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) u64 offset, u8 *dst)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) struct bio_vec bvec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) struct bvec_iter iter;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) struct btrfs_csum_item *item = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) struct extent_io_tree *io_tree = &BTRFS_I(inode)->io_tree;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) struct btrfs_path *path;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) const bool page_offsets = (offset == (u64)-1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) u8 *csum;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) u64 item_start_offset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) u64 item_last_offset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) u64 disk_bytenr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) u64 page_bytes_left;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) u32 diff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) int nblocks;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) int count = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) u16 csum_size = btrfs_super_csum_size(fs_info->super_copy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) path = btrfs_alloc_path();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) if (!path)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) return BLK_STS_RESOURCE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) nblocks = bio->bi_iter.bi_size >> inode->i_sb->s_blocksize_bits;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) if (!dst) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) struct btrfs_io_bio *btrfs_bio = btrfs_io_bio(bio);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) if (nblocks * csum_size > BTRFS_BIO_INLINE_CSUM_SIZE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) btrfs_bio->csum = kmalloc_array(nblocks, csum_size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) GFP_NOFS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) if (!btrfs_bio->csum) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) btrfs_free_path(path);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) return BLK_STS_RESOURCE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) btrfs_bio->csum = btrfs_bio->csum_inline;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) csum = btrfs_bio->csum;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) csum = dst;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) if (bio->bi_iter.bi_size > PAGE_SIZE * 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) path->reada = READA_FORWARD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) * the free space stuff is only read when it hasn't been
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) * updated in the current transaction. So, we can safely
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) * read from the commit root and sidestep a nasty deadlock
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) * between reading the free space cache and updating the csum tree.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) if (btrfs_is_free_space_inode(BTRFS_I(inode))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) path->search_commit_root = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) path->skip_locking = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) disk_bytenr = (u64)bio->bi_iter.bi_sector << 9;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) bio_for_each_segment(bvec, bio, iter) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) page_bytes_left = bvec.bv_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) if (count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) goto next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) if (page_offsets)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) offset = page_offset(bvec.bv_page) + bvec.bv_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) count = btrfs_find_ordered_sum(BTRFS_I(inode), offset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) disk_bytenr, csum, nblocks);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) if (count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) goto found;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) if (!item || disk_bytenr < item_start_offset ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) disk_bytenr >= item_last_offset) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) struct btrfs_key found_key;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) u32 item_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) if (item)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) btrfs_release_path(path);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) item = btrfs_lookup_csum(NULL, fs_info->csum_root,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) path, disk_bytenr, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) if (IS_ERR(item)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) count = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) memset(csum, 0, csum_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) if (BTRFS_I(inode)->root->root_key.objectid ==
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) BTRFS_DATA_RELOC_TREE_OBJECTID) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) set_extent_bits(io_tree, offset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) offset + fs_info->sectorsize - 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) EXTENT_NODATASUM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) btrfs_info_rl(fs_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) "no csum found for inode %llu start %llu",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) btrfs_ino(BTRFS_I(inode)), offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) item = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) btrfs_release_path(path);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) goto found;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) btrfs_item_key_to_cpu(path->nodes[0], &found_key,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) path->slots[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) item_start_offset = found_key.offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) item_size = btrfs_item_size_nr(path->nodes[0],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) path->slots[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) item_last_offset = item_start_offset +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) (item_size / csum_size) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) fs_info->sectorsize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) item = btrfs_item_ptr(path->nodes[0], path->slots[0],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) struct btrfs_csum_item);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) * this byte range must be able to fit inside
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) * a single leaf so it will also fit inside a u32
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) diff = disk_bytenr - item_start_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) diff = diff / fs_info->sectorsize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) diff = diff * csum_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) count = min_t(int, nblocks, (item_last_offset - disk_bytenr) >>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) inode->i_sb->s_blocksize_bits);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) read_extent_buffer(path->nodes[0], csum,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) ((unsigned long)item) + diff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) csum_size * count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) found:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) csum += count * csum_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) nblocks -= count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) next:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) while (count > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) count--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) disk_bytenr += fs_info->sectorsize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) offset += fs_info->sectorsize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) page_bytes_left -= fs_info->sectorsize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) if (!page_bytes_left)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) break; /* move to next bio */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) WARN_ON_ONCE(count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) btrfs_free_path(path);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) return BLK_STS_OK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) int btrfs_lookup_csums_range(struct btrfs_root *root, u64 start, u64 end,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) struct list_head *list, int search_commit)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) struct btrfs_fs_info *fs_info = root->fs_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) struct btrfs_key key;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) struct btrfs_path *path;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) struct extent_buffer *leaf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) struct btrfs_ordered_sum *sums;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) struct btrfs_csum_item *item;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) LIST_HEAD(tmplist);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) unsigned long offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) size_t size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) u64 csum_end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) u16 csum_size = btrfs_super_csum_size(fs_info->super_copy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) ASSERT(IS_ALIGNED(start, fs_info->sectorsize) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) IS_ALIGNED(end + 1, fs_info->sectorsize));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) path = btrfs_alloc_path();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) if (!path)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) if (search_commit) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) path->skip_locking = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) path->reada = READA_FORWARD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) path->search_commit_root = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) key.objectid = BTRFS_EXTENT_CSUM_OBJECTID;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) key.offset = start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) key.type = BTRFS_EXTENT_CSUM_KEY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) if (ret > 0 && path->slots[0] > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) leaf = path->nodes[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) btrfs_item_key_to_cpu(leaf, &key, path->slots[0] - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) if (key.objectid == BTRFS_EXTENT_CSUM_OBJECTID &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) key.type == BTRFS_EXTENT_CSUM_KEY) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) offset = (start - key.offset) >>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) fs_info->sb->s_blocksize_bits;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) if (offset * csum_size <
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) btrfs_item_size_nr(leaf, path->slots[0] - 1))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) path->slots[0]--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) while (start <= end) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) leaf = path->nodes[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) if (path->slots[0] >= btrfs_header_nritems(leaf)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) ret = btrfs_next_leaf(root, path);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) if (ret > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) leaf = path->nodes[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) btrfs_item_key_to_cpu(leaf, &key, path->slots[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) if (key.objectid != BTRFS_EXTENT_CSUM_OBJECTID ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) key.type != BTRFS_EXTENT_CSUM_KEY ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) key.offset > end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) if (key.offset > start)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) start = key.offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) size = btrfs_item_size_nr(leaf, path->slots[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) csum_end = key.offset + (size / csum_size) * fs_info->sectorsize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) if (csum_end <= start) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) path->slots[0]++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) csum_end = min(csum_end, end + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) item = btrfs_item_ptr(path->nodes[0], path->slots[0],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) struct btrfs_csum_item);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) while (start < csum_end) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) size = min_t(size_t, csum_end - start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) max_ordered_sum_bytes(fs_info, csum_size));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) sums = kzalloc(btrfs_ordered_sum_size(fs_info, size),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) GFP_NOFS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) if (!sums) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) sums->bytenr = start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) sums->len = (int)size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) offset = (start - key.offset) >>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) fs_info->sb->s_blocksize_bits;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) offset *= csum_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) size >>= fs_info->sb->s_blocksize_bits;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) read_extent_buffer(path->nodes[0],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) sums->sums,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) ((unsigned long)item) + offset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) csum_size * size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) start += fs_info->sectorsize * size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) list_add_tail(&sums->list, &tmplist);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) path->slots[0]++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) fail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) while (ret < 0 && !list_empty(&tmplist)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) sums = list_entry(tmplist.next, struct btrfs_ordered_sum, list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) list_del(&sums->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) kfree(sums);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) list_splice_tail(&tmplist, list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) btrfs_free_path(path);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) * btrfs_csum_one_bio - Calculates checksums of the data contained inside a bio
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) * @inode: Owner of the data inside the bio
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) * @bio: Contains the data to be checksummed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) * @file_start: offset in file this bio begins to describe
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) * @contig: Boolean. If true/1 means all bio vecs in this bio are
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) * contiguous and they begin at @file_start in the file. False/0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) * means this bio can contains potentially discontigous bio vecs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) * so the logical offset of each should be calculated separately.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) blk_status_t btrfs_csum_one_bio(struct btrfs_inode *inode, struct bio *bio,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) u64 file_start, int contig)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) struct btrfs_fs_info *fs_info = inode->root->fs_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) SHASH_DESC_ON_STACK(shash, fs_info->csum_shash);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) struct btrfs_ordered_sum *sums;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) struct btrfs_ordered_extent *ordered = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) char *data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) struct bvec_iter iter;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) struct bio_vec bvec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) int index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) int nr_sectors;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) unsigned long total_bytes = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) unsigned long this_sum_bytes = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) u64 offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) unsigned nofs_flag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) const u16 csum_size = btrfs_super_csum_size(fs_info->super_copy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) nofs_flag = memalloc_nofs_save();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) sums = kvzalloc(btrfs_ordered_sum_size(fs_info, bio->bi_iter.bi_size),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) memalloc_nofs_restore(nofs_flag);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) if (!sums)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) return BLK_STS_RESOURCE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) sums->len = bio->bi_iter.bi_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) INIT_LIST_HEAD(&sums->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) if (contig)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) offset = file_start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) offset = 0; /* shut up gcc */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) sums->bytenr = (u64)bio->bi_iter.bi_sector << 9;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) index = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) shash->tfm = fs_info->csum_shash;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) bio_for_each_segment(bvec, bio, iter) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) if (!contig)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) offset = page_offset(bvec.bv_page) + bvec.bv_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) if (!ordered) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) ordered = btrfs_lookup_ordered_extent(inode, offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) * The bio range is not covered by any ordered extent,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) * must be a code logic error.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) if (unlikely(!ordered)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) WARN(1, KERN_WARNING
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) "no ordered extent for root %llu ino %llu offset %llu\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) inode->root->root_key.objectid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) btrfs_ino(inode), offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) kvfree(sums);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) return BLK_STS_IOERR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) nr_sectors = BTRFS_BYTES_TO_BLKS(fs_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) bvec.bv_len + fs_info->sectorsize
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) for (i = 0; i < nr_sectors; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) if (offset >= ordered->file_offset + ordered->num_bytes ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) offset < ordered->file_offset) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) unsigned long bytes_left;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) sums->len = this_sum_bytes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) this_sum_bytes = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) btrfs_add_ordered_sum(ordered, sums);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) btrfs_put_ordered_extent(ordered);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) bytes_left = bio->bi_iter.bi_size - total_bytes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) nofs_flag = memalloc_nofs_save();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) sums = kvzalloc(btrfs_ordered_sum_size(fs_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) bytes_left), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) memalloc_nofs_restore(nofs_flag);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) BUG_ON(!sums); /* -ENOMEM */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) sums->len = bytes_left;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) ordered = btrfs_lookup_ordered_extent(inode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) ASSERT(ordered); /* Logic error */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) sums->bytenr = ((u64)bio->bi_iter.bi_sector << 9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) + total_bytes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) index = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) data = kmap_atomic(bvec.bv_page);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) crypto_shash_digest(shash, data + bvec.bv_offset
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) + (i * fs_info->sectorsize),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) fs_info->sectorsize,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) sums->sums + index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) kunmap_atomic(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) index += csum_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) offset += fs_info->sectorsize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) this_sum_bytes += fs_info->sectorsize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) total_bytes += fs_info->sectorsize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) this_sum_bytes = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) btrfs_add_ordered_sum(ordered, sums);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) btrfs_put_ordered_extent(ordered);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) * helper function for csum removal, this expects the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) * key to describe the csum pointed to by the path, and it expects
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) * the csum to overlap the range [bytenr, len]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) * The csum should not be entirely contained in the range and the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) * range should not be entirely contained in the csum.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) * This calls btrfs_truncate_item with the correct args based on the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) * overlap, and fixes up the key as required.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) static noinline void truncate_one_csum(struct btrfs_fs_info *fs_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) struct btrfs_path *path,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) struct btrfs_key *key,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) u64 bytenr, u64 len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) struct extent_buffer *leaf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) u16 csum_size = btrfs_super_csum_size(fs_info->super_copy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) u64 csum_end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) u64 end_byte = bytenr + len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) u32 blocksize_bits = fs_info->sb->s_blocksize_bits;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) leaf = path->nodes[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) csum_end = btrfs_item_size_nr(leaf, path->slots[0]) / csum_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) csum_end <<= fs_info->sb->s_blocksize_bits;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) csum_end += key->offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) if (key->offset < bytenr && csum_end <= end_byte) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) * [ bytenr - len ]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) * [ ]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) * [csum ]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) * A simple truncate off the end of the item
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) u32 new_size = (bytenr - key->offset) >> blocksize_bits;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) new_size *= csum_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) btrfs_truncate_item(path, new_size, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) } else if (key->offset >= bytenr && csum_end > end_byte &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) end_byte > key->offset) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) * [ bytenr - len ]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) * [ ]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) * [csum ]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) * we need to truncate from the beginning of the csum
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) u32 new_size = (csum_end - end_byte) >> blocksize_bits;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) new_size *= csum_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) btrfs_truncate_item(path, new_size, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) key->offset = end_byte;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) btrfs_set_item_key_safe(fs_info, path, key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) BUG();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) * deletes the csum items from the csum tree for a given
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) * range of bytes.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) int btrfs_del_csums(struct btrfs_trans_handle *trans,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) struct btrfs_root *root, u64 bytenr, u64 len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) struct btrfs_fs_info *fs_info = trans->fs_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) struct btrfs_path *path;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) struct btrfs_key key;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) u64 end_byte = bytenr + len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) u64 csum_end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) struct extent_buffer *leaf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) u16 csum_size = btrfs_super_csum_size(fs_info->super_copy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) int blocksize_bits = fs_info->sb->s_blocksize_bits;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) ASSERT(root == fs_info->csum_root ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) root->root_key.objectid == BTRFS_TREE_LOG_OBJECTID);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) path = btrfs_alloc_path();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) if (!path)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) while (1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) key.objectid = BTRFS_EXTENT_CSUM_OBJECTID;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) key.offset = end_byte - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) key.type = BTRFS_EXTENT_CSUM_KEY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) path->leave_spinning = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) ret = btrfs_search_slot(trans, root, &key, path, -1, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) if (ret > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) if (path->slots[0] == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) path->slots[0]--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) } else if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) leaf = path->nodes[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) btrfs_item_key_to_cpu(leaf, &key, path->slots[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) if (key.objectid != BTRFS_EXTENT_CSUM_OBJECTID ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) key.type != BTRFS_EXTENT_CSUM_KEY) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) if (key.offset >= end_byte)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) csum_end = btrfs_item_size_nr(leaf, path->slots[0]) / csum_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) csum_end <<= blocksize_bits;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) csum_end += key.offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) /* this csum ends before we start, we're done */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) if (csum_end <= bytenr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) /* delete the entire item, it is inside our range */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) if (key.offset >= bytenr && csum_end <= end_byte) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) int del_nr = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) * Check how many csum items preceding this one in this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) * leaf correspond to our range and then delete them all
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) * at once.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) if (key.offset > bytenr && path->slots[0] > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) int slot = path->slots[0] - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) while (slot >= 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) struct btrfs_key pk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) btrfs_item_key_to_cpu(leaf, &pk, slot);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) if (pk.offset < bytenr ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) pk.type != BTRFS_EXTENT_CSUM_KEY ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) pk.objectid !=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) BTRFS_EXTENT_CSUM_OBJECTID)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) path->slots[0] = slot;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) del_nr++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) key.offset = pk.offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) slot--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) ret = btrfs_del_items(trans, root, path,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) path->slots[0], del_nr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) if (key.offset == bytenr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) } else if (key.offset < bytenr && csum_end > end_byte) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) unsigned long offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) unsigned long shift_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) unsigned long item_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) * [ bytenr - len ]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) * [csum ]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) * Our bytes are in the middle of the csum,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) * we need to split this item and insert a new one.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) * But we can't drop the path because the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) * csum could change, get removed, extended etc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) * The trick here is the max size of a csum item leaves
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) * enough room in the tree block for a single
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) * item header. So, we split the item in place,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) * adding a new header pointing to the existing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) * bytes. Then we loop around again and we have
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) * a nicely formed csum item that we can neatly
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) * truncate.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) offset = (bytenr - key.offset) >> blocksize_bits;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) offset *= csum_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) shift_len = (len >> blocksize_bits) * csum_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) item_offset = btrfs_item_ptr_offset(leaf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) path->slots[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) memzero_extent_buffer(leaf, item_offset + offset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) shift_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) key.offset = bytenr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) * btrfs_split_item returns -EAGAIN when the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) * item changed size or key
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) ret = btrfs_split_item(trans, root, path, &key, offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) if (ret && ret != -EAGAIN) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) btrfs_abort_transaction(trans, ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) key.offset = end_byte - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) truncate_one_csum(fs_info, path, &key, bytenr, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) if (key.offset < bytenr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) btrfs_release_path(path);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) btrfs_free_path(path);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) int btrfs_csum_file_blocks(struct btrfs_trans_handle *trans,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) struct btrfs_root *root,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) struct btrfs_ordered_sum *sums)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) struct btrfs_fs_info *fs_info = root->fs_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) struct btrfs_key file_key;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) struct btrfs_key found_key;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) struct btrfs_path *path;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) struct btrfs_csum_item *item;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) struct btrfs_csum_item *item_end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) struct extent_buffer *leaf = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) u64 next_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) u64 total_bytes = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) u64 csum_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) u64 bytenr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) u32 nritems;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) u32 ins_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) int index = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) int found_next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) u16 csum_size = btrfs_super_csum_size(fs_info->super_copy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) path = btrfs_alloc_path();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) if (!path)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) again:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) next_offset = (u64)-1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) found_next = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) bytenr = sums->bytenr + total_bytes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) file_key.objectid = BTRFS_EXTENT_CSUM_OBJECTID;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) file_key.offset = bytenr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) file_key.type = BTRFS_EXTENT_CSUM_KEY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) item = btrfs_lookup_csum(trans, root, path, bytenr, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) if (!IS_ERR(item)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) leaf = path->nodes[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) item_end = btrfs_item_ptr(leaf, path->slots[0],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) struct btrfs_csum_item);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) item_end = (struct btrfs_csum_item *)((char *)item_end +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) btrfs_item_size_nr(leaf, path->slots[0]));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) goto found;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) ret = PTR_ERR(item);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) if (ret != -EFBIG && ret != -ENOENT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) if (ret == -EFBIG) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) u32 item_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) /* we found one, but it isn't big enough yet */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) leaf = path->nodes[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) item_size = btrfs_item_size_nr(leaf, path->slots[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) if ((item_size / csum_size) >=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) MAX_CSUM_ITEMS(fs_info, csum_size)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) /* already at max size, make a new one */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) goto insert;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) int slot = path->slots[0] + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) /* we didn't find a csum item, insert one */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) nritems = btrfs_header_nritems(path->nodes[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) if (!nritems || (path->slots[0] >= nritems - 1)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) ret = btrfs_next_leaf(root, path);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) } else if (ret > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) found_next = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) goto insert;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) slot = path->slots[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) btrfs_item_key_to_cpu(path->nodes[0], &found_key, slot);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) if (found_key.objectid != BTRFS_EXTENT_CSUM_OBJECTID ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) found_key.type != BTRFS_EXTENT_CSUM_KEY) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) found_next = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) goto insert;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) next_offset = found_key.offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) found_next = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) goto insert;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) * At this point, we know the tree has a checksum item that ends at an
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) * offset matching the start of the checksum range we want to insert.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) * We try to extend that item as much as possible and then add as many
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) * checksums to it as they fit.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) * First check if the leaf has enough free space for at least one
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) * checksum. If it has go directly to the item extension code, otherwise
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) * release the path and do a search for insertion before the extension.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) if (btrfs_leaf_free_space(leaf) >= csum_size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) csum_offset = (bytenr - found_key.offset) >>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) fs_info->sb->s_blocksize_bits;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) goto extend_csum;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) btrfs_release_path(path);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) ret = btrfs_search_slot(trans, root, &file_key, path,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) csum_size, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) if (ret > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) if (path->slots[0] == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) goto insert;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) path->slots[0]--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) leaf = path->nodes[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) csum_offset = (bytenr - found_key.offset) >>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) fs_info->sb->s_blocksize_bits;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) if (found_key.type != BTRFS_EXTENT_CSUM_KEY ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) found_key.objectid != BTRFS_EXTENT_CSUM_OBJECTID ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) csum_offset >= MAX_CSUM_ITEMS(fs_info, csum_size)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) goto insert;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) extend_csum:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) if (csum_offset == btrfs_item_size_nr(leaf, path->slots[0]) /
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) csum_size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) int extend_nr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) u64 tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) u32 diff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) tmp = sums->len - total_bytes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) tmp >>= fs_info->sb->s_blocksize_bits;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) WARN_ON(tmp < 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) extend_nr = max_t(int, 1, (int)tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) diff = (csum_offset + extend_nr) * csum_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) diff = min(diff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) MAX_CSUM_ITEMS(fs_info, csum_size) * csum_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) diff = diff - btrfs_item_size_nr(leaf, path->slots[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) diff = min_t(u32, btrfs_leaf_free_space(leaf), diff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) diff /= csum_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) diff *= csum_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) btrfs_extend_item(path, diff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) goto csum;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) insert:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) btrfs_release_path(path);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) csum_offset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) if (found_next) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) u64 tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) tmp = sums->len - total_bytes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) tmp >>= fs_info->sb->s_blocksize_bits;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) tmp = min(tmp, (next_offset - file_key.offset) >>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) fs_info->sb->s_blocksize_bits);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) tmp = max_t(u64, 1, tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) tmp = min_t(u64, tmp, MAX_CSUM_ITEMS(fs_info, csum_size));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) ins_size = csum_size * tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) ins_size = csum_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) path->leave_spinning = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) ret = btrfs_insert_empty_item(trans, root, path, &file_key,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) ins_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) path->leave_spinning = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) if (WARN_ON(ret != 0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) leaf = path->nodes[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) csum:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) item = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_csum_item);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) item_end = (struct btrfs_csum_item *)((unsigned char *)item +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) btrfs_item_size_nr(leaf, path->slots[0]));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) item = (struct btrfs_csum_item *)((unsigned char *)item +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) csum_offset * csum_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) found:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) ins_size = (u32)(sums->len - total_bytes) >>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) fs_info->sb->s_blocksize_bits;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) ins_size *= csum_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) ins_size = min_t(u32, (unsigned long)item_end - (unsigned long)item,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) ins_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) write_extent_buffer(leaf, sums->sums + index, (unsigned long)item,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) ins_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) index += ins_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) ins_size /= csum_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) total_bytes += ins_size * fs_info->sectorsize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) btrfs_mark_buffer_dirty(path->nodes[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) if (total_bytes < sums->len) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) btrfs_release_path(path);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) cond_resched();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) goto again;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) btrfs_free_path(path);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) void btrfs_extent_item_to_extent_map(struct btrfs_inode *inode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) const struct btrfs_path *path,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) struct btrfs_file_extent_item *fi,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) const bool new_inline,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) struct extent_map *em)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) struct btrfs_fs_info *fs_info = inode->root->fs_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) struct btrfs_root *root = inode->root;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) struct extent_buffer *leaf = path->nodes[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) const int slot = path->slots[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) struct btrfs_key key;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) u64 extent_start, extent_end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) u64 bytenr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) u8 type = btrfs_file_extent_type(leaf, fi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) int compress_type = btrfs_file_extent_compression(leaf, fi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) btrfs_item_key_to_cpu(leaf, &key, slot);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) extent_start = key.offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) extent_end = btrfs_file_extent_end(path);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) em->ram_bytes = btrfs_file_extent_ram_bytes(leaf, fi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) if (type == BTRFS_FILE_EXTENT_REG ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) type == BTRFS_FILE_EXTENT_PREALLOC) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) em->start = extent_start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) em->len = extent_end - extent_start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) em->orig_start = extent_start -
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) btrfs_file_extent_offset(leaf, fi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) em->orig_block_len = btrfs_file_extent_disk_num_bytes(leaf, fi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) bytenr = btrfs_file_extent_disk_bytenr(leaf, fi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) if (bytenr == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) em->block_start = EXTENT_MAP_HOLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) if (compress_type != BTRFS_COMPRESS_NONE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) set_bit(EXTENT_FLAG_COMPRESSED, &em->flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) em->compress_type = compress_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) em->block_start = bytenr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) em->block_len = em->orig_block_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) bytenr += btrfs_file_extent_offset(leaf, fi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) em->block_start = bytenr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) em->block_len = em->len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) if (type == BTRFS_FILE_EXTENT_PREALLOC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) set_bit(EXTENT_FLAG_PREALLOC, &em->flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) } else if (type == BTRFS_FILE_EXTENT_INLINE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) em->block_start = EXTENT_MAP_INLINE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) em->start = extent_start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) em->len = extent_end - extent_start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) * Initialize orig_start and block_len with the same values
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) * as in inode.c:btrfs_get_extent().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) em->orig_start = EXTENT_MAP_HOLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) em->block_len = (u64)-1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) if (!new_inline && compress_type != BTRFS_COMPRESS_NONE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) set_bit(EXTENT_FLAG_COMPRESSED, &em->flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) em->compress_type = compress_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) btrfs_err(fs_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) "unknown file extent item type %d, inode %llu, offset %llu, "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) "root %llu", type, btrfs_ino(inode), extent_start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) root->root_key.objectid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) * Returns the end offset (non inclusive) of the file extent item the given path
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) * points to. If it points to an inline extent, the returned offset is rounded
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) * up to the sector size.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) u64 btrfs_file_extent_end(const struct btrfs_path *path)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) const struct extent_buffer *leaf = path->nodes[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) const int slot = path->slots[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) struct btrfs_file_extent_item *fi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) struct btrfs_key key;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) u64 end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) btrfs_item_key_to_cpu(leaf, &key, slot);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) ASSERT(key.type == BTRFS_EXTENT_DATA_KEY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) fi = btrfs_item_ptr(leaf, slot, struct btrfs_file_extent_item);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) if (btrfs_file_extent_type(leaf, fi) == BTRFS_FILE_EXTENT_INLINE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) end = btrfs_file_extent_ram_bytes(leaf, fi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) end = ALIGN(key.offset + end, leaf->fs_info->sectorsize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) end = key.offset + btrfs_file_extent_num_bytes(leaf, fi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) return end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) }