merge
This commit is contained in:
commit
2330fdb537
4 changed files with 256 additions and 64 deletions
|
@ -235,7 +235,7 @@ dirgen(int off, Dir *d, void*)
|
||||||
for(p = tab; p < tab + nelem(tab); p++, n++){
|
for(p = tab; p < tab + nelem(tab); p++, n++){
|
||||||
if(!p->inuse)
|
if(!p->inuse)
|
||||||
continue;
|
continue;
|
||||||
if(n == off){
|
if(off-- == 0){
|
||||||
d->name = estrdup9p(p->name);
|
d->name = estrdup9p(p->name);
|
||||||
d->length = p->length*sectsize;
|
d->length = p->length*sectsize;
|
||||||
d->mode = p->mode;
|
d->mode = p->mode;
|
||||||
|
|
|
@ -20,7 +20,8 @@ enum
|
||||||
Qctl,
|
Qctl,
|
||||||
Qraw,
|
Qraw,
|
||||||
Qdata,
|
Qdata,
|
||||||
Qmax,
|
Qpart,
|
||||||
|
Qmax = Maxparts,
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct Dirtab Dirtab;
|
typedef struct Dirtab Dirtab;
|
||||||
|
@ -30,13 +31,156 @@ struct Dirtab
|
||||||
int mode;
|
int mode;
|
||||||
};
|
};
|
||||||
|
|
||||||
static Dirtab dirtab[] =
|
ulong ctlmode = 0664;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Partition management (adapted from disk/partfs)
|
||||||
|
*/
|
||||||
|
|
||||||
|
Part *
|
||||||
|
lookpart(Umsc *lun, char *name)
|
||||||
{
|
{
|
||||||
[Qdir] "/", DMDIR|0555,
|
Part *part, *p;
|
||||||
[Qctl] "ctl", 0664, /* nothing secret here */
|
|
||||||
[Qraw] "raw", 0640,
|
part = lun->part;
|
||||||
[Qdata] "data", 0640,
|
for(p=part; p < &part[Qmax]; p++){
|
||||||
};
|
if(p->inuse && strcmp(p->name, name) == 0)
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
Part *
|
||||||
|
freepart(Umsc *lun)
|
||||||
|
{
|
||||||
|
Part *part, *p;
|
||||||
|
|
||||||
|
part = lun->part;
|
||||||
|
for(p=part; p < &part[Qmax]; p++){
|
||||||
|
if(!p->inuse)
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
addpart(Umsc *lun, char *name, vlong start, vlong end, ulong mode)
|
||||||
|
{
|
||||||
|
Part *p;
|
||||||
|
|
||||||
|
if(start < 0 || start > end || end > lun->blocks){
|
||||||
|
werrstr("bad partition boundaries");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if(lookpart(lun, name) != nil) {
|
||||||
|
werrstr("partition name already in use");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
p = freepart(lun);
|
||||||
|
if(p == nil){
|
||||||
|
werrstr("no free partition slots");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
p->inuse = 1;
|
||||||
|
free(p->name);
|
||||||
|
p->id = p - lun->part;
|
||||||
|
p->name = estrdup(name);
|
||||||
|
p->offset = start;
|
||||||
|
p->length = end - start;
|
||||||
|
p->mode = mode;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
delpart(Umsc *lun, char *s)
|
||||||
|
{
|
||||||
|
Part *p;
|
||||||
|
|
||||||
|
p = lookpart(lun, s);
|
||||||
|
if(p == nil || p->id <= Qdata){
|
||||||
|
werrstr("partition not found");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
p->inuse = 0;
|
||||||
|
free(p->name);
|
||||||
|
p->name = nil;
|
||||||
|
p->vers++;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
makeparts(Umsc *lun)
|
||||||
|
{
|
||||||
|
addpart(lun, "/", 0, 0, DMDIR | 0555);
|
||||||
|
addpart(lun, "ctl", 0, 0, 0664);
|
||||||
|
addpart(lun, "raw", 0, 0, 0640);
|
||||||
|
addpart(lun, "data", 0, lun->blocks, 0640);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ctl parsing & formatting (adapted from partfs)
|
||||||
|
*/
|
||||||
|
|
||||||
|
static char*
|
||||||
|
ctlstring(Usbfs *fs)
|
||||||
|
{
|
||||||
|
Part *p, *part;
|
||||||
|
Fmt fmt;
|
||||||
|
Umsc *lun;
|
||||||
|
Ums *ums;
|
||||||
|
|
||||||
|
ums = fs->dev->aux;
|
||||||
|
lun = fs->aux;
|
||||||
|
part = &lun->part[0];
|
||||||
|
|
||||||
|
fmtstrinit(&fmt);
|
||||||
|
fmtprint(&fmt, "dev %s\n", fs->dev->dir);
|
||||||
|
fmtprint(&fmt, "lun %ld\n", lun - &ums->lun[0]);
|
||||||
|
if(lun->flags & Finqok)
|
||||||
|
fmtprint(&fmt, "inquiry %s\n", lun->inq);
|
||||||
|
if(lun->blocks > 0)
|
||||||
|
fmtprint(&fmt, "geometry %llud %ld\n", lun->blocks, lun->lbsize);
|
||||||
|
for (p = &part[Qdata+1]; p < &part[Qmax]; p++)
|
||||||
|
if (p->inuse)
|
||||||
|
fmtprint(&fmt, "part %s %lld %lld\n",
|
||||||
|
p->name, p->offset, p->length);
|
||||||
|
return fmtstrflush(&fmt);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
ctlparse(Usbfs *fs, char *msg)
|
||||||
|
{
|
||||||
|
vlong start, end;
|
||||||
|
char *argv[16];
|
||||||
|
int argc;
|
||||||
|
Umsc *lun;
|
||||||
|
|
||||||
|
lun = fs->aux;
|
||||||
|
argc = tokenize(msg, argv, nelem(argv));
|
||||||
|
|
||||||
|
if(argc < 1){
|
||||||
|
werrstr("empty control message");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(strcmp(argv[0], "part") == 0){
|
||||||
|
if(argc != 4){
|
||||||
|
werrstr("part takes 3 args");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
start = strtoll(argv[2], 0, 0);
|
||||||
|
end = strtoll(argv[3], 0, 0);
|
||||||
|
return addpart(lun, argv[1], start, end, 0640);
|
||||||
|
}else if(strcmp(argv[0], "delpart") == 0){
|
||||||
|
if(argc != 2){
|
||||||
|
werrstr("delpart takes 1 arg");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return delpart(lun, argv[1]);
|
||||||
|
}
|
||||||
|
werrstr("unknown ctl");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* These are used by scuzz scsireq
|
* These are used by scuzz scsireq
|
||||||
|
@ -152,6 +296,7 @@ umscapacity(Umsc *lun)
|
||||||
}
|
}
|
||||||
lun->blocks++; /* SRcapacity returns LBA of last block */
|
lun->blocks++; /* SRcapacity returns LBA of last block */
|
||||||
lun->capacity = (vlong)lun->blocks * lun->lbsize;
|
lun->capacity = (vlong)lun->blocks * lun->lbsize;
|
||||||
|
lun->part[Qdata].length = lun->blocks;
|
||||||
if(diskdebug)
|
if(diskdebug)
|
||||||
fprint(2, "disk: logical block size %lud, # blocks %llud\n",
|
fprint(2, "disk: logical block size %lud, # blocks %llud\n",
|
||||||
lun->lbsize, lun->blocks);
|
lun->lbsize, lun->blocks);
|
||||||
|
@ -329,59 +474,65 @@ Fail:
|
||||||
static int
|
static int
|
||||||
dwalk(Usbfs *fs, Fid *fid, char *name)
|
dwalk(Usbfs *fs, Fid *fid, char *name)
|
||||||
{
|
{
|
||||||
int i;
|
Umsc *lun;
|
||||||
Qid qid;
|
Part *p;
|
||||||
|
|
||||||
qid = fid->qid;
|
lun = fs->aux;
|
||||||
if((qid.type & QTDIR) == 0){
|
|
||||||
|
if((fid->qid.type & QTDIR) == 0){
|
||||||
werrstr("walk in non-directory");
|
werrstr("walk in non-directory");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(strcmp(name, "..") == 0)
|
if(strcmp(name, "..") == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
for(i = 1; i < nelem(dirtab); i++)
|
p = lookpart(lun, name);
|
||||||
if(strcmp(name, dirtab[i].name) == 0){
|
if(p == nil){
|
||||||
qid.path = i | fs->qid;
|
werrstr(Enotfound);
|
||||||
qid.vers = 0;
|
return -1;
|
||||||
qid.type = dirtab[i].mode >> 24;
|
}
|
||||||
fid->qid = qid;
|
fid->qid.path = p->id | fs->qid;
|
||||||
return 0;
|
fid->qid.vers = p->vers;
|
||||||
}
|
fid->qid.type = p->mode >> 24;
|
||||||
werrstr(Enotfound);
|
return 0;
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
static int
|
||||||
|
dstat(Usbfs *fs, Qid qid, Dir *d);
|
||||||
|
|
||||||
static void
|
static void
|
||||||
dostat(Usbfs *fs, int path, Dir *d)
|
dostat(Usbfs *fs, int path, Dir *d)
|
||||||
{
|
{
|
||||||
Dirtab *t;
|
|
||||||
Umsc *lun;
|
Umsc *lun;
|
||||||
|
Part *p;
|
||||||
|
|
||||||
t = &dirtab[path];
|
|
||||||
d->qid.path = path;
|
|
||||||
d->qid.type = t->mode >> 24;
|
|
||||||
d->mode = t->mode;
|
|
||||||
d->name = t->name;
|
|
||||||
lun = fs->aux;
|
lun = fs->aux;
|
||||||
if(path == Qdata)
|
p = &lun->part[path];
|
||||||
d->length = lun->capacity;
|
d->qid.path = path;
|
||||||
else
|
d->qid.vers = p->vers;
|
||||||
d->length = 0;
|
d->qid.type =p->mode >> 24;
|
||||||
|
d->mode = p->mode;
|
||||||
|
d->length = (vlong) p->length * lun->lbsize;
|
||||||
|
strecpy(d->name, d->name + Namesz - 1, p->name);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
dirgen(Usbfs *fs, Qid, int i, Dir *d, void*)
|
dirgen(Usbfs *fs, Qid, int n, Dir *d, void*)
|
||||||
{
|
{
|
||||||
i++; /* skip dir */
|
Umsc *lun;
|
||||||
if(i >= Qmax)
|
int i;
|
||||||
return -1;
|
|
||||||
else{
|
lun = fs->aux;
|
||||||
dostat(fs, i, d);
|
for(i = Qctl; i < Qmax; i++){
|
||||||
d->qid.path |= fs->qid;
|
if(lun->part[i].inuse == 0)
|
||||||
return 0;
|
continue;
|
||||||
|
if(n-- == 0)
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
if(i == Qmax)
|
||||||
|
return -1;
|
||||||
|
dostat(fs, i, d);
|
||||||
|
d->qid.path |= fs->qid;
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
@ -417,7 +568,7 @@ dopen(Usbfs *fs, Fid *fid, int)
|
||||||
* since we don't need general division nor its cost.
|
* since we don't need general division nor its cost.
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
setup(Umsc *lun, char *data, int count, vlong offset)
|
setup(Umsc *lun, Part *p, char *data, int count, vlong offset)
|
||||||
{
|
{
|
||||||
long nb, lbsize, lbshift, lbmask;
|
long nb, lbsize, lbshift, lbmask;
|
||||||
uvlong bno;
|
uvlong bno;
|
||||||
|
@ -432,13 +583,14 @@ setup(Umsc *lun, char *data, int count, vlong offset)
|
||||||
|
|
||||||
bno = offset >> lbshift; /* offset / lbsize */
|
bno = offset >> lbshift; /* offset / lbsize */
|
||||||
nb = ((offset + count + lbsize - 1) >> lbshift) - bno;
|
nb = ((offset + count + lbsize - 1) >> lbshift) - bno;
|
||||||
|
bno += p->offset; /* start of partition */
|
||||||
|
|
||||||
if(bno + nb > lun->blocks) /* past end of device? */
|
if(bno + nb > p->length) /* past end of partition? */
|
||||||
nb = lun->blocks - bno;
|
nb = p->length - bno;
|
||||||
if(nb * lbsize > Maxiosize)
|
if(nb * lbsize > Maxiosize)
|
||||||
nb = Maxiosize / lbsize;
|
nb = Maxiosize / lbsize;
|
||||||
lun->nb = nb;
|
lun->nb = nb;
|
||||||
if(bno >= lun->blocks || nb == 0)
|
if(bno >= p->length || nb == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
lun->offset = bno;
|
lun->offset = bno;
|
||||||
|
@ -461,8 +613,9 @@ dread(Usbfs *fs, Fid *fid, void *data, long count, vlong offset)
|
||||||
{
|
{
|
||||||
long n;
|
long n;
|
||||||
ulong path;
|
ulong path;
|
||||||
char buf[1024];
|
char buf[64];
|
||||||
char *s, *e;
|
char *s;
|
||||||
|
Part *p;
|
||||||
Umsc *lun;
|
Umsc *lun;
|
||||||
Ums *ums;
|
Ums *ums;
|
||||||
Qid q;
|
Qid q;
|
||||||
|
@ -478,15 +631,9 @@ dread(Usbfs *fs, Fid *fid, void *data, long count, vlong offset)
|
||||||
count = usbdirread(fs, q, data, count, offset, dirgen, nil);
|
count = usbdirread(fs, q, data, count, offset, dirgen, nil);
|
||||||
break;
|
break;
|
||||||
case Qctl:
|
case Qctl:
|
||||||
e = buf + sizeof(buf);
|
s = ctlstring(fs);
|
||||||
s = seprint(buf, e, "%s lun %ld: ", fs->dev->dir, lun - &ums->lun[0]);
|
count = usbreadbuf(data, count, offset, s, strlen(s));
|
||||||
if(lun->flags & Finqok)
|
free(s);
|
||||||
s = seprint(s, e, "inquiry %s ", lun->inq);
|
|
||||||
if(lun->blocks > 0)
|
|
||||||
s = seprint(s, e, "geometry %llud %ld",
|
|
||||||
lun->blocks, lun->lbsize);
|
|
||||||
s = seprint(s, e, "\n");
|
|
||||||
count = usbreadbuf(data, count, offset, buf, s - buf);
|
|
||||||
break;
|
break;
|
||||||
case Qraw:
|
case Qraw:
|
||||||
if(lun->lbsize <= 0 && umscapacity(lun) < 0){
|
if(lun->lbsize <= 0 && umscapacity(lun) < 0){
|
||||||
|
@ -515,7 +662,14 @@ dread(Usbfs *fs, Fid *fid, void *data, long count, vlong offset)
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case Qdata:
|
case Qdata:
|
||||||
count = setup(lun, data, count, offset);
|
default:
|
||||||
|
p = &lun->part[path];
|
||||||
|
if(!p->inuse){
|
||||||
|
count = -1;
|
||||||
|
werrstr(Eperm);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
count = setup(lun, p, data, count, offset);
|
||||||
if (count <= 0)
|
if (count <= 0)
|
||||||
break;
|
break;
|
||||||
n = SRread(lun, lun->bufp, lun->nb * lun->lbsize);
|
n = SRread(lun, lun->bufp, lun->nb * lun->lbsize);
|
||||||
|
@ -547,7 +701,9 @@ dwrite(Usbfs *fs, Fid *fid, void *data, long count, vlong offset)
|
||||||
ulong path;
|
ulong path;
|
||||||
uvlong bno;
|
uvlong bno;
|
||||||
Ums *ums;
|
Ums *ums;
|
||||||
|
Part *p;
|
||||||
Umsc *lun;
|
Umsc *lun;
|
||||||
|
char *s;
|
||||||
|
|
||||||
ums = fs->dev->aux;
|
ums = fs->dev->aux;
|
||||||
lun = fs->aux;
|
lun = fs->aux;
|
||||||
|
@ -555,12 +711,18 @@ dwrite(Usbfs *fs, Fid *fid, void *data, long count, vlong offset)
|
||||||
|
|
||||||
qlock(ums);
|
qlock(ums);
|
||||||
switch(path){
|
switch(path){
|
||||||
default:
|
case Qdir:
|
||||||
werrstr(Eperm);
|
|
||||||
count = -1;
|
count = -1;
|
||||||
|
werrstr(Eperm);
|
||||||
break;
|
break;
|
||||||
case Qctl:
|
case Qctl:
|
||||||
dprint(2, "usb/disk: ctl ignored\n");
|
s = emallocz(count+1, 1);
|
||||||
|
memmove(s, data, count);
|
||||||
|
if(s[count-1] == '\n')
|
||||||
|
s[count-1] = 0;
|
||||||
|
if(ctlparse(fs, s) == -1)
|
||||||
|
count = -1;
|
||||||
|
free(s);
|
||||||
break;
|
break;
|
||||||
case Qraw:
|
case Qraw:
|
||||||
if(lun->lbsize <= 0 && umscapacity(lun) < 0){
|
if(lun->lbsize <= 0 && umscapacity(lun) < 0){
|
||||||
|
@ -597,8 +759,15 @@ dwrite(Usbfs *fs, Fid *fid, void *data, long count, vlong offset)
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case Qdata:
|
case Qdata:
|
||||||
|
default:
|
||||||
|
p = &lun->part[path];
|
||||||
|
if(!p->inuse){
|
||||||
|
count = -1;
|
||||||
|
werrstr(Eperm);
|
||||||
|
break;
|
||||||
|
}
|
||||||
len = ocount = count;
|
len = ocount = count;
|
||||||
count = setup(lun, data, count, offset);
|
count = setup(lun, p, data, count, offset);
|
||||||
if (count <= 0)
|
if (count <= 0)
|
||||||
break;
|
break;
|
||||||
bno = lun->offset;
|
bno = lun->offset;
|
||||||
|
@ -788,6 +957,7 @@ diskmain(Dev *dev, int argc, char **argv)
|
||||||
lun->fs.dev = dev;
|
lun->fs.dev = dev;
|
||||||
incref(dev);
|
incref(dev);
|
||||||
lun->fs.aux = lun;
|
lun->fs.aux = lun;
|
||||||
|
makeparts(lun);
|
||||||
usbfsadd(&lun->fs);
|
usbfsadd(&lun->fs);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -7,6 +7,7 @@ typedef struct Umsc Umsc;
|
||||||
typedef struct Ums Ums;
|
typedef struct Ums Ums;
|
||||||
typedef struct Cbw Cbw; /* command block wrapper */
|
typedef struct Cbw Cbw; /* command block wrapper */
|
||||||
typedef struct Csw Csw; /* command status wrapper */
|
typedef struct Csw Csw; /* command status wrapper */
|
||||||
|
typedef struct Part Part;
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
|
@ -42,12 +43,27 @@ enum
|
||||||
CswOk = 0,
|
CswOk = 0,
|
||||||
CswFailed = 1,
|
CswFailed = 1,
|
||||||
CswPhaseErr = 2,
|
CswPhaseErr = 2,
|
||||||
|
|
||||||
|
Maxparts = 16,
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* corresponds to a lun.
|
* corresponds to a lun.
|
||||||
* these are ~600+Maxiosize bytes each; ScsiReq is not tiny.
|
* these are ~600+Maxiosize bytes each; ScsiReq is not tiny.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
struct Part
|
||||||
|
{
|
||||||
|
int id;
|
||||||
|
int inuse;
|
||||||
|
int vers;
|
||||||
|
ulong mode;
|
||||||
|
char *name;
|
||||||
|
vlong offset; /* in lbsize units */
|
||||||
|
vlong length; /* in lbsize units */
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
struct Umsc
|
struct Umsc
|
||||||
{
|
{
|
||||||
ScsiReq;
|
ScsiReq;
|
||||||
|
@ -59,6 +75,9 @@ struct Umsc
|
||||||
long off; /* offset within a block */
|
long off; /* offset within a block */
|
||||||
long nb; /* byte count */
|
long nb; /* byte count */
|
||||||
|
|
||||||
|
/* partitions */
|
||||||
|
Part part[Maxparts];
|
||||||
|
|
||||||
uchar rawcmd[10];
|
uchar rawcmd[10];
|
||||||
uchar phase;
|
uchar phase;
|
||||||
char *inq;
|
char *inq;
|
||||||
|
|
|
@ -183,6 +183,8 @@ fswalk(Usbfs*, Fid *fid, char *name)
|
||||||
int rc;
|
int rc;
|
||||||
Dev *dev;
|
Dev *dev;
|
||||||
Dir d;
|
Dir d;
|
||||||
|
char dname[Namesz];
|
||||||
|
|
||||||
int (*xfswalk)(Usbfs *fs, Fid *f, char *name);
|
int (*xfswalk)(Usbfs *fs, Fid *f, char *name);
|
||||||
|
|
||||||
q = fid->qid;
|
q = fid->qid;
|
||||||
|
@ -218,6 +220,7 @@ fswalk(Usbfs*, Fid *fid, char *name)
|
||||||
for(i = 0; i < nfs; i++)
|
for(i = 0; i < nfs; i++)
|
||||||
if(fs[i] != nil && strcmp(name, fs[i]->name) == 0){
|
if(fs[i] != nil && strcmp(name, fs[i]->name) == 0){
|
||||||
q.path = mkqid(i, Qdir);
|
q.path = mkqid(i, Qdir);
|
||||||
|
d.name = dname;
|
||||||
fs[i]->stat(fs[i], q, &d); /* may be a file */
|
fs[i]->stat(fs[i], q, &d); /* may be a file */
|
||||||
fid->qid = d.qid;
|
fid->qid = d.qid;
|
||||||
qunlock(&fslck);
|
qunlock(&fslck);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue