Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c40a3d38 authored by Chandan Rajendra's avatar Chandan Rajendra Committed by David Sterba
Browse files

Btrfs: Compute and look up csums based on sectorsized blocks



Checksums are applicable to sectorsize units. The current code uses
bio->bv_len units to compute and look up checksums. This works on machines
where sectorsize == PAGE_SIZE. This patch makes the checksum computation and
look up code to work with sectorsize units.

Reviewed-by: default avatarLiu Bo <bo.li.liu@oracle.com>
Signed-off-by: default avatarChandan Rajendra <chandan@linux.vnet.ibm.com>
Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
parent 2e78c927
Loading
Loading
Loading
Loading
+59 −33
Original line number Diff line number Diff line
@@ -172,6 +172,7 @@ static int __btrfs_lookup_bio_sums(struct btrfs_root *root,
	u64 item_start_offset = 0;
	u64 item_last_offset = 0;
	u64 disk_bytenr;
	u64 page_bytes_left;
	u32 diff;
	int nblocks;
	int bio_index = 0;
@@ -220,6 +221,8 @@ static int __btrfs_lookup_bio_sums(struct btrfs_root *root,
	disk_bytenr = (u64)bio->bi_iter.bi_sector << 9;
	if (dio)
		offset = logical_offset;

	page_bytes_left = bvec->bv_len;
	while (bio_index < bio->bi_vcnt) {
		if (!dio)
			offset = page_offset(bvec->bv_page) + bvec->bv_offset;
@@ -243,7 +246,7 @@ static int __btrfs_lookup_bio_sums(struct btrfs_root *root,
				if (BTRFS_I(inode)->root->root_key.objectid ==
				    BTRFS_DATA_RELOC_TREE_OBJECTID) {
					set_extent_bits(io_tree, offset,
						offset + bvec->bv_len - 1,
						offset + root->sectorsize - 1,
						EXTENT_NODATASUM, GFP_NOFS);
				} else {
					btrfs_info(BTRFS_I(inode)->root->fs_info,
@@ -281,11 +284,17 @@ static int __btrfs_lookup_bio_sums(struct btrfs_root *root,
found:
		csum += count * csum_size;
		nblocks -= count;
		bio_index += count;

		while (count--) {
			disk_bytenr += bvec->bv_len;
			offset += bvec->bv_len;
			disk_bytenr += root->sectorsize;
			offset += root->sectorsize;
			page_bytes_left -= root->sectorsize;
			if (!page_bytes_left) {
				bio_index++;
				bvec++;
				page_bytes_left = bvec->bv_len;
			}

		}
	}
	btrfs_free_path(path);
@@ -432,6 +441,8 @@ int btrfs_csum_one_bio(struct btrfs_root *root, struct inode *inode,
	struct bio_vec *bvec = bio->bi_io_vec;
	int bio_index = 0;
	int index;
	int nr_sectors;
	int i;
	unsigned long total_bytes = 0;
	unsigned long this_sum_bytes = 0;
	u64 offset;
@@ -459,9 +470,18 @@ int btrfs_csum_one_bio(struct btrfs_root *root, struct inode *inode,
		if (!contig)
			offset = page_offset(bvec->bv_page) + bvec->bv_offset;

		data = kmap_atomic(bvec->bv_page);

		nr_sectors = BTRFS_BYTES_TO_BLKS(root->fs_info,
						bvec->bv_len + root->sectorsize
						- 1);

		for (i = 0; i < nr_sectors; i++) {
			if (offset >= ordered->file_offset + ordered->len ||
				offset < ordered->file_offset) {
				unsigned long bytes_left;

				kunmap_atomic(data);
				sums->len = this_sum_bytes;
				this_sum_bytes = 0;
				btrfs_add_ordered_sum(inode, ordered, sums);
@@ -473,27 +493,33 @@ int btrfs_csum_one_bio(struct btrfs_root *root, struct inode *inode,
					GFP_NOFS);
				BUG_ON(!sums); /* -ENOMEM */
				sums->len = bytes_left;
			ordered = btrfs_lookup_ordered_extent(inode, offset);
			BUG_ON(!ordered); /* Logic error */
			sums->bytenr = ((u64)bio->bi_iter.bi_sector << 9) +
				       total_bytes;
				ordered = btrfs_lookup_ordered_extent(inode,
								offset);
				ASSERT(ordered); /* Logic error */
				sums->bytenr = ((u64)bio->bi_iter.bi_sector << 9)
					+ total_bytes;
				index = 0;
		}

				data = kmap_atomic(bvec->bv_page);
			}

			sums->sums[index] = ~(u32)0;
		sums->sums[index] = btrfs_csum_data(data + bvec->bv_offset,
			sums->sums[index]
				= btrfs_csum_data(data + bvec->bv_offset
						+ (i * root->sectorsize),
						sums->sums[index],
						    bvec->bv_len);
		kunmap_atomic(data);
						root->sectorsize);
			btrfs_csum_final(sums->sums[index],
					(char *)(sums->sums + index));
			index++;
			offset += root->sectorsize;
			this_sum_bytes += root->sectorsize;
			total_bytes += root->sectorsize;
		}

		kunmap_atomic(data);

		bio_index++;
		index++;
		total_bytes += bvec->bv_len;
		this_sum_bytes += bvec->bv_len;
		offset += bvec->bv_len;
		bvec++;
	}
	this_sum_bytes = 0;