dm verity: Fix IO priority lost when reading FEC and hash
After obtaining the data, verification or error correction process may trigger a new IO that loses the priority of the original IO, that is, the verification of the higher priority IO may be blocked by the lower priority IO. Make the IO used for verification and error correction follow the priority of the original IO. Co-developed-by: Yibin Ding <yibin.ding@unisoc.com> Signed-off-by: Yibin Ding <yibin.ding@unisoc.com> Signed-off-by: Hongyu Jin <hongyu.jin@unisoc.com> Reviewed-by: Eric Biggers <ebiggers@google.com> Reviewed-by: Mikulas Patocka <mpatocka@redhat.com> Signed-off-by: Mike Snitzer <snitzer@kernel.org>
This commit is contained in:
parent
e9b2238e47
commit
d95e2c34a3
|
@ -60,7 +60,8 @@ static int fec_decode_rs8(struct dm_verity *v, struct dm_verity_fec_io *fio,
|
|||
* 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 int *offset, struct dm_buffer **buf,
|
||||
unsigned short ioprio)
|
||||
{
|
||||
u64 position, block, rem;
|
||||
u8 *res;
|
||||
|
@ -69,7 +70,7 @@ static u8 *fec_read_parity(struct dm_verity *v, u64 rsb, int index,
|
|||
block = div64_u64_rem(position, v->fec->io_size, &rem);
|
||||
*offset = (unsigned int)rem;
|
||||
|
||||
res = dm_bufio_read(v->fec->bufio, block, buf);
|
||||
res = dm_bufio_read_with_ioprio(v->fec->bufio, block, buf, ioprio);
|
||||
if (IS_ERR(res)) {
|
||||
DMERR("%s: FEC %llu: parity read failed (block %llu): %ld",
|
||||
v->data_dev->name, (unsigned long long)rsb,
|
||||
|
@ -121,16 +122,17 @@ static inline unsigned int fec_buffer_rs_index(unsigned int i, unsigned int j)
|
|||
* Decode all RS blocks from buffers and copy corrected bytes into fio->output
|
||||
* starting from block_offset.
|
||||
*/
|
||||
static int fec_decode_bufs(struct dm_verity *v, struct dm_verity_fec_io *fio,
|
||||
u64 rsb, int byte_index, unsigned int block_offset,
|
||||
int neras)
|
||||
static int fec_decode_bufs(struct dm_verity *v, struct dm_verity_io *io,
|
||||
struct dm_verity_fec_io *fio, u64 rsb, int byte_index,
|
||||
unsigned int block_offset, int neras)
|
||||
{
|
||||
int r, corrected = 0, res;
|
||||
struct dm_buffer *buf;
|
||||
unsigned int n, i, offset;
|
||||
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);
|
||||
par = fec_read_parity(v, rsb, block_offset, &offset, &buf, bio_prio(bio));
|
||||
if (IS_ERR(par))
|
||||
return PTR_ERR(par);
|
||||
|
||||
|
@ -158,7 +160,7 @@ static int fec_decode_bufs(struct dm_verity *v, struct dm_verity_fec_io *fio,
|
|||
if (offset >= v->fec->io_size) {
|
||||
dm_bufio_release(buf);
|
||||
|
||||
par = fec_read_parity(v, rsb, block_offset, &offset, &buf);
|
||||
par = fec_read_parity(v, rsb, block_offset, &offset, &buf, bio_prio(bio));
|
||||
if (IS_ERR(par))
|
||||
return PTR_ERR(par);
|
||||
}
|
||||
|
@ -210,6 +212,7 @@ static int fec_read_bufs(struct dm_verity *v, struct dm_verity_io *io,
|
|||
u8 *bbuf, *rs_block;
|
||||
u8 want_digest[HASH_MAX_DIGESTSIZE];
|
||||
unsigned int n, k;
|
||||
struct bio *bio = dm_bio_from_per_bio_data(io, v->ti->per_io_data_size);
|
||||
|
||||
if (neras)
|
||||
*neras = 0;
|
||||
|
@ -248,7 +251,7 @@ static int fec_read_bufs(struct dm_verity *v, struct dm_verity_io *io,
|
|||
bufio = v->bufio;
|
||||
}
|
||||
|
||||
bbuf = dm_bufio_read(bufio, block, &buf);
|
||||
bbuf = dm_bufio_read_with_ioprio(bufio, block, &buf, bio_prio(bio));
|
||||
if (IS_ERR(bbuf)) {
|
||||
DMWARN_LIMIT("%s: FEC %llu: read failed (%llu): %ld",
|
||||
v->data_dev->name,
|
||||
|
@ -377,7 +380,7 @@ static int fec_decode_rsb(struct dm_verity *v, struct dm_verity_io *io,
|
|||
if (unlikely(r < 0))
|
||||
return r;
|
||||
|
||||
r = fec_decode_bufs(v, fio, rsb, r, pos, neras);
|
||||
r = fec_decode_bufs(v, io, fio, rsb, r, pos, neras);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
|
|
|
@ -51,6 +51,7 @@ static DEFINE_STATIC_KEY_FALSE(use_tasklet_enabled);
|
|||
struct dm_verity_prefetch_work {
|
||||
struct work_struct work;
|
||||
struct dm_verity *v;
|
||||
unsigned short ioprio;
|
||||
sector_t block;
|
||||
unsigned int n_blocks;
|
||||
};
|
||||
|
@ -294,6 +295,7 @@ static int verity_verify_level(struct dm_verity *v, struct dm_verity_io *io,
|
|||
int r;
|
||||
sector_t hash_block;
|
||||
unsigned int offset;
|
||||
struct bio *bio = dm_bio_from_per_bio_data(io, v->ti->per_io_data_size);
|
||||
|
||||
verity_hash_at_level(v, block, level, &hash_block, &offset);
|
||||
|
||||
|
@ -307,8 +309,10 @@ static int verity_verify_level(struct dm_verity *v, struct dm_verity_io *io,
|
|||
*/
|
||||
return -EAGAIN;
|
||||
}
|
||||
} else
|
||||
data = dm_bufio_read(v->bufio, hash_block, &buf);
|
||||
} else {
|
||||
data = dm_bufio_read_with_ioprio(v->bufio, hash_block,
|
||||
&buf, bio_prio(bio));
|
||||
}
|
||||
|
||||
if (IS_ERR(data))
|
||||
return PTR_ERR(data);
|
||||
|
@ -752,14 +756,16 @@ static void verity_prefetch_io(struct work_struct *work)
|
|||
hash_block_end = v->hash_blocks - 1;
|
||||
}
|
||||
no_prefetch_cluster:
|
||||
dm_bufio_prefetch(v->bufio, hash_block_start,
|
||||
hash_block_end - hash_block_start + 1);
|
||||
dm_bufio_prefetch_with_ioprio(v->bufio, hash_block_start,
|
||||
hash_block_end - hash_block_start + 1,
|
||||
pw->ioprio);
|
||||
}
|
||||
|
||||
kfree(pw);
|
||||
}
|
||||
|
||||
static void verity_submit_prefetch(struct dm_verity *v, struct dm_verity_io *io)
|
||||
static void verity_submit_prefetch(struct dm_verity *v, struct dm_verity_io *io,
|
||||
unsigned short ioprio)
|
||||
{
|
||||
sector_t block = io->block;
|
||||
unsigned int n_blocks = io->n_blocks;
|
||||
|
@ -787,6 +793,7 @@ static void verity_submit_prefetch(struct dm_verity *v, struct dm_verity_io *io)
|
|||
pw->v = v;
|
||||
pw->block = block;
|
||||
pw->n_blocks = n_blocks;
|
||||
pw->ioprio = ioprio;
|
||||
queue_work(v->verify_wq, &pw->work);
|
||||
}
|
||||
|
||||
|
@ -829,7 +836,7 @@ static int verity_map(struct dm_target *ti, struct bio *bio)
|
|||
|
||||
verity_fec_init_io(io);
|
||||
|
||||
verity_submit_prefetch(v, io);
|
||||
verity_submit_prefetch(v, io, bio_prio(bio));
|
||||
|
||||
submit_bio_noacct(bio);
|
||||
|
||||
|
|
Loading…
Reference in New Issue