⬢ DragonFlyBSD Kernel Audit
DF-2833 / fix.diff
← back to finding ↓ download raw
--- sys/kern/vfs_sync.c	2026-06-29 12:51:19.000000000 +0000
+++ /tmp/opencode/v26/fixtree/sys/kern/vfs_sync.c	2026-10-24 16:33:07.789715562 +0000
@@ -93,8 +93,31 @@
 SYSCTL_INT(_kern, OID_AUTO, metadelay, CTLFLAG_RW,
 		&metadelay, 0, "VFS metadata synchronization delay");
 time_t retrydelay = 1;		/* retry delay after failure */
-SYSCTL_INT(_kern, OID_AUTO, retrydelay, CTLFLAG_RW,
-		&retrydelay, 0, "VFS retry synchronization delay");
+
+static int
+sysctl_kern_retrydelay(SYSCTL_HANDLER_ARGS)	/* DF-2833 */
+{
+	int error;
+	int v = retrydelay;
+
+	error = sysctl_handle_int(oidp, &v, 0, req);
+	if (error || !req->newptr)
+		return (error);
+	/*
+	 * retrydelay <= 0 requeues drained vnodes into the bucket being
+	 * drained (vn_syncer_add slot == syncer_delayno) and livelocks
+	 * the syncer while it holds sc_token.
+	 */
+	if (v < 1)
+		v = 1;
+	retrydelay = v;
+
+	return(0);
+}
+
+SYSCTL_PROC(_kern, OID_AUTO, retrydelay, CTLTYPE_INT | CTLFLAG_RW,
+		0, 0, sysctl_kern_retrydelay, "I",
+		"VFS retry synchronization delay");
 static int rushjob;			/* number of slots to run ASAP */
 static int stat_rush_requests;	/* number of times I/O speeded up */
 SYSCTL_INT(_debug, OID_AUTO, rush_requests, CTLFLAG_RW,
@@ -132,8 +155,8 @@
 		return (error);
 	if (v < 1)
 		v = 1;
-	if (v > SYNCER_MAXDELAY)
-		v = SYNCER_MAXDELAY;
+	if (v > SYNCER_MAXDELAY - 2)
+		v = SYNCER_MAXDELAY - 2;
 	syncdelay = v;
 
 	return(0);
@@ -205,7 +228,15 @@
 		--ctx->syncer_count;
 	}
 	if (delay <= 0) {
-		slot = -delay & ctx->syncer_mask;
+		/*
+		 * DF-2833: never requeue into the bucket currently being
+		 * drained - that livelocks the syncer drain loop while it
+		 * holds sc_token.
+		 */
+		slot = (ctx->syncer_delayno + (-delay ? -delay : 1)) &
+		    ctx->syncer_mask;
+		if (slot == (ctx->syncer_delayno & ctx->syncer_mask))
+			slot = (ctx->syncer_delayno + 1) & ctx->syncer_mask;
 	} else {
 		if (delay > SYNCER_MAXDELAY - 2)
 			delay = SYNCER_MAXDELAY - 2;