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()
{