Skip to content

Commit 1e25a2e

Browse files
Johannes Thumshirnkdave
authored andcommitted
btrfs: don't assume ordered sums to be 4 bytes
BTRFS has the implicit assumption that a checksum in btrfs_orderd_sums is 4 bytes. While this is true for CRC32C, it is not for any other checksum. Change the data type to be a byte array and adjust loop index calculation accordingly. This includes moving the adjustment of 'index' by 'ins_size' in btrfs_csum_file_blocks() before dividing 'ins_size' by the checksum size, because before this patch the 'sums' member of 'struct btrfs_ordered_sum' was 4 Bytes in size and afterwards it is only one byte. Reviewed-by: Nikolay Borisov <[email protected]> Signed-off-by: Johannes Thumshirn <[email protected]> Reviewed-by: David Sterba <[email protected]> Signed-off-by: David Sterba <[email protected]>
1 parent 4bb3c2e commit 1e25a2e

File tree

6 files changed

+34
-24
lines changed

6 files changed

+34
-24
lines changed

fs/btrfs/compression.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -631,7 +631,7 @@ blk_status_t btrfs_submit_compressed_read(struct inode *inode, struct bio *bio,
631631

632632
if (!(BTRFS_I(inode)->flags & BTRFS_INODE_NODATASUM)) {
633633
ret = btrfs_lookup_bio_sums(inode, comp_bio,
634-
sums);
634+
(u8 *)sums);
635635
BUG_ON(ret); /* -ENOMEM */
636636
}
637637
sums += DIV_ROUND_UP(comp_bio->bi_iter.bi_size,
@@ -657,7 +657,7 @@ blk_status_t btrfs_submit_compressed_read(struct inode *inode, struct bio *bio,
657657
BUG_ON(ret); /* -ENOMEM */
658658

659659
if (!(BTRFS_I(inode)->flags & BTRFS_INODE_NODATASUM)) {
660-
ret = btrfs_lookup_bio_sums(inode, comp_bio, sums);
660+
ret = btrfs_lookup_bio_sums(inode, comp_bio, (u8 *) sums);
661661
BUG_ON(ret); /* -ENOMEM */
662662
}
663663

fs/btrfs/ctree.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3199,7 +3199,8 @@ int btrfs_find_name_in_ext_backref(struct extent_buffer *leaf, int slot,
31993199
struct btrfs_dio_private;
32003200
int btrfs_del_csums(struct btrfs_trans_handle *trans,
32013201
struct btrfs_fs_info *fs_info, u64 bytenr, u64 len);
3202-
blk_status_t btrfs_lookup_bio_sums(struct inode *inode, struct bio *bio, u32 *dst);
3202+
blk_status_t btrfs_lookup_bio_sums(struct inode *inode, struct bio *bio,
3203+
u8 *dst);
32033204
blk_status_t btrfs_lookup_bio_sums_dio(struct inode *inode, struct bio *bio,
32043205
u64 logical_offset);
32053206
int btrfs_insert_file_extent(struct btrfs_trans_handle *trans,

fs/btrfs/file-item.c

Lines changed: 21 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,13 @@
2222
#define MAX_CSUM_ITEMS(r, size) (min_t(u32, __MAX_CSUM_ITEMS(r, size), \
2323
PAGE_SIZE))
2424

25-
#define MAX_ORDERED_SUM_BYTES(fs_info) ((PAGE_SIZE - \
26-
sizeof(struct btrfs_ordered_sum)) / \
27-
sizeof(u32) * (fs_info)->sectorsize)
25+
static inline u32 max_ordered_sum_bytes(struct btrfs_fs_info *fs_info,
26+
u16 csum_size)
27+
{
28+
u32 ncsums = (PAGE_SIZE - sizeof(struct btrfs_ordered_sum)) / csum_size;
29+
30+
return ncsums * fs_info->sectorsize;
31+
}
2832

