summaryrefslogtreecommitdiff
path: root/sys/src/cmd
diff options
context:
space:
mode:
authorcinap_lenrek <cinap_lenrek@felloff.net>2023-04-30 18:44:29 +0000
committercinap_lenrek <cinap_lenrek@felloff.net>2023-04-30 18:44:29 +0000
commitd24b5a7a0e45186f13d19ddefde62b0932726e42 (patch)
treea3cfeee8dd915bbd60e9f6be96c7318f81e1dfd1 /sys/src/cmd
parent101b3c2724779fcb0e503ae274abd7b751a3a48f (diff)
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.
Diffstat (limited to 'sys/src/cmd')
-rw-r--r--sys/src/cmd/dossrv/dat.h5
-rw-r--r--sys/src/cmd/dossrv/devio.c23
-rw-r--r--sys/src/cmd/dossrv/dosfs.c22
-rw-r--r--sys/src/cmd/dossrv/dossubs.c181
-rw-r--r--sys/src/cmd/dossrv/iotrack.c174
-rw-r--r--sys/src/cmd/dossrv/iotrack.h21
-rw-r--r--sys/src/cmd/dossrv/xfile.c7
7 files changed, 204 insertions, 229 deletions
diff --git a/sys/src/cmd/dossrv/dat.h b/sys/src/cmd/dossrv/dat.h
index 80af491b0..7546d229f 100644
--- a/sys/src/cmd/dossrv/dat.h
+++ b/sys/src/cmd/dossrv/dat.h
@@ -118,7 +118,6 @@ struct Fatinfo
*/
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 @@ struct Dosptr{
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 @@ struct Xfs{
uchar isfat32; /* is a fat 32 file system? */
short dev;
short fmt;
+ int sectsize;
+ int sect2trk;
vlong offset;
void *ptr;
};
diff --git a/sys/src/cmd/dossrv/devio.c b/sys/src/cmd/dossrv/devio.c
index 5193bdafd..2caaaa064 100644
--- 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 @@ deverror(char *name, Xfs *xf, long addr, long n, long nret)
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 @@ devread(Xfs *xf, vlong addr, void *buf, long n)
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 @@ devwrite(Xfs *xf, vlong addr, void *buf, long n)
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;
-}
diff --git a/sys/src/cmd/dossrv/dosfs.c b/sys/src/cmd/dossrv/dosfs.c
index 72c94768e..3acd0ea33 100644
--- a/sys/src/cmd/dossrv/dosfs.c
+++ b/sys/src/cmd/dossrv/dosfs.c
@@ -138,7 +138,7 @@ rwalk(void)
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 @@ rwalk(void)
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 @@ badperm:
*/
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 @@ doremove(Xfs *xf, Dosptr *dp)
}
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 @@ out:
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,17 +664,17 @@ dostat(Xfile *f, Dir *d)
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);
}
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 @@ rwstat(void)
/*
* 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);
diff --git a/sys/src/cmd/dossrv/dossubs.c b/sys/src/cmd/dossrv/dossubs.c
index d77062554..eaabcd8bb 100644
--- a/sys/src/cmd/dossrv/dossubs.c
+++ b/sys/src/cmd/dossrv/dossubs.c
@@ -39,9 +39,10 @@ isdosfs(uchar *buf)
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 @@ dosfs(Xfs *xf)
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 @@ dosfs(Xfs *xf)
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 @@ dosfs(Xfs *xf)
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 @@ dosfs(Xfs *xf)
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 @@ getfile(Xfile *f)
*/
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 @@ putstart(Xfs *xf, Dosdir *d, long start)
long
fileclust(Xfile *f, long iclust, int cflag)
{
- Dosbpb *bp;
- Dosptr *dp;
- Dosdir *d;
- long start, clust, nskip, next;
-
- bp = f->xf->ptr;
- dp = f->ptr;
- d = dp->d;
- next = 0;
+ Xfs *xf = f->xf;
+ Dosbpb *bp = xf->ptr;
+ Dosptr *dp = f->ptr;
+ Dosdir *d = dp->d;
+ long start, clust, nskip, 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 @@ fileclust(Xfile *f, long iclust, int cflag)
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 @@ fileclust(Xfile *f, long iclust, int cflag)
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 @@ fileclust(Xfile *f, long iclust, int cflag)
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,14 +514,12 @@ searchdir(Xfile *f, char *name, Dosptr *dp, int cflag, int longtype)
{
Xfs *xf;
Iosect *p;
- Dosbpb *bp;
Dosdir *d;
char buf[261], *bname;
int isect, o, o1, islong, have, need, sum;
vlong addr, addr1, addr2, prevaddr, prevaddr1;
xf = f->xf;
- bp = xf->ptr;
addr1 = -1;
addr2 = -1;
prevaddr1 = -1;
@@ -548,7 +548,7 @@ searchdir(Xfile *f, char *name, Dosptr *dp, int cflag, int longtype)
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 @@ searchdir(Xfile *f, char *name, Dosptr *dp, int cflag, int longtype)
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 @@ int
emptydir(Xfile *f)
{
Xfs *xf = f->xf;
- Dosbpb *bp = xf->ptr;
int isect, o;
vlong addr;
Iosect *p;
@@ -654,7 +653,7 @@ emptydir(Xfile *f)
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 @@ long
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 @@ readdir(Xfile *f, void *vbuf, vlong offset, long count)
buf = vbuf;
rcnt = 0;
xf = f->xf;
- bp = xf->ptr;
if(count <= 0)
return 0;
islong = 0;
@@ -704,7 +701,7 @@ readdir(Xfile *f, void *vbuf, vlong offset, long count)
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 @@ readdir(Xfile *f, void *vbuf, vlong offset, long count)
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 @@ walkup(Xfile *f, Dosptr *ndp)
/*
* 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 @@ walkup(Xfile *f, Dosptr *ndp)
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,26 +815,26 @@ walkup(Xfile *f, Dosptr *ndp)
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;
}
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 @@ walkup(Xfile *f, Dosptr *ndp)
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 @@ walkup(Xfile *f, Dosptr *ndp)
* 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 @@ walkup(Xfile *f, Dosptr *ndp)
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,14 +879,14 @@ walkup(Xfile *f, Dosptr *ndp)
}
if(xd->name[0] == DOSEMPTY)
continue;
- st = getstart(f->xf, xd);
+ st = getstart(xf, xd);
if(st == pstart)
goto out;
}
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 @@ walkup(Xfile *f, Dosptr *ndp)
}
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 @@ long
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 @@ readfile(Xfile *f, void *vbuf, vlong offset, long count)
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 @@ writefile(Xfile *f, void *vbuf, vlong offset, long count)
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 @@ writefile(Xfile *f, void *vbuf, vlong offset, long count)
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 @@ truncfile(Xfile *f, vlong length)
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 @@ putdir(Dosdir *d, Dir *dp)
* 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 @@ getdir(Xfs *xfs, Dir *dp, Dosdir *d, vlong addr, int offset)
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 @@ getdir(Xfs *xfs, Dir *dp, Dosdir *d, vlong addr, int offset)
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 @@ aliassum(Dosdir *d)
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 @@ putlongname(Xfs *xf, Dosptr *ndp, char *name, char sname[13])
putname(sname, &tmpd);
sum = aliassum(&tmpd);
- bp = xf->ptr;
first = 1;
len = utftorunes(longname, name, DOSNAMELEN);
if(chatty){
@@ -1330,7 +1323,7 @@ putlongname(Xfs *xf, Dosptr *ndp, char *name, char sname[13])
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 @@ getfat(Xfs *xf, long n)
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 @@ putfat(Xfs *xf, int n, ulong val)
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 @@ putfat(Xfs *xf, int n, ulong val)
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 @@ putfat(Xfs *xf, int n, ulong val)
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 @@ makecontig(Xfile *f, int nextra)
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 @@ falloc(Xfs *xf)
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);
}
diff --git a/sys/src/cmd/dossrv/iotrack.c b/sys/src/cmd/dossrv/iotrack.c
index 6081a5509..f1833ae56 100644
--- 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 @@ static Iotrack iobuf[NIOBUF]; /* the real ones */
#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 @@ getosect(Xfs *xf, vlong addr)
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 @@ getiosect(Xfs *xf, vlong addr, int rflag)
}
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 @@ putsect(Iosect *p)
unmlock(&p->lock);
}
-Iotrack *
+static Iotrack *
getiotrack(Xfs *xf, vlong addr)
{
Iotrack *hp, *p;
@@ -142,8 +166,14 @@ loop:
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 @@ out:
return p;
}
-void
+static void
purgetrack(Iotrack *t)
{
- int i, ref = Sect2trk;
- Iosect *p;
-
- for(i=0; i<Sect2trk; i++){
- p = t->tp->p[i];
- if(p == 0){
- --ref;
- continue;
- }
- if(canmlock(&p->lock)){
- freesect(p);
- --ref;
- t->tp->p[i] = 0;
+ if(t->tp != nil){
+ Xfs *xf = t->xf;
+ int i, ref = xf->sect2trk;
+
+ 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(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 @@ twrite(Iotrack *t)
}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 @@ twrite(Iotrack *t)
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 @@ iotrack_init(void)
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);
-}
diff --git a/sys/src/cmd/dossrv/iotrack.h b/sys/src/cmd/dossrv/iotrack.h
index 921a75c3f..098677ab2 100644
--- 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 @@ struct Iotrack
Iotrack *hprev;
MLock lock;
int ref;
- Track *tp;
-};
-
-enum{
- Sectorsize = 512,
- Sect2trk = 9,
- Trksize = Sectorsize*Sect2trk
-};
-
-struct Track
-{
- Iosect *p[Sect2trk];
- uchar buf[Sect2trk][Sectorsize];
+ Iosect **tp;
};
#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*);
diff --git a/sys/src/cmd/dossrv/xfile.c b/sys/src/cmd/dossrv/xfile.c
index f734a7857..5a4c4c1f1 100644
--- a/sys/src/cmd/dossrv/xfile.c
+++ b/sys/src/cmd/dossrv/xfile.c
@@ -44,7 +44,8 @@ getxfs(char *user, char *name)
errno = Enofilsys;
return 0;
}
- offset *= Sectorsize;
+ /* FIXME: should probably use devices sector size? */
+ offset *= 512;
}
if(readonly)
@@ -83,8 +84,6 @@ getxfs(char *user, char *name)
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 @@ dosptrreloc(Xfile *f, Dosptr *dp, vlong addr, ulong offset)
memmove(xdp, dp, sizeof(Dosptr));
xdp->p = nil;
xdp->d = nil;
- p->qid.path = QIDPATH(xdp);
+ p->qid.path = QIDPATH(xdp, f->xf);
}
}
}