diff options
| author | ment <thement@ibawizard.net> | 2011-05-08 21:55:24 +0200 |
|---|---|---|
| committer | ment <thement@ibawizard.net> | 2011-05-08 21:55:24 +0200 |
| commit | 2330fdb5378da73a6506f4e814fb604ddad9f090 (patch) | |
| tree | 4ab62aac9ffe8533d45485dc50ec7ae6aaa70901 | |
| parent | 4351887efd9dc8ab1eb334615262690a9751236c (diff) | |
| parent | 263b059960ed3fb300d63f91777798d64235726a (diff) | |
| download | plan9front-2330fdb5378da73a6506f4e814fb604ddad9f090.tar.xz | |
merge
| -rw-r--r-- | sys/src/cmd/disk/partfs.c | 2 | ||||
| -rw-r--r-- | sys/src/cmd/usb/disk/disk.c | 296 | ||||
| -rw-r--r-- | sys/src/cmd/usb/disk/ums.h | 19 | ||||
| -rw-r--r-- | sys/src/cmd/usb/lib/fsdir.c | 3 |
4 files changed, 256 insertions, 64 deletions
diff --git a/sys/src/cmd/disk/partfs.c b/sys/src/cmd/disk/partfs.c index d353b73b9..a14e2c91a 100644 --- a/sys/src/cmd/disk/partfs.c +++ b/sys/src/cmd/disk/partfs.c @@ -235,7 +235,7 @@ dirgen(int off, Dir *d, void*) 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; diff --git a/sys/src/cmd/usb/disk/disk.c b/sys/src/cmd/usb/disk/disk.c index 884df2d04..d99141318 100644 --- a/sys/src/cmd/usb/disk/disk.c +++ b/sys/src/cmd/usb/disk/disk.c @@ -20,7 +20,8 @@ enum Qctl, Qraw, Qdata, - Qmax, + Qpart, + Qmax = Maxparts, }; typedef struct Dirtab Dirtab; @@ -30,13 +31,156 @@ struct Dirtab 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 @@ -152,6 +296,7 @@ umscapacity(Umsc *lun) } 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 @@ Fail: 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 @@ dopen(Usbfs *fs, Fid *fid, int) * 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 @@ setup(Umsc *lun, char *data, int count, vlong offset) 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 @@ dread(Usbfs *fs, Fid *fid, void *data, long count, vlong offset) { 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 @@ dread(Usbfs *fs, Fid *fid, void *data, long count, vlong offset) 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 @@ dread(Usbfs *fs, Fid *fid, void *data, long count, vlong offset) } 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 @@ dwrite(Usbfs *fs, Fid *fid, void *data, long count, vlong offset) ulong path; uvlong bno; Ums *ums; + Part *p; Umsc *lun; + char *s; ums = fs->dev->aux; lun = fs->aux; @@ -555,12 +711,18 @@ dwrite(Usbfs *fs, Fid *fid, void *data, long count, vlong offset) 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 @@ dwrite(Usbfs *fs, Fid *fid, void *data, long count, vlong offset) } 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 @@ diskmain(Dev *dev, int argc, char **argv) if(argc != 0) { return usage(); } - + // notify(ding); ums = dev->aux = emallocz(sizeof(Ums), 1); ums->maxlun = -1; @@ -788,6 +957,7 @@ diskmain(Dev *dev, int argc, char **argv) lun->fs.dev = dev; incref(dev); lun->fs.aux = lun; + makeparts(lun); usbfsadd(&lun->fs); } return 0; diff --git a/sys/src/cmd/usb/disk/ums.h b/sys/src/cmd/usb/disk/ums.h index d65f8897b..16f782a69 100644 --- a/sys/src/cmd/usb/disk/ums.h +++ b/sys/src/cmd/usb/disk/ums.h @@ -7,6 +7,7 @@ typedef struct Umsc Umsc; typedef struct Ums Ums; typedef struct Cbw Cbw; /* command block wrapper */ typedef struct Csw Csw; /* command status wrapper */ +typedef struct Part Part; enum { @@ -42,12 +43,27 @@ enum CswOk = 0, CswFailed = 1, CswPhaseErr = 2, + + Maxparts = 16, }; /* * 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; @@ -59,6 +75,9 @@ struct Umsc long off; /* offset within a block */ long nb; /* byte count */ + /* partitions */ + Part part[Maxparts]; + uchar rawcmd[10]; uchar phase; char *inq; diff --git a/sys/src/cmd/usb/lib/fsdir.c b/sys/src/cmd/usb/lib/fsdir.c index 92bd68866..ee4f42c2b 100644 --- a/sys/src/cmd/usb/lib/fsdir.c +++ b/sys/src/cmd/usb/lib/fsdir.c @@ -183,6 +183,8 @@ fswalk(Usbfs*, Fid *fid, char *name) int rc; Dev *dev; Dir d; + char dname[Namesz]; + int (*xfswalk)(Usbfs *fs, Fid *f, char *name); q = fid->qid; @@ -218,6 +220,7 @@ fswalk(Usbfs*, Fid *fid, char *name) 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); |
