Skip to content

Commit 28f07f2

Browse files
Mikulas PatockaMike Snitzer
authored andcommitted
dm-verity: don't use blocking calls from tasklets
The commit 5721d4e enhanced dm-verity, so that it can verify blocks from tasklets rather than from workqueues. This reportedly improves performance significantly. However, dm-verity was using the flag CRYPTO_TFM_REQ_MAY_SLEEP from tasklets which resulted in warnings about sleeping function being called from non-sleeping context. BUG: sleeping function called from invalid context at crypto/internal.h:206 in_atomic(): 1, irqs_disabled(): 0, non_block: 0, pid: 14, name: ksoftirqd/0 preempt_count: 100, expected: 0 RCU nest depth: 0, expected: 0 CPU: 0 PID: 14 Comm: ksoftirqd/0 Tainted: G W 6.7.0-rc1 #1 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.14.0-2 04/01/2014 Call Trace: <TASK> dump_stack_lvl+0x32/0x50 __might_resched+0x110/0x160 crypto_hash_walk_done+0x54/0xb0 shash_ahash_update+0x51/0x60 verity_hash_update.isra.0+0x4a/0x130 [dm_verity] verity_verify_io+0x165/0x550 [dm_verity] ? free_unref_page+0xdf/0x170 ? psi_group_change+0x113/0x390 verity_tasklet+0xd/0x70 [dm_verity] tasklet_action_common.isra.0+0xb3/0xc0 __do_softirq+0xaf/0x1ec ? smpboot_thread_fn+0x1d/0x200 ? sort_range+0x20/0x20 run_ksoftirqd+0x15/0x30 smpboot_thread_fn+0xed/0x200 kthread+0xdc/0x110 ? kthread_complete_and_exit+0x20/0x20 ret_from_fork+0x28/0x40 ? kthread_complete_and_exit+0x20/0x20 ret_from_fork_asm+0x11/0x20 </TASK> This commit fixes dm-verity so that it doesn't use the flags CRYPTO_TFM_REQ_MAY_SLEEP and CRYPTO_TFM_REQ_MAY_BACKLOG from tasklets. The crypto API would do GFP_ATOMIC allocation instead, it could return -ENOMEM and we catch -ENOMEM in verity_tasklet and requeue the request to the workqueue. Signed-off-by: Mikulas Patocka <[email protected]> Cc: [email protected] # v6.0+ Fixes: 5721d4e ("dm verity: Add optional "try_verify_in_tasklet" feature") Signed-off-by: Mike Snitzer <[email protected]>
1 parent 2a69506 commit 28f07f2

File tree

3 files changed

+15
-14
lines changed

3 files changed

+15
-14
lines changed

drivers/md/dm-verity-fec.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,7 @@ static int fec_is_erasure(struct dm_verity *v, struct dm_verity_io *io,
185185
{
186186
if (unlikely(verity_hash(v, verity_io_hash_req(v, io),
187187
data, 1 << v->data_dev_block_bits,
188-
verity_io_real_digest(v, io))))
188+
verity_io_real_digest(v, io), true)))
189189
return 0;
190190

