ref: d24b5a7a0e45186f13d19ddefde62b0932726e42
parent: 101b3c2724779fcb0e503ae274abd7b751a3a48f
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Sun Apr 30 14:44:29 EDT 2023
dossrv: Implement support for != 512 sector and track sizes The iotrack buffer layer always assumed 512 byte sector size and 9 sectors per track. To support 4K sector size fats, make the iotrack code deal with it. Instead of the fixed size Track structure, we just allocate the pointers and buffers dynamically, and move the sector size and tack size in the Xfs structure. Tracks can still be reused between differnet file-systems after a purgetrack(). The initial fat header has to be read with devread() instead of getsect() to determine the sector/track size of the file-system.
--- a/sys/src/cmd/dossrv/dat.h
+++ b/sys/src/cmd/dossrv/dat.h
@@ -118,7 +118,6 @@
*/
struct Dosbpb{
MLock; /* access to fat */
- int sectsize; /* in bytes */
int clustsize; /* in sectors */
int nresrv; /* sectors */
int nfats; /* usually 2; modified to 1 if fat mirroring disabled */
@@ -190,7 +189,7 @@
Dosdir *d;
};
-#define QIDPATH(p) ((p)->addr*(Sectorsize/DOSDIRSIZE) + \
+#define QIDPATH(p, xf) ((p)->addr*((xf)->sectsize/DOSDIRSIZE) + \
(p)->offset/DOSDIRSIZE)
struct Xfs{
@@ -203,6 +202,8 @@
uchar isfat32; /* is a fat 32 file system? */
short dev;
short fmt;
+ int sectsize;
+ int sect2trk;
vlong offset;
void *ptr;
};
--- a/sys/src/cmd/dossrv/devio.c
+++ b/sys/src/cmd/dossrv/devio.c
@@ -7,7 +7,7 @@
int readonly;
static int
-deverror(char *name, Xfs *xf, long addr, long n, long nret)
+deverror(char *name, Xfs *xf, vlong addr, long n, long nret)
{
errno = Eio;
if(nret < 0){
@@ -16,7 +16,7 @@
xf->dev = -1;
return -1;
}
- fprint(2, "dev %d sector %ld, %s: %ld, should be %ld\n", xf->dev, addr, name, nret, n);
+ fprint(2, "dev %d sector %lld, %s: %ld, should be %ld\n", xf->dev, addr, name, nret, n);
return -1;
}
@@ -27,7 +27,7 @@
if(xf->dev < 0)
return -1;
- nread = pread(xf->dev, buf, n, xf->offset+addr*Sectorsize);
+ nread = pread(xf->dev, buf, n, xf->offset+addr*xf->sectsize);
if (nread == n)
return 0;
return deverror("read", xf, addr, n, nread);
@@ -43,23 +43,8 @@
if(xf->dev < 0)
return -1;
- nwrite = pwrite(xf->dev, buf, n, xf->offset+addr*Sectorsize);
+ nwrite = pwrite(xf->dev, buf, n, xf->offset+addr*xf->sectsize);
if (nwrite == n)
return 0;
return deverror("write", xf, addr, n, nwrite);
-}
-
-int
-devcheck(Xfs *xf)
-{
- char buf[Sectorsize];
-
- if(xf->dev < 0)
- return -1;
- if(pread(xf->dev, buf, Sectorsize, 0) != Sectorsize){
- close(xf->dev);
- xf->dev = -1;
- return -1;
- }
- return 0;
}
--- a/sys/src/cmd/dossrv/dosfs.c
+++ b/sys/src/cmd/dossrv/dosfs.c
@@ -138,7 +138,7 @@
if(isroot(dp->addr))
f->qid.path = f->xf->rootqid.path;
else
- f->qid.path = QIDPATH(dp);
+ f->qid.path = QIDPATH(dp, f->xf);
}
}else{
fixname(req->wname[rep->nwqid]);
@@ -155,7 +155,7 @@
if(r < 0)
goto error;
memmove(f->ptr, dp, sizeof(Dosptr));
- f->qid.path = QIDPATH(dp);
+ f->qid.path = QIDPATH(dp, f->xf);
f->qid.type = QTFILE;
if(isroot(dp->addr))
f->qid.path = f->xf->rootqid.path;
@@ -457,7 +457,7 @@
*/
f->ptr = ndp;
f->qid.type = QTFILE;
- f->qid.path = QIDPATH(ndp);
+ f->qid.path = QIDPATH(ndp, f->xf);
//ZZZ set type for excl, append?
if(req->perm & DMDIR){
@@ -567,7 +567,7 @@
}
if(prevdo < 0 && dp->prevaddr != -1){
p = getsect(xf, dp->prevaddr);
- for(prevdo = ((Dosbpb*)xf->ptr)->sectsize-DOSDIRSIZE; prevdo >= 0; prevdo -= DOSDIRSIZE){
+ for(prevdo = xf->sectsize-DOSDIRSIZE; prevdo >= 0; prevdo -= DOSDIRSIZE){
if(p->iobuf[prevdo+11] != 0xf)
break;
p->iobuf[prevdo] = DOSEMPTY;
@@ -636,17 +636,17 @@
static int
dostat(Xfile *f, Dir *d)
{
- Dosptr *dp;
+ Xfs *xf = f->xf;
+ Dosptr *dp = f->ptr;
Iosect *p;
char *name, namebuf[DOSNAMELEN];
int islong, sum, prevdo;
- dp = f->ptr;
if(isroot(dp->addr)){
memset(d, 0, sizeof(Dir));
d->name = "/";
d->qid.type = QTDIR;
- d->qid.path = f->xf->rootqid.path;
+ d->qid.path = xf->rootqid.path;
d->mode = DMDIR|0777;
d->uid = "bill";
d->muid = "bill";
@@ -664,10 +664,10 @@
name = getnamesect(namebuf, name, &dp->p->iobuf[prevdo], &islong, &sum, -1);
}
if(prevdo < 0 && dp->prevaddr != -1){
- p = getsect(f->xf, dp->prevaddr);
+ p = getsect(xf, dp->prevaddr);
if(p == nil)
return -1;
- for(prevdo = ((Dosbpb*)f->xf->ptr)->sectsize-DOSDIRSIZE; prevdo >= 0; prevdo -= DOSDIRSIZE){
+ for(prevdo = xf->sectsize-DOSDIRSIZE; prevdo >= 0; prevdo -= DOSDIRSIZE){
if(p->iobuf[prevdo+11] != 0xf)
break;
name = getnamesect(namebuf, name, &p->iobuf[prevdo], &islong, &sum, -1);
@@ -674,7 +674,7 @@
}
putsect(p);
}
- getdir(f->xf, d, dp->d, dp->addr, dp->offset);
+ getdir(xf, d, dp->d, dp->addr, dp->offset);
if(islong && sum == -1 && nameok(namebuf))
strcpy(d->name, namebuf);
}
@@ -894,7 +894,7 @@
/*
* relocate up other fids to the same file, if it moved
*/
- f->qid.path = QIDPATH(dp);
+ f->qid.path = QIDPATH(dp, pf.xf);
if(oaddr != dp->addr || ooffset != dp->offset)
dosptrreloc(f, dp, oaddr, ooffset);
--- a/sys/src/cmd/dossrv/dossubs.c
+++ b/sys/src/cmd/dossrv/dossubs.c
@@ -39,9 +39,10 @@
int
dosfs(Xfs *xf)
{
- Iosect *p, *p1;
- Dosboot *b;
+ Iosect *p1;
Fatinfo *fi;
+ uchar buf[512];
+ Dosboot *b;
Dosboot32 *b32;
Dosbpb *bp;
long fisec, extflags;
@@ -72,22 +73,28 @@
isdos['&'] = 1;
}
- p = getsect(xf, 0);
- if(p == nil)
+ /* don't use getsect() before we we determinted real values */
+ xf->sectsize = 512;
+ xf->sect2trk = 9;
+ devread(xf, 0, buf, sizeof(buf));
+
+ if(!isdosfs(buf))
return -1;
- b = (Dosboot*)p->iobuf;
- if(b->clustsize == 0 || isdosfs(p->iobuf) == 0){
- putsect(p);
+ b = (Dosboot*)buf;
+
+ xf->sectsize = GSHORT(b->sectsize);
+ if(xf->sectsize < 32)
return -1;
- }
+ xf->sect2trk = GSHORT(b->trksize);
+ if(xf->sect2trk < 1)
+ return -1;
+
bp = malloc(sizeof(Dosbpb));
memset(bp, 0, sizeof(Dosbpb)); /* clear lock */
xf->ptr = bp;
xf->fmt = 1;
-
- bp->sectsize = GSHORT(b->sectsize);
bp->clustsize = b->clustsize;
bp->nresrv = GSHORT(b->nresrv);
bp->nfats = b->nfats;
@@ -102,13 +109,12 @@
bp->fatinfo = 0;
if(bp->fatsize == 0){ /* is FAT32 */
+ b32 = (Dosboot32*)buf;
if(chatty)
- bootsecdump32(2, xf, (Dosboot32*)b);
+ bootsecdump32(2, xf, b32);
xf->isfat32 = 1;
- b32 = (Dosboot32*)b;
bp->fatsize = GLONG(b32->fatsize32);
if(bp->fatsize == 0){
- putsect(p);
if(chatty)
fprint(2, "fatsize 0\n");
return -1;
@@ -155,7 +161,7 @@
bootdump(2, b);
bp->rootaddr = bp->fataddr + bp->nfats*bp->fatsize;
bp->rootstart = 0;
- bp->dataaddr = bp->rootaddr + (bp->rootsize*DOSDIRSIZE + bp->sectsize-1)/bp->sectsize;
+ bp->dataaddr = bp->rootaddr + (bp->rootsize*DOSDIRSIZE + xf->sectsize-1)/xf->sectsize;
bp->freeptr = FATRESRV;
}
bp->fatclusters = FATRESRV + (bp->volsize - bp->dataaddr)/bp->clustsize;
@@ -172,7 +178,6 @@
chat("fat %d: %lld...", i, bp->fataddr+i*bp->fatsize);
chat("root: %lld...", bp->rootaddr);
chat("data: %lld...", bp->dataaddr);
- putsect(p);
return 0;
}
@@ -215,8 +220,8 @@
*/
dp->d = nil;
if(!isroot(dp->addr)){
- if(f->qid.path != QIDPATH(dp)){
- chat("qid mismatch f=%#llux d=%#llux...", f->qid.path, QIDPATH(dp));
+ if(f->qid.path != QIDPATH(dp, f->xf)){
+ chat("qid mismatch f=%#llux d=%#llux...", f->qid.path, QIDPATH(dp, f->xf));
putsect(p);
errno = Enonexist;
return -1;
@@ -265,33 +270,29 @@
long
fileclust(Xfile *f, long iclust, int cflag)
{
- Dosbpb *bp;
- Dosptr *dp;
- Dosdir *d;
- long start, clust, nskip, next;
+ Xfs *xf = f->xf;
+ Dosbpb *bp = xf->ptr;
+ Dosptr *dp = f->ptr;
+ Dosdir *d = dp->d;
+ long start, clust, nskip, next = 0;
- bp = f->xf->ptr;
- dp = f->ptr;
- d = dp->d;
- next = 0;
-
/*
* asking for the cluster of the root directory
* is not a well-formed question, since the root directory
* does not begin on a cluster boundary.
*/
- if(!f->xf->isfat32 && isroot(dp->addr))
+ if(!xf->isfat32 && isroot(dp->addr))
return -1;
- if(f->xf->isfat32 && isroot(dp->addr)){
+ if(xf->isfat32 && isroot(dp->addr)){
start = bp->rootstart;
}else{
- start = getstart(f->xf, d);
+ start = getstart(xf, d);
if(start == 0){
if(!cflag)
return -1;
mlock(bp);
- start = falloc(f->xf);
+ start = falloc(xf);
unmlock(bp);
if(start <= 0)
return -1;
@@ -315,7 +316,7 @@
if(nskip > 0){
mlock(bp);
while(--nskip >= 0){
- next = getfat(f->xf, clust);
+ next = getfat(xf, clust);
if(chatty > 1)
chat("->%#lx", next);
if(next > 0){
@@ -329,10 +330,10 @@
break;
/* cfalloc will call putfat for us, since clust may change */
} else {
- next = falloc(f->xf);
+ next = falloc(xf);
if(next < 0)
break;
- putfat(f->xf, clust, next);
+ putfat(xf, clust, next);
}
clust = next;
}
@@ -353,14 +354,15 @@
vlong
fileaddr(Xfile *f, long isect, int cflag)
{
+ Xfs *xf = f->xf;
Dosbpb *bp;
Dosptr *dp;
long clust;
- bp = f->xf->ptr;
+ bp = xf->ptr;
dp = f->ptr;
if(!f->xf->isfat32 && isroot(dp->addr)){
- if(isect*bp->sectsize >= bp->rootsize*DOSDIRSIZE)
+ if(isect*xf->sectsize >= bp->rootsize*DOSDIRSIZE)
return -1;
return bp->rootaddr + isect;
}
@@ -512,7 +514,6 @@
{
Xfs *xf;
Iosect *p;
- Dosbpb *bp;
Dosdir *d;
char buf[261], *bname;
int isect, o, o1, islong, have, need, sum;
@@ -519,7 +520,6 @@
vlong addr, addr1, addr2, prevaddr, prevaddr1;
xf = f->xf;
- bp = xf->ptr;
addr1 = -1;
addr2 = -1;
prevaddr1 = -1;
@@ -548,7 +548,7 @@
p = getsect(xf, addr);
if(p == nil)
break;
- for(o=0; o<bp->sectsize; o+=DOSDIRSIZE){
+ for(o=0; o<xf->sectsize; o+=DOSDIRSIZE){
d = (Dosdir *)&p->iobuf[o];
if(d->name[0] == 0x00){
chat("end dir(0)...");
@@ -569,7 +569,7 @@
prevaddr1 = prevaddr;
o1 = o;
}
- if(addr2 < 0 && (bp->sectsize-o)/DOSDIRSIZE + have < need){
+ if(addr2 < 0 && (xf->sectsize-o)/DOSDIRSIZE + have < need){
addr2 = fileaddr(f, isect+1, cflag);
if(addr2 < 0)
goto breakout;
@@ -641,7 +641,6 @@
emptydir(Xfile *f)
{
Xfs *xf = f->xf;
- Dosbpb *bp = xf->ptr;
int isect, o;
vlong addr;
Iosect *p;
@@ -654,7 +653,7 @@
p = getsect(xf, addr);
if(p == nil)
return -1;
- for(o=0; o<bp->sectsize; o+=DOSDIRSIZE){
+ for(o=0; o<xf->sectsize; o+=DOSDIRSIZE){
d = (Dosdir *)&p->iobuf[o];
if(d->name[0] == 0x00){
putsect(p);
@@ -678,7 +677,6 @@
readdir(Xfile *f, void *vbuf, vlong offset, long count)
{
Xfs *xf;
- Dosbpb *bp;
Dir dir;
int isect, o, islong, sum;
vlong addr;
@@ -691,7 +689,6 @@
buf = vbuf;
rcnt = 0;
xf = f->xf;
- bp = xf->ptr;
if(count <= 0)
return 0;
islong = 0;
@@ -704,7 +701,7 @@
p = getsect(xf, addr);
if(p == nil)
return -1;
- for(o=0; o<bp->sectsize; o+=DOSDIRSIZE){
+ for(o=0; o<xf->sectsize; o+=DOSDIRSIZE){
d = (Dosdir *)&p->iobuf[o];
if(d->name[0] == 0x00){
putsect(p);
@@ -763,15 +760,14 @@
int
walkup(Xfile *f, Dosptr *ndp)
{
- Dosbpb *bp;
- Dosptr *dp;
+ Xfs *xf = f->xf;
+ Dosbpb *bp = xf->ptr;
+ Dosptr *dp = f->ptr;
Dosdir *xd;
Iosect *p;
long o, so, start, pstart, ppstart, st, ppclust;
vlong k;
- bp = f->xf->ptr;
- dp = f->ptr;
memset(ndp, 0, sizeof(Dosptr));
ndp->prevaddr = -1;
ndp->naddr = -1;
@@ -789,12 +785,12 @@
/*
* find the start of our parent's directory
*/
- p = getsect(f->xf, dp->paddr);
+ p = getsect(xf, dp->paddr);
if(p == nil)
goto error;
xd = (Dosdir *)&p->iobuf[dp->poffset];
dirdump(xd);
- start = getstart(f->xf, xd);
+ start = getstart(xf, xd);
chat("start=%#lx...", start);
if(start == 0)
goto error;
@@ -808,7 +804,7 @@
goto error;
xd = (Dosdir *)p->iobuf;
dirdump(xd);
- st = getstart(f->xf, xd);
+ st = getstart(xf, xd);
if(xd->name[0]!='.' || xd->name[1]!=' ' || start!=st)
goto error;
@@ -819,19 +815,19 @@
dirdump(xd);
if(xd->name[0] != '.' || xd->name[1] != '.')
goto error;
- pstart = getstart(f->xf, xd);
+ pstart = getstart(xf, xd);
putsect(p);
/*
* we're done if parent is root
*/
- if(pstart == 0 || f->xf->isfat32 && pstart == bp->rootstart)
+ if(pstart == 0 || xf->isfat32 && pstart == bp->rootstart)
return 0;
/*
* verify that parent's . points to itself
*/
- p = getsect(f->xf, clust2sect(bp, pstart));
+ p = getsect(xf, clust2sect(bp, pstart));
if(p == nil){
chat("getsect %ld failed\n", pstart);
goto error;
@@ -838,7 +834,7 @@
}
xd = (Dosdir *)p->iobuf;
dirdump(xd);
- st = getstart(f->xf, xd);
+ st = getstart(xf, xd);
if(xd->name[0]!='.' || xd->name[1]!=' ' || pstart!=st)
goto error;
@@ -849,7 +845,7 @@
dirdump(xd);
if(xd->name[0] != '.' || xd->name[1] != '.')
goto error;
- ppstart = getstart(f->xf, xd);
+ ppstart = getstart(xf, xd);
putsect(p);
/*
@@ -857,12 +853,12 @@
* need this to find parent's parent's addr and offset
*/
ppclust = ppstart;
- if(f->xf->isfat32 && ppclust == 0){
+ if(xf->isfat32 && ppclust == 0){
ppclust = bp->rootstart;
chat("ppclust 0, resetting to rootstart\n");
}
k = ppclust ? clust2sect(bp, ppclust) : bp->rootaddr;
- p = getsect(f->xf, k);
+ p = getsect(xf, k);
if(p == nil){
chat("getsect %lld failed\n", k);
goto error;
@@ -870,12 +866,12 @@
xd = (Dosdir *)p->iobuf;
dirdump(xd);
if(ppstart){
- st = getstart(f->xf, xd);
+ st = getstart(xf, xd);
if(xd->name[0]!='.' || xd->name[1]!=' ' || ppstart!=st)
goto error;
}
for(so=1;; so++){
- for(o=0; o<bp->sectsize; o+=DOSDIRSIZE){
+ for(o=0; o<xf->sectsize; o+=DOSDIRSIZE){
xd = (Dosdir *)&p->iobuf[o];
if(xd->name[0] == 0x00){
chat("end dir\n");
@@ -883,7 +879,7 @@
}
if(xd->name[0] == DOSEMPTY)
continue;
- st = getstart(f->xf, xd);
+ st = getstart(xf, xd);
if(st == pstart)
goto out;
}
@@ -890,7 +886,7 @@
if(ppclust){
if(so%bp->clustsize == 0){
mlock(bp);
- ppclust = getfat(f->xf, ppclust);
+ ppclust = getfat(xf, ppclust);
unmlock(bp);
if(ppclust < 0){
chat("getfat %ld failed\n", ppclust);
@@ -899,12 +895,12 @@
}
k = clust2sect(bp, ppclust) + so%bp->clustsize;
}else{
- if(so*bp->sectsize >= bp->rootsize*DOSDIRSIZE)
+ if(so*xf->sectsize >= bp->rootsize*DOSDIRSIZE)
goto error;
k = bp->rootaddr + so;
}
putsect(p);
- p = getsect(f->xf, k);
+ p = getsect(xf, k);
if(p == nil){
chat("getsect %lld failed\n", k);
goto error;
@@ -926,7 +922,6 @@
readfile(Xfile *f, void *vbuf, vlong offset, long count)
{
Xfs *xf = f->xf;
- Dosbpb *bp = xf->ptr;
Dosptr *dp = f->ptr;
Dosdir *d = dp->d;
int isect, o, c;
@@ -947,13 +942,13 @@
return 0;
if(offset+count >= length)
count = length - offset;
- isect = offset/bp->sectsize;
- o = offset%bp->sectsize;
+ isect = offset/xf->sectsize;
+ o = offset%xf->sectsize;
while(count > 0){
addr = fileaddr(f, isect++, 0);
if(addr < 0)
break;
- c = bp->sectsize - o;
+ c = xf->sectsize - o;
if(c > count)
c = count;
p = getsect(xf, addr);
@@ -989,16 +984,16 @@
rcnt = 0;
addr = 0;
buf = vbuf;
- isect = offset/bp->sectsize;
- o = offset%bp->sectsize;
+ isect = offset/xf->sectsize;
+ o = offset%xf->sectsize;
while(count > 0){
addr = fileaddr(f, isect++, 1);
if(addr < 0)
break;
- c = bp->sectsize - o;
+ c = xf->sectsize - o;
if(c > count)
c = count;
- if(c == bp->sectsize){
+ if(c == xf->sectsize){
p = getosect(xf, addr);
p->flags = 0;
}else{
@@ -1020,7 +1015,7 @@
if(rcnt > 0)
length = offset+rcnt;
else if(dp->addr && dp->clust){
- c = bp->clustsize*bp->sectsize;
+ c = bp->clustsize*xf->sectsize;
if(dp->iclust > (dlen+c-1)/c)
length = (ulong)c*dp->iclust;
}
@@ -1045,18 +1040,18 @@
return -1;
mlock(bp);
- clust = getstart(f->xf, d);
+ clust = getstart(xf, d);
n = length;
if(n <= 0)
- putstart(f->xf, d, 0);
+ putstart(xf, d, 0);
else
- n -= bp->sectsize;
+ n -= xf->sectsize;
while(clust > 0){
next = getfat(xf, clust);
if(n <= 0)
putfat(xf, clust, 0);
else
- n -= bp->clustsize*bp->sectsize;
+ n -= bp->clustsize*xf->sectsize;
clust = next;
}
unmlock(bp);
@@ -1089,7 +1084,7 @@
* creation and access dates
*/
void
-getdir(Xfs *xfs, Dir *dp, Dosdir *d, vlong addr, int offset)
+getdir(Xfs *xf, Dir *dp, Dosdir *d, vlong addr, int offset)
{
if(d == nil || addr == 0)
panic("getdir on root");
@@ -1097,7 +1092,7 @@
dp->dev = 0;
getname(dp->name, d);
- dp->qid.path = addr*(Sectorsize/DOSDIRSIZE) +
+ dp->qid.path = addr*(xf->sectsize/DOSDIRSIZE) +
offset/DOSDIRSIZE;
dp->qid.vers = 0;
@@ -1116,7 +1111,7 @@
dp->length = GLONG(d->length);
if(d->attr & DSYSTEM){
dp->mode |= DMEXCL;
- if(iscontig(xfs, d))
+ if(iscontig(xf, d))
dp->mode |= DMAPPEND;
}
@@ -1308,7 +1303,6 @@
int
putlongname(Xfs *xf, Dosptr *ndp, char *name, char sname[13])
{
- Dosbpb *bp;
Dosdir tmpd;
Rune longname[DOSNAMELEN+1];
int i, first, sum, nds, len;
@@ -1317,7 +1311,6 @@
putname(sname, &tmpd);
sum = aliassum(&tmpd);
- bp = xf->ptr;
first = 1;
len = utftorunes(longname, name, DOSNAMELEN);
if(chatty){
@@ -1330,7 +1323,7 @@
putnamesect(&ndp->p->iobuf[ndp->offset], longname, nds, first, sum);
first = 0;
ndp->offset += 32;
- if(ndp->offset == bp->sectsize){
+ if(ndp->offset == xf->sectsize){
chat("long name moving over sector boundary\n");
ndp->p->flags |= BMOD;
putsect(ndp->p);
@@ -1368,15 +1361,15 @@
return -1;
fb = bp->fatbits;
k = (fb * n) >> 3;
- if(k >= bp->fatsize*bp->sectsize)
+ if(k >= bp->fatsize*xf->sectsize)
panic("getfat");
- sect = k/bp->sectsize + bp->fataddr;
- o = k%bp->sectsize;
+ sect = k/xf->sectsize + bp->fataddr;
+ o = k%xf->sectsize;
p = getsect(xf, sect);
if(p == nil)
return -1;
k = p->iobuf[o++];
- if(o >= bp->sectsize){
+ if(o >= xf->sectsize){
putsect(p);
p = getsect(xf, sect+1);
if(p == nil)
@@ -1426,12 +1419,12 @@
if(n < FATRESRV || n >= bp->fatclusters)
panic("putfat n=%d", n);
k = (bp->fatbits * n) >> 3;
- if(k >= bp->fatsize*bp->sectsize)
+ if(k >= bp->fatsize*xf->sectsize)
panic("putfat");
- sect = k/bp->sectsize + bp->fataddr;
+ sect = k/xf->sectsize + bp->fataddr;
esect = sect + bp->nfats * bp->fatsize;
for(; sect<esect; sect+=bp->fatsize){
- o = k%bp->sectsize;
+ o = k%xf->sectsize;
p = getsect(xf, sect);
if(p == nil)
continue;
@@ -1440,7 +1433,7 @@
if(n&1){
p->iobuf[o] &= 0x0f;
p->iobuf[o++] |= val<<4;
- if(o >= bp->sectsize){
+ if(o >= xf->sectsize){
p->flags |= BMOD;
putsect(p);
p = getsect(xf, sect+1);
@@ -1451,7 +1444,7 @@
p->iobuf[o] = val>>4;
}else{
p->iobuf[o++] = val;
- if(o >= bp->sectsize){
+ if(o >= xf->sectsize){
p->flags |= BMOD;
putsect(p);
p = getsect(xf, sect+1);
@@ -1633,7 +1626,7 @@
return -1;
wp = getosect(xf, ws);
assert(wp != nil);
- memmove(wp->iobuf, rp->iobuf, bp->sectsize);
+ memmove(wp->iobuf, rp->iobuf, xf->sectsize);
wp->flags = BMOD;
putsect(rp);
putsect(wp);
@@ -1702,7 +1695,7 @@
k = clust2sect(bp, n);
for(i=0; i<bp->clustsize; i++){
p = getosect(xf, k+i);
- memset(p->iobuf, 0, bp->sectsize);
+ memset(p->iobuf, 0, xf->sectsize);
p->flags = BMOD;
putsect(p);
}
--- a/sys/src/cmd/dossrv/iotrack.c
+++ b/sys/src/cmd/dossrv/iotrack.c
@@ -4,6 +4,9 @@
#include "dat.h"
#include "fns.h"
+static MLock freelock;
+static Iosect * freelist;
+
#define HIOB 31 /* a prime */
#define NIOBUF 80
@@ -19,6 +22,10 @@
#define TOFRONT(h, p) ((h)->next != (p) && (UNLINK(p, next, prev), LINK(h,p, next, prev)))
+static Iotrack *getiotrack(Xfs*, vlong);
+static Iosect *getiosect(Xfs*, vlong, int);
+static void purgetrack(Iotrack*);
+
Iosect *
getsect(Xfs *xf, vlong addr)
{
@@ -31,19 +38,21 @@
return getiosect(xf, addr, 0);
}
-Iosect *
+static Iosect *
getiosect(Xfs *xf, vlong addr, int rflag)
{
- Iotrack *t;
vlong taddr;
int toff;
+ Iotrack *t;
Iosect *p;
if(addr < 0)
return nil;
- toff = addr % Sect2trk;
+ toff = addr % xf->sect2trk;
taddr = addr - toff;
t = getiotrack(xf, taddr);
+ if(t == nil)
+ return nil;
if(rflag && (t->flags&BSTALE)){
if(tread(t) < 0){
unmlock(&t->lock);
@@ -51,16 +60,31 @@
}
t->flags &= ~BSTALE;
}
- t->ref++;
- p = t->tp->p[toff];
- if(p == 0){
- p = newsect();
- t->tp->p[toff] = p;
+ p = t->tp[toff];
+ if(p == nil){
+ mlock(&freelock);
+ p = freelist;
+ if(p != nil)
+ freelist = p->next;
+ else {
+ p = malloc(sizeof(Iosect));
+ if(p == nil) {
+ unmlock(&freelock);
+ unmlock(&t->lock);
+ return nil;
+ }
+ }
+ p->next = nil;
+ unmlock(&freelock);
+
p->flags = t->flags&BSTALE;
p->lock.key = 0;
+ p->iobuf = ((uchar*)&t->tp[xf->sect2trk]) + toff*xf->sectsize;
p->t = t;
- p->iobuf = t->tp->buf[toff];
+
+ t->tp[toff] = p;
}
+ t->ref++;
unmlock(&t->lock);
mlock(&p->lock);
return p;
@@ -87,7 +111,7 @@
unmlock(&p->lock);
}
-Iotrack *
+static Iotrack *
getiotrack(Xfs *xf, vlong addr)
{
Iotrack *hp, *p;
@@ -142,8 +166,14 @@
goto loop;
}
purgetrack(p);
- p->addr = addr;
+ p->tp = malloc(xf->sect2trk*sizeof(Iosect*) + xf->sect2trk*xf->sectsize);
+ if(p->tp == nil){
+ unmlock(&p->lock);
+ return nil;
+ }
+ memset(p->tp, 0, xf->sect2trk*sizeof(Iosect*));
p->xf = xf;
+ p->addr = addr;
p->flags = BSTALE;
out:
mlock(&hp->lock);
@@ -155,39 +185,55 @@
return p;
}
-void
+static void
purgetrack(Iotrack *t)
{
- int i, ref = Sect2trk;
- Iosect *p;
+ if(t->tp != nil){
+ Xfs *xf = t->xf;
+ int i, ref = xf->sect2trk;
- for(i=0; i<Sect2trk; i++){
- p = t->tp->p[i];
- if(p == 0){
- --ref;
- continue;
+ for(i=0; i<xf->sect2trk; i++){
+ Iosect *p = t->tp[i];
+ if(p == nil){
+ --ref;
+ continue;
+ }
+ if(canmlock(&p->lock)){
+ t->tp[i] = nil;
+
+ mlock(&freelock);
+ p->next = freelist;
+ freelist = p;
+ unmlock(&freelock);
+ --ref;
+ }
}
- if(canmlock(&p->lock)){
- freesect(p);
- --ref;
- t->tp->p[i] = 0;
- }
+ if(t->ref != ref)
+ panic("purgetrack");
+ if(ref != 0)
+ return;
+
+ free(t->tp);
}
- if(t->ref != ref)
- panic("purgetrack");
+ assert(t->ref == 0);
+ t->tp = nil;
+ t->xf = nil;
+ t->addr = -1;
+ t->flags = 0;
}
int
twrite(Iotrack *t)
{
- int i, ref;
+ Xfs *xf = t->xf;
- chat("[twrite %lld...", t->addr);
+ chat("[twrite %lld+%lld...", t->addr, xf->offset);
if(t->flags & BSTALE){
- for(ref=0,i=0; i<Sect2trk; i++)
- if(t->tp->p[i])
+ int i, ref = 0;
+ for(i=0; i<xf->sect2trk; i++)
+ if(t->tp[i] != nil)
++ref;
- if(ref < Sect2trk){
+ if(ref < xf->sect2trk){
if(tread(t) < 0){
chat("error]");
return -1;
@@ -195,7 +241,7 @@
}else
t->flags &= ~BSTALE;
}
- if(devwrite(t->xf, t->addr, t->tp->buf, Trksize) < 0){
+ if(devwrite(xf, t->addr, (uchar*)&t->tp[xf->sect2trk], xf->sect2trk*xf->sectsize) < 0){
chat("error]");
return -1;
}
@@ -206,33 +252,31 @@
int
tread(Iotrack *t)
{
+ Xfs *xf = t->xf;
int i, ref = 0;
- uchar buf[Sect2trk][Sectorsize];
- for(i=0; i<Sect2trk; i++)
- if(t->tp->p[i])
+ chat("[tread %lld+%lld...", t->addr, xf->offset);
+ for(i=0; i<xf->sect2trk; i++)
+ if(t->tp[i] != nil)
++ref;
- chat("[tread %lld+%lld...", t->addr, t->xf->offset);
if(ref == 0){
- if(devread(t->xf, t->addr, t->tp->buf, Trksize) < 0){
+ if(devread(xf, t->addr, (uchar*)&t->tp[xf->sect2trk], xf->sect2trk*xf->sectsize) < 0){
chat("error]");
return -1;
}
- chat("done]");
- t->flags &= ~BSTALE;
- return 0;
- }
- if(devread(t->xf, t->addr, buf, Trksize) < 0){
- chat("error]");
- return -1;
- }
- for(i=0; i<Sect2trk; i++)
- if(t->tp->p[i] == 0){
- memmove(t->tp->buf[i], buf[i], Sectorsize);
+ } else {
+ for(i=0; i<xf->sect2trk; i++){
+ if(t->tp[i] != nil)
+ continue;
+ if(devread(xf, t->addr + i, ((uchar*)&t->tp[xf->sect2trk]) + i*xf->sectsize, xf->sectsize) < 0){
+ chat("error]");
+ return -1;
+ }
chat("%d ", i);
}
- chat("done]");
+ }
t->flags &= ~BSTALE;
+ chat("done]");
return 0;
}
@@ -285,34 +329,6 @@
p->hprev = p->hnext = p;
p->prev = p->next = p;
TOFRONT(mp, p);
- p->tp = sbrk(sizeof(Track));
- memset(p->tp->p, 0, sizeof p->tp->p);
+ purgetrack(p);
}
-}
-
-static MLock freelock;
-static Iosect * freelist;
-
-Iosect *
-newsect(void)
-{
- Iosect *p;
-
- mlock(&freelock);
- if(p = freelist) /* assign = */
- freelist = p->next;
- else
- p = malloc(sizeof(Iosect));
- unmlock(&freelock);
- p->next = 0;
- return p;
-}
-
-void
-freesect(Iosect *p)
-{
- mlock(&freelock);
- p->next = freelist;
- freelist = p;
- unmlock(&freelock);
}
--- a/sys/src/cmd/dossrv/iotrack.h
+++ b/sys/src/cmd/dossrv/iotrack.h
@@ -1,7 +1,6 @@
typedef struct MLock MLock;
typedef struct Iosect Iosect;
typedef struct Iotrack Iotrack;
-typedef struct Track Track;
typedef struct Xfs Xfs;
struct MLock
@@ -29,41 +28,23 @@
Iotrack *hprev;
MLock lock;
int ref;
- Track *tp;
+ Iosect **tp;
};
-enum{
- Sectorsize = 512,
- Sect2trk = 9,
- Trksize = Sectorsize*Sect2trk
-};
-
-struct Track
-{
- Iosect *p[Sect2trk];
- uchar buf[Sect2trk][Sectorsize];
-};
-
#define BMOD (1<<0)
#define BIMM (1<<1)
#define BSTALE (1<<2)
-Iosect* getiosect(Xfs*, vlong, int);
Iosect* getosect(Xfs*, vlong);
Iosect* getsect(Xfs*, vlong);
-Iosect* newsect(void);
-Iotrack* getiotrack(Xfs*, vlong);
int canmlock(MLock*);
-int devcheck(Xfs*);
int devread(Xfs*, vlong, void*, long);
int devwrite(Xfs*, vlong, void*, long);
int tread(Iotrack*);
int twrite(Iotrack*);
-void freesect(Iosect*);
void iotrack_init(void);
void mlock(MLock*);
void purgebuf(Xfs*);
-void purgetrack(Iotrack*);
void putsect(Iosect*);
void sync(void);
void unmlock(MLock*);
--- a/sys/src/cmd/dossrv/xfile.c
+++ b/sys/src/cmd/dossrv/xfile.c
@@ -44,7 +44,8 @@
errno = Enofilsys;
return 0;
}
- offset *= Sectorsize;
+ /* FIXME: should probably use devices sector size? */
+ offset *= 512;
}
if(readonly)
@@ -83,8 +84,6 @@
continue;
if(strcmp(xf->name, name) != 0 || xf->dev < 0)
continue;
- if(devcheck(xf) < 0) /* look for media change */
- continue;
if(offset && xf->offset != offset)
continue;
chat("incref \"%s\", dev=%d...", xf->name, xf->dev);
@@ -239,7 +238,7 @@
memmove(xdp, dp, sizeof(Dosptr));
xdp->p = nil;
xdp->d = nil;
- p->qid.path = QIDPATH(xdp);
+ p->qid.path = QIDPATH(xdp, f->xf);
}
}
}