Browse Source

Common code for all fcall operations.

Signed-off-by: golubovsky <golubovsky@gmail.com>
golubovsky 7 years ago
parent
commit
4e32884194
1 changed files with 68 additions and 67 deletions
  1. 68 67
      sys/src/9/port/dev9p.c

+ 68 - 67
sys/src/9/port/dev9p.c

@@ -150,57 +150,82 @@ do_request(int tidx, void *inbuf, int32_t inlen, void *outbuf, int32_t outlen)
 	return 0;
 }
 
-// Send a version message over the given virtqueue.
+typedef int64_t(*post_t)(Fcall *, int, void *);
 
-static int
-v9pversion(int tidx)
+// Common code to send/receive a fcall. It takes a post-processing function
+// to evaluate the return from fcall. This code takes care of buffer allocation,
+// message conversion, checks for Rerror result and errors out automatically,
+// checks for the result code matching the request code (request + 1), and errors out if not matching,
+// then passes control to the post processing function, finally releases all the buffers
+// it allocated.
+
+static int64_t
+do_fcall(Fcall *pf, int tidx, int32_t msize, void *data, post_t post)
 {
 	uint8_t *msg, *rsp;
 	usize k;
-	Fcall f;
-	f.type = Tversion;
-	f.tag = NOTAG;
-	f.msize = MAXRPC;
-	f.version = VERSION9PU;
-	msg = mallocz(BUFSZ, 1);
-	rsp = mallocz(BUFSZ, 1);
+	uint8_t rtype = pf->type;
+	msg = mallocz(msize, 1);
+	rsp = mallocz(msize, 1);
 	if(msg == nil || rsp == nil)
-		exhausted("version memory");
-	k = convS2M(&f, msg, BUFSZ);
+		exhausted("do_fcall buffer memory");
+	k = convS2M(pf, msg, msize);
 	if(k == 0) {
 		free(msg);
 		free(rsp);
-		error("bad version conversion on send");
+		error("do_fcall bad conversion on send");
 	}
-	int rc = do_request(tidx, rsp, BUFSZ, msg, BUFSZ);
-	int retval = rc;
+	int rc = do_request(tidx, rsp, msize, msg, msize);
 	free(msg);
-	if(rc >= 0) {
-		k = convM2S(rsp, BUFSZ, &f);
-		if(f.type == Rerror) {
-			free(rsp);
-			error(f.ename);
-			return -1;
-		} else if(f.type != Rversion) {
-			free(rsp);
-			error("unexpected reply type in fversion");
-			return -1;
-		}
+	if(rc < 0) {
+		free(rsp);
+		error("do_fcall virtio request error");
 	}
-	if(f.msize > MAXRPC) {
+	k = convM2S(rsp, msize, pf);
+	if(pf->type != rtype + 1) {
 		free(rsp);
+		error((pf->type == Rerror)?pf->ename:"do_fcall inconsistent return type");
+	}
+	int64_t rc2 = (*post)(pf, tidx, data);
+	free(rsp);
+	return rc2;
+}
+
+// Send a version message over the given virtqueue.
+
+static int64_t
+post_version(Fcall *pf, int tidx, void *data)
+{
+	if(pf->msize > MAXRPC) {
 		error("server tries to increase msize in fversion");
 		return -1;
 	}
-	if(f.msize<256 || f.msize>1024*1024) {
-		free(rsp);
+	if(pf->msize<256 || pf->msize>1024*1024) {
 		error("nonsense value of msize in fversion");
 		return -1;
 	}
-	mounts[tidx].msize = f.msize;
-	mounts[tidx].version = strdup(f.version);
-	free(rsp);
-	return retval;
+	mounts[tidx].msize = pf->msize;
+	mounts[tidx].version = strdup(pf->version);
+	return 0;
+}
+
+static int
+v9pversion(int tidx)
+{
+	Fcall f = {
+		.type = Tversion,
+		.tag = NOTAG,
+		.msize = MAXRPC,
+		.version = VERSION9PU
+	};
+	return do_fcall(&f, tidx, BUFSZ, nil, post_version);
+}
+
+static int64_t
+post_attach(Fcall *pf, int tidx, Chan *ch)
+{
+	ch->qid = pf->qid;
+	return 0;
 }
 
 static Chan*
@@ -219,40 +244,16 @@ print("v9pattach %s\n", spec);
 			return nil;
 		}
 	}
-	Chan *ch = devattach(v9pdevtab.dc, spec);
-	Fcall r;
-	r.type = Tattach;
-	r.tag = alloctag();
-	r.fid = ch->fid;
-	r.afid = NOFID;
-	r.uname = "";
-	r.aname = "";
-	uint8_t *msg, *rsp;
-	uint32_t ms = mounts[tidx].msize;
-	msg = mallocz(ms, 1);
-	rsp = mallocz(ms, 1);
-	if(msg == nil || rsp == nil)
-		exhausted("attach memory");
-	usize k = convS2M(&r, msg, ms);
-	if(k == 0) {
-		free(msg);
-		free(rsp);
-		freetag(r.tag);
-		error("bad attach conversion on send");
-	}
-	int rc = do_request(tidx, rsp, ms, msg, ms);
-	freetag(r.tag);
-	free(msg);
-	if(rc >= 0) {
-		k = convM2S(rsp, ms, &r);
-		if(r.type == Rerror) {
-			free(rsp);
-			error(r.ename);
-			return nil;
-		}
-		ch->qid = r.qid;
-	}
-	free(rsp);
+	Chan *ch = devattach(v9pdevtab.dc, mounts[tidx].tag);
+	Fcall r = {
+		.type = Tattach,
+		.tag = alloctag(),
+		.fid = ch->fid,
+		.afid = NOFID,
+		.uname = "",
+		.aname = ""
+	};
+	do_fcall(&r, tidx, mounts[tidx].msize, (void *)ch, (post_t)post_attach);
 	return ch;
 }