191191
return memcmp(verity_io_real_digest(v, io), want_digest,
@@ -386,7 +386,7 @@ static int fec_decode_rsb(struct dm_verity *v, struct dm_verity_io *io,
386386
/* Always re-validate the corrected block against the expected hash */
387387
r = verity_hash(v, verity_io_hash_req(v, io), fio->output,
388388
1 << v->data_dev_block_bits,
389-
verity_io_real_digest(v, io));
389+
verity_io_real_digest(v, io), true);
390390
if (unlikely(r < 0))
391391
return r;
392392

drivers/md/dm-verity-target.c

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -135,20 +135,21 @@ static int verity_hash_update(struct dm_verity *v, struct ahash_request *req,
135135
* Wrapper for crypto_ahash_init, which handles verity salting.
136136
*/
137137
static int verity_hash_init(struct dm_verity *v, struct ahash_request *req,
138-
struct crypto_wait *wait)
138+
struct crypto_wait *wait, bool may_sleep)
139139
{
140140
int r;
141141

142142
ahash_request_set_tfm(req, v->tfm);
143-
ahash_request_set_callback(req, CRYPTO_TFM_REQ_MAY_SLEEP |
144-
CRYPTO_TFM_REQ_MAY_BACKLOG,
145-
crypto_req_done, (void *)wait);
143+
ahash_request_set_callback(req,
144+
may_sleep ? CRYPTO_TFM_REQ_MAY_SLEEP | CRYPTO_TFM_REQ_MAY_BACKLOG : 0,
145+
crypto_req_done, (void *)wait);
146146
crypto_init_wait(wait);
147147

148148
r = crypto_wait_req(crypto_ahash_init(req), wait);
149149

150150
if (unlikely(r < 0)) {
151-
DMERR("crypto_ahash_init failed: %d", r);
151+
if (r != -ENOMEM)
152+
DMERR("crypto_ahash_init failed: %d", r);
152153
return r;
153154
}
154155

@@ -179,12 +180,12 @@ static int verity_hash_final(struct dm_verity *v, struct ahash_request *req,
179180
}
180181

181182
int verity_hash(struct dm_verity *v, struct ahash_request *req,
182-
const u8 *data, size_t len, u8 *digest)
183+
const u8 *data, size_t len, u8 *digest, bool may_sleep)
183184
{
184185
int r;
185186
struct crypto_wait wait;
186187

187-
r = verity_hash_init(v, req, &wait);
188+
r = verity_hash_init(v, req, &wait, may_sleep);
188189
if (unlikely(r < 0))
189190
goto out;
190191

@@ -322,7 +323,7 @@ static int verity_verify_level(struct dm_verity *v, struct dm_verity_io *io,
322323

323324
r = verity_hash(v, verity_io_hash_req(v, io),
324325
data, 1 << v->hash_dev_block_bits,
325-
verity_io_real_digest(v, io));
326+
verity_io_real_digest(v, io), !io->in_tasklet);
326327
if (unlikely(r < 0))
327328
goto release_ret_r;
328329

@@ -556,7 +557,7 @@ static int verity_verify_io(struct dm_verity_io *io)
556557
continue;
557558
}
558559

559-
r = verity_hash_init(v, req, &wait);
560+
r = verity_hash_init(v, req, &wait, !io->in_tasklet);
560561
if (unlikely(r < 0))
561562
return r;
562563

@@ -652,7 +653,7 @@ static void verity_tasklet(unsigned long data)
652653

653654
io->in_tasklet = true;
654655
err = verity_verify_io(io);
655-
if (err == -EAGAIN) {
656+
if (err == -EAGAIN || err == -ENOMEM) {
656657
/* fallback to retrying with work-queue */
657658
INIT_WORK(&io->work, verity_work);
658659
queue_work(io->v->verify_wq, &io->work);
@@ -1033,7 +1034,7 @@ static int verity_alloc_zero_digest(struct dm_verity *v)
10331034
goto out;
10341035

10351036
r = verity_hash(v, req, zero_data, 1 << v->data_dev_block_bits,
1036-
v->zero_digest);
1037+
v->zero_digest, true);
10371038

10381039
out:
10391040
kfree(req);

drivers/md/dm-verity.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ extern int verity_for_bv_block(struct dm_verity *v, struct dm_verity_io *io,
128128
u8 *data, size_t len));
129129

130130
extern int verity_hash(struct dm_verity *v, struct ahash_request *req,
131-
const u8 *data, size_t len, u8 *digest);
131+
const u8 *data, size_t len, u8 *digest, bool may_sleep);
132132

133133
extern int verity_hash_for_block(struct dm_verity *v, struct dm_verity_io *io,
134134
sector_t block, u8 *digest, bool *is_zero);

0 commit comments

Comments
 (0)