diff --git a/sys/src/9/port/devmnt.c b/sys/src/9/port/devmnt.c
index 2b6610afc..91d6ad2f9 100644
--- a/sys/src/9/port/devmnt.c
+++ b/sys/src/9/port/devmnt.c
@@ -634,32 +634,11 @@ static long
 mntread(Chan *c, void *buf, long n, vlong off)
 {
 	uchar *p, *e;
-	int nc, cache, isdir, dirlen;
-
-	isdir = 0;
-	cache = c->flag & CCACHE;
-	if(c->qid.type & QTDIR) {
-		cache = 0;
-		isdir = 1;
-	}
+	int dirlen;
 
 	p = buf;
-	if(cache) {
-		nc = cread(c, buf, n, off);
-		if(nc > 0) {
-			n -= nc;
-			if(n == 0)
-				return nc;
-			p += nc;
-			off += nc;
-		}
-		n = mntrdwr(Tread, c, p, n, off);
-		cupdate(c, p, n, off);
-		return n + nc;
-	}
-
-	n = mntrdwr(Tread, c, buf, n, off);
-	if(isdir) {
+	n = mntrdwr(Tread, c, p, n, off);
+	if(c->qid.type & QTDIR) {
 		for(e = &p[n]; p+BIT16SZ < e; p += dirlen){
 			dirlen = BIT16SZ+GBIT16(p);
 			if(p+dirlen > e)
@@ -695,6 +674,14 @@ mntrdwr(int type, Chan *c, void *buf, long n, vlong off)
 	if(c->qid.type & QTDIR)
 		cache = 0;
 	for(;;) {
+		if(cache && type == Tread) {
+			nr = cread(c, (uchar*)uba, n, off);
+			if(nr > 0) {
+				nreq = nr;
+				goto Next;
+			}
+		}
+
 		r = mntralloc(c, m->msize);
 		if(waserror()) {
 			mntfree(r);
@@ -714,13 +701,39 @@ mntrdwr(int type, Chan *c, void *buf, long n, vlong off)
 		if(nr > nreq)
 			nr = nreq;
 
+		if(cache) {
+			/*
+			 * note that we cannot update the cache from uba as
+			 * the user could change its contents from another
+			 * process before the data gets copied to the cached.
+			 */
+			if(type == Tread) {
+				ulong nc, nn;
+				Block *b;
+
+				nc = 0;
+				for(b = r->b; b != nil; b = b->next) {
+					nn = BLEN(b);
+					if(nc+nn > nr)
+						nn = nr - nc;
+					cupdate(c, b->rp, nn, off + nc);
+					nc += nn;
+					if(nc >= nr)
+						break;
+				}
+			} else {
+				if(convM2S(r->rpc, r->rpclen, &r->request) == 0)
+					panic("convM2S");
+				cwrite(c, (uchar*)r->request.data, nr, off);
+			}
+		}
+
 		if(type == Tread)
 			r->b = bl2mem((uchar*)uba, r->b, nr);
-		else if(cache)
-			cwrite(c, (uchar*)uba, nr, off);
-
-		poperror();
 		mntfree(r);
+		poperror();
+
+	Next:
 		off += nr;
 		uba += nr;
 		cnt += nr;
@@ -807,7 +820,6 @@ mountio(Mnt *m, Mntrpc *r)
 			up->text, up->pid, n, r->request.tag, r->request.fid, r->request.type);
 		error(Emountrpc);
 	}
-		
 	if(devtab[m->c->type]->write(m->c, r->rpc, n, 0) != n)
 		error(Emountrpc);