code: mafs

Download patch

ref: b5d191e8cfa4fac05a02ea309df2541a2652ff23
parent: f79b530d2184b14082fa130261c8d070c168f06c
author: 9ferno <gophone2015@gmail.com>
date: Thu Nov 10 16:33:14 EST 2022

implemented exclusive use files

--- a/9p.c
+++ b/9p.c
@@ -1,5 +1,7 @@
 #include "all.h"
 
+Tlock	*tlockhead = nil, *tlocktail = nil;
+QLock	tlock;
 extern int mpstarted;
 extern u8 synchronouswrites;
 
@@ -57,10 +59,38 @@
 static void
 fsdestroyfid(Fid *fid)
 {
+	Tlock *t;
+
 	if((fid->qid.type & QTAUTH) != 0){
 		authdestroy(fid);
 		return;
 	}
+	if(((Aux*)fid->aux)->tlocked == 1){
+		qlock(&tlock);
+		if(tlocktail == nil){
+			qunlock(&tlock);
+			panic("locked but tlock queue is empty\n");
+			return;
+		}else{
+			for(t = tlockhead; t != nil; t = t->next){
+				if(t->dblkno == ((Aux*)fid->aux)->dblkno &&
+					t->qpath == fid->qid.path){
+					if(t->prev != nil)
+						t->prev->next = t->next;
+					if(t->next != nil)
+						t->next->prev = t->prev;
+					if(tlocktail == t)
+						tlocktail = t->prev;
+					if(tlockhead == t)
+						tlockhead = t->next;
+					((Aux*)fid->aux)->tlocked = 0;
+					free(t);
+					break;
+				}
+			}
+		}
+		qunlock(&tlock);
+	}
 	freeaux(fid->aux);
 }
 
@@ -452,6 +482,7 @@
 	Aux *aux;
 	u32 perm;
 	Fid *fid;
