Commit 0b7958fa authored by Linus Torvalds's avatar Linus Torvalds
Browse files

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

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

Pull device mapper fixes from Mikulas Patocka:

 - dm-array fixes

 - dm-verity forward error correction fixes

 - remove the flag DM_TARGET_PASSES_INTEGRITY from dm-ebs

 - dm-thin RCU list fix

* tag 'for-6.13/dm-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/device-mapper/linux-dm:
  dm thin: make get_first_thin use rcu-safe list first function
  dm-ebs: don't set the flag DM_TARGET_PASSES_INTEGRITY
  dm-verity FEC: Avoid copying RS parity bytes twice.
  dm-verity FEC: Fix RS FEC repair for roots unaligned to block size (take 2)
  dm array: fix cursor index when skipping across block boundaries
  dm array: fix unreleased btree blocks on closing a faulty array cursor
  dm array: fix releasing a faulty array block twice in dm_array_cursor_end
parents 09a0fa92 80f130bf
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -442,7 +442,7 @@ static int ebs_iterate_devices(struct dm_target *ti,
static struct target_type ebs_target = {
	.name		 = "ebs",
	.version	 = {1, 0, 1},
	.features	 = DM_TARGET_PASSES_INTEGRITY,
	.features	 = 0,
	.module		 = THIS_MODULE,
	.ctr		 = ebs_ctr,
	.dtr		 = ebs_dtr,
+2 −3
Original line number Diff line number Diff line
@@ -2332,10 +2332,9 @@ static struct thin_c *get_first_thin(struct pool *pool)
	struct thin_c *tc = NULL;

	rcu_read_lock();
	if (!list_empty(&pool->active_thins)) {
		tc = list_entry_rcu(pool->active_thins.next, struct thin_c, list);
	tc = list_first_or_null_rcu(&pool->active_thins, struct thin_c, list);
	if (tc)
		thin_get(tc);
	}
	rcu_read_unlock();

	return tc;
+30 −29
Original line number Diff line number Diff line
@@ -39,36 +39,24 @@ static inline u64 fec_interleave(struct dm_verity *v, u64 offset)
	return offset + mod * (v->fec->rounds << v->data_dev_block_bits);
}

/*
 * Decode an RS block using Reed-Solomon.
 */
static int fec_decode_rs8(struct dm_verity *v, struct dm_verity_fec_io *fio,
			  u8 *data, u8 *fec, int neras)
{
	int i;
	uint16_t par[DM_VERITY_FEC_RSM - DM_VERITY_FEC_MIN_RSN];

	for (i = 0; i < v->fec->roots; i++)
		par[i] = fec[i];

	return decode_rs8(fio->rs, data, par, v->fec->rsn, NULL, neras,
			  fio->erasures, 0, NULL);
}

/*
 * Read error-correcting codes for the requested RS block. Returns a pointer
 * to the data block. Caller is responsible for releasing buf.
 */
static u8 *fec_read_parity(struct dm_verity *v, u64 rsb, int index,
			   unsigned int *offset, struct dm_buffer **buf,
			   unsigned short ioprio)
			   unsigned int *offset, unsigned int par_buf_offset,
			   struct dm_buffer **buf, unsigned short ioprio)
{
	u64 position, block, rem;
	u8 *res;

	/* We have already part of parity bytes read, skip to the next block */
	if (par_buf_offset)
		index++;

	position = (index + rsb) * v->fec->roots;
	block = div64_u64_rem(position, v->fec->io_size, &rem);
	*offset = (unsigned int)rem;
	*offset = par_buf_offset ? 0 : (unsigned int)rem;

