shithub: gefs

Download patch

ref: 9c12f278297212e8644ba85975f2b1ab3bd2c8b9
parent: 521bb145a502cdb04984d67336c959a2fed424fa
author: Ori Bernstein <[email protected]>
date: Tue Dec 26 13:31:37 EST 2023

fs; make mounts participate in deferred reclamation

there was a deadlock with the mountlk, where both sides
of the channel required the mountlk to be held; this could
be fixed in several ways, but the most elegant is eliminating
the lock entirely. The data isn't mutated often.

--- a/dat.h
+++ b/dat.h
@@ -434,6 +434,7 @@
 
 enum {
 	DFblk,
+	DFmnt,
 	DFtree,
 };
 
@@ -440,6 +441,7 @@
 struct Bfree {
 	Bfree	*next;
 	int	op;
+	Mount	*m;
 	Tree	*t;
 	Blk	*b;
 	Bptr	bp;
@@ -507,7 +509,6 @@
 	QLock	synclk;
 	Rendez	syncrz;
 
-	Lock	mountlk;
 	Mount	*mounts;
 	Mount	*snapmnt;
 	Lock	connlk;
--- a/fs.c
+++ b/fs.c
@@ -86,11 +86,9 @@
 	 *  can take a consistent snapshot.
          */
 	qlock(&fs->mutlk);
-	lock(&fs->mountlk);
 	dlsync();
-	for(mnt = fs->mounts; mnt != nil; mnt = mnt->next)
+	for(mnt = agetp(&fs->mounts); mnt != nil; mnt = mnt->next)
 		updatesnap(&mnt->root, mnt->root, mnt->name);
-	unlock(&fs->mountlk);
 	for(i = 0; i < fs->narena; i++){
 		a = &fs->arenas[i];
 		qlock(a);
@@ -174,15 +172,13 @@
 	Tree *t, *s;
 	Mount *mnt;
 
-	lock(&fs->mountlk);
 	if(waserror()){
 		*tp = nil;
-		unlock(&fs->mountlk);
 		nexterror();
 	}
 	t = nil;
 	*tp = nil;
-	for(mnt = fs->mounts; mnt != nil; mnt = mnt->next){
+	for(mnt = agetp(&fs->mounts); mnt != nil; mnt = mnt->next){
 		if(strcmp(a->old, mnt->name) == 0){
 			updatesnap(&mnt->root, mnt->root, mnt->name);
 			t = agetp(&mnt->root);
@@ -193,7 +189,6 @@
 	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);
-		unlock(&fs->mountlk);
 		poperror();
 		return;
 	}
@@ -201,7 +196,6 @@
 		if(mnt != nil) {
 			if(a->fd != -1)
 				fprint(a->fd, "snap: snap is mounted: '%s'\n", a->old);
-			unlock(&fs->mountlk);
 			poperror();
 			return;
 		}
@@ -215,7 +209,6 @@
 			if(a->fd != -1)
 				fprint(a->fd, "snap: already exists '%s'\n", a->new);
 			closesnap(s);
-			unlock(&fs->mountlk);
 			poperror();
 			return;
 		}
@@ -222,7 +215,6 @@
 		tagsnap(t, a->new, a->flag);
 	}
 	closesnap(t);
-	unlock(&fs->mountlk);
 	poperror();
 	if(a->fd != -1){
 		if(a->delete)
@@ -593,8 +585,7 @@
 		return fs->snapmnt;
 	}
 
-	lock(&fs->mountlk);
-	for(mnt = fs->mounts; mnt != nil; mnt = mnt->next){
+	for(mnt = agetp(&fs->mounts); mnt != nil; mnt = mnt->next){
 		if(strcmp(name, mnt->name) == 0){
 			ainc(&mnt->ref);
 			goto Out;
@@ -604,7 +595,6 @@
 	if((mnt = mallocz(sizeof(*mnt), 1)) == nil)
 		error(Enomem);
 	if(waserror()){
-		unlock(&fs->mountlk);
 		free(mnt);
 		nexterror();
 	}
@@ -617,11 +607,10 @@
 	mnt->noauto = (flg & Lnoauto) != 0;
 	mnt->root = t;
 	mnt->next = fs->mounts;
-	fs->mounts = mnt;
+	asetp(&fs->mounts, mnt);
 	poperror();
 
 Out:
-	unlock(&fs->mountlk);
 	return mnt;
 }
 
@@ -629,10 +618,10 @@
 clunkmount(Mount *mnt)
 {
 	Mount *me, **p;
+	Bfree *f;
 
 	if(mnt == nil)
 		return;
-	lock(&fs->mountlk);
 	if(adec(&mnt->ref) == 0){
 		for(p = &fs->mounts; (me = *p) != nil; p = &me->next){
 			if(me == mnt)
@@ -639,10 +628,12 @@
 				break;
 		}
 		assert(me != nil);
+		f = emalloc(sizeof(Bfree), 0);
+		f->op = DFblk;
+		f->m = mnt;
 		*p = me->next;
-		free(mnt);
+		limbo(f);
 	}
-	unlock(&fs->mountlk);
 }
 
 static void
@@ -2509,8 +2500,7 @@
 		chsend(fs->admchan, a);
 
 		tmnow(&now, nil);
-		lock(&fs->mountlk);
-		for(mnt = fs->mounts; mnt != nil; mnt = mnt->next){
+		for(mnt = agetp(&fs->mounts); mnt != nil; mnt = mnt->next){
 			if(mnt->noauto)
 				continue;
 			if(now.yday != then.yday){
@@ -2533,7 +2523,6 @@
 				snapmsg("main", mnt->minutely[m], Lauto);
 			}
 		}
-		unlock(&fs->mountlk);
 		if(now.hour != then.hour)
 			h = (h+1)%24;
 		if(now.min != then.min)
--- a/snap.c
+++ b/snap.c
@@ -3,9 +3,9 @@
 #include <fcall.h>
 #include <avl.h>
 
+#include "atomic.h"
 #include "dat.h"
 #include "fns.h"
-#include "atomic.h"
 
 static void
 dlflush(Dlist *dl)
@@ -310,7 +310,7 @@
 	btupsert(&fs->snap, m, nm);
 	reclaimblocks(t->gen, succ, t->pred);
 	if(deltree){
-		for(mnt = fs->mounts; mnt != nil; mnt = mnt->next){
+		for(mnt = agetp(&fs->mounts); mnt != nil; mnt = mnt->next){
 			if(mnt->root->gen == t->succ)
 				mnt->root->pred = t->pred;
 			if(mnt->root->gen == t->pred)