⬢ DragonFlyBSD Kernel Audit
DF-3237 / fix.diff
← back to finding ↓ download raw
--- a/sys/vfs/nfs/nfs_iod.c
+++ b/sys/vfs/nfs/nfs_iod.c
@@ -241,9 +241,19 @@ nfssvc_iod_writer_wakeup(struct nfsmount *nmp)
 {
 	if (nmp->nm_txstate == NFSSVC_WAITING) {
 		nmp->nm_txstate = NFSSVC_PENDING;
 		wakeup(&nmp->nm_txstate);
+		return;
 	}
+	/*
+	 * Once the writer is STOPPING/DONE nothing will drain nm_reqtxq
+	 * again; anything still queued must complete now or it strands a
+	 * nfsreq + nfsm_info + bio (biodone never called).
+	 */
+	if (nmp->nm_txstate == NFSSVC_STOPPING || nmp->nm_txstate == NFSSVC_DONE) {
+		struct nfs_req *req;
+		while ((req = TAILQ_FIRST(&nmp->nm_reqtxq)) != NULL) {
+			TAILQ_REMOVE(&nmp->nm_reqtxq, req, r_chain);
+			atomic_subtract_int(&nmp->nm_bioqlen, 1);
+			req->r_info->done(req->r_info);
+		}
+	}
 }