Skip to content

Commit 04d4ba4

Browse files
adam900710kdave
authored andcommitted
btrfs: make check_compressed_csum() to be subpage compatible
Currently check_compressed_csum() completely relies on sectorsize == PAGE_SIZE to do checksum verification for compressed extents. To make it subpage compatible, this patch will: - Do extra calculation for the csum range Since we have multiple sectors inside a page, we need to only hash the range we want, not the full page anymore. - Do sector-by-sector hash inside the page With this patch and previous conversion on btrfs_submit_compressed_read(), now we can read subpage compressed extents properly, and do proper csum verification. Reviewed-by: Anand Jain <anand.jain@oracle.com> Signed-off-by: Qu Wenruo <wqu@suse.com> Signed-off-by: David Sterba <dsterba@suse.com>
1 parent be6a136 commit 04d4ba4

1 file changed

Lines changed: 26 additions & 13 deletions

File tree

fs/btrfs/compression.c

Lines changed: 26 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,7 @@ static int check_compressed_csum(struct btrfs_inode *inode, struct bio *bio,
141141
struct btrfs_fs_info *fs_info = inode->root->fs_info;
142142
SHASH_DESC_ON_STACK(shash, fs_info->csum_shash);
143143
const u32 csum_size = fs_info->csum_size;
144+
const u32 sectorsize = fs_info->sectorsize;
144145
struct page *page;
145146
unsigned long i;
146147
char *kaddr;
@@ -154,22 +155,34 @@ static int check_compressed_csum(struct btrfs_inode *inode, struct bio *bio,
154155
shash->tfm = fs_info->csum_shash;
155156

156157
for (i = 0; i < cb->nr_pages; i++) {
158+
u32 pg_offset;
159+
u32 bytes_left = PAGE_SIZE;
157160
page = cb->compressed_pages[i];
158161

159-
kaddr = kmap_atomic(page);
160-
crypto_shash_digest(shash, kaddr, PAGE_SIZE, csum);
161-
kunmap_atomic(kaddr);
162-
163-
if (memcmp(&csum, cb_sum, csum_size)) {
164-
btrfs_print_data_csum_error(inode, disk_start,
165-
csum, cb_sum, cb->mirror_num);
166-
if (btrfs_io_bio(bio)->device)
167-
btrfs_dev_stat_inc_and_print(
168-
btrfs_io_bio(bio)->device,
169-
BTRFS_DEV_STAT_CORRUPTION_ERRS);
170-
return -EIO;
162+
/* Determine the remaining bytes inside the page first */
163+
if (i == cb->nr_pages - 1)
164+
bytes_left = cb->compressed_len - i * PAGE_SIZE;
165+
166+
/* Hash through the page sector by sector */
167+
for (pg_offset = 0; pg_offset < bytes_left;
168+
pg_offset += sectorsize) {
169+
kaddr = kmap_atomic(page);
170+
crypto_shash_digest(shash, kaddr + pg_offset,
171+
sectorsize, csum);
172+
kunmap_atomic(kaddr);
173+
174+
if (memcmp(&csum, cb_sum, csum_size) != 0) {
175+
btrfs_print_data_csum_error(inode, disk_start,
176+
csum, cb_sum, cb->mirror_num);
177+
if (btrfs_io_bio(bio)->device)
178+
btrfs_dev_stat_inc_and_print(
179+
btrfs_io_bio(bio)->device,
180+
BTRFS_DEV_STAT_CORRUPTION_ERRS);
181+
return -EIO;
182+
}
183+
cb_sum += csum_size;
184+
disk_start += sectorsize;
171185
}
172-
cb_sum += csum_size;
173186
}
174187
return 0;
175188
}

0 commit comments

Comments
 (0)