Commit 63dcd69d authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'for-5.12/dm-fixes' of...

Merge tag 'for-5.12/dm-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/device-mapper/linux-dm

Pull device mapper fixes from Mike Snitzer:
 "Fix DM verity target's optional Forward Error Correction (FEC) for
  Reed-Solomon roots that are unaligned to block size"

* tag 'for-5.12/dm-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/device-mapper/linux-dm:
  dm verity: fix FEC for RS roots unaligned to block size
  dm bufio: subtract the number of initial sectors in dm_bufio_get_device_size
parents 47454caf df7b59ba
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -1526,6 +1526,10 @@ EXPORT_SYMBOL_GPL(dm_bufio_get_block_size);
sector_t dm_bufio_get_device_size(struct dm_bufio_client *c)
{
	sector_t s = i_size_read(c->bdev->bd_inode) >> SECTOR_SHIFT;
	if (s >= c->start)
		s -= c->start;
	else
		s = 0;
	if (likely(c->sectors_per_block_bits >= 0))
		s >>= c->sectors_per_block_bits;
	else
+12 −11
Original line number Diff line number Diff line
@@ -61,19 +61,18 @@ static int fec_decode_rs8(struct dm_verity *v, struct dm_verity_fec_io *fio,
static u8 *fec_read_parity(struct dm_verity *v, u64 rsb, int index,
			   unsigned *offset, struct dm_buffer **buf)
{
	u64 position, block;
	u64 position, block, rem;
	u8 *res;

	position = (index + rsb) * v->fec->roots;
	block = position >> v->data_dev_block_bits;
	*offset = (unsigned)(position - (block << v->data_dev_block_bits));
	block = div64_u64_rem(position, v->fec->roots << SECTOR_SHIFT, &rem);
	*offset = (unsigned)rem;

	res = dm_bufio_read(v->fec->bufio, v->fec->start + block, buf);
	res = dm_bufio_read(v->fec->bufio, block, buf);
	if (IS_ERR(res)) {
		DMERR("%s: FEC %llu: parity read failed (block %llu): %ld",
		      v->data_dev->name, (unsigned long long)rsb,
		      (unsigned long long)(v->fec->start + block),
		      PTR_ERR(res));
		      (unsigned long long)block, PTR_ERR(res));
		*buf = NULL;
	}

@@ -155,7 +154,7 @@ static int fec_decode_bufs(struct dm_verity *v, struct dm_verity_fec_io *fio,

		/* read the next block when we run out of parity bytes */
		offset += v->fec->roots;
		if (offset >= 1 << v->data_dev_block_bits) {
		if (offset >= v->fec->roots << SECTOR_SHIFT) {
			dm_bufio_release(buf);

			par = fec_read_parity(v, rsb, block_offset, &offset, &buf);
@@ -674,7 +673,7 @@ int verity_fec_ctr(struct dm_verity *v)
{
	struct dm_verity_fec *f = v->fec;
	struct dm_target *ti = v->ti;
	u64 hash_blocks;
	u64 hash_blocks, fec_blocks;
	int ret;

	if (!verity_fec_is_enabled(v)) {
@@ -744,15 +743,17 @@ int verity_fec_ctr(struct dm_verity *v)
	}

	f->bufio = dm_bufio_client_create(f->dev->bdev,
					  1 << v->data_dev_block_bits,
					  f->roots << SECTOR_SHIFT,
					  1, 0, NULL, NULL);
	if (IS_ERR(f->bufio)) {
		ti->error = "Cannot initialize FEC bufio client";
		return PTR_ERR(f->bufio);
	}

	if (dm_bufio_get_device_size(f->bufio) <
	    ((f->start + f->rounds * f->roots) >> v->data_dev_block_bits)) {
	dm_bufio_set_sector_offset(f->bufio, f->start << (v->data_dev_block_bits - SECTOR_SHIFT));

	fec_blocks = div64_u64(f->rounds * f->roots, v->fec->roots << SECTOR_SHIFT);
	if (dm_bufio_get_device_size(f->bufio) < fec_blocks) {
		ti->error = "FEC device is too small";
		return -E2BIG;
	}