Module Name:    src
Committed By:   knakahara
Date:           Wed Apr  5 08:51:04 UTC 2017

Modified Files:
        src/sys/opencrypto: crypto.c cryptodev.c

Log Message:
fix processes accessing /dev/crypto stall when over three processes run with a 
hardware encryption driver

The process has stalled at cv_wait(&crp->crp_cv) because cryptodev_cb()
is not called as cryptoret() kthread keep waiting at cv_wait(&cryptoret_cv).
Previous opencrypto implementation assumes the thread from cryptodev.c
does all processing in the same context, so skips enqueueing and sending
cryptoret_cv. However, the context can be switched, e.g. when we use
a hardware encryption driver.

And add debug messages.


To generate a diff of this commit:
cvs rdiff -u -r1.51 -r1.52 src/sys/opencrypto/crypto.c
cvs rdiff -u -r1.85 -r1.86 src/sys/opencrypto/cryptodev.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/opencrypto/crypto.c
diff -u src/sys/opencrypto/crypto.c:1.51 src/sys/opencrypto/crypto.c:1.52
--- src/sys/opencrypto/crypto.c:1.51	Wed Mar 29 23:02:43 2017
+++ src/sys/opencrypto/crypto.c	Wed Apr  5 08:51:04 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: crypto.c,v 1.51 2017/03/29 23:02:43 knakahara Exp $ */
+/*	$NetBSD: crypto.c,v 1.52 2017/04/05 08:51:04 knakahara Exp $ */
 /*	$FreeBSD: src/sys/opencrypto/crypto.c,v 1.4.2.5 2003/02/26 00:14:05 sam Exp $	*/
 /*	$OpenBSD: crypto.c,v 1.41 2002/07/17 23:52:38 art Exp $	*/
 
@@ -53,7 +53,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: crypto.c,v 1.51 2017/03/29 23:02:43 knakahara Exp $");
+__KERNEL_RCSID(0, "$NetBSD: crypto.c,v 1.52 2017/04/05 08:51:04 knakahara Exp $");
 
 #include <sys/param.h>
 #include <sys/reboot.h>
@@ -418,6 +418,9 @@ crypto_newsession(u_int64_t *sid, struct
 				(*sid) <<= 32;
 				(*sid) |= (lid & 0xffffffff);
 				crypto_drivers[hid].cc_sessions++;
+			} else {
+				DPRINTF(("%s: crypto_drivers[%d].cc_newsession() failed. error=%d\n",
+					__func__, hid, error));
 			}
 			goto done;
 			/*break;*/
@@ -1124,19 +1127,20 @@ crypto_done(struct cryptop *crp)
 	} else {
 		mutex_spin_enter(&crypto_ret_q_mtx);
 		crp->crp_flags |= CRYPTO_F_DONE;
-
+#if 0
 		if (crp->crp_flags & CRYPTO_F_USER) {
-			/* the request has completed while
-			 * running in the user context
-			 * so don't queue it - the user
-			 * thread won't sleep when it sees
-			 * the CRYPTO_F_DONE flag.
-			 * This is an optimization to avoid
-			 * unecessary context switches.
+			/*
+			 * TODO:
+			 * If crp->crp_flags & CRYPTO_F_USER and the used
+			 * encryption driver does all the processing in
+			 * the same context, we can skip enqueueing crp_ret_q
+			 * and cv_signal(&cryptoret_cv).
 			 */
 			DPRINTF(("crypto_done[%u]: crp %p CRYPTO_F_USER\n",
 				CRYPTO_SESID2LID(crp->crp_sid), crp));
-		} else {
+		} else
+#endif
+		{
 			wasempty = TAILQ_EMPTY(&crp_ret_q);
 			DPRINTF(("crypto_done[%u]: queueing %p\n",
 				CRYPTO_SESID2LID(crp->crp_sid), crp));

Index: src/sys/opencrypto/cryptodev.c
diff -u src/sys/opencrypto/cryptodev.c:1.85 src/sys/opencrypto/cryptodev.c:1.86
--- src/sys/opencrypto/cryptodev.c:1.85	Thu Jul  7 06:55:43 2016
+++ src/sys/opencrypto/cryptodev.c	Wed Apr  5 08:51:04 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: cryptodev.c,v 1.85 2016/07/07 06:55:43 msaitoh Exp $ */
+/*	$NetBSD: cryptodev.c,v 1.86 2017/04/05 08:51:04 knakahara Exp $ */
 /*	$FreeBSD: src/sys/opencrypto/cryptodev.c,v 1.4.2.4 2003/06/03 00:09:02 sam Exp $	*/
 /*	$OpenBSD: cryptodev.c,v 1.53 2002/07/10 22:21:30 mickey Exp $	*/
 
@@ -64,7 +64,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: cryptodev.c,v 1.85 2016/07/07 06:55:43 msaitoh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: cryptodev.c,v 1.86 2017/04/05 08:51:04 knakahara Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -578,10 +578,10 @@ cryptodev_op(struct csession *cse, struc
 
 
 	crp->crp_ilen = cop->len;
-	/* The reqest is flagged as CRYPTO_F_USER as long as it is running
-	 * in the user IOCTL thread.  This flag lets us skip using the retq for
-	 * the request if it completes immediately. If the request ends up being
-	 * delayed or is not completed immediately the flag is removed.
+	/*
+	 * The request is flagged as CRYPTO_F_USER as long as it is running
+	 * in the user IOCTL thread. However, whether the request completes
+	 * immediately or belatedly is depends on the used encryption driver.
 	 */
 	crp->crp_flags = CRYPTO_F_IOV | (cop->flags & COP_F_BATCH) | CRYPTO_F_USER |
 			flags;
@@ -643,12 +643,9 @@ eagain:
 	mutex_enter(&crypto_mtx);
 
 	/* 
-	 * If the request was going to be completed by the
-	 * ioctl thread then it would have been done by now.
-	 * Remove the F_USER flag so crypto_done() is not confused
-	 * if the crypto device calls it after this point.
+	 * Don't touch crp before returned by any error or recieved
+	 * cv_signal(&crp->crp_cv). It is required to restructure locks.
 	 */
-	crp->crp_flags &= ~(CRYPTO_F_USER);
 
 	switch (error) {
 #ifdef notyet	/* don't loop forever -- but EAGAIN not possible here yet */

Reply via email to