	res = dm_bufio_read_with_ioprio(v->fec->bufio, block, buf, ioprio);
	if (IS_ERR(res)) {
@@ -128,11 +116,13 @@ static int fec_decode_bufs(struct dm_verity *v, struct dm_verity_io *io,
{
	int r, corrected = 0, res;
	struct dm_buffer *buf;
	unsigned int n, i, offset;
	unsigned int n, i, j, offset, par_buf_offset = 0;
	uint16_t par_buf[DM_VERITY_FEC_RSM - DM_VERITY_FEC_MIN_RSN];
	u8 *par, *block;
	struct bio *bio = dm_bio_from_per_bio_data(io, v->ti->per_io_data_size);

	par = fec_read_parity(v, rsb, block_offset, &offset, &buf, bio_prio(bio));
	par = fec_read_parity(v, rsb, block_offset, &offset,
			      par_buf_offset, &buf, bio_prio(bio));
	if (IS_ERR(par))
		return PTR_ERR(par);

@@ -142,7 +132,11 @@ static int fec_decode_bufs(struct dm_verity *v, struct dm_verity_io *io,
	 */
	fec_for_each_buffer_rs_block(fio, n, i) {
		block = fec_buffer_rs_block(v, fio, n, i);
		res = fec_decode_rs8(v, fio, block, &par[offset], neras);
		for (j = 0; j < v->fec->roots - par_buf_offset; j++)
			par_buf[par_buf_offset + j] = par[offset + j];
		/* Decode an RS block using Reed-Solomon */
		res = decode_rs8(fio->rs, block, par_buf, v->fec->rsn,
				 NULL, neras, fio->erasures, 0, NULL);
		if (res < 0) {
			r = res;
			goto error;
@@ -155,12 +149,22 @@ static int fec_decode_bufs(struct dm_verity *v, struct dm_verity_io *io,
		if (block_offset >= 1 << v->data_dev_block_bits)
			goto done;

		/* read the next block when we run out of parity bytes */
		offset += v->fec->roots;
		/* Read the next block when we run out of parity bytes */
		offset += (v->fec->roots - par_buf_offset);
		/* Check if parity bytes are split between blocks */
		if (offset < v->fec->io_size && (offset + v->fec->roots) > v->fec->io_size) {
			par_buf_offset = v->fec->io_size - offset;
			for (j = 0; j < par_buf_offset; j++)
				par_buf[j] = par[offset + j];
			offset += par_buf_offset;
		} else
			par_buf_offset = 0;

		if (offset >= v->fec->io_size) {
			dm_bufio_release(buf);

			par = fec_read_parity(v, rsb, block_offset, &offset, &buf, bio_prio(bio));
			par = fec_read_parity(v, rsb, block_offset, &offset,
					      par_buf_offset, &buf, bio_prio(bio));
			if (IS_ERR(par))
				return PTR_ERR(par);
		}
@@ -724,10 +728,7 @@ int verity_fec_ctr(struct dm_verity *v)
		return -E2BIG;
	}

	if ((f->roots << SECTOR_SHIFT) & ((1 << v->data_dev_block_bits) - 1))
	f->io_size = 1 << v->data_dev_block_bits;
	else
		f->io_size = v->fec->roots << SECTOR_SHIFT;

	f->bufio = dm_bufio_client_create(f->dev->bdev,
					  f->io_size,
+12 −7
Original line number Diff line number Diff line
@@ -917,23 +917,27 @@ static int load_ablock(struct dm_array_cursor *c)
	if (c->block)
		unlock_ablock(c->info, c->block);

	c->block = NULL;
	c->ab = NULL;
	c->index = 0;

	r = dm_btree_cursor_get_value(&c->cursor, &key, &value_le);
	if (r) {
		DMERR("dm_btree_cursor_get_value failed");
		dm_btree_cursor_end(&c->cursor);
		goto out;

	} else {
		r = get_ablock(c->info, le64_to_cpu(value_le), &c->block, &c->ab);
		if (r) {
			DMERR("get_ablock failed");
			dm_btree_cursor_end(&c->cursor);
			goto out;
		}
	}

	return 0;

out:
	dm_btree_cursor_end(&c->cursor);
	c->block = NULL;
	c->ab = NULL;
	return r;
}

@@ -956,11 +960,11 @@ EXPORT_SYMBOL_GPL(dm_array_cursor_begin);

void dm_array_cursor_end(struct dm_array_cursor *c)
{
	if (c->block) {
	if (c->block)
		unlock_ablock(c->info, c->block);

	dm_btree_cursor_end(&c->cursor);
}
}
EXPORT_SYMBOL_GPL(dm_array_cursor_end);

int dm_array_cursor_next(struct dm_array_cursor *c)
@@ -999,6 +1003,7 @@ int dm_array_cursor_skip(struct dm_array_cursor *c, uint32_t count)
		}

		count -= remaining;
		c->index += (remaining - 1);
		r = dm_array_cursor_next(c);

	} while (!r);