code: plan9front

Download patch

ref: 06221c080dad6650b1e1af88857951775803bf32
parent: 6c9c2beb6e54a2ced1466615452e338d9bb7d48d
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Sat Mar 16 13:07:03 EDT 2024

qio: fix queue bloat blocking condition for qwrite()

The code in qwrite() that enters a non-interruptable
blocking loop is there because normally
flow control is done after Block's have been queued.

A process can skip that flow-control by receiving
a note duing qflow(). If that happens in a loop
it can bloat the queue without limit.

So if normal flow control fails to maintain the limit,
we want to block before allocating and queuing
the blocks as a last resort.

The condition however should be q->len >= q->limit,
not q->len/2 >= q->limit.

--- a/sys/src/9/port/qio.c
+++ b/sys/src/9/port/qio.c
@@ -1165,7 +1165,7 @@
 		print("qwrite hi %#p\n", getcallerpc(&q));
 
 	/* stop queue bloat before allocating blocks */
-	if(q->len/2 >= q->limit && q->noblock == 0 && q->bypass == nil){
+	if(q->len >= q->limit && q->noblock == 0 && q->bypass == nil){
 		while(waserror()){
 			if(up->procctl == Proc_exitme || up->procctl == Proc_exitbig)
 				error(Egreg);
@@ -1222,10 +1222,7 @@
 
 		ilock(q);
 
-		/* we use an artificially high limit for kernel prints since anything
-		 * over the limit gets dropped
-		 */
-		if((q->state & Qclosed) != 0 || q->len/2 >= q->limit){
+		if((q->state & Qclosed) != 0 || q->len >= q->limit){
 			iunlock(q);
 			freeb(b);
 			break;