Don't blast out of mountio on a timeout
[akaros.git] / kern / drivers / dev / mnt.c
index ac0c426..fbffd81 100644 (file)
@@ -506,7 +506,7 @@ static int mntstat(struct chan *c, uint8_t * dp, int n)
        } else {
                n = r->reply.nstat;
                memmove(dp, r->reply.stat, n);
-               validstat(dp, n);
+               validstat(dp, n, 0);
                mntdirfix(dp, c);
        }
        poperror();
@@ -654,10 +654,17 @@ static int mntwstat(struct chan *c, uint8_t * dp, int n)
        return n;
 }
 
+/* the servers should either return units of whole directory entries
+ * OR support seeking to an arbitrary place. One or other.
+ * Both are fine, but at least one is a minimum.
+ * If the return a partial result, but more than one result,
+ * we'll return a shorter read and the next offset will be aligned
+ */
 static long mntread(struct chan *c, void *buf, long n, int64_t off)
 {
        uint8_t *p, *e;
        int nc, cache, isdir, dirlen;
+       int numdirent = 0;
 
        isdir = 0;
        cache = c->flag & CCACHE;
@@ -682,16 +689,24 @@ static long mntread(struct chan *c, void *buf, long n, int64_t off)
        }
 
        n = mntrdwr(Tread, c, buf, n, off);
+
        if (isdir) {
                for (e = &p[n]; p + BIT16SZ < e; p += dirlen) {
                        dirlen = BIT16SZ + GBIT16(p);
-                       if (p + dirlen > e)
+                       if (p + dirlen > e){
                                break;
-                       validstat(p, dirlen);
+                       }
+                       validstat(p, dirlen, 0);
                        mntdirfix(p, c);
+                       numdirent += dirlen;
+               }
+               if (p != e) {
+                       //error(Esbadstat);
+                       /* not really. Maybe the server supports
+                        * arbitrary seek like go9p now does.
+                        */
+                       n = numdirent;
                }
-               if (p != e)
-                       error(Esbadstat);
        }
        return n;
 }
@@ -802,19 +817,12 @@ void mountrpc(struct mnt *m, struct mntrpc *r)
 
 void mountio(struct mnt *m, struct mntrpc *r)
 {
-       ERRSTACK(1);
+       ERRSTACK(2);
        int n;
 
        while (waserror()) {
                if (m->rip == current)
                        mntgate(m);
-               if (!strcmp(current_errstr(), "syscall aborted")) {
-                       /* not sure what devmnt wants us to do here.  bail on aborted
-                        * syscall?  keep looping forever? (probably not) */
-                       printk("[kernel] mountio had aborted syscall");
-                       mntflushfree(m, r);
-                       nexterror();
-               }
                if (strcmp(current_errstr(), Eintr) != 0) {
                        mntflushfree(m, r);
                        nexterror();
@@ -847,7 +855,24 @@ void mountio(struct mnt *m, struct mntrpc *r)
                if (m->rip == 0)
                        break;
                spin_unlock(&m->lock);
+               /* Strcmp to check the error? Yep, it's a strcmp. Don't worry:
+                * 1. it's after a LONG timeout
+                * 2. it's after a packet IO, which is also long
+                * 3. it will almost certainly not match after about 1 character
+                * So, in theory, bad; in practice, not an issue.
+                */
+               if (waserror()) {
+                       if (strcmp(current_errstr(), "syscall aborted")) {
+                               /* not a timeout? Well, then, things are bleak. */
+                               nexterror();
+                       }
+                       printk("mountio had a timeout\n");
+                       poperror();
+                       continue;
+               }
+
                rendez_sleep(&r->r, rpcattn, r);
+               poperror();
                if (r->done) {
                        poperror();
                        mntflushfree(m, r);
@@ -929,6 +954,8 @@ int mntrpcread(struct mnt *m, struct mntrpc *r)
        *l = NULL;
        do {
                b = qremove(m->q);
+               /* TODO: have better block helpers for this and the memmove below */
+               b = linearizeblock(b);
                if (hlen > 0) {
                        b->rp += hlen;
                        len -= hlen;