shithub: riscv

Download patch

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);