2933
int btrfs_insert_file_extent(struct btrfs_trans_handle *trans,
3034
struct btrfs_root *root,
@@ -144,7 +148,7 @@ int btrfs_lookup_file_extent(struct btrfs_trans_handle *trans,
144148
}
145149

146150
static blk_status_t __btrfs_lookup_bio_sums(struct inode *inode, struct bio *bio,
147-
u64 logical_offset, u32 *dst, int dio)
151+
u64 logical_offset, u8 *dst, int dio)
148152
{
149153
struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
150154
struct bio_vec bvec;
@@ -211,7 +215,7 @@ static blk_status_t __btrfs_lookup_bio_sums(struct inode *inode, struct bio *bio
211215
if (!dio)
212216
offset = page_offset(bvec.bv_page) + bvec.bv_offset;
213217
count = btrfs_find_ordered_sum(inode, offset, disk_bytenr,
214-
(u32 *)csum, nblocks);
218+
csum, nblocks);
215219
if (count)
216220
goto found;
217221

@@ -283,7 +287,8 @@ static blk_status_t __btrfs_lookup_bio_sums(struct inode *inode, struct bio *bio
283287
return 0;
284288
}
285289

286-
blk_status_t btrfs_lookup_bio_sums(struct inode *inode, struct bio *bio, u32 *dst)
290+
blk_status_t btrfs_lookup_bio_sums(struct inode *inode, struct bio *bio,
291+
u8 *dst)
287292
{
288293
return __btrfs_lookup_bio_sums(inode, bio, 0, dst, 0);
289294
}
@@ -374,7 +379,7 @@ int btrfs_lookup_csums_range(struct btrfs_root *root, u64 start, u64 end,
374379
struct btrfs_csum_item);
375380
while (start < csum_end) {
376381
size = min_t(size_t, csum_end - start,
377-
MAX_ORDERED_SUM_BYTES(fs_info));
382+
max_ordered_sum_bytes(fs_info, csum_size));
378383
sums = kzalloc(btrfs_ordered_sum_size(fs_info, size),
379384
GFP_NOFS);
380385
if (!sums) {
@@ -439,6 +444,7 @@ blk_status_t btrfs_csum_one_bio(struct inode *inode, struct bio *bio,
439444
int i;
440445
u64 offset;
441446
unsigned nofs_flag;
447+
const u16 csum_size = btrfs_super_csum_size(fs_info->super_copy);
442448

443449
nofs_flag = memalloc_nofs_save();
444450
sums = kvzalloc(btrfs_ordered_sum_size(fs_info, bio->bi_iter.bi_size),
@@ -473,6 +479,8 @@ blk_status_t btrfs_csum_one_bio(struct inode *inode, struct bio *bio,
473479
- 1);
474480

475481
for (i = 0; i < nr_sectors; i++) {
482+
u32 tmp;
483+
476484
if (offset >= ordered->file_offset + ordered->len ||
477485
offset < ordered->file_offset) {
478486
unsigned long bytes_left;
@@ -498,17 +506,16 @@ blk_status_t btrfs_csum_one_bio(struct inode *inode, struct bio *bio,
498506
index = 0;
499507
}
500508

501-
sums->sums[index] = ~(u32)0;
509+
memset(&sums->sums[index], 0xff, csum_size);
502510
data = kmap_atomic(bvec.bv_page);
503-
sums->sums[index]
504-
= btrfs_csum_data(data + bvec.bv_offset
511+
tmp = btrfs_csum_data(data + bvec.bv_offset
505512
+ (i * fs_info->sectorsize),
506-
sums->sums[index],
513+
*(u32 *)&sums->sums[index],
507514
fs_info->sectorsize);
508515
kunmap_atomic(data);
509-
btrfs_csum_final(sums->sums[index],
516+
btrfs_csum_final(tmp,
510517
(char *)(sums->sums + index));
511-
index++;
518+
index += csum_size;
512519
offset += fs_info->sectorsize;
513520
this_sum_bytes += fs_info->sectorsize;
514521
total_bytes += fs_info->sectorsize;
@@ -904,9 +911,9 @@ int btrfs_csum_file_blocks(struct btrfs_trans_handle *trans,
904911
write_extent_buffer(leaf, sums->sums + index, (unsigned long)item,
905912
ins_size);
906913

914+
index += ins_size;
907915
ins_size /= csum_size;
908916
total_bytes += ins_size * fs_info->sectorsize;
909-
index += ins_size;
910917

911918
btrfs_mark_buffer_dirty(path->nodes[0]);
912919
if (total_bytes < sums->len) {

fs/btrfs/ordered-data.c

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -924,14 +924,16 @@ int btrfs_ordered_update_i_size(struct inode *inode, u64 offset,
924924
* be reclaimed before their checksum is actually put into the btree
925925
*/
926926
int btrfs_find_ordered_sum(struct inode *inode, u64 offset, u64 disk_bytenr,
927-
u32 *sum, int len)
927+
u8 *sum, int len)
928928
{
929+
struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
929930
struct btrfs_ordered_sum *ordered_sum;
930931
struct btrfs_ordered_extent *ordered;
931932
struct btrfs_ordered_inode_tree *tree = &BTRFS_I(inode)->ordered_tree;
932933
unsigned long num_sectors;
933934
unsigned long i;
934935
u32 sectorsize = btrfs_inode_sectorsize(inode);
936+
const u16 csum_size = btrfs_super_csum_size(fs_info->super_copy);
935937
int index = 0;
936938

937939
ordered = btrfs_lookup_ordered_extent(inode, offset);
@@ -947,10 +949,10 @@ int btrfs_find_ordered_sum(struct inode *inode, u64 offset, u64 disk_bytenr,
947949
num_sectors = ordered_sum->len >>
948950
inode->i_sb->s_blocksize_bits;
949951
num_sectors = min_t(int, len - index, num_sectors - i);
950-
memcpy(sum + index, ordered_sum->sums + i,
951-
num_sectors);
952+
memcpy(sum + index, ordered_sum->sums + i * csum_size,
953+
num_sectors * csum_size);
952954

953-
index += (int)num_sectors;
955+
index += (int)num_sectors * csum_size;
954956
if (index == len)
955957
goto out;
956958
disk_bytenr += num_sectors * sectorsize;

fs/btrfs/ordered-data.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ struct btrfs_ordered_sum {
2323
int len;
2424
struct list_head list;
2525
/* last field is a variable length array of csums */
26-
u32 sums[];
26+
u8 sums[];
2727
};
2828

2929
/*
@@ -183,7 +183,7 @@ struct btrfs_ordered_extent *btrfs_lookup_ordered_range(
183183
int btrfs_ordered_update_i_size(struct inode *inode, u64 offset,
184184
struct btrfs_ordered_extent *ordered);
185185
int btrfs_find_ordered_sum(struct inode *inode, u64 offset, u64 disk_bytenr,
186-
u32 *sum, int len);
186+
u8 *sum, int len);
187187
u64 btrfs_wait_ordered_extents(struct btrfs_root *root, u64 nr,
188188
const u64 range_start, const u64 range_len);
189189
u64 btrfs_wait_ordered_roots(struct btrfs_fs_info *fs_info, u64 nr,

fs/btrfs/scrub.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2448,7 +2448,7 @@ static int scrub_find_csum(struct scrub_ctx *sctx, u64 logical, u8 *csum)
24482448
ASSERT(index < UINT_MAX);
24492449

24502450
num_sectors = sum->len / sctx->fs_info->sectorsize;
2451-
memcpy(csum, sum->sums + index, sctx->csum_size);
2451+
memcpy(csum, sum->sums + index * sctx->csum_size, sctx->csum_size);
24522452
if (index == num_sectors - 1) {
24532453
list_del(&sum->list);
24542454
kfree(sum);

0 commit comments

Comments
 (0)