code: plan9front

Download patch

ref: 79323e05d14bc7d2672edac45aae88e494c06eaa
parent: 04d0d77e4b8a5525a86e7d84e0620001a099324f
author: Ori Bernstein <ori@eigenstate.org>
date: Wed May 29 13:12:21 EDT 2024

gefs: make dent cache per-mount

with a global dent cache, directory entries from different
trees can be cached. This almost works, but QID state can
change as the files get modified -- ownership, permissions,
and similar can get changed.

A global mount cache means that changes to a qid may leak
across mount boundaries. Don't do that.

--- a/sys/src/cmd/gefs/dat.h
+++ b/sys/src/cmd/gefs/dat.h
@@ -545,10 +545,6 @@
 	User	*users;
 	int	nusers;
 
-	/* open directory entries */
-	Lock	dtablk;
-	Dent	*dtab[Ndtab];
-
 	/* slow block io */
 	QLock	blklk[32];
 	
@@ -635,6 +631,10 @@
 	Tree	*root;	/* EBR protected */
 
 	int	flag;
+
+	/* open directory entries */
+	Lock	dtablk;
+	Dent	*dtab[Ndtab];
 
 	/* snapshot history */
 	char	minutely[60][128];
--- a/sys/src/cmd/gefs/fs.c
+++ b/sys/src/cmd/gefs/fs.c
@@ -527,7 +527,7 @@
 }
 
 static Dent*
-getdent(vlong pqid, Xdir *d)
+getdent(Mount *mnt, vlong pqid, Xdir *d)
 {
 	Dent *de;
 	char *e;
@@ -534,8 +534,8 @@
 	u32int h;
 
 	h = ihash(d->qid.path) % Ndtab;
-	lock(&fs->dtablk);
-	for(de = fs->dtab[h]; de != nil; de = de->next){
+	lock(&mnt->dtablk);
+	for(de = mnt->dtab[h]; de != nil; de = de->next){
 		if(de->qid.path == d->qid.path){
 			ainc(&de->ref);
 			goto Out;
@@ -558,11 +558,11 @@
 	de->k = de->buf;
 	de->nk = e - de->buf;
 	de->name = de->buf + 11;
-	de->next = fs->dtab[h];
-	fs->dtab[h] = de;
+	de->next = mnt->dtab[h];
+	mnt->dtab[h] = de;
 
 Out:
-	unlock(&fs->dtablk);
+	unlock(&mnt->dtablk);
 	return de;
 }
 
@@ -674,7 +674,7 @@
 }
 
 static void
-clunkdent(Dent *de)
+clunkdent(Mount *mnt, Dent *de)
 {
 	Dent *e, **pe;
 	u32int h;
@@ -685,12 +685,12 @@
 		free(de);
 		return;
 	}
-	lock(&fs->dtablk);
+	lock(&mnt->dtablk);
 	if(adec(&de->ref) != 0)
 		goto Out;
 	h = ihash(de->qid.path) % Ndtab;
-	pe = &fs->dtab[h];
-	for(e = fs->dtab[h]; e != nil; e = e->next){
+	pe = &mnt->dtab[h];
+	for(e = mnt->dtab[h]; e != nil; e = e->next){
 		if(e == de)
 			break;
 		pe = &e->next;
@@ -699,7 +699,7 @@
 	*pe = e->next;
 	free(de);
 Out:
-	unlock(&fs->dtablk);
+	unlock(&mnt->dtablk);
 }
 
 static Fid*
@@ -724,8 +724,8 @@
 {
 	if(adec(&f->ref) != 0)
 		return;
+	clunkdent(f->mnt, f->dent);
 	clunkmount(f->mnt);
-	clunkdent(f->dent);
 	free(f);
 }
 
@@ -1163,7 +1163,7 @@
 			error(Enosnap);
 		kv2dir(&kv, &d);
 	}
-	de = getdent(-1, &d);
+	de = getdent(mnt, -1, &d);
 	memset(&f, 0, sizeof(Fid));
 	f.fid = NOFID;
 	f.mnt = mnt;
@@ -1190,7 +1190,7 @@
 	poperror();
 
 
-Err:	clunkdent(de);
+Err:	clunkdent(mnt, de);
 	clunkmount(mnt);
 }
 
@@ -1312,15 +1312,15 @@
 			nexterror();
 		}
 		if(up == Qdump)
-			dent = getdent(-1ULL, &d);
+			dent = getdent(mnt, -1ULL, &d);
 		else
-			dent = getdent(up, &d);
+			dent = getdent(mnt, up, &d);
+		clunkdent(f->mnt, f->dent);
 		if(mnt != f->mnt){
 			clunkmount(f->mnt);
 			ainc(&mnt->ref);
 			f->mnt = mnt;
 		}
-		clunkdent(f->dent);
 		f->qpath = r.wqid[i-1].path;
 		f->pqpath = up;
 		f->dent = dent;
@@ -1694,8 +1694,8 @@
 	}
 	upsert(f->mnt, mb, nm);
 
-	de = getdent(f->qpath, &d);
-	clunkdent(f->dent);
+	de = getdent(f->mnt, f->qpath, &d);
+	clunkdent(f->mnt, f->dent);
 	f->mode = mode2bits(m->mode);
 	f->pqpath = f->qpath;
 	f->qpath = d.qid.path;
@@ -2616,7 +2616,7 @@
 				am->dent->trunc = 0;
 				rwakeup(&am->dent->truncrz);
 				qunlock(&am->dent->trunclk);
-				clunkdent(am->dent);
+				clunkdent(am->mnt, am->dent);
 			}
 			clunkmount(am->mnt);
 			poperror();