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.
This commit is contained in:
Pawel Jakub Dawidek 2006-05-22 07:48:45 +00:00
parent c4d39d8076
commit bda0abc627
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=158823

View File

@ -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