diff options
author | pjd <pjd@FreeBSD.org> | 2006-05-22 07:48:45 +0000 |
---|---|---|
committer | pjd <pjd@FreeBSD.org> | 2006-05-22 07:48:45 +0000 |
commit | 161ff0f03667052d20a1d997f9e8a945563136fd (patch) | |
tree | 21816577fcd10f3c20d67262fa7c3e16c6f9a566 /sys | |
parent | 04beefe3f75547ae3500d4e4a187810d08831fe6 (diff) | |
download | FreeBSD-src-161ff0f03667052d20a1d997f9e8a945563136fd.zip FreeBSD-src-161ff0f03667052d20a1d997f9e8a945563136fd.tar.gz |
We must synchronize access to cc_qblocked, because there could be a race
where crypto_invoke() returns ERESTART and before we set cc_qblocked to 1,
crypto_unblock() is called and sets it to 0. This way we mark device as
blocked forever.
Fix it by not setting cc_qblocked in the fast path and by protecting
crypto_invoke() in the crypto_proc thread with CRYPTO_Q_LOCK().
This won't slow things down, because there is no contention - we have
only one crypto thread. Actually it can be slightly faster, because we
save two atomic ops per crypto request.
The fast code path remains lock-less.
Diffstat (limited to 'sys')
-rw-r--r-- | sys/opencrypto/crypto.c | 21 |
1 files changed, 4 insertions, 17 deletions
diff --git a/sys/opencrypto/crypto.c b/sys/opencrypto/crypto.c index 74f147e..38d285c 100644 --- a/sys/opencrypto/crypto.c +++ b/sys/opencrypto/crypto.c @@ -694,19 +694,10 @@ crypto_dispatch(struct cryptop *crp) result = crypto_invoke(cap, crp, 0); if (result != ERESTART) return (result); - else { - /* - * The driver ran out of resources, mark the - * driver ``blocked'' for cryptop's and put - * the request on the queue. - * - * XXX ops are placed at the tail so their - * order is preserved but this can place them - * behind batch'd ops. - */ - cap->cc_qblocked = 1; - cryptostats.cs_blocks++; - } + /* + * The driver ran out of resources, put the request on + * the queue. + */ } } CRYPTO_Q_LOCK(); @@ -1102,13 +1093,11 @@ crypto_proc(void) } if (submit != NULL) { TAILQ_REMOVE(&crp_q, submit, crp_next); - CRYPTO_Q_UNLOCK(); hid = CRYPTO_SESID2HID(submit->crp_sid); cap = crypto_checkdriver(hid); KASSERT(cap != NULL, ("%s:%u Driver disappeared.", __func__, __LINE__)); result = crypto_invoke(cap, submit, hint); - CRYPTO_Q_LOCK(); if (result == ERESTART) { /* * The driver ran out of resources, mark the @@ -1138,9 +1127,7 @@ crypto_proc(void) } if (krp != NULL) { TAILQ_REMOVE(&crp_kq, krp, krp_next); - CRYPTO_Q_UNLOCK(); result = crypto_kinvoke(krp); - CRYPTO_Q_LOCK(); if (result == ERESTART) { /* * The driver ran out of resources, mark the |