shithub: gefs

Download patch

ref: 9e424a38e935655dc2c755056afb54e2840c0855
parent: 2a05dca22fba164e7549e359771aa26d88a7018a
author: Ori Bernstein <ori@eigenstate.org>
date: Sun May 12 19:02:00 EDT 2024

fs: implement ORCLOSE

--- a/dat.h
+++ b/dat.h
@@ -320,6 +320,7 @@
 	AOsnap,
 	AOsync,
 	AOclear,
+	AOrclose,
 };
 
 struct Bptr {
@@ -392,7 +393,7 @@
 		struct {	/* AOsync */
 			int	halt;
 		};
-		struct {	/* AOclear */
+		struct {	/* AOclear, AOrclose */
 			Mount	*mnt;
 			Dent	*dent;
 			vlong	qpath;
@@ -683,6 +684,7 @@
 	int	dmode;
 
 	char	permit;
+	char	rclose;
 };
 
 enum {
--- a/fs.c
+++ b/fs.c
@@ -1511,7 +1511,7 @@
 
 
 static void
-fsclunk(Fmsg *m)
+fsclunk(Fmsg *m, Amsg **ao)
 {
 	Fcall r;
 	Fid *f;
@@ -1521,6 +1521,23 @@
 		return;
 	}
 	lock(f);
+	if(f->rclose){
+		qlock(&f->dent->trunclk);
+		f->dent->trunc = 1;
+		qunlock(&f->dent->trunclk);
+		wlock(f->dent);
+		f->dent->gone = 1;
+		wunlock(f->dent);
+		*ao = emalloc(sizeof(Amsg), 1);
+		aincl(&f->dent->ref, 1);
+		aincl(&f->mnt->ref, 1);
+		(*ao)->op = AOrclose;
+		(*ao)->mnt = f->mnt;
+		(*ao)->qpath = f->qpath;
+		(*ao)->off = 0;
+		(*ao)->end = f->dent->length;
+		(*ao)->dent = f->dent;
+	}
 	if(f->scan != nil){
 		free(f->scan);
 		f->scan = nil;
@@ -1632,6 +1649,8 @@
 	f->pqpath = f->qpath;
 	f->qpath = d.qid.path;
 	f->dent = de;
+	if(m->mode & ORCLOSE)
+		f->rclose = 1;
 
 	r.type = Rcreate;
 	r.qid = d.qid;
@@ -1744,7 +1763,7 @@
 static void
 fsopen(Fmsg *m, int id, Amsg **ao)
 {
-	char *p, buf[Kvmax];
+	char *p, *e, buf[Kvmax];
 	int mbits;
 	Tree *t;
 	Fcall r;
@@ -1783,6 +1802,9 @@
 	if(f->dent->qid.type & QTEXCL)
 	if(f->dent->ref != 1)
 		error(Elocked);
+	if(m->mode & ORCLOSE)
+		if((e = candelete(f)) != nil)
+			error(e);
 	if(fsaccess(f, d.mode, d.uid, d.gid, mbits) == -1)
 		error(Eperm);
 	f->dent->length = d.length;
@@ -1797,7 +1819,6 @@
 		unlock(f);
 		error(Einuse);
 	}
-	f->mode = mode2bits(m->mode);
 	if(m->mode & OTRUNC){
 		wlock(f->dent);
 
@@ -1838,6 +1859,9 @@
 		wunlock(f->dent);
 		poperror();
 	}
+	f->mode = mode2bits(m->mode);
+	if(m->mode & ORCLOSE)
+		f->rclose = 1;
 	unlock(f);
 	poperror();
 	respond(m, &r);
@@ -2149,6 +2173,7 @@
 {
 	char err[128];
 	RWLock *lk;
+	Amsg *a;
 	Conn *c;
 	Fcall r;
 	Fmsg *m;
@@ -2180,13 +2205,14 @@
 			rlock(lk);
 		}
 
+		a = nil;
 		h = ihash(m->fid) % fs->nreaders;
 		switch(m->type){
 		/* sync setup, must not access tree */
 		case Tversion:	fsversion(m);	break;
 		case Tauth:	fsauth(m);	break;
-		case Tclunk:	fsclunk(m);	break;
 		case Tflush:	fsflush(m);	break;
+		case Tclunk:	fsclunk(m, &a);	break;
 
 		/* mutators */
 		case Tcreate:	chsend(fs->wrchan, m);	break;
@@ -2202,7 +2228,7 @@
 
 		/* both */
 		case Topen:
-			if((m->mode & OTRUNC) || (m->mode & 0xf) == OEXEC)
+			if((m->mode & OTRUNC) || (m->mode & ORCLOSE) != 0)
 				chsend(fs->wrchan, m);
 			else
 				chsend(fs->rdchan[h], m);
@@ -2217,6 +2243,8 @@
 			break;
 		}
 		assert(estacksz() == 0);
+		if(a != nil)
+			chsend(fs->admchan, a);
 	}
 }
 
@@ -2349,7 +2377,7 @@
 void
 runsweep(int id, void*)
 {
-	char buf[Offksz];
+	char buf[Kvmax];
 	Bptr bp, nb, *oldhd;
 	vlong off;
 	Tree *t;
@@ -2356,8 +2384,8 @@
 	Arena *a;
 	Amsg *am;
 	Blk *b;
-	Msg m;
-	int i;
+	Msg m, mb[2];
+	int i, nm;
 
 	if((oldhd = calloc(fs->narena, sizeof(Bptr))) == nil)
 		sysfatal("malloc log heads");
@@ -2459,6 +2487,23 @@
 			poperror();
 			break;
 
+		case AOrclose:
+			nm = 0;
+			mb[nm].op = Odelete;
+			mb[nm].k = am->dent->k;
+			mb[nm].nk = am->dent->nk;
+			mb[nm].nv = 0;
+			nm++;
+			if(am->dent->qid.type & QTDIR){
+				packsuper(buf, sizeof(buf), am->qpath);
+				mb[nm].op = Oclobber;
+				mb[nm].k = buf;
+				mb[nm].nk = Upksz;
+				mb[nm].nv = 0;
+				nm++;
+			}
+			upsert(am->mnt, mb, nm);
+			/* fallthrough */
 		case AOclear:
 			tracem("bgclear");
 			if(waserror()){