shithub: riscv

Download patch

ref: 45333cdc92654eb58dc8c820dd58ae23c4a49640
parent: bc306a5a6322fece62d459b6f80ecc8f9867dcb1
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Fri Aug 8 19:28:47 EDT 2014

devmnt: fix potential race with mntflushfree(), remove mntstats, 0 vs nil cleanup

when mountmux() completes a request for another process, enforce odering
of the loads and stores to the request prior to writing q->done = 1
so mntflushfree() sees q->done != 0 only when the request has actually
completed. otherwise, the q->done = 1 store could have been reordered
before the load from q->z, reading from already freed request and causing
spurious wakeups.

removing unused mntstats callback.

use nil for pointers instead of 0.

--- a/sys/src/9/port/devmnt.c
+++ b/sys/src/9/port/devmnt.c
@@ -74,9 +74,7 @@
 char	Esbadstat[] = "invalid directory entry received from server";
 char	Enoversion[] = "version not established for mount channel";
 
-void	(*mntstats)(int, Chan*, uvlong, ulong);
 
-
 static void
 mntreset(void)
 {
@@ -213,11 +211,11 @@
 	/* now build Mnt associated with this connection */
 	lock(&mntalloc);
 	m = mntalloc.mntfree;
-	if(m != 0)
+	if(m != nil)
 		mntalloc.mntfree = m->list;
 	else {
 		m = malloc(sizeof(Mnt));
-		if(m == 0) {
+		if(m == nil) {
 			qfree(q);
 			free(v);
 			unlock(&mntalloc);
@@ -239,8 +237,8 @@
 	free(msg);
 
 	lock(m);
-	m->queue = 0;
-	m->rip = 0;
+	m->queue = nil;
+	m->rip = nil;
 
 	c->flag |= CMSG;
 	c->mux = m;
@@ -587,7 +585,7 @@
 
 	lock(&mntalloc);
 	l = &mntalloc.list;
-	for(f = *l; f; f = f->list) {
+	for(f = *l; f != nil; f = f->list) {
 		if(f == m) {
 			*l = m->list;
 			break;
@@ -815,7 +813,7 @@
 	/* Gate readers onto the mount point one at a time */
 	for(;;) {
 		lock(m);
-		if(m->rip == 0)
+		if(m->rip == nil)
 			break;
 		unlock(m);
 		sleep(r->z, rpcattn, r);
@@ -933,8 +931,8 @@
 	Mntrpc *q;
 
 	lock(m);
-	m->rip = 0;
-	for(q = m->queue; q; q = q->list) {
+	m->rip = nil;
+	for(q = m->queue; q != nil; q = q->list) {
 		if(q->done == 0)
 		if(wakeup(q->z))
 			break;
@@ -950,28 +948,26 @@
 
 	lock(m);
 	l = &m->queue;
-	for(q = *l; q; q = q->list) {
+	for(q = *l; q != nil; q = q->list) {
 		/* look for a reply to a message */
 		if(q->request.tag == r->reply.tag) {
 			*l = q->list;
-			if(mntstats != nil)
-				(*mntstats)(q->request.type,
-					m->c, q->stime,
-					q->reqlen + r->replen);
-			if(q != r) {
-				/*
-				 * Completed someone else.
-				 * Trade pointers to receive buffer.
-				 */
-				q->reply = r->reply;
-				q->b = r->b;
-				r->b = nil;
-				z = q->z;
-			} else
-				z = nil;
-			q->done = 1;	/* hands off */
-			if(z != nil)
-				wakeup(z);
+			if(q == r) {
+				q->done = 1;
+				unlock(m);
+				return;
+			}
+			/*
+			 * Completed someone else.
+			 * Trade pointers to receive buffer.
+			 */
+			q->reply = r->reply;
+			q->b = r->b;
+			r->b = nil;
+			z = q->z;
+			coherence();
+			q->done = 1;
+			wakeup(z);
 			unlock(m);
 			return;
 		}
@@ -1014,7 +1010,7 @@
 {
 	Mntrpc *fr;
 
-	while(r){
+	while(r != nil){
 		fr = r->flushed;
 		if(!r->done){
 			r->reply.type = Rflush;
@@ -1133,7 +1129,7 @@
 	r->done = 1;
 
 	l = &m->queue;
-	for(f = *l; f; f = f->list) {
+	for(f = *l; f != nil; f = f->list) {
 		if(f == r) {
 			*l = r->list;
 			break;
@@ -1190,7 +1186,7 @@
 	Mntrpc *r;
 
 	r = v;
-	return r->done || r->m->rip == 0;
+	return r->done || r->m->rip == nil;
 }
 
 Dev mntdevtab = {