code: plan9front

Download patch

ref: dd82b07a863d8ace74ae63a98513db69b24b0019
parent: 79323e05d14bc7d2672edac45aae88e494c06eaa
author: Ori Bernstein <ori@eigenstate.org>
date: Wed May 29 15:34:14 EDT 2024

gefs: correctly serialize updates to mounts

we don't need a lock free list, we just need an
rwlock; this isn't a high contention data structure.

--- a/sys/src/cmd/gefs/blk.c
+++ b/sys/src/cmd/gefs/blk.c
@@ -928,9 +928,6 @@
 		case DFtree:
 			free(p->t);
 			break;
-		case DFmnt:
-			free(p->m);
-			break;
 		case DFblk:
 			a = getarena(p->bp.addr);
 			qe.op = Qfree;
--- a/sys/src/cmd/gefs/dat.h
+++ b/sys/src/cmd/gefs/dat.h
@@ -433,7 +433,6 @@
 
 enum {
 	DFblk,
-	DFmnt,
 	DFtree,
 };
 
@@ -517,6 +516,7 @@
 	QLock	synclk;
 	Rendez	syncrz;
 
+	RWLock	mountlk;
 	Mount	*mounts;
 	Mount	*snapmnt;
 	Lock	connlk;
--- a/sys/src/cmd/gefs/fs.c
+++ b/sys/src/cmd/gefs/fs.c
@@ -96,8 +96,10 @@
          */
 	qlock(&fs->mutlk);
 	tracem("packb");
-	for(mnt = agetp(&fs->mounts); mnt != nil; mnt = mnt->next)
+	rlock(&fs->mountlk);
+	for(mnt = fs->mounts; mnt != nil; mnt = mnt->next)
 		updatesnap(&mnt->root, mnt->root, mnt->name, mnt->flag);
+	runlock(&fs->mountlk);
 	/*
 	 * Now that we've updated the snaps, we can sync the
 	 * dlist; the snap tree will not change from here.
@@ -199,7 +201,8 @@
 	}
 	t = nil;
 	*tp = nil;
-	for(mnt = agetp(&fs->mounts); mnt != nil; mnt = mnt->next){
+	rlock(&fs->mountlk);
+	for(mnt = fs->mounts; mnt != nil; mnt = mnt->next){
 		if(strcmp(a->old, mnt->name) == 0){
 			updatesnap(&mnt->root, mnt->root, mnt->name, mnt->flag);
 			t = agetp(&mnt->root);
@@ -207,6 +210,7 @@
 			break;
 		}
 	}
+	runlock(&fs->mountlk);
 	if(t == nil && (t = opensnap(a->old, nil)) == nil){
 		if(a->fd != -1)
 			fprint(a->fd, "snap: open '%s': does not exist\n", a->old);
@@ -623,13 +627,13 @@
 		return fs->snapmnt;
 	}
 
-	for(mnt = agetp(&fs->mounts); mnt != nil; mnt = mnt->next){
+	wlock(&fs->mountlk);
+	for(mnt = fs->mounts; mnt != nil; mnt = mnt->next){
 		if(strcmp(name, mnt->name) == 0){
 			ainc(&mnt->ref);
 			goto Out;
 		}
 	}
-
 	if((mnt = mallocz(sizeof(*mnt), 1)) == nil)
 		error(Enomem);
 	if(waserror()){
@@ -644,10 +648,11 @@
 	mnt->flag = flg;
 	mnt->root = t;
 	mnt->next = fs->mounts;
-	asetp(&fs->mounts, mnt);
+	fs->mounts = mnt;
 	poperror();
 
 Out:
+	wunlock(&fs->mountlk);
 	return mnt;
 }
 
@@ -654,22 +659,22 @@
 void
 clunkmount(Mount *mnt)
 {
-	Mount *me, **p;
-	Bfree *f;
+	Mount *e, **p;
 
 	if(mnt == nil)
 		return;
 	if(adec(&mnt->ref) == 0){
-		for(p = &fs->mounts; (me = *p) != nil; p = &me->next){
-			if(me == mnt)
+		wlock(&fs->mountlk);
+		p = &fs->mounts;
+		for(e = fs->mounts; e != nil; e = e->next){
+			if(e == mnt)
 				break;
+			p = &e->next;
 		}
-		assert(me != nil);
-		f = emalloc(sizeof(Bfree), 0);
-		f->op = DFmnt;
-		f->m = mnt;
-		*p = me->next;
-		limbo(f);
+		assert(e != nil);
+		*p = e->next;
+		free(mnt);
+		wunlock(&fs->mountlk);
 	}
 }
 
@@ -2673,7 +2678,8 @@
 		chsend(fs->admchan, a);
 
 		tmnow(&now, nil);
-		for(mnt = agetp(&fs->mounts); mnt != nil; mnt = mnt->next){
+		rlock(&fs->mountlk);
+		for(mnt = fs->mounts; mnt != nil; mnt = mnt->next){
 			if(!(mnt->flag & Ltsnap))
 				continue;
 			if(now.yday != then.yday){
@@ -2696,6 +2702,7 @@
 				snapmsg("main", mnt->minutely[m], Lauto);
 			}
 		}
+		runlock(&fs->mountlk);
 		if(now.hour != then.hour)
 			h = (h+1)%24;
 		if(now.min != then.min)
--- a/sys/src/cmd/gefs/snap.c
+++ b/sys/src/cmd/gefs/snap.c
@@ -348,12 +348,14 @@
 	btupsert(&fs->snap, m, nm);
 	if(deltree){
 		reclaimblocks(t->gen, succ, t->pred);
-		for(mnt = agetp(&fs->mounts); mnt != nil; mnt = mnt->next){
+		rlock(&fs->mountlk);
+		for(mnt = fs->mounts; mnt != nil; mnt = mnt->next){
 			if(mnt->root->gen == t->succ)
 				mnt->root->pred = t->pred;
 			if(mnt->root->gen == t->pred)
 				mnt->root->succ = t->succ;
 		}
+		runlock(&fs->mountlk);
 	}
 }