ref: 2330fdb5378da73a6506f4e814fb604ddad9f090
parent: 4351887efd9dc8ab1eb334615262690a9751236c
parent: 263b059960ed3fb300d63f91777798d64235726a
author: ment <[email protected]>
date: Sun May 8 17:55:24 EDT 2011
merge
--- a/sys/src/cmd/disk/partfs.c
+++ b/sys/src/cmd/disk/partfs.c
@@ -235,7 +235,7 @@
for(p = tab; p < tab + nelem(tab); p++, n++){
if(!p->inuse)
continue;
- if(n == off){
+ if(off-- == 0){
d->name = estrdup9p(p->name);
d->length = p->length*sectsize;
d->mode = p->mode;
--- a/sys/src/cmd/usb/disk/disk.c
+++ b/sys/src/cmd/usb/disk/disk.c
@@ -20,7 +20,8 @@
Qctl,
Qraw,
Qdata,
- Qmax,
+ Qpart,
+ Qmax = Maxparts,
};
typedef struct Dirtab Dirtab;
@@ -30,15 +31,158 @@
int mode;
};
-static Dirtab dirtab[] =
+ulong ctlmode = 0664;
+
+/*
+ * Partition management (adapted from disk/partfs)
+ */
+
+Part *
+lookpart(Umsc *lun, char *name)
{
- [Qdir] "/", DMDIR|0555,
- [Qctl] "ctl", 0664, /* nothing secret here */
- [Qraw] "raw", 0640,
- [Qdata] "data", 0640,
-};
+ Part *part, *p;
+
+ part = lun->part;
+ 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
*/
int exabyte, force6bytecmds;
@@ -152,6 +296,7 @@
}
lun->blocks++; /* SRcapacity returns LBA of last block */
lun->capacity = (vlong)lun->blocks * lun->lbsize;
+ lun->part[Qdata].length = lun->blocks;
if(diskdebug)
fprint(2, "disk: logical block size %lud, # blocks %llud\n",
lun->lbsize, lun->blocks);
@@ -329,59 +474,65 @@
static int
dwalk(Usbfs *fs, Fid *fid, char *name)
{
- int i;
- Qid qid;
-
- qid = fid->qid;
- if((qid.type & QTDIR) == 0){
+ Umsc *lun;
+ Part *p;
+
+ lun = fs->aux;
+
+ if((fid->qid.type & QTDIR) == 0){
werrstr("walk in non-directory");
return -1;
}
-
if(strcmp(name, "..") == 0)
return 0;
-
- for(i = 1; i < nelem(dirtab); i++)
- if(strcmp(name, dirtab[i].name) == 0){
- qid.path = i | fs->qid;
- qid.vers = 0;
- qid.type = dirtab[i].mode >> 24;
- fid->qid = qid;
- return 0;
- }
- werrstr(Enotfound);
- return -1;
+
+ p = lookpart(lun, name);
+ if(p == nil){
+ werrstr(Enotfound);
+ return -1;
+ }
+ fid->qid.path = p->id | fs->qid;
+ fid->qid.vers = p->vers;
+ fid->qid.type = p->mode >> 24;
+ return 0;
}
+static int
+dstat(Usbfs *fs, Qid qid, Dir *d);
static void
dostat(Usbfs *fs, int path, Dir *d)
{
- Dirtab *t;
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;
- if(path == Qdata)
- d->length = lun->capacity;
- else
- d->length = 0;
+ p = &lun->part[path];
+ d->qid.path = path;
+ d->qid.vers = p->vers;
+ 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
-dirgen(Usbfs *fs, Qid, int i, Dir *d, void*)
+dirgen(Usbfs *fs, Qid, int n, Dir *d, void*)
{
- i++; /* skip dir */
- if(i >= Qmax)
- return -1;
- else{
- dostat(fs, i, d);
- d->qid.path |= fs->qid;
- return 0;
+ Umsc *lun;
+ int i;
+
+ lun = fs->aux;
+ for(i = Qctl; i < Qmax; i++){
+ if(lun->part[i].inuse == 0)
+ continue;
+ if(n-- == 0)
+ break;
}
+ if(i == Qmax)
+ return -1;
+ dostat(fs, i, d);
+ d->qid.path |= fs->qid;
+ return 0;
}
static int
@@ -417,7 +568,7 @@
* since we don't need general division nor its cost.
*/
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;
uvlong bno;
@@ -432,13 +583,14 @@
bno = offset >> lbshift; /* offset / lbsize */
nb = ((offset + count + lbsize - 1) >> lbshift) - bno;
+ bno += p->offset; /* start of partition */
- if(bno + nb > lun->blocks) /* past end of device? */
- nb = lun->blocks - bno;
+ if(bno + nb > p->length) /* past end of partition? */
+ nb = p->length - bno;
if(nb * lbsize > Maxiosize)
nb = Maxiosize / lbsize;
lun->nb = nb;
- if(bno >= lun->blocks || nb == 0)
+ if(bno >= p->length || nb == 0)
return 0;
lun->offset = bno;
@@ -461,8 +613,9 @@
{
long n;
ulong path;
- char buf[1024];
- char *s, *e;
+ char buf[64];
+ char *s;
+ Part *p;
Umsc *lun;
Ums *ums;
Qid q;
@@ -478,15 +631,9 @@
count = usbdirread(fs, q, data, count, offset, dirgen, nil);
break;
case Qctl:
- e = buf + sizeof(buf);
- s = seprint(buf, e, "%s lun %ld: ", fs->dev->dir, lun - &ums->lun[0]);
- if(lun->flags & Finqok)
- 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);
+ s = ctlstring(fs);
+ count = usbreadbuf(data, count, offset, s, strlen(s));
+ free(s);
break;
case Qraw:
if(lun->lbsize <= 0 && umscapacity(lun) < 0){
@@ -515,7 +662,14 @@
}
break;
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)
break;
n = SRread(lun, lun->bufp, lun->nb * lun->lbsize);
@@ -547,7 +701,9 @@
ulong path;
uvlong bno;
Ums *ums;
+ Part *p;
Umsc *lun;
+ char *s;
ums = fs->dev->aux;
lun = fs->aux;
@@ -555,12 +711,18 @@
qlock(ums);
switch(path){
- default:
- werrstr(Eperm);
+ case Qdir:
count = -1;
+ werrstr(Eperm);
break;
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;
case Qraw:
if(lun->lbsize <= 0 && umscapacity(lun) < 0){
@@ -597,8 +759,15 @@
}
break;
case Qdata:
+ default:
+ p = &lun->part[path];
+ if(!p->inuse){
+ count = -1;
+ werrstr(Eperm);
+ break;
+ }
len = ocount = count;
- count = setup(lun, data, count, offset);
+ count = setup(lun, p, data, count, offset);
if (count <= 0)
break;
bno = lun->offset;
@@ -759,7 +928,7 @@
if(argc != 0) {
return usage();
}
-
+
// notify(ding);
ums = dev->aux = emallocz(sizeof(Ums), 1);
ums->maxlun = -1;
@@ -788,6 +957,7 @@
lun->fs.dev = dev;
incref(dev);
lun->fs.aux = lun;
+ makeparts(lun);
usbfsadd(&lun->fs);
}
return 0;
--- a/sys/src/cmd/usb/disk/ums.h
+++ b/sys/src/cmd/usb/disk/ums.h
@@ -7,6 +7,7 @@
typedef struct Ums Ums;
typedef struct Cbw Cbw; /* command block wrapper */
typedef struct Csw Csw; /* command status wrapper */
+typedef struct Part Part;
enum
{
@@ -42,6 +43,8 @@
CswOk = 0,
CswFailed = 1,
CswPhaseErr = 2,
+
+ Maxparts = 16,
};
/*
@@ -48,6 +51,19 @@
* corresponds to a lun.
* 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
{
ScsiReq;
@@ -58,6 +74,9 @@
char *bufp;
long off; /* offset within a block */
long nb; /* byte count */
+
+ /* partitions */
+ Part part[Maxparts];
uchar rawcmd[10];
uchar phase;
--- a/sys/src/cmd/usb/lib/fsdir.c
+++ b/sys/src/cmd/usb/lib/fsdir.c
@@ -183,6 +183,8 @@
int rc;
Dev *dev;
Dir d;
+ char dname[Namesz];
+
int (*xfswalk)(Usbfs *fs, Fid *f, char *name);
q = fid->qid;
@@ -218,6 +220,7 @@
for(i = 0; i < nfs; i++)
if(fs[i] != nil && strcmp(name, fs[i]->name) == 0){
q.path = mkqid(i, Qdir);
+ d.name = dname;
fs[i]->stat(fs[i], q, &d); /* may be a file */
fid->qid = d.qid;
qunlock(&fslck);