ref: 88a739c07b9bbf452a5cbfa1a33cbe7730aaae37
parent: 334cd4d87fc9fd8e48183128e9d60de669ab29fe
author: 9ferno <gophone2015@gmail.com>
date: Tue Nov 22 09:45:40 EST 2022
copy on write for all blocks
--- a/9p.c
+++ b/9p.c
@@ -7,6 +7,7 @@
s32 readfile(u64 dblkno, u64 qpath, char *rbuf, s32 rbufsize, u64 offset, Req *req);
s32 writefile(u64 dblkno, u64 qpath, s16 uid, char *wbuf, s32 wbufsize, u64 offset, Req *req);
+s32 writeallappend(Iobuf *dbuf, Dentry *d, u64 dblkno);
Aux*
newaux(u64 addr, u16 uid)
@@ -32,7 +33,6 @@
{
short uid;
Iobuf *dbuf;
- Dentry *d;
if(authattach(req) < 0){
return;
@@ -43,15 +43,14 @@
return;
}
- dbuf = getbufchk(Bdroot, Breadonly, Tdentry, Qproot);
+ dbuf = getmetachk(Bdroot, Breadonly, Tdentry, Qproot);
if(dbuf == nil){
respond(req, "phase error");
return;
}
- d = dbuf->d;
req->fid->aux = newaux(Bdroot, uid);
- req->fid->qid = (Qid){Qproot, d->qid.version, QTDIR};
- putbuf(dbuf);
+ req->fid->qid = (Qid){Qproot, dbuf->cur->version, QTDIR};
+ putbuf(dbuf, 0);
req->ofcall.qid = req->fid->qid;
respond(req, nil);
}
@@ -60,6 +59,7 @@
fsdestroyfid(Fid *fid)
{
Tlock *t;
+ Iobuf *dbuf;
if((fid->qid.type & QTAUTH) != 0){
authdestroy(fid);
@@ -91,6 +91,12 @@
}
qunlock(&tlock);
}
+ dbuf = getmetachk(((Aux*)fid->aux)->dblkno,
+ Bwritable, Tdentry, fid->qid.path);
+ if(dbuf != nil){
+ writeallappend(dbuf, (Dentry*)dbuf->new, ((Aux*)fid->aux)->dblkno);
+ putbuf(dbuf, 1);
+ }
freeaux(fid->aux);
}
@@ -98,7 +104,7 @@
fsmkdir(Dentry *d, Dir *dir, char *buf)
{
memset(dir, 0, sizeof(*dir));
- dir->qid = (Qid){d->qid.path, d->qid.version, (d->mode&DMDIR)? QTDIR : QTFILE};
+ dir->qid = (Qid){d->path, d->version, (d->mode&DMDIR)? QTDIR : QTFILE};
dir->mode = (d->mode & 0777) | (dir->qid.type << 24);
dir->atime = time(nil);
dir->mtime = d->mtime/Nsec; /* ns to seconds */
@@ -126,7 +132,7 @@
Dentry *d;
Iobuf *dbuf;
- dbuf = getbufchk(((Aux*)req->fid->aux)->dblkno, Breadonly,
+ dbuf = getmetachk(((Aux*)req->fid->aux)->dblkno, Breadonly,
Tdentry, req->fid->qid.path);
if(dbuf == nil){
dprint("fsstat dbuf == nil dblkno %llud qpath %llud\n",
@@ -135,12 +141,12 @@
return;
}
- d = dbuf->d;
+ d = (Dentry*)dbuf->cur;
/* nothing to do for already zero'ed out slots */
if(d->path != Qpnone)
fsmkdir(d, &req->d, nil);
- putbuf(dbuf);
+ putbuf(dbuf, 0);
respond(req, nil);
}
@@ -192,15 +198,15 @@
/* TODO cwfs/9p2.c, hjfs/fs2.c and kfs64.b do more here. Get that stuff in. */
- dbuf = getbufchk(((Aux*)req->fid->aux)->dblkno, Bwritable,
+ dbuf = getmetachk(((Aux*)req->fid->aux)->dblkno, Bwritable,
Tdentry, req->fid->qid.path);
if(dbuf == nil){
respond(req, errstring[Eperm]);
return;
}
- d = dbuf->d;
+ d = (Dentry*)dbuf->new;
if(canaccess(((Aux*)req->fid->aux)->uid, d, DMWRITE) == 0){
- putbuf(dbuf);
+ putbuf(dbuf, 0);
respond(req, errstring[Eaccess]);
return;
}
@@ -207,7 +213,7 @@
/* invalid to change the directory bit stat(5) */
if(req->d.mode != ~0 &&
(req->d.mode&DMDIR) != (d->mode&DMDIR)){
- putbuf(dbuf);
+ putbuf(dbuf, 0);
respond(req, errstring[Einval]);
return;
}
@@ -234,8 +240,8 @@
}
}
- putbuf(dbuf);
respond(req, nil);
+ putbuf(dbuf, 1);
return;
noperm:
respond(req, errstring[Eperm]);
@@ -280,7 +286,7 @@
return;
}
((Aux*)req->fid->aux)->dri++;
- }while(d->qid.path == 0);
+ }while(d->path == 0);
fsmkdir(d, &dir, nbuf);
req->ofcall.count = n = convD2M(&dir, (u8*)req->ofcall.data, req->ifcall.count);
@@ -293,8 +299,8 @@
}
readfile(((Aux*)req->fid->aux)->dblkno, req->fid->qid.path,
- req->ofcall.data, req->ifcall.count, req->ifcall.offset,
- req);
+ req->ofcall.data, req->ifcall.count,
+ req->ifcall.offset, req);
}
@@ -323,7 +329,8 @@
writefile(((Aux*)req->fid->aux)->dblkno, req->fid->qid.path,
((Aux*)req->fid->aux)->uid,
- req->ifcall.data, req->ifcall.count, req->ifcall.offset, req);
+ req->ifcall.data, req->ifcall.count,
+ req->ifcall.offset, req);
}
static void
@@ -380,22 +387,22 @@
if(chatty9p > 1)
dprint("fswalk1 .. fid->qid.path %llud aux->dblkno %llud\n",
fid->qid.path, aux->dblkno);
- dbuf = getbufchk(aux->dblkno, Breadonly, Tdentry, fid->qid.path);
+ dbuf = getmetachk(aux->dblkno, Breadonly, Tdentry, fid->qid.path);
if(dbuf == nil)
return errstring[Ephase];
- d = dbuf->d;
+ d = (Dentry*)dbuf->cur;
if(chatty9p > 1)
dprint("fswalk1 .. d->name %s d->qid.path %llud d->pdblkno %llud\n",
- d->name, d->qid.path, d->pdblkno);
- pbuf = getbufchk(d->pdblkno, Breadonly, Tdentry, d->pqpath);
+ d->name, d->path, d->pdblkno);
+ pbuf = getmetachk(d->pdblkno, Breadonly, Tdentry, d->pqpath);
if(pbuf == nil)
return errstring[Ephase];
- putbuf(dbuf);
- p = pbuf->d;
- *qid = (Qid){p->qid.path, p->qid.version, (p->mode&DMDIR) ? QTDIR : QTFILE};
+ putbuf(dbuf, 0);
+ p = (Dentry*)pbuf->cur;
+ *qid = (Qid){p->path, p->version, (p->mode&DMDIR) ? QTDIR : QTFILE};
if(aux != nil)
aux->dblkno = pbuf->blkno;
- putbuf(pbuf);
+ putbuf(pbuf, 0);
fid->qid = *qid;
return nil;
}
@@ -411,7 +418,7 @@
freesearchstate(&dbuf, &cbuf);
return errstring[Eperm];
}
- *qid = (Qid){d->qid.path, d->qid.version, (d->mode&DMDIR) ? QTDIR : QTFILE};
+ *qid = (Qid){d->path, d->version, (d->mode&DMDIR) ? QTDIR : QTFILE};
if(aux != nil)
aux->dblkno = cbuf->blkno;
freesearchstate(&dbuf, &cbuf);
@@ -435,7 +442,7 @@
}
/*
- * error(Eperm) if open permission not granted for up->user.
+ * error(Eperm) if open permission not granted for up->newr.
*/
int
permcheck(u16 fileuid, u16 filegid, u16 uid, ulong perm, int omode)
@@ -512,12 +519,12 @@
cbuf = nil;
USED(cbuf);
zblkno = 0;
- dbuf = getbufchk(aux->dblkno, Bwritable, Tdentry, fid->qid.path);
+ dbuf = getmetachk(aux->dblkno, Bwritable, Tdentry, fid->qid.path);
if(dbuf == nil){
respond(req, errstring[Ephase]);
return;
}
- dparent = dbuf->d;
+ dparent = (Dentry*)dbuf->cur;
if(canaccess(((Aux*)req->fid->aux)->uid, dparent, DMWRITE) == 0){
respond(req, errstring[Eperm]);
return;
@@ -524,7 +531,7 @@
}
if(canaccess(aux->uid, dparent, DMWRITE) == 0){
- putbuf(dbuf);
+ putbuf(dbuf, 0);
respond(req, errstring[Eaccess]);
return;
}
@@ -542,7 +549,7 @@
fid->omode = OREAD+OWRITE;
break;
default:
- putbuf(dbuf);
+ putbuf(dbuf, 0);
respond(req, errstring[Emode]);
return;
}
@@ -554,24 +561,24 @@
if(blkno == 0){
/* end reached, nothing found, create */
if(zblkno != 0){
- cbuf = getbufchk(zblkno, Bwritable, Tdentry, Qpnone);
+ cbuf = getmetachk(zblkno, Bwritable, Tdentry, Qpnone);
if(cbuf == nil){
- putbuf(dbuf);
+ putbuf(dbuf, 0);
respond(req, errstring[Ephase]);
return;
}
}else{
- cbuf = allocblock(Tdentry, fid->qid.path);
+ cbuf = allocmeta(Tdentry, fid->qid.path);
if(cbuf == nil){
- putbuf(dbuf);
+ putbuf(dbuf, 0);
respond(req, errstring[Efull]);
return;
}
}
- dchild = cbuf->d;
+ dchild = (Dentry*)cbuf->new;
dchild->size = 0;
dchild->pdblkno = dbuf->blkno;
- dchild->pqpath = dparent->qid.path;
+ dchild->pqpath = dparent->path;
dchild->mtime = nsec();
dchild->uid = dchild->muid = aux->uid;
dchild->gid = dparent->gid;
@@ -579,8 +586,8 @@
if(perm&DMDIR){
if((req->ifcall.mode & OTRUNC) || (perm & DMAPPEND) ||
(fid->omode & OWRITE)){
- putbuf(cbuf);
- putbuf(dbuf);
+ putbuf(cbuf, 1);
+ putbuf(dbuf, 0);
respond(req, errstring[Eaccess]);
return;
}
@@ -594,21 +601,21 @@
if(perm&DMEXCL)
dchild->mode |= DMEXCL;
if(canaccess(aux->uid, dchild, DMWRITE) == 0){
- putbuf(cbuf);
- putbuf(dbuf);
+ putbuf(cbuf, 0);
+ putbuf(dbuf, 0);
respond(req, errstring[Eaccess]);
return;
}
- dchild->qid.path = newqpath();
- dchild->qid.version = 0;
+ dchild->path = newqpath();
+ dchild->version = 0;
strncpy(dchild->name, req->ifcall.name, Namelen);
- fid->qid = (Qid){dchild->qid.path, 0, (perm&DMDIR) ? QTDIR : QTFILE};
+ fid->qid = (Qid){dchild->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->qpath = dchild->path;
t->dblkno = aux->dblkno;
qlock(&tlock);
if(tlocktail == nil){
@@ -624,8 +631,8 @@
aux->tlocked = 0;
req->ofcall.qid = fid->qid;
req->ofcall.iounit = Iounit;
- settag(cbuf, Tdentry, dchild->qid.path);
- putbuf(cbuf); /* save Iobuf of the content */
+ settag(cbuf, Tdentry, dchild->path);
+ putbuf(cbuf, 1); /* save Iobuf of the content */
/*
only add it to the directory dentry if we are adding a new dentry block
if we are reusing a zero'ed out slot, it already exists in the
@@ -633,24 +640,24 @@
*/
if(zblkno == 0 &&
addrelative(dparent, dbuf->blkno, reli, aux->dblkno) == 0){
- putbuf(dbuf);
+ putbuf(dbuf, 1);
respond(req, errstring[Ephase]);
return;
}
- putbuf(dbuf);
+ putbuf(dbuf, 1);
respond(req, nil);
return;
}else{
- cbuf = getbuf(blkno, Dentryunits, Breadonly, Bused);
+ cbuf = getmeta(blkno, Breadonly, Bused);
if(cbuf == nil){
- putbuf(dbuf);
+ putbuf(dbuf, 0);
respond(req, errstring[Ephase]);
return;
}
- dchild = cbuf->d;
+ dchild = (Dentry*)cbuf->cur;
/* nothing to do for already zero'ed out slots */
- if(dchild->path == Qpnone){
+ if(dchild->qpath == Qpnone){
if(zblkno == 0)
zblkno = cbuf->blkno;
goto Nextdentry;
@@ -657,8 +664,8 @@
}
if(dchild->tag != Tdentry){
- putbuf(cbuf);
- putbuf(dbuf);
+ putbuf(cbuf, 0);
+ putbuf(dbuf, 0);
respond(req, errstring[Ephase]);
return;
}
@@ -670,7 +677,7 @@
return;
}
dchild->muid = aux->uid;
- fid->qid = (Qid){dchild->qid.path, dchild->qid.version,
+ fid->qid = (Qid){dchild->qpath, dchild->version,
(req->ifcall.mode&DMDIR) ? QTDIR : QTFILE};
aux->dblkno = blkno;
aux->dri = 0;
@@ -680,22 +687,16 @@
save Iobuf of the child so truncate can open
it with a wlock(), if needed
*/
- putbuf(cbuf);
+ putbuf(cbuf, 0);
if(req->ofcall.qid.path >= Qpusers &&
req->ofcall.qid.type == QTFILE)
truncatefile(req->ofcall.qid.path, blkno, aux->uid);
- putbuf(dbuf);
- /* DBG("> mafscreate c->path %s mode 0x%ux omode0 0x%ux\n"
- " c->qid.path 0x%zux c->qid.vers %lud c->qid.type %ud 0x%ux\n"
- " c->aux 0x%p\n",
- chanpath(c), c->mode, omode, c->qid.path,
- c->qid.vers, c->qid.type, c->qid.type,
- c->aux);*/
+ putbuf(dbuf, 0);
respond(req, nil);
return;
}
Nextdentry:
- putbuf(cbuf);
+ putbuf(cbuf, 0);
}
}
}
@@ -722,12 +723,12 @@
if(readonly && (mode & (ORCLOSE | OTRUNC | OWRITE | ORDWR)) != 0)
goto inval;
- dbuf = getbufchk(aux->dblkno, Breadonly, Tdentry, fid->qid.path);
+ dbuf = getmetachk(aux->dblkno, Breadonly, Tdentry, fid->qid.path);
if(dbuf == nil){
respond(req, errstring[Ephase]);
return;
}
- d = dbuf->d;
+ d = (Dentry*)dbuf->cur;
if((mode & OTRUNC) != 0 &&
canaccess(aux->uid, d, DMWRITE) == 0)
@@ -784,12 +785,12 @@
if((mode & ORCLOSE) != 0)
omode |= ORCLOSE;
- fid->qid = (Qid){d->qid.path, d->qid.version, (d->mode&DMDIR) ? QTDIR : QTFILE};
+ fid->qid = (Qid){d->path, d->version, (d->mode&DMDIR) ? QTDIR : QTFILE};
fid->omode = omode;
req->ofcall.iounit = Iounit;
req->ofcall.qid = fid->qid;
- putbuf(dbuf);
+ putbuf(dbuf, 0);
if((mode & OTRUNC) == 0){
respond(req, nil);
return;
@@ -800,12 +801,12 @@
return;
inval:
if(dbuf != nil)
- putbuf(dbuf);
+ putbuf(dbuf, 0);
respond(req, errstring[Einval]);
return;
perm:
if(dbuf != nil)
- putbuf(dbuf);
+ putbuf(dbuf, 0);
respond(req, errstring[Eaccess]);
return;
}
@@ -961,10 +962,11 @@
all the clients that mounted it. Just shutdown and let the respective clients
deal with their mess.
*/
+/* TODO need to track open fids and close them */
void
shutdown(void)
{
- u64 n;
+// u64 n;
/* User *u, *v; */
if(chatty9p > 1)
@@ -978,7 +980,7 @@
rwakeupall(&buf.isempty);
qunlock(&buf.lck);
}
- if(synchronouswrites == 0){
+/* if(synchronouswrites == 0){
while((n=pendingwrites())>0){
if(chatty9p > 1)
dprint("shutdown: pendingwrites %llud of write queue\n", n);
@@ -985,8 +987,9 @@
sleep(1000);
}
}
+*/
savefrees(Bdfrees);
- if(synchronouswrites == 0){
+/* if(synchronouswrites == 0){
while((n=pendingwrites())>0){
if(chatty9p > 1)
dprint("shutdown: pendingwrites %llud of frees\n", n);
@@ -994,15 +997,15 @@
}
stopwriter();
}
-
+*/
/* free users, why bother? leave it alone */
-/* u = t->users;
+/* u = t->newrs;
while(u != nil){
v = u->next;
free(u);
u = v;
}
- t->users = nil;*/
+ t->newrs = nil;*/
if(chatty9p > 1)
dprint("shutdown: exiting\n");
@@ -1230,11 +1233,11 @@
u64 filesize;
Iobuf *dbuf;
- dbuf = getbufchk(dblkno, Breadonly, Tdentry, qpath);
+ dbuf = getmetachk(dblkno, Breadonly, Tdentry, qpath);
if(dbuf == nil)
return 0;
- filesize = dbuf->d->size;
- putbuf(dbuf);
+ filesize = dbuf->cur->size;
+ putbuf(dbuf, 0);
return filesize;
}
s32
@@ -1244,21 +1247,22 @@
s64 tosend, sent, filesize;
s32 n;
Iobuf *dbuf, *buf;
+ u64 datablocksize;
- dbuf = getbufchk(dblkno, Breadonly, Tdentry, qpath);
+ dbuf = getmetachk(dblkno, Breadonly, Tdentry, qpath);
if(dbuf == nil)
return 0;
- d = dbuf->d;
- filesize = d->size;
+ d = (Dentry*)dbuf->cur;
+ filesize = d->size+dbuf->appendsize;
if(offset >= filesize){
- putbuf(dbuf);
+ putbuf(dbuf, 0);
return 0;
}
if(filesize < Ddatasize){
n = min(filesize-offset, rbufsize);
memcpy(rbuf, d->buf+offset, n);
- putbuf(dbuf);
+ putbuf(dbuf, 0);
return n;
}
if(filesize - offset > rbufsize)
@@ -1267,32 +1271,43 @@
tosend = filesize - offset;
for(sent = 0; sent < tosend && offset+sent < d->size; ){
- buf = getdatablkat(d, (offset+sent)/Datablocksize, Breadonly);
+ buf = getdatablkat(d, (offset+sent)/Maxdatablocksize);
if(buf == nil){
- putbuf(dbuf);
+ putbuf(dbuf, 0);
return -1;
}
- n = min(Datablocksize-((offset+sent)%Datablocksize), tosend-sent);
- memcpy(rbuf+sent, buf->io->buf+((offset+sent)%Datablocksize), n);
+ if(buf->len == Maxdatablockunits)
+ datablocksize = Maxdatablocksize;
+ else
+ datablocksize = buf->len*Blocksize -sizeof(Datahdr) -sizeof(u64 /* trailing path */);
+ n = min(datablocksize-((offset+sent)%Maxdatablocksize), tosend-sent);
+ memcpy(rbuf+sent, buf->io->buf+((offset+sent)%Maxdatablocksize), n);
sent += n;
- putbuf(buf);
+ putbuf(buf, 0);
}
+ if(dbuf->append && sent < tosend && offset+sent < d->size+dbuf->appendsize){
+ /* assuming that rbufsize < Maxdatablocksize */
+ n = min(d->size+dbuf->appendsize-(offset+sent), tosend-sent);
+ memcpy(rbuf+sent, dbuf->append+(offset+sent-d->size), n);
+ sent += n;
+ }
if(req != nil){
req->ofcall.count = sent;
req->ofcall.offset = req->ifcall.offset+sent;
respond(req, nil);
}
- putbuf(dbuf);
+ putbuf(dbuf, 0);
return sent;
}
/* only for updating existing data */
+/* TODO copy on write */
s32
update(Dentry *d, u64 /* dblkno */, char *wbuf, s32 wbufsize, u64 offset)
{
Iobuf *buf;
s32 howmuch;
- u64 blkno, to;
+ u64 blkno, to, nblocks;
if(d == nil || wbuf == nil || wbufsize == 0)
return 0;
@@ -1304,19 +1319,22 @@
/* get the extent
overlay data
*/
-
- blkno = rel2abs(d, offset/Datablocksize);
+ blkno = rel2abs(d, offset/Maxdatablocksize);
+ if(offset/Maxdatablocksize < d->size/Maxdatablocksize)
+ nblocks = Maxdatablockunits;
+ else
+ nblocks = nlastdatablocks(d->size);
if(chatty9p > 1)
dprint("update d->name %s d->size %llud offset %llud"
" rel2abs(offset/Datablocksize %llud) = blkno %llud\n",
- d->name, d->size, offset, offset/Datablocksize, blkno);
- buf = getbufchk(blkno, Bwritable, Tdata, d->qid.path);
+ d->name, d->size, offset, offset/Maxdatablocksize, blkno);
+ buf = getbufchk(blkno, nblocks, Bwritable, Tdata, d->path);
if(buf == nil)
return -1;
/* overlay the new contents */
- to = offset%Datablocksize;
- howmuch = min(Datablocksize-to, wbufsize);
+ to = offset%Maxdatablocksize;
+ howmuch = min((nblocks*Blocksize)-to, wbufsize);
if(chatty9p > 1){
dprint("updating buf->blkno %llud offset %llud size %llud\n",
buf->blkno, to, howmuch);
@@ -1327,87 +1345,212 @@
dprint("update after\n");
showbuf(buf);
}
- putbuf(buf);
+ putbuf(buf, 1);
return howmuch;
}
+/*
+ Scenarios:
+ 1. last block is full or no last block
+ 2. last block is partially full
+ */
s32
-append(Dentry *d, u64 dblkno, char *wbuf, s32 wbufsize)
+writefullappend(Iobuf *dbuf, Dentry *d, u64 dblkno)
{
- Iobuf *buf;
+ Iobuf *oldbuf, *newbuf;
s32 howmuch;
- u64 blkno, lastblksize;
+ u64 newblkno, newbufsize, lastdatablksize, oldblkno;
- if(d == nil || wbuf == nil || wbufsize == 0)
- return 0;
- if(chatty9p > 1)
- dprint("append wbufsize %d\n", wbufsize);
+ /* last data block is full or there is no last block.
+ write out the append
+ */
+ if(d->size%Maxdatablocksize == 0 &&
+ dbuf->appendsize == Maxdatablocksize){
- if((lastblksize=d->size%Datablocksize) == 0){
- /* last block is full, use a new block */
- if(chatty9p > 1)
- dprint("append new data block rel2abs d->name %s reli d->size %llud"
- " d->size/Datablocksize %llud\n",
- d->name, d->size, d->size/Datablocksize);
-
- /* write single block */
- howmuch = min(Datablocksize, wbufsize);
- buf = allocblock(Tdata, d->qid.path);
- if(buf == nil)
+ /* allocate new blocks */
+ newbuf = allocblocks(Maxdatablockunits,Tdata, d->path);
+ if(newbuf == nil)
return -1;
- blkno = buf->blkno;
- memcpy(buf->io->buf, wbuf, howmuch);
- putbuf(buf);
+ newblkno = newbuf->blkno;
- if(addrelative(d, dblkno, d->size/Datablocksize, blkno) == 0){
+ /* add the contents of append to those new blocks */
+ memcpy(newbuf->io->buf, dbuf->append, dbuf->appendsize);
+
+ /* add this newly allocated blocks to the Dentry */
+ if(addrelative(d, dblkno, d->size/Maxdatablocksize, newblkno) == 0){
panic("could not write Tdata block\n");
- freeblock(blkno, Tdata, d->qid.path);
- return -2;
+ freeblocks(newblkno, Maxdatablockunits, Tdata, d->path);
+ return -1;
}
- return howmuch;
- }else{
- /* last block is partially full, fill it up */
+ d->size += dbuf->appendsize;
+ dbuf->appendsize = 0;
+ putbuf(newbuf, 1);
+ return 1;
- blkno = rel2abs(d, d->size/Datablocksize);
- if(blkno == 0)
- panic("append update rel2abs blkno == 0"
- " d->name %s reli d->size %llud"
- " d->size/Datablocksize %llud s.blkno %llud\n",
- d->name, d->size, d->size/Datablocksize, blkno);
- if(chatty9p > 1)
- dprint("append update rel2abs d->name %s reli d->size %llud"
- " d->size/Datablocksize %llud blkno %llud\n",
- d->name, d->size, d->size/Datablocksize, blkno);
- buf = getbufchk(blkno, Bwritable, Tdata, d->qid.path);
- if(buf == nil)
+ }else if(d->size%Maxdatablocksize > 0 &&
+ (d->size%Maxdatablocksize)+dbuf->appendsize >= Maxdatablocksize){
+
+ /* last data block is not full.
+ write a full last data block and leave the rest in append
+ */
+
+ /* allocate new blocks */
+ newbuf = allocblocks(Maxdatablockunits, Tdata, d->path);
+ if(newbuf == nil)
return -1;
+ newblkno = newbuf->blkno;
+ newbufsize = 0;
- howmuch = min(Datablocksize-lastblksize, wbufsize);
- if(chatty9p > 1)
- dprint("fill lastblksize %llud howmuch %llud\n",
- lastblksize, howmuch);
- memcpy(buf->io->buf+lastblksize, wbuf, howmuch);
- putbuf(buf);
- return howmuch;
+ /* read from the last block */
+ /* copy that to the new allocated blocks */
+ oldbuf = nil;
+ if(lastdatablksize=d->size%Maxdatablocksize){
+ /* partial block, above is = not == */
+ oldblkno = rel2abs(d, d->size/Maxdatablocksize);
+ oldbuf = getbufchk(oldblkno, nlastdatablocks(lastdatablksize),
+ Bwritable, Tdata, d->path);
+ if(oldbuf == nil){
+ freeblocks(newblkno, Maxdatablockunits, Tdata, d->path);
+ return -1;
+ }
+ memcpy(newbuf->io->buf, oldbuf->io->buf, lastdatablksize);
+ newbufsize = lastdatablksize;
+ }
+
+ /* add the contents of append to those new blocks */
+ howmuch = Maxdatablocksize-newbufsize;
+ memcpy(newbuf->io->buf+newbufsize, dbuf->append, howmuch);
+
+ /* move the left over append stuff to the front */
+ memmove(dbuf->append, dbuf->append+howmuch, dbuf->appendsize-howmuch);
+
+ /* add this newly allocated blocks to the Dentry */
+ if(addrelative(d, dblkno, d->size/Maxdatablocksize, newblkno) == 0){
+ panic("could not write Tdata block\n");
+ freeblocks(newblkno, Maxdatablockunits, Tdata, d->path);
+ return -2;
+ }
+ d->size += howmuch;
+ dbuf->appendsize -= howmuch;
+ putbuf(newbuf, 1);
+
+ /* free the old last blocks */
+ if(oldbuf)
+ putbuffree(oldbuf);
+ return 1;
}
+ return 0;
}
-/* pad blanks one span at a time */
-static s32
-padblanks(Dentry *d, u64 dblkno, s32 size)
+/*
+ Scenarios:
+ 1. last block is full or no last block
+ 2. last block is partially full
+ */
+s32
+writeallappend(Iobuf *dbuf, Dentry *d, u64 dblkno)
{
- s8 *buf;
- int n;
+ Iobuf *oldbuf, *newbuf;
+ u64 newblkno, newbufsize, lastdatablksize, oldblkno, newblocks;
+ s32 rv;
- if(d == nil || size <= 0)
- return 0;
- n = min(size, Datablocksize - d->size%Datablocksize);
- buf = emalloc9p(n);
- n = append(d, dblkno, buf, n);
- free(buf);
- return n;
+ if(dbuf->appendsize == 0)
+ return 1;
+
+ rv = 0;
+ if((d->size%Maxdatablocksize)+dbuf->appendsize >= Maxdatablocksize)
+ rv = writefullappend(dbuf, d, dblkno);
+
+ if(rv < 0)
+ return rv;
+ if(dbuf->appendsize == 0)
+ return 1;
+
+ /* last data block is full or there is no last block. */
+ if(d->size%Maxdatablocksize == 0){
+
+ /* allocate new blocks */
+ newbuf = allocblocks(nlastdatablocks(dbuf->appendsize),Tdata, d->path);
+ if(newbuf == nil)
+ return -1;
+ newblkno = newbuf->blkno;
+
+ /* add the contents of append to those new blocks */
+ memcpy(newbuf->io->buf, dbuf->append, dbuf->appendsize);
+ newbuf->io->len = nlastdatablocks(dbuf->appendsize);
+
+ /* add this newly allocated blocks to the Dentry */
+ if(addrelative(d, dblkno, d->size/Maxdatablocksize, newblkno) == 0){
+ panic("could not write Tdata block\n");
+ freeblocks(newblkno, nlastdatablocks(dbuf->appendsize), Tdata, d->path);
+ return -1;
+ }
+ d->size += dbuf->appendsize;
+ dbuf->appendsize = 0;
+ putbuf(newbuf, 1);
+ return 1;
+ }
+
+ /* allocate new blocks */
+ newblocks = nlastdatablocks((d->size%Maxdatablocksize) +dbuf->appendsize);
+ newbuf = allocblocks(newblocks, Tdata, d->path);
+ if(newbuf == nil)
+ return -1;
+ newblkno = newbuf->blkno;
+ newbufsize = 0;
+
+ /* read from the last block */
+ /* copy that to the new allocated blocks */
+ oldbuf = nil;
+ if(lastdatablksize=d->size%Maxdatablocksize){
+ /* partial block, above is = not == */
+ oldblkno = rel2abs(d, d->size/Maxdatablocksize);
+ oldbuf = getbufchk(oldblkno, nlastdatablocks(lastdatablksize),
+ Bwritable, Tdata, d->path);
+ if(oldbuf == nil){
+ freeblocks(newblkno, newblocks, Tdata, d->path);
+ return -1;
+ }
+ memcpy(newbuf->io->buf, oldbuf->io->buf, lastdatablksize);
+ newbufsize = lastdatablksize;
+ }
+
+ /* add the contents of append to those new blocks */
+ /* writefullappend() takes care of bigger sizes */
+ memcpy(newbuf->io->buf+newbufsize, dbuf->append, dbuf->appendsize);
+ newbuf->io->len = newblocks;
+
+ /* nothing left in append to move to the front */
+
+ /* add this newly allocated blocks to the Dentry */
+ if(addrelative(d, dblkno, d->size/Maxdatablocksize, newblkno) == 0){
+ panic("could not write Tdata block\n");
+ freeblocks(newblkno, newblocks, Tdata, d->path);
+ return -2;
+ }
+
+ /* free the old last blocks */
+ if(oldbuf)
+ putbuffree(oldbuf);
+ d->size += dbuf->appendsize;
+ dbuf->appendsize = 0;
+ putbuf(newbuf, 1);
+ return 1;
}
+s32
+newappend(Iobuf *dbuf, u64 dblkno, u64 path)
+{
+ dbuf->append = (Data*)allocmemunits(Maxdatablockunits);
+ if(dbuf->append == nil)
+ return -1;
+ dbuf->appendsize = 0;
+ dbuf->append->tag = Tdata;
+ dbuf->append->len = Maxdatablockunits;
+ dbuf->append->dblkno = dblkno;
+ dbuf->append->path = path;
+ return 1;
+}
/*
3 scenarios
offset < filesize && offset+wbufsize <= filesize
@@ -1424,15 +1567,16 @@
{
Dentry *d;
s64 written;
- s32 n;
- Iobuf *dbuf, *buf;
- u64 blkno;
+ s32 n, rv;
+ Iobuf *dbuf;
+ u8 dowrite;
- dbuf = getbufchk(dblkno, Bwritable, Tdentry, qpath);
+ dbuf = getmetachk(dblkno, Bwritable, Tdentry, qpath);
if(dbuf == nil)
return 0;
- d = dbuf->d;
+ d = dbuf->new;
d->muid = uid;
+ rv = dowrite = 0;
// odentry(d);
// little data, stuff it in the Dentry
@@ -1441,20 +1585,16 @@
if(offset+wbufsize > d->size)
d->size = offset+wbufsize;
written = wbufsize;
+ dowrite = 1;
goto writeend;
}
// more data, relocate it to a proper data block
if(d->size > 0 && d->size <= Ddatasize && offset+wbufsize > Ddatasize){
- buf = allocblock(Tdata, d->qid.path);
- if(buf == nil){
- written = 0;
- goto writeend;
- }
- blkno = buf->blkno;
- memcpy(buf->io->buf, d->buf, d->size);
- putbuf(buf);
- memset(d->buf, 0, d->size);
- d->dblocks[0] = blkno;
+ newappend(dbuf, dblkno, d->path);
+ memcpy(dbuf->append, d->buf, d->size);
+ dbuf->appendsize = d->size;
+ d->size = 0;
+ dowrite = 1;
}
for(written = 0; written < wbufsize; ){
@@ -1466,7 +1606,7 @@
/* all the below functions only write upto the end of an extent.
Hence, the need for a loop to keep repeating.
*/
- if(offset > d->size){
+ if(offset > d->size+dbuf->appendsize){
/* new blank blocks until offset
fill blank data upto offset */
@@ -1473,14 +1613,11 @@
if(chatty9p > 1)
dprint("writefile(): blank blocks until offset\n");
- n = padblanks(d, dblkno, offset+wbufsize-d->size);
- if(chatty9p > 1)
- dprint("writefile(): padblanks returned %d\n", n);
- if(n<0){
- dprint("padblanks has an issue %d\n", n);
- goto writeend;
- }else
- d->size += n;
+ if(dbuf->append == nil)
+ if((rv = newappend(dbuf, dblkno, d->path)) < 0)
+ goto writeend;
+ n = min(Maxdatablocksize, offset-d->size);
+ dbuf->appendsize = n;
}else if(offset+written < d->size){
/* replacing existing data
@@ -1489,7 +1626,7 @@
if(chatty9p > 1)
dprint("writefile(): replace existing data\n");
- n = update(d, dblkno,
+ rv = n = update(d, dblkno,
wbuf+written, /* from where */
/* how much */
min(wbufsize-written, d->size-(offset+written)),
@@ -1502,32 +1639,41 @@
}else
written += n;
- }else if(offset+written >= d->size){
+ }else if(offset+written >= d->size &&
+ offset+written < d->size+dbuf->appendsize){
+ /* changing append contents */
+ n = min(dbuf->appendsize-(offset+written),wbufsize-written);
+ memcpy(dbuf->append+dbuf->appendsize, wbuf+written, n);
+ dbuf->appendsize += n;
+ written += n;
+
+ }else if(offset+written >= d->size+dbuf->appendsize){
+ /* assuming that wbufsize <= append */
/* append data, changes file size
data blocks from offset until offset+wbufsize */
- if(chatty9p > 1)
- dprint("writefile(): append\n");
- n = append(d, dblkno, wbuf+written, /* from where */
- wbufsize-written /* how much */);
- if(chatty9p > 1)
- dprint("writefile(): append returned %d\n", n);
- if(n<0){
- dprint("append has an issue %d\n", n);
- goto writeend;
- }
+ if(dbuf->append == nil)
+ if((rv = newappend(dbuf, dblkno, d->path)) < 0)
+ goto writeend;
+ n = min(Maxdatablocksize-dbuf->appendsize, wbufsize-written);
+ memcpy(dbuf->append+dbuf->appendsize, wbuf+written, n);
+ dbuf->appendsize += n;
written += n;
- d->size += n;
}
else
panic("writefile: should not be here");
+
+ if(dbuf->appendsize == Maxdatablocksize)
+ dowrite = 1;
+ if((rv=writefullappend(dbuf, d, dblkno)) < 0)
+ goto writeend;
}
writeend:
d->mtime = nsec();
if(req != nil){
- if(written == -3)
+ if(rv == -3)
respond(req, errstring[Efull]);
- else if(written == -1 || written == -2)
+ else if(rv == -1 || rv == -2)
respond(req, errstring[Ephase]);
else{
req->ofcall.count = written;
@@ -1535,6 +1681,6 @@
respond(req, nil);
}
}
- putbuf(dbuf);
+ putbuf(dbuf, dowrite);
return written;
}
--- a/all.h
+++ b/all.h
@@ -82,31 +82,11 @@
Data *io;
Metadata *m;
};
- Metadata *use; /* use this unit for changes */
+ Metadataunit *cur; /* this has the current Indirect or Dentry values */
+ Metadataunit *new; /* use this unit for Indirect or Dentry changes */
- /* head of a linked list of children with changes yet to be written */
- Iobuf *changes;
-
- /* linked list of sibling changes not yet written */
- u8 change; /* Add or Remove. Am I being added or removed? */
- Iobuf *prev, *next;
-
- u8 *append; /* appended data added not yet written to disk */
-
- /* obsolete
- This field is used by mafs to ensure that Iobufs are not reused
- while there are pending writes.
-
- dowrite() uses a Ref instead of a wlock() to mark Iobuf's
- with pending writes.
- Using a wlock() in dowrite() causes a deadlock with putwrite()
- especially when the writer queue is full.
- getbuf() guarantees that even a free'ed block cannot be
- stolen until the dirties == 0. This avoids dirty blocks
- being stolen for other block numbers.
- incref(dirties) only happens while holding a wlock() in putwrite().
- */
- Ref dirties; /* number of versions of this block yet to be written by the writer */
+ Data *append; /* appended data added not yet written to disk */
+ u64 appendsize;
};
extern u64 nbuckets; /* n hash buckets for i/o */
@@ -118,11 +98,13 @@
void initmemunitpool(u64 nunits);
u8 *allocmemunits(u16 len);
void freememunits(u8 *m, u16 len);
-int checktag(Iobuf *p, u8 tag, u64 qpath);
-Iobuf* getbuf(u64 blkno, u64 len, u8 readonly, u8 freshalloc);
-Iobuf* getbufchk(u64 blkno, u64 len, u8 readonly, int tag, u64 qpath);
+int checktag(Iobuf *p, u16 len, u8 tag, u64 qpath);
+Iobuf* getbuf(u64 blkno, u16 len, u8 readonly, u8 freshalloc);
+Iobuf* getbufchk(u64 blkno, u16 len, u8 readonly, int tag, u64 qpath);
+Iobuf* getmeta(u64 blkno, u8 readonly, u8 freshalloc);
+Iobuf* getmetachk(u64 blkno, u8 readonly, int tag, u64 qpath);
void iobufinit(void);
-void putbuf(Iobuf *p);
+void putbuf(Iobuf *p, u8 dowrite);
void putbuffree(Iobuf *p);
void settag(Iobuf *p, u8 tag, u64 qpath);
void showbuf(Iobuf *p);
@@ -135,12 +117,15 @@
/* routines to manipulate the contents */
Iobuf* allocblocks(u64 len, int tag, u64 qpath);
+Iobuf* allocmeta(int tag, u64 qpath);
void freeblockbuf(Iobuf *buf);
void freeblocks(u64 blkno, u64 len, u16 tag, u64 qpath);
void fsok(int ok);
void init(int doream, u64 size);
-u64 newqpath();
+u64 newqpath(void);
u64 nperiblock(u16 tag);
+u64 nperindunit(u16 tag);
+u64 power( u64 base, int n);
void ream(u64 size);
u64 rel2abs(Dentry *d, u64 reli);
void rmfile(u64 qpath, u64 dblkno);
@@ -154,12 +139,15 @@
/* dentry routines */
u64 addrelative(Dentry *d, u64 dblkno, u64 reli, u64 blkno);
-Iobuf* getdatablkat(Dentry *d, u64 reli, int flags);
+void freeaux(Aux *a);
+Iobuf* getdatablkat(Dentry *d, u64 reli);
void loadfrees(u64 dblkno);
+Aux* newaux(u64 addr, u16 uid);
s32 readfile(u64 dblkno, u64 qpath, char *rbuf, s32 rbufsize, u64 offset, Req *req);
s32 readfilesize(u64 dblkno, u64 qpath);
void savefrees(u64 dblkno);
void truncatefile(u64 qpath, u64 dblkno, s16 uid);
+s32 writeallappend(Iobuf *dbuf, Dentry *d, u64 dblkno);
s32 writefile(u64 dblkno, u64 qpath, s16 uid, char *wbuf, s32 wbufsize, u64 offset, Req *req);
/* user access routines */
@@ -173,13 +161,9 @@
u8 chkwunlock(RWLock *q);
void cmd_user(void);
char* cname(char*);
-void ctlread(Req *req);
-void ctlwrite(Req *req);
-int dprint(char *fmt, ...);
void sublockinit(void);
int fname(char*);
void formatinit(void);
-void freeaux(Aux *a);
void freesearchstate(Iobuf **dbuf, Iobuf **buf);
int iaccess(short uid, Dentry *d, int m);
int ingroup(s16 uid, s16 gid, int locked);
@@ -186,23 +170,23 @@
void initconfig(u64 bno);
int leadgroup(s16 uid, s16 gid);
s16 lookupid(char *name);
-u64 min(u64 a, u64 b);
-Aux *newaux(u64 addr, u16 uid);
-u64 newqpath(void);
void newstart(void);
-u64 nperindunit(u16 tag);
int oconvD2M(Dentry*, void*);
int oconvM2D(void*, Dentry*);
int ofcallfmt(Fmt*);
-u64 power( u64 base, int n);
-int prime(long);
-void putsuper(int locked);
int strtouid(char*);
int strtouid1(char*);
-void sync(void);
void syncusers(void);
char *username(s16 uid, char *username);
void usersinit(void);
void writeconfig(u64 bno);
+
+void ctlread(Req *req);
+void ctlwrite(Req *req);
+
+int dprint(char *fmt, ...);
+int prime(long);
+u64 min(u64 a, u64 b);
+void sync(void);
#pragma varargck argpos panic 1
--- a/blk.c
+++ b/blk.c
@@ -88,20 +88,20 @@
void
showblock(int fd, u8 *buf)
{
+ u8 tag;
Data *t;
Dentry *d;
- u8 tag;
Indirect *r;
tag = buf[0];
- d = (Dentry*)buf;
t = (Data*)buf;
r = (Indirect*)buf;
+ d = (Dentry*)buf;
if(tag == Tblank){
fprint(fd, "%s\n", tagnames[tag]);
return;
}else if(tag == Tdentry){
- fprint(fd, "%s %llud %d\n", tagnames[tag], d->path, d->ver);
+ fprint(fd, "%s %llud %d\n", tagnames[tag], d->path, d->verd);
showdentry(fd, buf);
return;
}else if(tag == Tdata){
@@ -109,10 +109,35 @@
showdata(fd, buf);
return;
}else if(tag < Maxtind)
- fprint(fd, "%s %d %llud %llud\n", tagnames[tag], r->ver, r->dblkno, r->path);
+ fprint(fd, "%s %d %llud %llud\n", tagnames[tag], r->veri, r->dblkno, r->path);
- if(t->tag >= Tind0 && t->tag < Maxtind)
+ if(tag >= Tind0 && tag < Maxtind)
showind(fd, buf);
- else if(t->tag != 0 || t->path != 0)
- fprint(fd, "unknown tag type %d path %llud\n", t->tag, t->path);
+ else
+ fprint(fd, "unknown tag type %d\n", tag);
}
+
+u8
+recentmetadata(void *buf, void **cur, void **new)
+{
+ Metadataunit *ms;
+
+ if(buf == nil)
+ panic("recentmetadata buf == nil\n");
+
+ ms = buf;
+ if((ms[0].verd == 0 && ms[1].verd == 255) ||
+ (ms[0].verd >= ms[1].verd)){
+ if(new != nil)
+ *new = ms+1;
+ if(cur != nil)
+ *cur = ms;
+ return 0;
+ }
+
+ if(new != nil)
+ *new = ms;
+ if(cur != nil)
+ *cur = ms+1;
+ return 1;
+}
\ No newline at end of file
--- a/block.c
+++ b/block.c
@@ -19,7 +19,7 @@
main(int argc, char *argv[])
{
u64 size, blkno, nunits;
- u8 buf[Rawblocksize];
+ u8 buf[Blocksize];
ARGBEGIN{
default: usage();
@@ -47,11 +47,8 @@
sizeof(Dentryhdr), Ddatasize, Namelen);
}
- nunits = size/Unit;
- if(blkno+Rawblockunits > nunits)
- devread(blkno, buf, Dentryunits);
- else
- devread(blkno, buf, Rawblockunits);
+ // nunits = size/Blocksize;
+ devread(blkno, buf, 1);
showblock(1, buf);
close(devfd);
exits(0);
--- a/config.c
+++ b/config.c
@@ -5,14 +5,14 @@
initconfig(u64 dblkno)
{
Iobuf *buf;
- char *tokens[128], cfg[Datablocksize], *nl;
+ char *tokens[128], cfg[Ddatasize], *nl;
s32 n, i;
- buf = getbufchk(dblkno, Breadonly, Tdentry, Qpconfig);
+ buf = getmetachk(dblkno, Breadonly, Tdentry, Qpconfig);
if(buf == nil)
panic("cannot find config file in %llud block\n", dblkno);
- memcpy(cfg, buf->d->buf, buf->d->size);
- putbuf(buf);
+ memcpy(cfg, buf->cur->buf, buf->cur->size);
+ putbuf(buf, 0);
n = tokenize(cfg, tokens, 128);
if(n > 128)
@@ -67,21 +67,18 @@
dprint("config:\n"
"size %llud\n"
"nblocks %llud\n"
- "backup config %llud to %llud %llud\n"
- "backup super %llud to %llud %llud\n"
- "backup root %llud to %llud %llud\n",
+ "backup config %llud to %llud\n"
+ "backup super %llud to %llud\n"
+ "backup root %llud to %llud\n",
"service %s\n",
config.size,
config.nblocks,
config.config.srcbno,
config.config.dest[0],
- config.config.dest[1],
config.super.srcbno,
config.super.dest[0],
- config.super.dest[1],
config.root.srcbno,
config.root.dest[0],
- config.root.dest[1],
config.service);
}
@@ -91,32 +88,29 @@
Iobuf *buf;
s32 n;
- buf = getbufchk(bno, Bwritable, Tdentry, Qpconfig);
+ buf = getmetachk(bno, Bwritable, Tdentry, Qpconfig);
if(buf == nil)
panic("cannot write config");
- n = snprint((s8*)buf->d->buf, Ddatasize,
+ n = snprint((s8*)buf->new->buf, Ddatasize,
"size %llud\n"
"nblocks %llud\n"
- "backup config %llud to %llud %llud\n"
- "backup super %llud to %llud %llud\n"
- "backup root %llud to %llud %llud\n"
+ "backup config %llud to %llud\n"
+ "backup super %llud to %llud\n"
+ "backup root %llud to %llud\n"
"service %s\n",
config.size,
config.nblocks,
config.config.srcbno,
config.config.dest[0],
- config.config.dest[1],
config.super.srcbno,
config.super.dest[0],
- config.super.dest[1],
config.root.srcbno,
config.root.dest[0],
- config.root.dest[1],
config.service);
if(n == Ddatasize)
panic("config needs more blocks");
- buf->d->size = n;
+ buf->new->size = n;
if(chatty9p > 1)
- dprint("config:\n%s", buf->d->buf);
- putbuf(buf);
+ dprint("config:\n%s", buf->cur->buf);
+ putbuf(buf, 1);
}
--- a/ctl.c
+++ b/ctl.c
@@ -18,8 +18,8 @@
int
cmdsync(Cmdbuf *)
{
- sync();
- dprint("sync\n");
+// sync();
+ dprint("sync TODO\n");
return 0;
}
@@ -93,7 +93,8 @@
free = nfrees(&frees);
used = config.nblocks - free;
- n = snprint(buf, 1024, "pending writes %llud blocks\n", pendingwrites());
+/* n = snprint(buf, 1024, "pending writes %llud blocks\n", pendingwrites());*/
+ n = 0;
if(config.size > TiB)
n += snprint(buf+n, 1024-n, "(blocks) free %ulld, used %ulld, total %ulld\n"
"(MiB) free %ulld, used %ulld, total %ulld\n"
@@ -153,8 +154,8 @@
{
Cmdbuf *cb;
Cmdtab *ct;
- int n;
char srvfilename[Namelen];
+ int n;
if(chatty9p)
dprint("consproc: >%s\n", req->ifcall.data);
@@ -173,7 +174,7 @@
this stuff is only needed when the worker is doing
the shutdown()
*/
- n = remove(srvfilename);
+ remove(srvfilename);
close(req->srv->infd);
close(req->srv->outfd);
if(mpsrvpid > 0){
--- a/dat.h
+++ b/dat.h
@@ -11,6 +11,7 @@
typedef struct Config Config;
typedef struct Data Data;
typedef struct Metadata Metadata;
+typedef struct Metadataunit Metadataunit;
typedef struct Dentryhdr Dentryhdr;
typedef struct Dentry Dentry;
typedef struct Datahdr Datahdr;
@@ -78,9 +79,12 @@
Bdctl = 16, /* block number of /adm/ctl dentry, empty contents, virtual file */
Bdusersstaging = 18,/* block number of /adm/users/staging dentry */
Bdroot = 20, /* block number of root directory */
- Nbused, /* blocks used up by default */
- Nminblocks = Nbused+(Nbkp*3), /* number of blocks used by the above and the backup blocks */
+ Nbused = Bdroot+2, /* blocks used up by default */
+
+ /* number of blocks used by the above and the backup blocks */
+ Nminblocks = Nbused+(Metadataunits*Nbkp*3),
+
/* Qpnone is the Tag.path of free blocks/extents(Tfree),
and zero'ed out dentry blocks */
Qpnone = 0,
@@ -117,7 +121,7 @@
struct Dentryhdr
{
u8 tag;
- u8 ver; /* a counter to do copy on write */
+ u8 verd;
s16 uid;
s16 gid;
s16 muid; /* 8 */
@@ -125,7 +129,7 @@
u64 pdblkno; /* block number of the parent directory entry. Will be 0 for root. - 24 */
u64 pqpath; /* parent qid.path - 32 */
u64 mtime; /* modified time in nano seconds from epoch - 40 */
- u64 path; /* unique identifier Qid.path 48 */
+ u64 qpath; /* unique identifier Qid.path 48 */
u32 version; /* Qid.version 52 */
u32 mode; /* same bits as defined in /sys/include/libc.h:/Dir\.mode/ - 56 */
u8 namelen; /* store name as a counted string 57 */
@@ -173,12 +177,12 @@
/* when size <= Dentrysize-184-sizeof(Tag), store the data here itself */
s8 buf[Ddatasize];
};
- u64 path;
+ u64 path; /* same as qid.path */
};
struct Indirect
{
u8 tag;
- u8 ver;
+ u8 veri;
u8 pad[6]; /* unused, to align to a multiple of 8 */
u64 dblkno; /* block number of the directory entry */
u64 bufa[Nindperblock];
@@ -194,7 +198,11 @@
};
struct Metadata
{
- struct Metadataunit m[2];
+ union
+ {
+ Indirect i[2];
+ Dentry d[2];
+ };
};
struct Data /* used to unmarshall the disk contents */
{
--- a/dentry.c
+++ b/dentry.c
@@ -17,18 +17,18 @@
if(blkno == 0){
return 0;
}
- if((buf = getbufchk(blkno, Breadonly, tag, path)) == nil){
+ if((buf = getmetachk(blkno, Breadonly, tag, path)) == nil){
dprint("%s",errstring[Ephase]);
return 0;
}
if(tag > Tind0){
n = nperindunit(tag);
- b = getindblk(buf->io->bufa[reli/n],
+ b = getindblk(buf->cur->bufa[reli/n],
reli%n, tag-1, path);
}else{
- b = buf->io->bufa[reli];
+ b = buf->cur->bufa[reli];
}
- putbuf(buf);
+ putbuf(buf, 0);
return b;
}
@@ -55,7 +55,7 @@
return d->dblocks[reli];
tag = rel2tind(reli);
- return getindblk(d->iblocks[tag-Tind0], reli-tagstartreli(tag), tag, d->qid.path);
+ return getindblk(d->iblocks[tag-Tind0], reli-tagstartreli(tag), tag, d->path);
}
u64
@@ -69,13 +69,13 @@
return 0;
}
if(indblkno == 0){
- if((buf = allocblock(tag, path)) == nil){
+ if((buf = allocmeta(tag, path)) == nil){
dprint("%s",errstring[Efull]);
return 0;
}
indblkno = buf->blkno;
}else{
- if((buf = getbufchk(indblkno, Bwritable, tag, path)) == nil){
+ if((buf = getmetachk(indblkno, Bwritable, tag, path)) == nil){
dprint("updateindblock: %s",errstring[Ephase]);
return 0;
}
@@ -99,10 +99,10 @@
dprint("%s",errstring[Ephase]);
return 0;
}
- childindblkno = updateindblock(buf->io->bufa[reli/n],
+ childindblkno = updateindblock(buf->new->bufa[reli/n],
reli%n, tag-1, path,
blkno);
- buf->io->bufa[reli/n] = childindblkno;
+ buf->new->bufa[reli/n] = childindblkno;
}else{
if(reli >= Nindperblock){
panic("updateindblock invalid reli: indblkno %llud reli %llud tag %s"
@@ -111,9 +111,9 @@
dprint("%s",errstring[Ephase]);
return 0;
}
- buf->io->bufa[reli] = blkno;
+ buf->new->bufa[reli] = blkno;
}
- putbuf(buf);
+ putbuf(buf, 1);
return indblkno;
}
@@ -135,7 +135,7 @@
dprint("addrelative %llud:%s reli %llud blkno %llud\n",
dblkno, d->name, reli, blkno);
- path = d->qid.path;
+ path = d->path;
if(reli < Ndblock){
d->dblocks[reli] = blkno;
return blkno;
@@ -161,8 +161,8 @@
as this would all be dangling stuff identifiable by the fsck
and removed by it on a crash.
*/
-void
-freeindblock(u64 iblkno, u16 tag, u64 qpath, u16 directtag)
+u64
+freeindblock(u64 iblkno, u16 tag, u64 qpath, u16 directtag, u64 reli, u64 lastreli, u64 lastunits)
{
Iobuf *ibuf;
int i;
@@ -169,27 +169,37 @@
u64 blkno;
if(iblkno == 0)
- return;
- ibuf = getbufchk(iblkno, Bwritable, tag, qpath);
- if(ibuf == nil)
- dprint("%s",errstring[Ephase]);
+ return reli;
+ ibuf = getmetachk(iblkno, Bwritable, tag, qpath);
+ if(ibuf == nil){
+ panic("%s",errstring[Ephase]);
+ return reli;
+ }
if(tag == Tind0)
for(i=0; i < Nindperblock; i++){
- blkno = ibuf->io->bufa[i];
+ blkno = ibuf->cur->bufa[i];
if(blkno == 0)
break;
- freeblock(blkno, directtag, qpath);
- ibuf->io->bufa[i] = 0;
+ if(directtag == Tdentry)
+ freeblocks(blkno, Metadataunits, directtag, qpath);
+ else if(reli < lastreli)
+ freeblocks(blkno, Maxdatablockunits, directtag, qpath);
+ else
+ freeblocks(blkno, lastunits, directtag, qpath);
+ ibuf->new->bufa[i] = 0;
+ reli++;
}
else
for(i=0; i < Nindperblock; i++){
- if(ibuf->io->bufa[i] == 0)
+ if(ibuf->cur->bufa[i] == 0)
break;
- freeindblock(ibuf->io->bufa[i], tag-1, qpath, directtag);
- ibuf->io->bufa[i] = 0;
+ reli = freeindblock(ibuf->cur->bufa[i], tag-1, qpath, directtag,
+ reli, lastreli, lastunits);
+ ibuf->new->bufa[i] = 0;
}
freeblockbuf(ibuf);
+ return reli;
}
/* dbuf should be wlock'ed */
@@ -198,8 +208,9 @@
{
Dentry *d, d1;
int i;
+ u64 reli, lastreli, lastblks;
- d = dbuf->d;
+ d = (Dentry*)dbuf->cur;
memcpy(&d1, d, sizeof(Dentry));
for(i=0; i<Ndblock; i++)
d->dblocks[i] = 0;
@@ -208,17 +219,23 @@
d->size = 0;
d->mtime = nsec();
d->muid = uid;
- putbuf(dbuf);
+ putbuf(dbuf, 1);
+ lastreli = d1.size/Maxdatablocksize;
+ lastblks = nlastdatablocks(d1.size);
for(i=0; i<Ndblock; i++){
if(d1.dblocks[i] == 0)
return;
- freeblock(d1.dblocks[i], Tdata, d1.qid.path);
+ if(i < lastreli)
+ freeblocks(d1.dblocks[i], Maxdatablockunits, Tdata, d1.path);
+ else
+ freeblocks(d1.dblocks[i], lastblks, Tdata, d1.path);
}
- for(i=0;i<Niblock; i++){
+ for(i=0, reli=Ndblock;i<Niblock; i++){
if(d1.iblocks[i] == 0)
return;
- freeindblock(d1.iblocks[i], Tind0+i, d1.qid.path, Tdata);
+ reli = freeindblock(d1.iblocks[i], Tind0+i, d1.path, Tdata,
+ reli, lastreli, lastblks);
}
}
@@ -237,7 +254,7 @@
if(qpath < Qpusers || dblkno == 0)
return;
- dbuf = getbufchk(dblkno, Bwritable, Tdentry, qpath);
+ dbuf = getmetachk(dblkno, Bwritable, Tdentry, qpath);
if(dbuf == nil)
dprint("%s",errstring[Ephase]);
@@ -262,31 +279,44 @@
Iobuf *dbuf;
Dentry d;
int i;
- u64 size;
+ u64 size, reli, lastreli, lastblks;
if(qpath < Qpusers || dblkno == 0)
return;
- dbuf = getbufchk(dblkno, Bwritable, Tdentry, qpath);
+ dbuf = getmetachk(dblkno, Bwritable, Tdentry, qpath);
if(dbuf == nil)
dprint("%s",errstring[Ephase]);
- size = dbuf->d->size;
- memcpy(&d, dbuf->d, sizeof(Dentry));
- memset(dbuf->d, 0, Dentrysize);
+ size = dbuf->cur->size;
+ memcpy(&d, dbuf->cur, sizeof(Dentry));
+ memset(dbuf->new, 0, Blocksize);
settag(dbuf, Tdentry, Qpnone);
- putbuf(dbuf);
+ dbuf->new->verd = dbuf->cur->verd+1;
+ devwrite(dblkno, dbuf->xiobuf, Metadataunits);
+ if(dbuf->append){ /* data not yet written */
+ freememunits((u8*)dbuf->append, Maxdatablockunits);
+ dbuf->append = nil;
+ dbuf->appendsize = 0;
+ }
+ putbuf(dbuf, 1);
if(size < Ddatasize)
return;
+ lastreli = d.size/Maxdatablocksize;
+ lastblks = nlastdatablocks(d.size);
for(i=0; i<Ndblock; i++){
if(d.dblocks[i] == 0)
return;
- freeblock(d.dblocks[i], Tdata, qpath);
+ if(i < lastreli)
+ freeblocks(d.dblocks[i], Maxdatablockunits, Tdata, qpath);
+ else
+ freeblocks(d.dblocks[i], lastblks, Tdata, qpath);
}
- for(i=0;i<Niblock; i++){
+ for(i=0, reli=Ndblock;i<Niblock; i++){
if(d.iblocks[i] == 0)
return;
- freeindblock(d.iblocks[i], Tind0+i, qpath, Tdata);
+ reli = freeindblock(d.iblocks[i], Tind0+i, qpath, Tdata,
+ reli, lastreli, lastblks);
}
}
@@ -304,13 +334,14 @@
if(qpath < Qpusers || dblkno == 0)
return;
/* clear the dentry to avoid links to removed content */
- dbuf = getbufchk(dblkno, Bwritable, Tdentry, qpath);
+ dbuf = getmetachk(dblkno, Bwritable, Tdentry, qpath);
if(dbuf == nil)
dprint("%s",errstring[Ephase]);
- memcpy(&d, dbuf->d, sizeof(Dentry));
- memset(dbuf->d, 0, Dentrysize);
+ memcpy(&d, dbuf->cur, sizeof(Dentry));
+ memset(dbuf->new, 0, Blocksize);
settag(dbuf, Tdentry, Qpnone);
- putbuf(dbuf);
+ dbuf->new->verd = dbuf->cur->verd+1;
+ putbuf(dbuf, 1);
/*
remove the children
@@ -321,12 +352,12 @@
if((blkno = rel2abs(&d, reli)) == 0)
break;
- buf = getbuf(blkno, Dentryunits, Breadonly, Bused);
- child = buf->d;
- cqpath = child->qid.path;
+ buf = getmeta(blkno, Breadonly, Bused);
+ child = (Dentry*)buf->cur;
+ cqpath = child->path;
mode = child->mode;
- ct = buf->d->tag;
- putbuf(buf);
+ ct = child->tag;
+ putbuf(buf, 0);
/* nothing to do for already zero'ed out slots */
if(cqpath == Qpnone || ct == Tnone)
@@ -345,12 +376,13 @@
for(i=0; i<Ndblock; i++){
if(d.dblocks[i] == 0)
return;
- freeblock(d.dblocks[i], Tdentry, Qpnone);
+ freeblocks(d.dblocks[i], Metadataunits, Tdentry, Qpnone);
}
- for(i=0;i<Niblock; i++){
+ for(i=0, reli=Ndblock;i<Niblock; i++){
if(d.iblocks[i] == 0)
return;
- freeindblock(d.iblocks[i], Tind0+i, qpath, Tdentry);
+ reli = freeindblock(d.iblocks[i], Tind0+i, qpath, Tdentry,
+ reli, 0, Metadataunits);
}
}
@@ -409,13 +441,13 @@
Dentry *d, *ch;
u64 blkno;
- *dbuf = getbufchk(dblkno, Breadonly, Tdentry, qpath);
+ *dbuf = getmetachk(dblkno, Breadonly, Tdentry, qpath);
if(*dbuf == nil)
return nil;
- d = (*dbuf)->d;
+ d = (Dentry*)((*dbuf)->cur);
if(canaccess(uid, d, DMEXEC) == 0){
- putbuf(*dbuf);
+ putbuf(*dbuf, 0);
*dbuf = nil;
dprint("%s",errstring[Ephase]);
return nil;
@@ -426,7 +458,7 @@
if((blkno = rel2abs(d, reli)) == 0){
- putbuf(*dbuf);
+ putbuf(*dbuf, 0);
*dbuf = nil;
return nil;
}
@@ -434,23 +466,23 @@
dprint("searchdir reli %d s.blkno %llud s.len %d\n",
reli, blkno);
- *buf = getbuf(blkno, Dentryunits, Breadonly, Bused);
+ *buf = getmeta(blkno, Breadonly, Bused);
if(*buf == nil){
- putbuf(*dbuf);
+ putbuf(*dbuf, 0);
*dbuf = nil;
dprint("%s",errstring[Ephase]);
return nil;
}
- ch = (*buf)->d;
+ ch = (Dentry*)(*buf)->cur;
if(chatty9p > 2)
dprint("searchdir: dblkno %llud qpath %llud searchname %s searchidx %d"
- " reli %llud blkno %llud ch->qid.path %llud\n",
+ " reli %llud blkno %llud ch->path %llud\n",
dblkno, qpath, searchname, searchidx, reli, blkno,
- ch->qid.path);
- if(checktag(*buf, Tdentry, ch->qid.path) == 0){
- putbuf(*buf);
- putbuf(*dbuf);
+ ch->path);
+ if(checktag(*buf, Metadataunits, Tdentry, ch->path) == 0){
+ putbuf(*buf, 0);
+ putbuf(*dbuf, 0);
*dbuf = *buf = nil;
dprint("%s",errstring[Ephase]);
return nil;
@@ -474,7 +506,7 @@
idx++; /* so that zero'ed slots do not match */
Nextdentry:
- putbuf(*buf);
+ putbuf(*buf, 0);
}
/* should never be here */
}
@@ -481,8 +513,8 @@
void
freesearchstate(Iobuf **dbuf, Iobuf **buf)
{
- putbuf(*buf);
- putbuf(*dbuf);
+ putbuf(*buf, 0);
+ putbuf(*dbuf, 0);
*dbuf = *buf = nil;
}
@@ -492,7 +524,7 @@
only for file contents. not for directory contents.
*/
Iobuf *
-getdatablkat(Dentry *d, u64 reli, int flags)
+getdatablkat(Dentry *d, u64 reli)
{
Iobuf *buf;
u64 blkno;
@@ -502,9 +534,13 @@
*/
if((blkno = rel2abs(d, reli)) == 0)
return nil;
- buf = getbufchk(blkno, flags, Tdata, d->qid.path);
+
+ if(reli < d->size/Maxdatablocksize)
+ buf = getbufchk(blkno, Maxdatablockunits, Breadonly, Tdata, d->path);
+ else
+ buf = getbufchk(blkno, nlastdatablocks(d->size), Breadonly, Tdata, d->path);
if(buf == nil){
- putbuf(buf);
+ putbuf(buf, 0);
dprint("%s",errstring[Ephase]);
return nil;
}
@@ -518,6 +554,7 @@
{
s32 nbuf;
s8 *buf;
+ Iobuf *dbuf;
/* should not be necessary as we clear out the file
in loadfrees() */
@@ -536,6 +573,16 @@
/* writing the actual extents now */
writefile(dblkno, Qpfrees, -1, buf, nbuf, 0, nil);
free(buf);
+
+ /* flush to the disk if append has stuff */
+ dbuf = getmetachk(dblkno, Bwritable, Tdentry, Qpfrees);
+ if(dbuf == nil)
+ return;
+ if(dbuf->append != nil){
+ writeallappend(dbuf, dbuf->cur, dblkno);
+ putbuf(dbuf, 1);
+ }else
+ putbuf(dbuf, 0);
}
void
@@ -564,10 +611,10 @@
/* I cannot use truncatefile() below as it would
bfree() the blocks (which are already in the Extents frees)
and that would cause an inconsistency/panic */
- dbuf = getbufchk(dblkno, Bwritable, Tdentry, Qpfrees);
+ dbuf = getmetachk(dblkno, Bwritable, Tdentry, Qpfrees);
if(dbuf == nil)
dprint("%s",errstring[Ephase]);
- d = dbuf->d;
+ d = (Dentry*)dbuf->new;
d->size = 0;
for(i=0; i<Ndblock; i++)
d->dblocks[i] = 0;
@@ -575,5 +622,5 @@
d->iblocks[i] = 0;
d->mtime = nsec();
d->muid = -1;
- putbuf(dbuf);
+ putbuf(dbuf, 1);
}
--- a/find.c
+++ b/find.c
@@ -62,7 +62,7 @@
if(size == 0)
panic("null size %s", devfile);
if(debug)
- print("%s %llud bytes %llud blocks\n", devfile, size, size/Unit);
+ print("%s %llud bytes %llud blocks\n", devfile, size, size/Blocksize);
walkdirectory(Bdroot, 0);
exits(0);
@@ -79,7 +79,7 @@
}
int
-checkvalid(u64 blkno, u8 dtag, u64 dpath, u8 tag, u64 qpath)
+checkvalid(u64 blkno, u8 dtag, u64 dpath, u8 tag, u64 qpath, u16 len)
{
int ret = 1;
@@ -91,7 +91,7 @@
ret=0;
}/*else
print("%llud\n", blkno);*/
- if(blkno == findblkno){
+ if(blkno <= findblkno || findblkno < blkno+len){
showparents();
exits(nil);
}
@@ -101,14 +101,15 @@
void
walkindir(u64 blkno, u8 tag, u8 bottomtag, u64 qpath, s8 depth)
{
- u8 buf[Rawblocksize], *cbuf;
- Content *t, *ct;
+ u8 buf[Metadatablocksize], *cbuf;
+ Indirect *t;
+ Data *ct;
u64 cblkno, *bufa;
int i;
- devread(blkno, buf, Rawblockunits);
- t = (Content*)buf;
- if(checkvalid(blkno, t->tag, t->path, tag, qpath)){
+ devread(blkno, buf, Metadataunits);
+ t = (Indirect*)buf;
+ if(checkvalid(blkno, t->tag, t->path, tag, qpath, Metadataunits)){
if(t->tag == Tind0){
bufa = (u64*)buf;
for(i = 0; i<Nindperblock; i++){
@@ -115,28 +116,25 @@
cblkno = bufa[i];
if(cblkno == 0)
return;
- cbuf = malloc(Rawblocksize);
- devread(cblkno, cbuf, Rawblockunits);
- ct = (Content*)cbuf;
if(Tdentry == bottomtag)
/* another directory */
walkdirectory(cblkno, depth);
- else
- checkvalid(cblkno, ct->tag, ct->path, bottomtag, qpath);
- free(cbuf);
+ else{
+ cbuf = malloc(Blocksize);
+ devread(cblkno, cbuf, 1);
+ ct = (Data*)cbuf;
+ checkvalid(cblkno, ct->tag, ct->path, bottomtag, qpath, ct->len);
+ free(cbuf);
+ }
}
}else{
- bufa = (u64*)buf;
- cbuf = malloc(Rawblocksize);
for(i = 0; i<Nindperblock; i++){
- cblkno = bufa[i];
+ cblkno = t->bufa[i];
if(cblkno == 0)
return;
- devread(cblkno, cbuf, Rawblockunits);
/* check tag */
walkindir(cblkno, tag-1, bottomtag, qpath, depth);
}
- free(cbuf);
}
}
return;
@@ -165,23 +163,23 @@
void
walkdirectory(u64 blkno, s8 depth)
{
- u8 buf[Dentrysize], *cbuf;
+ u8 buf[Metadatablocksize], *cbuf;
Dentry *d, *cd;
- Content *ct;
+ Indirect *ct;
u64 cblkno;
int i;
- devread(blkno, buf, Dentryunits);
+ devread(blkno, buf, Metadataunits);
d = (Dentry*)buf;
showdepth(depth);
print("%llud:%s\n", blkno, d->name);
if(debug)
- print("walkdentry %llud tag %s name %s d->qid.path %llud\n",
- blkno, tagnames[d->tag], d->name, d->qid.path);
- if(d->tag != Tdentry || d->path != d->qid.path){
+ print("walkdentry %llud tag %s name %s d->qpath %llud\n",
+ blkno, tagnames[d->tag], d->name, d->qpath);
+ if(d->tag != Tdentry || d->path != d->qpath){
if(debug)
print("walkdentry invalid %llud tag/path expected %s/%llud actual %s/%llud\n",
- blkno, tagnames[Tdentry], d->qid.path, tagnames[d->tag], d->path);
+ blkno, tagnames[Tdentry], d->qpath, tagnames[d->tag], d->path);
fprint(2, "%llud\n", blkno);
}/*else
print("%llud\n", blkno);*/
@@ -190,8 +188,8 @@
cblkno = d->dblocks[i];
if(cblkno == 0)
return;
- cbuf = malloc(Dentrysize);
- devread(cblkno, cbuf, Dentryunits);
+ cbuf = malloc(Metadatablocksize);
+ devread(cblkno, cbuf, Metadataunits);
cd = (Dentry*)cbuf;
if((cd->mode & DMDIR) > 0)
walkdirectory(cblkno, depth+1);
@@ -199,15 +197,15 @@
walkfile(cblkno, depth+1);
free(cbuf);
}
- cbuf = malloc(Rawblocksize);
+ cbuf = malloc(Metadatablocksize);
for(i = 0; i<Niblock; i++){
cblkno = d->iblocks[i];
if(cblkno == 0)
return;
- devread(cblkno, cbuf, Rawblockunits);
- ct = (Content*)cbuf;
+ devread(cblkno, cbuf, Metadataunits);
+ ct = (Indirect*)cbuf;
if(ct->tag == Tind0+i){
- walkindir(cblkno, Tind0+i, Tdentry, d->qid.path, depth);
+ walkindir(cblkno, Tind0+i, Tdentry, d->qpath, depth);
}else{
fprint(2, "invalid indir tag %llud\n", cblkno);
fprint(2, "%llud\n", cblkno);
@@ -220,23 +218,24 @@
void
walkfile(u64 blkno, s8 depth)
{
- u8 buf[Rawblocksize], *cbuf;
+ u8 buf[Metadatablocksize], *cbuf;
Dentry *d;
- Content *ct;
+ Data *ct;
+ Indirect *it;
u64 cblkno;
int i;
- devread(blkno, buf, Dentryunits);
+ devread(blkno, buf, Metadataunits);
d = (Dentry*)buf;
showdepth(depth);
print("%llud:%s\n", blkno, d->name);
if(debug)
print("walkfile %llud tag %s name %s d->qid.path %llud\n",
- blkno, tagnames[d->tag], d->name, d->qid.path);
- if(d->tag != Tdentry || d->path != d->qid.path){
+ blkno, tagnames[d->tag], d->name, d->qpath);
+ if(d->tag != Tdentry || d->path != d->qpath){
if(debug)
print("walkdentry invalid %llud tag/path expected %s/%llud actual %s/%llud\n",
- blkno, tagnames[Tdentry], d->qid.path, tagnames[d->tag], d->path);
+ blkno, tagnames[Tdentry], d->qpath, tagnames[d->tag], d->path);
fprint(2, "%llud\n", blkno);
}/*else
print("%llud\n", blkno);*/
@@ -247,21 +246,21 @@
cblkno = d->dblocks[i];
if(cblkno == 0)
return;
- cbuf = malloc(Rawblocksize);
- devread(cblkno, cbuf, Rawblockunits);
- ct = (Content*)cbuf;
- checkvalid(cblkno, ct->tag, ct->path, Tdata, d->qid.path);
+ cbuf = malloc(Metadatablocksize);
+ devread(cblkno, cbuf, Metadataunits);
+ ct = (Data*)cbuf;
+ checkvalid(cblkno, ct->tag, ct->path, Tdata, d->qpath, ct->len);
free(cbuf);
}
- cbuf = malloc(Rawblocksize);
+ cbuf = malloc(Metadatablocksize);
for(i = 0; i<Niblock; i++){
cblkno = d->iblocks[i];
if(cblkno == 0)
return;
- devread(cblkno, cbuf, Rawblockunits);
- ct = (Content*)cbuf;
- if(ct->tag == Tind0+i){
- walkindir(cblkno, Tind0+i, Tdata, d->qid.path, depth);
+ devread(cblkno, cbuf, Metadataunits);
+ it = (Indirect*)cbuf;
+ if(it->tag == Tind0+i){
+ walkindir(cblkno, Tind0+i, Tdata, d->qpath, depth);
}else{
fprint(2, "invalid indir tag %llud\n", cblkno);
fprint(2, "%llud\n", cblkno);
--- a/fns.h
+++ b/fns.h
@@ -1,4 +1,5 @@
+u64 nlastdatablocks(u64 size);
u64 nperiblock(u16 tag);
u64 nperindunit(u16 tag);
u8 rel2tind(u64 reli);
@@ -5,6 +6,8 @@
u64 tagstartreli(u8 tag);
u64 maxreli(u8 tag);
u64 maxblocks(u8 tag);
+u64 nlastdatablocks(u64 size);
+u64 size2datareli(u64 size);
/* actual device i/o routines */
u64 devinit(char *devfile);
@@ -22,6 +25,7 @@
void showind0(int fd, u8 *buf);
void showind(int fd, u8 *buf);
u16 blklen(u16 tag);
+u8 recentmetadata(void *buf, void **old, void **new);
void panic(char*, ...);
int fprint(int, char*, ...);
--- a/free.c
+++ b/free.c
@@ -47,7 +47,7 @@
if(size == 0)
panic("null size %s", devfile);
if(chatty9p)
- print("%s %llud bytes %llud blocks\n", devfile, size, size/Unit);
+ print("%s %llud bytes %llud blocks\n", devfile, size, size/Blocksize);
checkdentry(Bdfrees, Tdentry, Qpfrees);
initextents(&frees);
@@ -59,7 +59,7 @@
}
int
-checkvalid(u64 blkno, u8 dtag, u64 dpath, u8 tag, u64 qpath)
+checkvalid(u64 blkno, u8 dtag, u64 dpath, u8 tag, u64 qpath, u16 len)
{
if(dtag != tag || dpath != qpath){
/* if(chatty9p) */
@@ -69,7 +69,7 @@
return 0;
}
if(chatty9p)
- print("%llud\n", blkno);
+ print("%llud %d\n", blkno, len);
return 1;
}
@@ -76,12 +76,12 @@
int
checkdentry(u64 blkno, u8 tag, u64 qpath)
{
- u8 buf[Dentrysize];
+ u8 buf[Metadatablocksize];
Dentry *t;
- devread(blkno, buf, Dentryunits);
+ devread(blkno, buf, Metadataunits);
t = (Dentry*)buf;
- return checkvalid(blkno, t->tag, t->path, tag, qpath);
+ return checkvalid(blkno, t->tag, t->path, tag, qpath, Metadataunits);
}
void
@@ -89,9 +89,9 @@
{
s8 *buf;
- buf = emalloc(Rawblocksize);
- devread(blkno, buf, Rawblockunits);
- loadextents(&frees, buf, Datablocksize);
+ buf = emalloc(Metadatablocksize);
+ devread(blkno, buf, Metadataunits);
+ loadextents(&frees, buf, Maxdatablocksize);
free(buf);
}
@@ -98,26 +98,24 @@
void
walkindir(u64 blkno, u16 tag, u16 bottomtag, u64 qpath)
{
- u8 buf[Rawblocksize];
- Content *t;
- u64 cblkno, *bufa;
+ u8 buf[Metadatablocksize];
+ Indirect *t;
+ u64 cblkno;
int i;
- devread(blkno, buf, Rawblockunits);
- t = (Content*)buf;
- if(checkvalid(blkno, t->tag, t->path, tag, qpath)){
+ devread(blkno, buf, Metadataunits);
+ t = (Indirect*)buf;
+ if(checkvalid(blkno, t->tag, t->path, tag, qpath, Metadataunits)){
if(t->tag == Tind0){
- bufa = (u64*)buf;
for(i = 0; i<Nindperblock; i++){
- cblkno = bufa[i];
+ cblkno = t->bufa[i];
if(cblkno == 0)
return;
loadfreeextents(cblkno);
}
}else{
- bufa = (u64*)buf;
for(i = 0; i<Nindperblock; i++){
- cblkno = bufa[i];
+ cblkno = t->bufa[i];
if(cblkno == 0)
return;
/* check tag */
@@ -131,13 +129,13 @@
getfrees(u64 dblkno)
{
u64 size;
- u8 buf[Dentrysize];
+ u8 buf[Metadatablocksize];
Dentry *d;
u64 cblkno;
int i;
- devread(dblkno, buf, Dentryunits);
- d = (Dentry*)buf;
+ devread(dblkno, buf, Metadataunits);
+ recentmetadata(buf, &d, nil);
size = d->size;
if(size == 0)
panic("loadfreeextents size == 0");
@@ -146,7 +144,7 @@
loadextents(&frees, d->buf, d->size);
return;
}
- if(checkvalid(dblkno, d->tag, d->path, Tdentry, Qpfrees)){
+ if(checkvalid(dblkno, d->tag, d->path, Tdentry, Qpfrees, Metadataunits)){
for(i = 0; i<Ndblock; i++){
cblkno = d->dblocks[i];
if(cblkno == 0)
--- a/iobuf.c
+++ b/iobuf.c
@@ -6,7 +6,7 @@
extern u8 synchronouswrites;
/*
- extents of Unit units of memory used to store
+ extents of Blocksize units of memory used to store
the disk block contents in memory for the buffer cache
and write queue
*/
@@ -18,12 +18,12 @@
void
initmemunitpool(u64 nunits)
{
- memunitstart = sbrk((nunits+1) * Unit);
- memunitpool = memunitstart+Unit- ((u64)memunitstart%Unit);
+ memunitstart = sbrk((nunits+1) * Blocksize);
+ memunitpool = memunitstart+Blocksize- ((u64)memunitstart%Blocksize);
initextents(&memunits);
if(chatty9p > 4)
- dprint("initmemunitpool: memunitpool %p nunits*Unit %p\n",
- memunitpool, nunits*Unit);
+ dprint("initmemunitpool: memunitpool %p nunits*Blocksize %p\n",
+ memunitpool, nunits*Blocksize);
bfree(&memunits, 0, nunits);
}
@@ -36,7 +36,7 @@
if(chatty9p > 4)
dprint("allocmemunit: memunitpool %p m %p\n",
memunitpool, m);
- return memunitpool+(m*Unit);
+ return memunitpool+(m*Blocksize);
}
void
@@ -44,10 +44,10 @@
{
if(m == 0)
panic("freememunit: m == 0\n");
- if((m-memunitpool)%Unit)
- panic("freememunit: (m-memunitpool)%%Unit %llud\n",
- (u64)(m-memunitpool)%Unit);
- bfree(&memunits, (m-memunitpool)/Unit, len);
+ if((m-memunitpool)%Blocksize)
+ panic("freememunit: (m-memunitpool)%%Blocksize %llud\n",
+ (u64)(m-memunitpool)%Blocksize);
+ bfree(&memunits, (m-memunitpool)/Blocksize, len);
}
/*
@@ -146,7 +146,9 @@
freememunits(p->xiobuf, p->len);
p->xiobuf = allocmemunits(len);
p->len = len;
- if(freshalloc == 0)
+ if(freshalloc)
+ memset(p->xiobuf, 0, len*Blocksize);
+ else
devread(blkno, p->xiobuf, len);
if(readonly){
if(chkwunlock(p) == 0){
@@ -192,8 +194,8 @@
Another:
do{
p = s->back;
- if(p->ref == 0 && p->dirties.ref == 0 && canwlock(p)){
- if(p->dirties.ref > 0 || p->ref > 0){
+ if(p->ref == 0 && p->append == nil && canwlock(p)){
+ if(p->ref > 0){
wunlock(p);
goto Another;
}
@@ -227,7 +229,9 @@
if(chatty9p > 4)
dprint(" after qunlock(hp) hp 0x%p blkno %llud\n",
hp, blkno);
- if(freshalloc == 0)
+ if(freshalloc)
+ memset(p->xiobuf, 0, len*Blocksize);
+ else
devread(blkno, p->xiobuf, len);
if(readonly){
if(chatty9p > 4)
@@ -241,21 +245,23 @@
}
Iobuf *
-getbufchk(u64 blkno, u8 readonly, int tag, u64 qpath)
+getbufchk(u64 blkno, u16 len, u8 readonly, int tag, u64 qpath)
{
Iobuf *b;
- u16 len;
if(chatty9p > 4)
dprint("getbufchk caller pc 0x%p\n", getcallerpc(&blkno));
- if(tag == Tdentry)
- len = Dentryunits;
- else
- len = Rawblockunits;
b = getbuf(blkno, len, readonly, Bused);
if(b != nil)
- if(checktag(b, tag, qpath) == 0){
- putbuf(b);
+ if(tag != Tdata){
+ recentmetadata(b->m, &b->cur, &b->new);
+ if(readonly == 0){ /* writable */
+ memcpy(b->new, b->cur, Blocksize);
+ b->new->verd++;
+ }
+ }
+ if(checktag(b, len, tag, qpath) == 0){
+ putbuf(b, 0);
panic("checktag on %llud failed %s\n", blkno, errstring[Ephase]);
}
if(b->io == nil)
@@ -266,6 +272,28 @@
return b;
}
+Iobuf *
+getmetachk(u64 blkno, u8 readonly, int tag, u64 qpath)
+{
+ return getbufchk(blkno, Metadataunits, readonly, tag, qpath);
+}
+
+Iobuf *
+getmeta(u64 blkno, u8 readonly, u8 freshalloc)
+{
+ Iobuf *b;
+
+ b = getbuf(blkno, Metadataunits, readonly, freshalloc);
+ if(b == nil)
+ return nil;
+ recentmetadata(b->m, &b->cur, &b->new);
+ if(readonly == 0){ /* writable */
+ memcpy(b->new, b->cur, Blocksize);
+ b->new->verd++;
+ }
+ return b;
+}
+
/*
put the Iobuf of the disk block at addr back into
the buffer cache for others to use.
@@ -290,22 +318,21 @@
return;
}
- buf = getbufchk(bno, Bwritable, Tdentry, qpath);
+ buf = getmetachk(bno, Bwritable, Tdentry, qpath);
if(buf == nil){
panic("bkp: buf == nil\n");
}
- memcpy(buf->d->buf, contents, Ddatasize);
- buf->d->mtime = nsec();
+ memcpy(buf->new->buf, contents, Ddatasize);
+ buf->new->mtime = nsec();
// if(qpath == Qproot0 || qpath == Qproot1){
// buf->d->mode &= ~DMDIR; /* to avoid recursive du -a */
// }
- putbuf(buf);
+ putbuf(buf, 1);
}
void
-putbuf(Iobuf *p)
+putbuf(Iobuf *p, u8 dowrite)
{
- s8 i;
u8 buf[Ddatasize];
u64 srcbno;
@@ -329,34 +356,31 @@
if(chatty9p > 4)
dprint(" .. runlock()'ed\n");
}else{
- if(canwlock(p)){
- panic("putbuf: buffer not locked %llud\n", p->blkno);
- }
srcbno = p->blkno;
- if(p->blkno == config.config.srcbno ||
- p->blkno == config.super.srcbno ||
- p->blkno == config.root.srcbno){
- memcpy(buf, p->d->buf, Ddatasize);
- }
- if(synchronouswrites){
- if(p->blkno < 10)
+ if(dowrite){
+ if(p->xiobuf[0] == Tdata){
devwrite(p->blkno, p->xiobuf, p->len);
- if(chkwunlock(p) == 0){
- showbuf(p);
- panic("putbuf: chkwunlock(p) == 0 called by %#p\n", getcallerpc(&p));
+ }else{
+ if(p->blkno == config.config.srcbno ||
+ p->blkno == config.super.srcbno ||
+ p->blkno == config.root.srcbno)
+ memcpy(buf, p->new->buf, Ddatasize);
+ devwrite(p->blkno+(p->new>p->cur?1:0), p->new, 1);
}
- }else
- putwrite(p);
- if(srcbno == config.config.srcbno){
- for(i=0; i<Nbkp; i++)
- bkp(srcbno, buf, config.config.dest[i], Qpconfig0+i*3);
- }else if(srcbno == config.super.srcbno){
- for(i=0; i<Nbkp; i++)
- bkp(srcbno, buf, config.super.dest[i], Qpsuper0+i*3);
- }else if(srcbno == config.root.srcbno){
- for(i=0; i<Nbkp; i++)
- bkp(srcbno, buf, config.root.dest[i], Qproot0+i*3);
}
+ if(chkwunlock(p) == 0){
+ showbuf(p);
+ panic("putbuf: chkwunlock(p) == 0 called by %#p\n", getcallerpc(&p));
+ }
+ if(dowrite){
+ if(srcbno == config.config.srcbno){
+ bkp(srcbno, buf, config.config.dest[0], Qpconfig0);
+ }else if(srcbno == config.super.srcbno){
+ bkp(srcbno, buf, config.super.dest[0], Qpsuper0);
+ }else if(srcbno == config.root.srcbno){
+ bkp(srcbno, buf, config.root.dest[0], Qproot0);
+ }
+ }
}
}
@@ -398,22 +422,20 @@
}
int
-checktag(Iobuf *p, u8 tag, u64 qpath)
+checktag(Iobuf *p, u16 len, u8 tag, u64 qpath)
{
uintptr pc;
- u16 len;
u16 ptag;
u64 pqpath;
- if(tag == Tdentry){
- ptag = p->d->tag;
- pqpath = p->d->path;
- }else{
+ if(tag == Tdata){
ptag = p->io->tag;
pqpath = p->io->path;
+ }else{
+ ptag = ((Dentry*)p->cur)->tag;
+ pqpath = ((Dentry*)p->cur)->path;
}
- len = blklen(tag);
if(len != p->len ||
tag != ptag ||
(qpath != Qpnone && qpath != pqpath)){
@@ -423,10 +445,11 @@
(uint)ptag, (uint)tag, p->blkno);
if(qpath == Qpnone){
dprint("checktag pc=%p disk %s(block %llud) tag/path=%s/%llud;"
- " expected %s\n",
+ " expected %s len %llud p->len %llud\n",
pc, devfile, (u64)p->blkno,
tagnames[ptag], (u64)pqpath,
- tagnames[tag]);
+ tagnames[tag],
+ len, p->len);
} else {
dprint(" tag/path = %G/%llux; expected %G/%llux\n",
(uint)ptag, pqpath, tag, qpath);
@@ -450,12 +473,12 @@
if(p->io == nil)
panic("settag %s(%llux) tag/path=%s/%llud: p->io == nil\n",
devfile, (u64)p->blkno, tagnames[tag], qpath);
- if(tag == Tdentry){
- p->d->tag = Tdentry;
- p->d->path = qpath;
- }else{
- p->io->tag = tag;
+ if(tag == Tdata){
+ p->io->tag = Tdentry;
p->io->path = qpath;
+ }else{
+ ((Dentry*)p->new)->tag = tag;
+ ((Dentry*)p->new)->path = qpath;
}
}
@@ -506,7 +529,7 @@
return;
}
dprint("showbuf p 0x%p ref %d readers %d writer %d"
- " blkno %llud len %llud"
+ " blkno %llud len %d"
" fore 0x%p back 0x%p"
" xiobuf 0x%p"
" caller %#p\n",
--- a/mafs.c
+++ b/mafs.c
@@ -6,8 +6,6 @@
u8 noauth = 0;
u8 readonly = 0;
u8 shuttingdown = 0;
-u8 synchronouswrites = 0;
-extern u64 npendingwrites; /* write throttling */
int writeallow; /* never on; for compatibility with fs */
int wstatallow;
@@ -40,7 +38,6 @@
rfork(RFNAMEG|RFNOTEG|RFREND);
nbuckets = 0;
- npendingwrites = 0;
nmemunits = 0;
doream = stdio = 0;
@@ -55,7 +52,6 @@
case 'D': chatty9p++; break;
case 'f': devfile = ARGF(); break;
case 'h': nbuckets = atoll(EARGF(usage())); break;
- case 'w': npendingwrites = atoll(EARGF(usage())); break;
case 'm': nmemunits = atoll(EARGF(usage())); break;
case 'r':
doream = 1;
@@ -95,8 +91,8 @@
if(chatty9p){
dprint("\nPlan 9 %d-bit file server with %d-deep indirect blocks\n",
sizeof(u64)*8, Niblock);
- dprint("nmemunits %llud npendingwrites %llud nbuckets %llud\n",
- nmemunits, npendingwrites, nbuckets);
+ dprint("nmemunits %llud nbuckets %llud\n",
+ nmemunits, nbuckets);
}
formatinit();
@@ -103,7 +99,6 @@
initmemunitpool(nmemunits);
initextents(&frees);
- initwriter();
iobufinit();
/*
--- a/misc.c
+++ b/misc.c
@@ -17,7 +17,7 @@
chkwunlock(RWLock *q)
{
if(q->writer <= 0){
- print("wunlock(%#p): not locked: pc %#p\n",
+ panic("wunlock(%#p): not locked: pc %#p\n",
q, getcallerpc(&q));
return 0;
}
--- a/mkfile
+++ b/mkfile
@@ -16,8 +16,8 @@
sub.$O\
tag.$O\
user.$O\
- writer.$O\
+
HFILES=\
all.h\
dat.h\
@@ -34,22 +34,22 @@
</sys/src/cmd/mkmany
# LDFLAGS=-p
-$O.updatefrees: blk.$O dat.$O dev.$O misc.$O updatefrees.$O
+$O.updatefrees: blk.$O dat.$O dev.$O misc.$O tag.$O updatefrees.$O
$LD $LDFLAGS -o $target $prereq
-$O.unused: dat.$O dev.$O extents.$O unused.$O misc.$O
+$O.unused: blk.$O dat.$O dev.$O extents.$O unused.$O misc.$O
$LD $LDFLAGS -o $target $prereq
-$O.used: blk.$O dat.$O dev.$O extents.$O misc.$O used.$O
+$O.used: blk.$O dat.$O dev.$O extents.$O misc.$O tag.$O used.$O
$LD $LDFLAGS -o $target $prereq
-$O.free: dat.$O dev.$O extents.$O free.$O misc.$O
+$O.free: blk.$O dat.$O dev.$O extents.$O free.$O misc.$O tag.$O
$LD $LDFLAGS -o $target $prereq
-$O.block: blk.$O dat.$O dev.$O misc.$O block.$O
+$O.block: blk.$O dat.$O dev.$O misc.$O tag.$O block.$O
$LD $LDFLAGS -o $target $prereq
-$O.find: blk.$O dat.$O dev.$O misc.$O find.$O
+$O.find: blk.$O dat.$O dev.$O misc.$O tag.$O find.$O
$LD $LDFLAGS -o $target $prereq
$O.reconcile: dat.$O extents.$O misc.$O reconcile.$O
--- a/sub.c
+++ b/sub.c
@@ -11,17 +11,17 @@
s32 on, nn;
s8 buf[Ddatasize-16];
- sb = getbufchk(Bdsuper, Metadataunits, Bwritable, Tdentry, Qpsuper);
+ sb = getmetachk(Bdsuper, Bwritable, Tdentry, Qpsuper);
if(sb == nil){
panic("newqpath: sb == nil\n");
}
- s = (Dentry*)sb->use;
+ s = (Dentry*)sb->new;
on = snprint(buf, Ddatasize-16, "%llud", s->qidgen);
qpath = s->qidgen++;
nn = snprint(buf, Ddatasize-16, "%llud", s->qidgen);
if(on != nn)
s->size += nn-on;
- putbuf(sb);
+ putbuf(sb, 1);
return qpath;
}
@@ -91,10 +91,22 @@
/* clear the buf to avoid leaks on reuse */
memset(buf->xiobuf, 0, len*Blocksize);
+ if(tag != Tdata)
+ recentmetadata(buf->m, &buf->cur, &buf->new);
settag(buf, tag, qpath);
return buf;
}
+Iobuf *
+allocmeta(int tag, u64 qpath)
+{
+ Iobuf *b;
+
+ b = allocblocks(Metadataunits, tag, qpath);
+ b->new->verd++;
+ return b;
+}
+
/* the buf should have been wlock()'ed */
void
freeblockbuf(Iobuf *buf)
@@ -151,17 +163,17 @@
Iobuf *sb;
Dentry *s;
- sb = getbufchk(Bdsuper, Metadataunits, Bwritable, Tdentry, Qpsuper);
+ sb = getmetachk(Bdsuper, Bwritable, Tdentry, Qpsuper);
if(sb == nil){
panic("fsok: sb == nil\n");
}
- s = (Dentry*)sb->use;
+ s = (Dentry*)sb->new;
s->fsok = ok;
if(chatty9p > 1){
dprint("fsok ok %d\n", ok);
showsuper(2, (u8*)s);
}
- putbuf(sb);
+ putbuf(sb, 1);
}
void
@@ -172,16 +184,16 @@
}
void
-reamfile(u64 dblkno, u64 qpath, char *name, u64 size, u64 pdblkno, u64 pqpath, u64 contentblkno)
+reamfile(u64 dblkno, u64 qpath, char *name, u64 size, u64 pdblkno, u64 pqpath)
{
Iobuf *b;
Dentry *d;
- b = getbuf(dblkno, Metadataunits, Bwritable, Bfreshalloc);
- memset(b->m, 0, Metadatablocksize);
+ b = getmeta(dblkno, Bwritable, Bfreshalloc);
+ if(b == nil)
+ panic("reamfile dblkno %llud b == nil\n", dblkno);
settag(b, Tdentry, qpath);
- d = (Dentry*)b->use;
- d->ver++;
+ d = (Dentry*)b->new;
d->namelen = strlen(name);
strcpy(d->name, name);
d->uid = d->muid = d->gid = -1;
@@ -189,15 +201,13 @@
((DMREAD) << 6) |
((DMREAD) << 3) |
((DMREAD) << 0);
- d->path = qpath;
+ d->qpath = qpath;
d->version = 0;
d->mtime = nsec();
d->size = size;
d->pdblkno = pdblkno;
d->pqpath = pqpath;
- if(contentblkno > 0)
- d->dblocks[0] = contentblkno;
- putbuf(b);
+ putbuf(b, 1);
}
/*
@@ -223,11 +233,9 @@
"10006:%s:%s:\n", user, user, user);
/* cannot show this in /adm though as the block number is 0 */
- b = getbuf(Bdmagic, Metadataunits, Bwritable, Bfreshalloc);
- memset(b->m, 0, Metadatablocksize);
+ b = getmeta(Bdmagic, Bwritable, Bfreshalloc);
settag(b, Tdentry, Qpmagic);
- d = (Dentry*)b->use;
- d->ver++;
+ d = (Dentry*)b->new;
d->namelen = 5;
strncpy(d->name, "magic", 6);
d->uid = d->muid = d->gid = -1;
@@ -235,7 +243,7 @@
((DMREAD|DMWRITE|DMEXEC) << 6) |
((DMREAD|DMWRITE|DMEXEC) << 3) |
((DMREAD|DMWRITE|DMEXEC) << 0);
- d->path = Qpmagic;
+ d->qpath = Qpmagic;
d->version = 0;
d->mtime = nsec();
d->pdblkno = Bdadm;
@@ -243,13 +251,11 @@
n = snprint((s8*)d->buf, Ddatasize, "%s%llud\n",
magic, Blocksize);
d->size = n;
- putbuf(b);
+ putbuf(b, 1);
- b = getbuf(Bdadm, Metadataunits, Bwritable, Bfreshalloc);
- memset(b->m, 0, Metadatablocksize);
+ b = getmeta(Bdadm, Bwritable, Bfreshalloc);
settag(b, Tdentry, Qpadm);
- d = (Dentry*)b->use;
- d->ver++;
+ d = (Dentry*)b->new;
d->namelen = 3;
strncpy(d->name, "adm", 4);
d->uid = d->muid = d->gid = -1;
@@ -257,7 +263,7 @@
((DMREAD|DMWRITE|DMEXEC) << 6) |
((DMREAD|DMWRITE|DMEXEC) << 3) |
((DMREAD|DMWRITE|DMEXEC) << 0);
- d->path = Qpadm;
+ d->qpath = Qpadm;
d->version = 0;
d->mtime = nsec();
d->pdblkno = Bdroot;
@@ -268,13 +274,11 @@
d->dblocks[3] = Bdbkp;
d->dblocks[4] = Bdfrees;
d->dblocks[5] = Bdctl;
- putbuf(b);
+ putbuf(b, 1);
- b = getbuf(Bdbkp, Metadataunits, Bwritable, Bfreshalloc);
- memset(b->m, 0, Metadatablocksize);
+ b = getmeta(Bdbkp, Bwritable, Bfreshalloc);
settag(b, Tdentry, Qpbkp);
- d = (Dentry*)b->use;
- d->ver++;
+ d = (Dentry*)b->new;
d->namelen = 3;
strncpy(d->name, "bkp", 4);
d->uid = d->muid = d->gid = -1;
@@ -282,7 +286,7 @@
((DMREAD|DMWRITE|DMEXEC) << 6) |
((DMREAD|DMWRITE|DMEXEC) << 3) |
((DMREAD|DMWRITE|DMEXEC) << 0);
- d->path = Qpbkp;
+ d->qpath = Qpbkp;
d->version = 0;
d->mtime = nsec();
d->size = strlen(users)+1;
@@ -291,13 +295,11 @@
d->dblocks[0] = bdconfig0;
d->dblocks[1] = bdsuper0;
d->dblocks[2] = bdroot0;
- putbuf(b);
+ putbuf(b, 1);
- b = getbuf(Bdusers, Metadataunits, Bwritable, Bfreshalloc);
- memset(b->m, 0, Metadatablocksize);
+ b = getmeta(Bdusers, Bwritable, Bfreshalloc);
settag(b, Tdentry, Qpusers);
- d = (Dentry*)b->use;
- d->ver++;
+ d = (Dentry*)b->new;
d->namelen = 5;
strncpy(d->name, "users", 6);
d->uid = d->muid = d->gid = -1;
@@ -305,7 +307,7 @@
((DMREAD|DMWRITE|DMEXEC) << 6) |
((DMREAD|DMWRITE|DMEXEC) << 3) |
((DMREAD|DMWRITE|DMEXEC) << 0);
- d->path = Qpusers;
+ d->qpath = Qpusers;
d->version = 0;
d->mtime = nsec();
d->size = strlen(users)+1;
@@ -313,13 +315,11 @@
d->pqpath = Qpadm;
d->dblocks[0] = Bdusersinuse;
d->dblocks[1] = Bdusersstaging;
- putbuf(b);
+ putbuf(b, 1);
- b = getbuf(Bdusersinuse, Metadataunits, Bwritable, Bfreshalloc);
- memset(b->m, 0, Metadatablocksize);
+ b = getmeta(Bdusersinuse, Bwritable, Bfreshalloc);
settag(b, Tdentry, Qpusersinuse);
- d = (Dentry*)b->use;
- d->ver++;
+ d = (Dentry*)b->new;
d->namelen = 5;
strncpy(d->name, "inuse", 6);
d->uid = d->muid = d->gid = -1;
@@ -327,7 +327,7 @@
((DMREAD) << 6) |
((DMREAD) << 3) |
((DMREAD) << 0);
- d->path = Qpusersinuse;
+ d->qpath = Qpusersinuse;
d->version = 0;
d->mtime = nsec();
d->size = userslen;
@@ -334,13 +334,11 @@
d->pdblkno = Bdusers;
d->pqpath = Qpusers;
strcpy((s8*)d->buf, users);
- putbuf(b);
+ putbuf(b, 1);
- b = getbuf(Bdroot, Metadataunits, Bwritable, Bfreshalloc);
- memset(b->m, 0, Metadatablocksize);
+ b = getmeta(Bdroot, Bwritable, Bfreshalloc);
settag(b, Tdentry, Qproot);
- d = (Dentry*)b->use;
- d->ver++;
+ d = (Dentry*)b->new;
d->namelen = 1;
strncpy(d->name, "/", 5);
d->uid = d->muid = -1;
@@ -349,18 +347,18 @@
((DMREAD|DMWRITE|DMEXEC) << 6) |
((DMREAD|DMWRITE|DMEXEC) << 3) |
((DMREAD|DMWRITE|DMEXEC) << 0);
- d->path = Qproot;
+ d->qpath = Qproot;
d->version = 0;
d->mtime = nsec();
d->dblocks[0] = Bdadm;
- putbuf(b);
+ putbuf(b, 1);
- reamfile(Bdconfig, Qpconfig, "config", 0, Bdadm, Qpadm, 0);
- reamfile(Bdctl, Qpctl, "ctl", 0, Bdadm, Qpadm, 0);
- reamfile(Bdfrees, Qpfrees, "frees", 0, Bdadm, Qpadm, 0);
+ reamfile(Bdconfig, Qpconfig, "config", 0, Bdadm, Qpadm);
+ reamfile(Bdctl, Qpctl, "ctl", 0, Bdadm, Qpadm);
+ reamfile(Bdfrees, Qpfrees, "frees", 0, Bdadm, Qpadm);
reamfile(Bdusersstaging, Qpusersstaging, "staging",
- 0, Bdusers, Qpusers, 0);
+ 0, Bdusers, Qpusers);
}
void
@@ -374,10 +372,10 @@
sbuf = getbuf(Bdsuper, Metadataunits, Bwritable, Bfreshalloc);
if(sbuf == nil)
panic("superream: sbuf == nil");
- memset(sbuf->m, 0, Metadatablocksize);
+ sbuf->cur = sbuf->new = (Metadataunit*)sbuf->m;
settag(sbuf, Tdentry, Qpsuper);
- s = (Dentry*)sbuf->use;
- s->ver++;
+ s = (Dentry*)sbuf->new;
+ s->verd++;
s->namelen = 5;
strncpy(s->name, "super", 6);
s->uid = s->muid = s->gid = -1;
@@ -385,7 +383,7 @@
((DMREAD) << 6) |
((DMREAD) << 3) |
((DMREAD) << 0);
- s->path = Qpsuper;
+ s->qpath = Qpsuper;
s->version = 0;
s->mtime = nsec();
s->size = 18;
@@ -400,15 +398,21 @@
config.nblocks = nblocks;
config.config.dest[0] = nblocks-Bdconfig;
config.super.dest[0] = nblocks-Bdsuper;
- config.root.dest[0] = nblocks-3;
+ config.root.dest[0] = nblocks-6;
+ /* this will enable backups */
+ config.config.srcbno = Bdconfig;
+ config.super.srcbno = Bdsuper;
+ config.root.srcbno = Bdroot;
+ strncpy(config.service, service, Namelen);
+
reamfile(config.config.dest[0], Qpconfig0, "config.0",
- 0, Bdbkp, Qpbkp, config.config.dest[0]);
+ 0, Bdbkp, Qpbkp);
reamfile(config.super.dest[0], Qpsuper0, "super.0",
- 0, Bdbkp, Qpbkp, config.super.dest[0]);
+ 0, Bdbkp, Qpbkp);
reamfile(config.root.dest[0], Qproot0, "root.0",
- 0, Bdbkp, Qpbkp, config.root.dest[0]);
- putbuf(sbuf);
+ 0, Bdbkp, Qpbkp);
+ putbuf(sbuf, 1);
if(chatty9p > 1)
dprint("backup config %llud"
@@ -426,12 +430,6 @@
if(chatty9p > 1)
dprint("done\n");
- /* this will enable backups */
- config.config.srcbno = Bdconfig;
- config.super.srcbno = Bdsuper;
- config.root.srcbno = Bdroot;
- strncpy(config.service, service, Namelen);
-
fsok(0);
}
@@ -490,35 +488,35 @@
}
/* check magic */
- b = getbufchk(Bdmagic, Metadataunits, Breadonly, Tdentry, Qpmagic);
+ b = getmetachk(Bdmagic, Breadonly, Tdentry, Qpmagic);
if(b == nil){
panic("Invalid magic: %s",errstring[Ephase]);
return;
}
- if(strncmp((s8*)((Dentry*)b->use)->buf,magic,strlen(magic)) != 0){
+ if(strncmp((s8*)((Dentry*)b->cur)->buf,magic,strlen(magic)) != 0){
print("init: bad magic -%s-", (s8*)b->io+256);
panic("bad magic");
}
- unitsize = strtoul((s8*)((Dentry*)b->use)->buf+strlen(magic), &rptr, 10);
+ unitsize = strtoul((s8*)((Dentry*)b->cur)->buf+strlen(magic), &rptr, 10);
if(unitsize != Blocksize){
print("init incorrect block size Blocksize %llud unitsize %d\n",
Blocksize, unitsize);
panic("bad Blocksize != unitsize");
}
- putbuf(b);
+ putbuf(b, 0);
/* check super */
- sb = getbufchk(Bdsuper, Metadataunits, Breadonly, Tdentry, Qpsuper);
+ sb = getmetachk(Bdsuper, Breadonly, Tdentry, Qpsuper);
if(sb == nil){
panic("Invalid super: %s",errstring[Ephase]);
return;
}
- s = (Dentry*)sb->use;
+ s = (Dentry*)sb->cur;
if(s->fsok != 1 || config.size != size)
panic(errstring[Edirty]);
s->fsok = 0;
- putbuf(sb);
+ putbuf(sb, 1);
shuttingdown = 0;
usersinit();
}
--- a/tag.c
+++ b/tag.c
@@ -112,3 +112,39 @@
{
return maxreli(tag)+1;
}
+
+/* size to Tdata reli */
+u64
+size2datareli(u64 size)
+{
+ return size/Maxdatablocksize;
+}
+
+/* number of Tdata blocks for this size */
+u64
+size2ndata(u64 size)
+{
+ if(size == 0)
+ return 0;
+ if(size%Maxdatablocksize == 0)
+ return size/Maxdatablocksize;
+ else
+ return 1+ size/Maxdatablocksize;
+}
+
+/*
+ for allocate on flush.
+ number of blocks of the last Tdata block
+ */
+u64
+nlastdatablocks(u64 size)
+{
+ u64 lastblkholds;
+
+ if((lastblkholds = size%Maxdatablocksize) == 0)
+ return Maxdatablockunits;
+ if(lastblkholds%(Blocksize-sizeof(Datahdr)-sizeof(u64)) == 0)
+ return lastblkholds/(Blocksize-sizeof(Datahdr)-sizeof(u64));
+ else
+ return 1+(lastblkholds/(Blocksize-sizeof(Datahdr)-sizeof(u64)));
+}
--- a/tests/mkfile
+++ b/tests/mkfile
@@ -2,7 +2,7 @@
BIN=/$objtype/bin/disk
-TARG=sizes offsets testextents pwrites reli # mfsck
+TARG=sizes offsets testextents pwrites reli nlastdatablocks # mfsck
OFILES=\
../dat.$O\
--- a/tests/regress.rc
+++ b/tests/regress.rc
@@ -93,10 +93,10 @@
chkreli.rc
chkextents.rc
for (t in test.*){
- rununi mfs $t
+# rununi mfs $t
rununi mafs $t
- runmp mfs $t
- runmp mafs $t
+# runmp mfs $t
+# runmp mafs $t
}
}
if not {
@@ -107,9 +107,9 @@
chkextents.rc
}
if not {
- rununi mfs $*
+# rununi mfs $*
rununi mafs $*
- runmp mfs $*
- runmp mafs $*
+# runmp mfs $*
+# runmp mafs $*
}
}
--- a/updatefrees.c
+++ b/updatefrees.c
@@ -26,9 +26,9 @@
{
u64 size, freeblkno;
s32 nfreesize;
- s8 buf[Dentrysize], frees[Rawblocksize];
+ s8 buf[Metadatablocksize], frees[Maxdatablocksize];
int fd;
- Content *c;
+ Data *c;
Dentry *d;
ARGBEGIN{
@@ -47,19 +47,19 @@
if(freesfile == nil)
sysfatal("no frees file");
- memset(buf,0,Dentrysize);
- memset(frees, 0, Rawblocksize);
+ memset(buf,0,Metadatablocksize);
+ memset(frees, 0, Maxdatablocksize);
fd = open(freesfile, OREAD);
if(fd < 0)
sysfatal("updatefrees: cannot open freesfile %s\n", freesfile);
- nfreesize = read(fd, frees, Rawblocksize);
+ nfreesize = read(fd, frees, Maxdatablocksize);
if(nfreesize <= 0)
sysfatal("updatefrees: nfreesize %d <= 0\n", nfreesize);
- if(nfreesize > Datablocksize)
+ if(nfreesize > Maxdatablocksize)
sysfatal("updatefrees: unsupported nfreesize %d > Datablocksize %llud\n",
- nfreesize, Datablocksize);
+ nfreesize, Maxdatablocksize);
close(fd);
freeblkno = atoll((s8*)frees);
@@ -76,7 +76,7 @@
print("Dentry size %d\n", sizeof(Dentry));
}
- devread(Bdfrees, buf, Dentryunits);
+ devread(Bdfrees, buf, Metadataunits);
// showblock(1, buf);
d = (Dentry*)buf;
@@ -85,18 +85,18 @@
d->size = nfreesize;
if(nfreesize < Ddatasize){
strncpy(d->buf, frees, nfreesize);
- devwrite(Bdfrees, buf, Dentryunits);
+ devwrite(Bdfrees, buf, Metadataunits);
}else{
if(d->dblocks[0] != freeblkno)
print("changed dblocks[0]: %llud to %llud\n", d->dblocks[0], freeblkno);
d->dblocks[0] = freeblkno;
- c = (Content*)frees;
+ c = (Data*)frees;
c->tag = Tdata;
c->path = Qpfrees;
- devwrite(Bdfrees, buf, Dentryunits);
- devwrite(freeblkno, frees, Rawblockunits);
+ devwrite(Bdfrees, buf, Metadataunits);
+ devwrite(freeblkno, frees, nlastdatablocks(nfreesize));
}
close(devfd);
exits(0);
--- a/used.c
+++ b/used.c
@@ -49,7 +49,7 @@
if(size == 0)
panic("null size %s", devfile);
if(chatty9p)
- print("%s %llud bytes %llud blocks\n", devfile, size, size/Unit);
+ print("%s %llud bytes %llud blocks\n", devfile, size, size/Blocksize);
initextents(&useds);
checkdentry(Bdmagic, Tdentry, Qpmagic);
@@ -60,7 +60,7 @@
}
int
-checkvalid(u64 blkno, u8 dtag, u64 dpath, u8 tag, u64 qpath)
+checkvalid(u64 blkno, u8 dtag, u64 dpath, u8 tag, u64 qpath, u16 len)
{
if(dtag != tag || dpath != qpath){
/* if(chatty9p) */
@@ -72,7 +72,7 @@
if(chatty9p)
print("blkno %llud tag %s\n", blkno, tagnames[dtag]);
// print("%llud\n", blkno);
- add(&useds, blkno, blklen(tag));
+ add(&useds, blkno, len);
return 1;
}
@@ -79,38 +79,48 @@
int
checkdentry(u64 blkno, u8 tag, u64 qpath)
{
- u8 buf[Rawblocksize];
+ u8 buf[Metadatablocksize];
Dentry *d;
- devread(blkno, buf, Dentryunits);
- d = (Dentry*)buf;
- return checkvalid(blkno, d->tag, d->path, tag, qpath);
+ devread(blkno, buf, Metadataunits);
+ recentmetadata(buf, &d, nil);
+ return checkvalid(blkno, d->tag, d->path, tag, qpath, Metadataunits);
}
void
walkindir(u64 blkno, u16 tag, u16 bottomtag, u64 qpath)
{
- u8 buf[Rawblocksize], *cbuf;
- Content *t, *ct;
+ u8 buf[Metadatablocksize], *cbuf;
+ Indirect *t;
+ Data *da;
u64 cblkno;
int i;
+ Dentry *cd;
- devread(blkno, buf, blklen(tag));
- t = (Content*)buf;
- if(checkvalid(blkno, t->tag, t->path, tag, qpath)){
+ devread(blkno, buf, Metadataunits);
+ recentmetadata(buf, &t, nil);
+ if(checkvalid(blkno, t->tag, t->path, tag, qpath, Metadataunits)){
if(tag == Tind0){
for(i = 0; i<Nindperblock; i++){
cblkno = t->bufa[i];
if(cblkno == 0)
return;
- cbuf = malloc(blklen(bottomtag)*Unit);
- devread(cblkno, cbuf, blklen(bottomtag));
- ct = (Content*)cbuf;
- if(ct->tag == Tdentry && ct->tag == bottomtag)
- walkdirectory(cblkno);
- else
- checkvalid(cblkno, ct->tag, ct->path, bottomtag, qpath);
- free(cbuf);
+ if(bottomtag == Tdentry){
+ cbuf = malloc(Metadatablocksize);
+ devread(cblkno, cbuf, Metadataunits);
+ recentmetadata(cbuf, &cd, nil);
+ if((cd->mode & DMDIR) > 0)
+ walkdirectory(cblkno);
+ else
+ walkfile(cblkno);
+ free(cbuf);
+ }else{
+ cbuf = malloc(Maxdatablockunits*Blocksize);
+ devread(cblkno, cbuf, 1);
+ da = (Data*)cbuf;
+ checkvalid(cblkno, da->tag, da->path, Tdata, da->path, da->len);
+ free(cbuf);
+ }
}
}else{
for(i = 0; i<Nindperblock; i++){
@@ -127,25 +137,25 @@
void
walkdirectory(u64 blkno)
{
- u8 buf[Rawblocksize], *cbuf;
+ u8 buf[Metadatablocksize], *cbuf;
Dentry *d, *cd;
- Content *ct;
+ Indirect *it;
u64 cblkno;
int i;
- devread(blkno, buf, Dentryunits);
- d = (Dentry*)buf;
+ devread(blkno, buf, Metadataunits);
+ recentmetadata(buf, &d, nil);
if(chatty9p)
- print("walkdirectory %llud tag %s name %s d->qid.path %llud\n",
- blkno, tagnames[d->tag], d->name, d->qid.path);
- if(d->tag != Tdentry || d->path != d->qid.path){
+ print("walkdirectory %llud tag %s name %s d->path %llud\n",
+ blkno, tagnames[d->tag], d->name, d->path);
+ if(d->tag != Tdentry || d->path != d->qpath){
if(chatty9p)
print("walkdirectory invalid %llud tag/path expected %s/%llud actual %s/%llud\n",
- blkno, tagnames[Tdentry], d->qid.path, tagnames[d->tag], d->path);
+ blkno, tagnames[Tdentry], d->qpath, tagnames[d->tag], d->path);
fprint(2, "%llud\n", blkno);
}else{
// print("%llud\n", blkno);
- add(&useds, blkno, Dentryunits);
+ add(&useds, blkno, Metadataunits);
}
/* do not list the data blocks used by /adm/frees
as they are considered to be free blocks */
@@ -155,9 +165,9 @@
cblkno = d->dblocks[i];
if(cblkno == 0)
return;
- cbuf = malloc(Dentrysize);
- devread(cblkno, cbuf, Dentryunits);
- cd = (Dentry*)cbuf;
+ cbuf = malloc(Metadatablocksize);
+ devread(cblkno, cbuf, Metadataunits);
+ recentmetadata(cbuf, &cd, nil);
if((cd->mode & DMDIR) > 0)
walkdirectory(cblkno);
else
@@ -164,15 +174,15 @@
walkfile(cblkno);
free(cbuf);
}
- cbuf = malloc(Rawblocksize);
+ cbuf = malloc(Metadatablocksize);
for(i = 0; i<Niblock; i++){
cblkno = d->iblocks[i];
if(cblkno == 0)
return;
- devread(cblkno, cbuf, Dentryunits);
- ct = (Content*)cbuf;
- if(ct->tag == Tind0+i){
- walkindir(cblkno, Tind0+i, Tdentry, d->qid.path);
+ devread(cblkno, cbuf, Metadataunits);
+ recentmetadata(cbuf, &it, nil);
+ if(it->tag == Tind0+i){
+ walkindir(cblkno, Tind0+i, Tdentry, d->qpath);
}else{
fprint(2, "invalid indir tag %llud\n", cblkno);
fprint(2, "%llud\n", cblkno);
@@ -185,25 +195,26 @@
void
walkfile(u64 blkno)
{
- u8 buf[Rawblocksize], *cbuf;
+ u8 buf[Metadatablocksize], *cbuf;
Dentry *d;
- Content *ct;
+ Data *ct;
+ Indirect *it;
u64 cblkno;
int i;
- devread(blkno, buf, Dentryunits);
- d = (Dentry*)buf;
+ devread(blkno, buf, Metadataunits);
+ recentmetadata(buf, &d, nil);
if(chatty9p)
print("walkfile %llud tag %s name %s d->qid.path %llud\n",
- blkno, tagnames[d->tag], d->name, d->qid.path);
- if(d->tag != Tdentry || d->path != d->qid.path){
+ blkno, tagnames[d->tag], d->name, d->qpath);
+ if(d->tag != Tdentry || d->path != d->qpath){
if(chatty9p)
print("walkfile invalid %llud tag/path expected %s/%llud actual %s/%llud\n",
- blkno, tagnames[Tdentry], d->qid.path, tagnames[d->tag], d->path);
+ blkno, tagnames[Tdentry], d->qpath, tagnames[d->tag], d->path);
fprint(2, "%llud\n", blkno);
}else{
// print("%llud\n", blkno);
- add(&useds, blkno, Dentryunits);
+ add(&useds, blkno, Metadataunits);
}
/* do not list the data blocks used by /adm/frees
as they are considered to be free blocks */
@@ -211,25 +222,28 @@
return;
if(d->size <= Ddatasize)
return;
+
+ cbuf = malloc(Maxdatablockunits*Blocksize);
for(i = 0; i<Ndblock; i++){
cblkno = d->dblocks[i];
- if(cblkno == 0)
+ if(cblkno == 0){
+ free(cbuf);
return;
- cbuf = malloc(Rawblocksize);
- devread(cblkno, cbuf, Rawblockunits);
- ct = (Content*)cbuf;
- checkvalid(cblkno, ct->tag, ct->path, Tdata, d->qid.path);
- free(cbuf);
+ }
+ devread(cblkno, cbuf, 1);
+ ct = (Data*)cbuf;
+ checkvalid(cblkno, ct->tag, ct->path, Tdata, d->qpath, ct->len);
}
- cbuf = malloc(Rawblocksize);
for(i = 0; i<Niblock; i++){
cblkno = d->iblocks[i];
- if(cblkno == 0)
+ if(cblkno == 0){
+ free(cbuf);
return;
- devread(cblkno, cbuf, Rawblockunits);
- ct = (Content*)cbuf;
- if(ct->tag == Tind0+i){
- walkindir(cblkno, Tind0+i, Tdata, d->qid.path);
+ }
+ devread(cblkno, cbuf, Metadataunits);
+ recentmetadata(buf, &it, nil);
+ if(it->tag == Tind0+i){
+ walkindir(cblkno, Tind0+i, Tdata, d->qpath);
}else{
fprint(2, "invalid indir tag %llud\n", cblkno);
fprint(2, "%llud\n", cblkno);
--- a/user.c
+++ b/user.c
@@ -423,10 +423,10 @@
User *us;
int rv;
- ubuf = getbufchk(Bdusersinuse, Breadonly, Tdentry, Qpusersinuse);
- usize = ubuf->d->size+1;
+ ubuf = getmetachk(Bdusersinuse, Breadonly, Tdentry, Qpusersinuse);
+ usize = ubuf->cur->size+1;
buf = emalloc9p(usize);
- putbuf(ubuf);
+ putbuf(ubuf, 0);
readfile(Bdusersinuse, Qpusersinuse, buf, usize, 0, nil);
if((rv=parseusers(&us, buf, usize)) != 0)
@@ -451,10 +451,10 @@
u64 usize;
User *us, *old;
- ubuf = getbufchk(Bdusersstaging, Breadonly, Tdentry, Qpusersstaging);
- usize = ubuf->d->size+1;
+ ubuf = getmetachk(Bdusersstaging, Breadonly, Tdentry, Qpusersstaging);
+ usize = ubuf->cur->size+1;
buf = emalloc9p(usize);
- putbuf(ubuf);
+ putbuf(ubuf, 0);
readfile(Bdusersstaging, Qpusersstaging, buf, usize, 0, nil);
if(parseusers(&us, buf, usize) != 0)