git: 9front

Download patch

ref: fcfd1b0c4b49a34ebe2d3629ebdfcc95764f7dea
parent: b38f538653510b92aebe6414a8125bf53d01d2b1
author: cinap_lenrek <cinap_lenrek@localhost>
date: Fri Aug 19 01:19:57 EDT 2011

nusb/ptp: implement flushing

--- a/sys/src/cmd/nusb/ptp/usbptp.c
+++ b/sys/src/cmd/nusb/ptp/usbptp.c
@@ -112,45 +112,18 @@
 }
 
 static int
-isinterrupt(void)
+wasinterrupt(void)
 {
 	char err[ERRMAX];
-	rerrstr(err, sizeof(err));
-	return !!(strstr(err, "interrupted") || strstr(err, "request timed out"));
-}
 
-static int
-usbread(Dev *ep, void *data, int len)
-{
-	int n, try;
-
-	n = 0;
-	for(try = 0; try < 4; try++){
-		n = read(ep->dfd, data, len);
-		if(n == 0)
-			continue;
-		if(n >= 0 || !isinterrupt())
-			break;
+	rerrstr(err, sizeof(err));
+	if(strstr(err, "interrupted") || strstr(err, "request timed out")){
+		werrstr("interrupted");
+		return 1;
 	}
-	return n;
+	return 0;
 }
 
-static int
-usbwrite(Dev *ep, void *data, int len)
-{
-	int n, try;
-
-	n = 0;
-	for(try = 0; try < 4; try++){
-		n = write(ep->dfd, data, len);
-		if(n == 0)
-			continue;
-		if(n >= 0 || !isinterrupt())
-			break;
-	}
-	return n;
-}
-
 static char *
 ptperrstr(int code)
 {
@@ -205,32 +178,31 @@
 
 	if(length < 4+2+2+4){
 		werrstr("short response: %d < %d", length, 4+2+2+4);
-		return -1;
+		return 1;
 	}
 	if(GET4(rpc->length) < length){
 		werrstr("unexpected response length 0x%x < 0x%x", GET4(rpc->length), length);
-		return -1;
+		return 1;
 	}
 	if(GET4(rpc->transid) != transid){
 		werrstr("unexpected transaction id 0x%x != 0x%x", GET4(rpc->transid), transid);
-		return -1;
+		return 1;
 	}
+	if(GET2(rpc->type) != type){
+		werrstr("unexpected response type 0x%x != 0x%x", GET2(rpc->type), type);
+		return 1;
+	}
 	if(s = ptperrstr(GET2(rpc->code))){
 		werrstr("%s", s);
 		return -GET2(rpc->code);
 	}
-	if(GET2(rpc->type) != type){
-		werrstr("unexpected response type 0x%x != 0x%x", GET2(rpc->type), type);
-		return -1;
-	}
 	return 0;
 }
 
 static int
-ptprpc(int code, int flags, ...)
+vptprpc(int code, int flags, va_list a)
 {
 	Ptprpc rpc;
-	va_list a;
 	int np, n, t, i, l;
 	uchar *b, *p, *e;
 
@@ -243,7 +215,6 @@
 	PUT2(rpc.code, code);
 	PUT4(rpc.transid, t);
 
-	va_start(a, flags);
 	for(i=0; i<np; i++){
 		int x = va_arg(a, int);
 		PUT4(rpc.p[i], x);
@@ -250,8 +221,12 @@
 	}
 	if(debug)
 		hexdump("req>", (uchar*)&rpc, n);
-	if(usbwrite(usbep[Out], &rpc, n) < 0)
+
+	werrstr("");
+	if(write(usbep[Out]->dfd, &rpc, n) != n){
+		wasinterrupt();
 		return -1;
+	}
 
 	if(flags & DataSend){
 		void *sdata;
@@ -276,11 +251,15 @@
 
 		if(debug)
 			hexdump("data>", (uchar*)&rpc, n);
-		if(usbwrite(usbep[Out], &rpc, n) < 0)
+		if(write(usbep[Out]->dfd, &rpc, n) != n){
+			wasinterrupt();
 			return -1;
+		}
 		while(p < e){	
-			if((n = usbwrite(usbep[Out], p, e-p)) < 0)
+			if((n = write(usbep[Out]->dfd, p, e-p)) < 0){
+				wasinterrupt();
 				break;
+			}
 			p += n;
 		}
 	}
@@ -295,13 +274,16 @@
 		*prdata = nil;
 		*prdatalen = 0;
 
-		if((n = usbread(usbep[In], &rpc, sizeof(rpc))) < 0)
-			return -1;
-		
-		if(debug)
-			hexdump("data<", (uchar*)&rpc, n);
-		if(ptpcheckerr(&rpc, 2, t, n))
-			goto Err;
+		do{
+			if((n = read(usbep[In]->dfd, &rpc, sizeof(rpc))) < 0){
+				wasinterrupt();
+				return -1;
+			}
+			if(debug > 1)
+				hexdump("data<", (uchar*)&rpc, n);
+			if((l = ptpcheckerr(&rpc, 2, t, n)) < 0)
+				return -1;
+		} while(l);
 
 		l = GET4(rpc.length);
 		if((l < 4+2+2+4) || (l < n)){
@@ -319,7 +301,8 @@
 		p += n;
 
 		while(p < e){
-			if((n = usbread(usbep[In], p, e-p)) < 0){
+			if((n = read(usbep[In]->dfd, p, e-p)) < 0){
+				wasinterrupt();
 				free(b);
 				return -1;
 			}
@@ -329,17 +312,17 @@
 		*prdatalen =  e-b;
 	}
 
-	if((n = usbread(usbep[In], &rpc, sizeof(rpc))) < 0)
-		return -1;
-	if(debug)
-		hexdump("resp<", (uchar*)&rpc, n);
+	do {
+		if((n = read(usbep[In]->dfd, &rpc, sizeof(rpc))) < 0){
+			wasinterrupt();
+			return -1;
+		}
+		if(debug > 1)
+			hexdump("resp<", (uchar*)&rpc, n);
+		if((l = ptpcheckerr(&rpc, 3, t, n)) < 0)
+			return -1;
+	} while(l);
 
-Err:
-	if(ptpcheckerr(&rpc, 3, t, n) < 0){
-		werrstr("ptp %x: %r", code);
-		return -1;
-	}
-
 	if(flags & OutParam){
 		int *pp;
 
@@ -349,10 +332,36 @@
 			*pp = GET4(rpc.p[i]);
 		}
 	}
-	va_end(a);
 	return 0;
 }
 
+static int
+ptprpc(Req *r, int code, int flags, ...)
+{
+	static long ptpsem = 1;
+	va_list a;
+	int i;
+
+	if(r != nil){
+		r->aux = (void*)getpid();
+		srvrelease(r->srv);
+	}
+	i = semacquire(&ptpsem, 1);
+	if(i == 1){
+		va_start(a, flags);
+		i = vptprpc(code, flags, a);
+		va_end(a);
+		semrelease(&ptpsem, 1);
+	}
+	if(i < 0 && debug)
+		fprint(2, "ptprpc: req=%p %r\n", r);
+	if(r != nil){
+		srvacquire(r->srv);
+		r->aux = (void*)-1;
+	}
+	return i;
+}
+
 static int*
 ptparray4(uchar *d, uchar *e)
 {
@@ -424,7 +433,7 @@
 }
 
 static Node*
-getnode(uvlong path)
+getnode(uvlong path, Req *r)
 {
 	int i, j;
 	Node *x;
@@ -451,10 +460,12 @@
 	x->d.gid = estrdup9p(uname);
 	x->d.atime = x->d.mtime = time0;
 
+	p = nil;
+	np = 0;
 	switch(TYPE(path)){
 	case Qroot:
 		x->d.qid.type = QTDIR;
-		x->d.mode = DMDIR|0555;
+		x->d.mode = DMDIR|0777;
 		x->d.name = estrdup9p("/");
 		break;
 
@@ -462,7 +473,7 @@
 		x->store = NUM(path);
 		x->handle = 0xffffffff;
 		x->d.qid.type = QTDIR;
-		x->d.mode = DMDIR|0555;
+		x->d.mode = DMDIR|0777;
 		x->d.name = emalloc9p(10);
 		sprint(x->d.name, "%x", x->store);
 		break;
@@ -469,26 +480,41 @@
 
 	case Qobj:
 	case Qthumb:
-		x->handle = NUM(path);
-		if(ptprpc(GetObjectInfo, 1|DataRecv, x->handle, &p, &np) < 0)
+		if(ptprpc(r, GetObjectInfo, 1|DataRecv, NUM(path), &p, &np) < 0)
 			goto err;
-		if(debug)
+		if(debug > 1)
 			hexdump("objectinfo", p, np);
 		if(np < 52){
 			werrstr("bad objectinfo");
 			goto err;
 		}
+
+		j = -1;
+		for(i=0; i<nnodes; i++){
+			if(nodes[i] == nil){
+				j = i;
+				continue;
+			}
+			if(nodes[i]->d.qid.path == path){
+				/* never mind */
+				cleardir(&x->d);
+				free(x);
+				return nodes[i];
+			}
+		}
+
 		if((x->d.name = ptpstring2(p+52, p+np)) == nil){
 			werrstr("bad objectinfo");
 			goto err;
 		}
+		x->handle = NUM(path);
 		x->store = GET4(p);
 		x->format = GET2(p+4);
 		if(x->format == 0x3001 && GET2(p+42) == 1){
 			x->d.qid.type = QTDIR;
-			x->d.mode = DMDIR|0555;
+			x->d.mode = DMDIR|0777;
 		} else {
-			x->d.mode = 0444;
+			x->d.mode = 0666;
 			if(TYPE(path) == Qthumb){
 				char *t;
 
@@ -541,6 +567,8 @@
 err:
 	cleardir(&x->d);
 	free(x);
+	free(p);
+
 	return nil;
 }
 
@@ -562,7 +590,7 @@
 }
 
 static int
-readchilds(Node *nod)
+readchilds(Node *nod, Req *r)
 {
 	int i;
 	int *a;
@@ -570,31 +598,33 @@
 	int np;
 	Node *x, **xx;
 
-	xx = &nod->child;
 	switch(TYPE(nod->d.qid.path)){
 	case Qroot:
-		if(ptprpc(GetStorageIds, 0|DataRecv, &p, &np) < 0)
+		if(ptprpc(r, GetStorageIds, 0|DataRecv, &p, &np) < 0)
 			return -1;
 		a = ptparray4(p, p+np);
 		free(p);
+		xx = &nod->child;
 		for(i=0; a && i<a[0]; i++){
-			if(x = getnode(PATH(Qstore, a[i+1]))){
+			if(x = getnode(PATH(Qstore, a[i+1]), r)){
 				x->parent = nod;
 				*xx = x;
 				xx = &x->next;
 			}
 		}		
+		*xx = nil;
 		free(a);
 		break;
 
 	case Qstore:
 	case Qobj:
-		if(ptprpc(GetObjectHandles, 3|DataRecv, nod->store, 0, nod->handle, &p, &np) < 0)
+		if(ptprpc(r, GetObjectHandles, 3|DataRecv, nod->store, 0, nod->handle, &p, &np) < 0)
 			return -1;
 		a = ptparray4(p, p+np);
 		free(p);
+		xx = &nod->child;
 		for(i=0; a && i<a[0]; i++){
-			if(x = getnode(PATH(Qobj, a[i+1]))){
+			if(x = getnode(PATH(Qobj, a[i+1]), r)){
 				x->parent = nod;
 				*xx = x;
 				xx = &x->next;
@@ -603,16 +633,16 @@
 				if((x->format & 0xFF00) != 0x3800)
 					continue;
 			}
-			if(x = getnode(PATH(Qthumb, a[i+1]))){
+			if(x = getnode(PATH(Qthumb, a[i+1]), r)){
 				x->parent = nod;
 				*xx = x;
 				xx = &x->next;
 			}
 		}
+		*xx = nil;
 		free(a);
 		break;
 	}
-	*xx = nil;
 
 	return 0;
 }
@@ -638,7 +668,7 @@
 {
 	Node *nod;
 
-	if((nod = getnode(r->fid->qid.path)) == nil){
+	if((nod = getnode(r->fid->qid.path, r)) == nil){
 		responderror(r);
 		return;
 	}
@@ -661,34 +691,31 @@
 }
 
 static char*
-fswalk1(Fid *fid, char *name, Qid *qid)
+fswalk1(Req *r, char *name, Qid *qid)
 {
-	Node *nod;
-	uvlong path;
 	static char buf[ERRMAX];
+	uvlong path;
+	Node *nod;
+	Fid *fid;
 
+	fid = r->newfid;
 	path = fid->qid.path;
 	if(!(fid->qid.type&QTDIR))
 		return "walk in non-directory";
 
-	if((nod = getnode(path)) == nil)
+	if((nod = getnode(path, r)) == nil)
 		goto err;
 
 	if(strcmp(name, "..") == 0){
-		if(nod = nod->parent){
+		if(nod = nod->parent)
 			*qid = nod->d.qid;
-			fid->qid = *qid;
-		}
 		return nil;
 	}
-
-	if(readchilds(nod) < 0)
+	if(readchilds(nod, r) < 0)
 		goto err;
-
 	for(nod=nod->child; nod; nod=nod->next){
 		if(strcmp(nod->d.name, name) == 0){
 			*qid = nod->d.qid;
-			fid->qid = *qid;
 			return nil;
 		}
 	}
@@ -699,21 +726,50 @@
 	return buf;
 }
 
+static char*
+oldwalk1(Fid *fid, char *name, void *arg)
+{
+	Qid qid;
+	char *e;
+	Req *r;
+
+	r = arg;
+	assert(fid == r->newfid);
+	if(e = fswalk1(r, name, &qid))
+		return e;
+	fid->qid = qid;
+	return nil;
+}
+
+static char*
+oldclone(Fid *, Fid *, void *)
+{
+	return nil;
+}
+
 static void
+fswalk(Req *r)
+{
+	walkandclone(r, oldwalk1, oldclone, r);
+}
+
+static void
 fsread(Req *r)
 {
-	Node *nod;
 	uvlong path;
+	Node *nod;
+	uchar *p;
+	int np;
 
+	np = 0;
+	p = nil;
 	path = r->fid->qid.path;
-
-	if((nod = getnode(path)) == nil)
+	if((nod = getnode(path, r)) == nil)
 		goto err;
 
 	if(nod->d.qid.type & QTDIR){
-		if(readchilds(nod) < 0)
+		if(readchilds(nod, r) < 0)
 			goto err;
-
 		dirread9p(r, nodegen, nod);
 		respond(r, nil);
 		return;
@@ -727,14 +783,11 @@
 	case Qobj:
 	case Qthumb:
 		if(nod->data == nil){
-			uchar *p;
-			int np;
-
 			if(TYPE(path)==Qthumb){
-				if(ptprpc(GetThumb, 1|DataRecv, nod->handle, &p, &np) < 0)
+				if(ptprpc(r, GetThumb, 1|DataRecv, nod->handle, &p, &np) < 0)
 					goto err;
 			} else {
-				if(ptprpc(GetObject, 1|DataRecv, nod->handle, &p, &np) < 0)
+				if(ptprpc(r, GetObject, 1|DataRecv, nod->handle, &p, &np) < 0)
 					goto err;
 			}
 			nod->data = p;
@@ -744,8 +797,8 @@
 		respond(r, nil);
 		return;
 	}
-
 err:
+	free(p);
 	responderror(r);
 }
 
@@ -756,8 +809,7 @@
 	uvlong path;
 
 	path = r->fid->qid.path;
-
-	if((nod = getnode(path)) == nil)
+	if((nod = getnode(path, r)) == nil)
 		goto err;
 
 	switch(TYPE(path)){
@@ -764,17 +816,14 @@
 	default:
 		werrstr("bug in fsremove path=%llux", path);
 		break;
-
 	case Qobj:
-		if(ptprpc(DeleteObject, 2, nod->handle, 0) < 0)
+		if(ptprpc(r, DeleteObject, 2, nod->handle, 0) < 0)
 			goto err;
-
 	case Qthumb:
 		freenode(nod);
 		respond(r, nil);
 		return;
 	}
-
 err:
 	responderror(r);
 }
@@ -782,6 +831,10 @@
 static void
 fsopen(Req *r)
 {
+	if(r->ifcall.mode != OREAD){
+		respond(r, "permission denied");
+		return;
+	}
 	respond(r, nil);
 }
 
@@ -788,6 +841,17 @@
 static void
 fsflush(Req *r)
 {
+	Req *o;
+
+	if(o = r->oldreq){
+		if(debug)
+			fprint(2, "fsflush: req=%p\n", o);
+		int pid = (int)o->aux;
+		if(pid != -1 && pid != 0){
+			o->aux = (void*)-1;
+			postnote(PNPROC, pid, "interrupt");
+		}
+	}
 	respond(r, nil);
 }
 
@@ -801,7 +865,7 @@
 	switch(TYPE(path)){
 	case Qobj:
 	case Qthumb:
-		if(nod = getnode(path)){
+		if(nod = getnode(path, nil)){
 			free(nod->data);
 			nod->data = nil;
 			nod->ndata = 0;
@@ -813,7 +877,7 @@
 static void
 fsend(Srv *)
 {
-	ptprpc(CloseSession, 0);
+	ptprpc(nil, CloseSession, 0);
 }
 
 static int
@@ -854,7 +918,7 @@
 {
 .attach=		fsattach,
 .destroyfid=	fsdestroyfid,
-.walk1=		fswalk1,
+.walk=		fswalk,
 .open=		fsopen,
 .read=		fsread,
 .remove=		fsremove,
@@ -871,7 +935,7 @@
 }
 
 void
-threadmain(int argc, char **argv)
+main(int argc, char **argv)
 {
 	int epin, epout;
 	char name[64], desc[64];
@@ -879,8 +943,7 @@
 
 	ARGBEGIN {
 	case 'd':
-		debug = 1;
-		usbdebug++;
+		debug++;
 		break;
 	case 'D':
 		chatty9p++;
@@ -910,7 +973,7 @@
 		sysfatal("open endpoints: %r");
 
 	sessionId = getpid();
-	if(ptprpc(OpenSession, 1, sessionId) < 0)
+	if(ptprpc(nil, OpenSession, 1, sessionId) < 0)
 		return;
 
 	atnotify(inote, 1);
@@ -918,7 +981,7 @@
 
 	snprint(name, sizeof name, "sdU%d.0", d->id);
 	snprint(desc, sizeof desc, "%d.ptp", d->id);
-	threadpostsharesrv(&fs, nil, name, desc);
+	postsharesrv(&fs, nil, name, desc);
 
-	threadexits(0);
+	exits(0);
 }
--