⬢ DragonFlyBSD Kernel Audit
DF-4509 / fix.diff
← back to finding ↓ download raw
--- a/sys/dev/raid/twa/tw_cl_misc.c
+++ b/sys/dev/raid/twa/tw_cl_misc.c
@@ -380,6 +380,19 @@
 	if (req) {
 		if (req->data)
 			ctlr->internal_req_busy = TW_CL_FALSE;
+
+		/*
+		 * DF-4509: on ETIMEDOUT (or any break while the firmware
+		 * still owns the request), req is still linked in
+		 * TW_CLI_BUSY_Q or TW_CLI_PENDING_Q.  Unlink it before
+		 * returning it to the free queue, or it ends up with
+		 * membership in two queues and is handed out twice.
+		 */
+		if (req->state == TW_CLI_REQ_STATE_BUSY)
+			tw_cli_req_q_remove_item(req, TW_CLI_BUSY_Q);
+		else if (req->state == TW_CLI_REQ_STATE_PENDING)
+			tw_cli_req_q_remove_item(req, TW_CLI_PENDING_Q);
+
 		tw_cli_req_q_insert_tail(req, TW_CLI_FREE_Q);
 	}
 	return(error);