+	Tlock *t;
 
 	/* no create's when shutting down */
 	if(shuttingdown){
@@ -558,7 +589,7 @@
 			dchild->mtime = nsec();
 			dchild->uid = dchild->muid = aux->uid;
 			dchild->gid = dparent->gid;
-			/* TODO DMAPPEND and DMEXCL attributes */
+			/* TODO DMAPPEND attributes */
 			if(perm&DMDIR){
 				if((req->ifcall.mode & OTRUNC) || (perm & DMAPPEND) ||
 					(fid->omode & OWRITE)){
@@ -574,8 +605,8 @@
 				dchild->mode = perm & (~0666 | (dparent->mode & 0666));
 			if(perm&DMAPPEND)
 				dchild->mode |= DMAPPEND;
-			/* if(perm&DMEXCL) TODO create a list of locks
-				dchild->mode |= DMEXCL; */
+			if(perm&DMEXCL)
+				dchild->mode |= DMEXCL;
 			if(canaccess(aux->uid, dchild, DMWRITE) == 0){
 				putbuf(cbuf);
 				putbuf(dbuf);
@@ -588,6 +619,23 @@
 			fid->qid = (Qid){dchild->qid.path, 0, (perm&DMDIR) ? QTDIR : QTFILE};
 			aux->dblkno = cbuf->blkno;
 			aux->dri = 0;
+			if(perm&DMEXCL){
+				t = emalloc9p(sizeof(Tlock));
+				t->time = nsec();
+				t->qpath = dchild->qid.path;
+				t->dblkno = aux->dblkno;
+				qlock(&tlock);
+				if(tlocktail == nil){
+					tlocktail = tlockhead = t;
+				}else{
+					tlocktail->next = t;
+					t->prev = tlocktail;
+					tlocktail = t;
+				}
+				qunlock(&tlock);
+				aux->tlocked = 1;
+			}else
+				aux->tlocked = 0;
 			req->ofcall.qid = fid->qid;
 			req->ofcall.iounit = Iounit;
 			settag(cbuf, Tdentry, dchild->qid.path);
@@ -676,6 +724,7 @@
 	Iobuf *dbuf;
 	Aux *aux;
 	Dentry *d;
+	Tlock *t;
 
 	dbuf = nil;
 	mode = req->ifcall.mode;
@@ -710,8 +759,30 @@
 			goto perm;
 	}
 	if((d->mode & DMEXCL) != 0){
-		respond(req, "DMEXCL read not implemented");
-		return;
+		qlock(&tlock);
+		if(tlocktail != nil){
+			for(t = tlockhead; t != nil; t = t->next){
+				if(t->dblkno == ((Aux*)fid->aux)->dblkno &&
+					t->qpath == fid->qid.path){
+					qunlock(&tlock);
+					respond(req, "DMEXCL locked");
+					return;
+				}
+			}
+		}
+		t = emalloc9p(sizeof(Tlock));
+		t->time = nsec();
+		t->qpath = fid->qid.path;
+		t->dblkno = aux->dblkno;
+		if(tlocktail == nil){
+			tlocktail = tlockhead = t;
+		}else{
+			tlocktail->next = t;
+			t->prev = tlocktail;
+			tlocktail = t;
+		}
+		qunlock(&tlock);
+		aux->tlocked = 1;
 	}
 	switch(mode & OEXEC){
 	case ORDWR:
--- a/TODO
+++ b/TODO
@@ -1,11 +1,10 @@
-test -A announce
-profiling
 mafswrite():
 	add user and remove user messages
 	users format has changed as per this http://9p.io/wiki/plan9/Setting_up_Fossil/index.html
+APPEND files
+profiling
 read only mode
 need rlock() when looking up user id, group id, or user attributes
-EXCL files - maintain a list of locks in the tree
 Clean up the Iobuf locking description?
 
 not a priority, are they even needed?
@@ -18,4 +17,3 @@
 correct /adm/ctl operation:
 	echo df >> /adm/ctl
 	cat /adm/ctl
-APPEND files
--- a/dat.h
+++ b/dat.h
@@ -82,7 +82,6 @@
 	Nbused, /* blocks used up by default */
 	Nminblocks = Nbused+(Nbkp*3), /* number of blocks used by the above and the backup blocks */
 
-	NTLOCK	= 200,	/* number of active file Tlocks */
 	Nthdirty = 9,	/* dirty byte is the 9th byte in the Tag */
 };
 
@@ -208,7 +207,8 @@
 {
 	u64 time;
 	u64 qpath;
-	u64 dblockno;
+	u64 dblkno;
+	Tlock *prev, *next;
 };
 
 struct Aux
@@ -215,7 +215,7 @@
 {
 	u64 dblkno; /* dentry absolute block number */
 	u16 uid;
-	Tlock *tlock;	/* for exclusive use files */
+	u8 tlocked;	/* for exclusive use files, flag to indicate lock */
 	u64 dri;	/* directory index while reading a directory */
 	/* u64 lastreadahead; TODO */
 };
@@ -354,7 +354,6 @@
 #define	TLOCK		MINUTE(5)
 
 extern	char*	errstring[MAXERR];
-extern	Tlock	*tlocks;
 extern	char	service[Namelen];
 extern	char	*tagnames[];
 extern	char	*devfile;	/* device file path */
--- a/docs/mafs.ms
+++ b/docs/mafs.ms
@@ -1555,6 +1555,8 @@
 Design considerations
 .ft R
 .sp
+For exclusive use (mode has DMEXCL bit set) files, there is no timeout.
+.sp
 Why are you not using a checksum to verify the contents?
 .br
 Checksums are probabilistic and can be implemented as a bespoke application instead of complicating the file system implementation.
--- a/mafs.c
+++ b/mafs.c
@@ -121,8 +121,6 @@
 
 	initmemunitpool(nmemunits);
 	initextents(&frees);
-
-	tlocks = emalloc9p(NTLOCK * sizeof *tlocks);
 	initwriter();
 	iobufinit();
 
--- a/mfs.c
+++ b/mfs.c
@@ -114,8 +114,6 @@
 
 	initmemunitpool(nmemunits);
 	initextents(&frees);
-
-	tlocks = emalloc9p(NTLOCK * sizeof *tlocks);
 	iobufinit();
 
 	/*
--- a/sub.c
+++ b/sub.c
@@ -2,33 +2,6 @@
 
 extern Srv mysrv;
 
-Tlock*
-tlocked(Iobuf *, Dentry *d)
-{
-	Tlock *t, *t1;
-	long qpath, tim;
-
-	tim = time(0);
-	qpath = d->qid.path;
-	t1 = 0;
-	for(t=tlocks+NTLOCK-1; t>=tlocks; t--) {
-		if(t->qpath == qpath)
-		if(t->time >= tim)
-			return 0;		/* its locked */
-		if(!t1 && t->time < tim)
-			t1 = t;			/* steal first lock */
-	}
-	if(t1) {
-		t1->qpath = qpath;
-		t1->time = tim + TLOCK;
-	}
-	/* botch
-	 * out of tlock nodes simulates
-	 * a locked file
-	 */
-	return t1;
-}
-
 u64
 newqpath()
 {