]> git.lizzy.rs Git - plan9front.git/blobdiff - sys/src/9/port/devmnt.c
kernel: use 64-bit virtual entry point for expanded header, document behaviour in...
[plan9front.git] / sys / src / 9 / port / devmnt.c
index e6bbd02dc15600018e8bccaeb3adf97f51936032..a132b9a6ea21f0ffa3de4fb721d3b20e0485d0cb 100644 (file)
@@ -26,8 +26,7 @@ struct Mntrpc
        Fcall   reply;          /* Incoming reply */
        Mnt*    m;              /* Mount device during rpc */
        Rendez* z;              /* Place to hang out */
-       uchar*  rpc;            /* I/O Data buffer */
-       uint    rpclen;         /* len of buffer */
+       Block*  w;              /* copy of write rpc for cache */
        Block*  b;              /* reply blocks */
        Mntrpc* flushed;        /* message this one flushes */
        char    done;           /* Rpc completed */
@@ -35,7 +34,7 @@ struct Mntrpc
 
 enum
 {
-       TAGSHIFT = 5,                   /* ulong has to be 32 bits */
+       TAGSHIFT = 5,
        TAGMASK = (1<<TAGSHIFT)-1,
        NMASK = (64*1024)>>TAGSHIFT,
 };
@@ -49,7 +48,7 @@ static struct Mntalloc
        ulong   nrpcfree;
        ulong   nrpcused;
        ulong   id;
-       ulong   tagmask[NMASK];
+       u32int  tagmask[NMASK];
 } mntalloc;
 
 static Chan*   mntchan(void);
@@ -68,6 +67,8 @@ static void   mountmux(Mnt*, Mntrpc*);
 static void    mountrpc(Mnt*, Mntrpc*);
 static int     rpcattn(void*);
 
+#define cachedchan(c) (((c)->flag & CCACHE) != 0 && (c)->mcp != nil)
+
 char   Esbadstat[] = "invalid directory entry received from server";
 char   Enoversion[] = "version not established for mount channel";
 
@@ -77,7 +78,7 @@ mntreset(void)
 {
        mntalloc.id = 1;
        mntalloc.tagmask[0] = 1;                        /* don't allow 0 as a tag */
-       mntalloc.tagmask[NMASK-1] = 0x80000000UL;       /* don't allow NOTAG */
+       mntalloc.tagmask[NMASK-1] = 0x80000000;         /* don't allow NOTAG */
        fmtinstall('F', fcallfmt);
        fmtinstall('D', dirfmt);
 /* We can't install %M since eipfmt does and is used in the kernel [sape] */
@@ -306,6 +307,9 @@ mntattach(Chan *c, Chan *ac, char *spec, int flags)
        Mnt *m;
        Mntrpc *r;
 
+       if(ac != nil && ac->mchan != c)
+               error(Ebadusefd);
+
        m = c->mux;
        if(m == nil){
                mntversion(c, nil, 0, 0);
@@ -520,8 +524,11 @@ mntopencreate(int type, Chan *c, char *name, int omode, ulong perm)
        poperror();
        mntfree(r);
 
-       if(c->flag & CCACHE)
-               copen(c);
+       if(c->flag & CCACHE){
+               if(copen(c))
+               if(type == Tcreate || (omode&OTRUNC) != 0)
+                       ctrunc(c);
+       }
 
        return c;
 }
@@ -619,6 +626,11 @@ mntwstat(Chan *c, uchar *dp, int n)
        mountrpc(m, r);
        poperror();
        mntfree(r);
+
+       if(c->flag & CCACHE)
+       if(GBIT64(&dp[STATFIXLEN-4*BIT16SZ-BIT64SZ]) != ~0ULL)
+               ctrunc(c);
+
        return n;
 }
 
@@ -659,7 +671,7 @@ mntcache(Mntrpc *r)
        Chan *c;
 
        c = r->c;
-       if((c->flag & CCACHE) == 0 || c->mcp == nil)
+       if(!cachedchan(c))
                return;
        off = r->request.offset;
        switch(r->reply.type){
@@ -676,9 +688,13 @@ mntcache(Mntrpc *r)
                }
                break;
        case Rwrite:
-               if(convM2S(r->rpc, r->rpclen, &r->request) == 0)
+               b = r->w;
+               if(convM2S(b->rp, BLEN(b), &r->request) == 0)
                        panic("convM2S");
-               cwrite(c, (uchar*)r->request.data, r->request.count, off);
+               m = r->reply.count;
+               if(m > r->request.count)
+                       m = r->request.count;
+               cwrite(c, (uchar*)r->request.data, m, off);
                break;
        }
 }
@@ -700,7 +716,7 @@ mntrdwr(int type, Chan *c, void *buf, long n, vlong off)
                if(nreq > c->iounit)
                        nreq = c->iounit;
 
-               if(type == Tread && (c->flag&CCACHE) != 0) {
+               if(type == Tread && cachedchan(c)) {
                        nr = cread(c, (uchar*)uba, nreq, off);
                        if(nr > 0) {
                                nreq = nr;
@@ -724,7 +740,7 @@ mntrdwr(int type, Chan *c, void *buf, long n, vlong off)
                if(nr > nreq)
                        nr = nreq;
                if(type == Tread)
-                       r->b = bl2mem((uchar*)uba, r->b, nr);
+                       nr = readblist(r->b, (uchar*)uba, nr, 0);
                mntfree(r);
                poperror();
 
@@ -897,7 +913,7 @@ mntrahread(Mntrah *rah, Chan *c, uchar *buf, long len, vlong off)
        if(rah->seq >= 2*c->iounit){
                w = (off / c->iounit) * c->iounit;
                e = w + rah->seq;
-               for(o = w; w < e; o += c->iounit){
+               for(o = w; o < e; o += c->iounit){
                        if(rahfindrpc(rah, o) != nil)
                                continue;
 
@@ -992,6 +1008,7 @@ mountrpc(Mnt *m, Mntrpc *r)
 static void
 mountio(Mnt *m, Mntrpc *r)
 {
+       Block *b;
        int n;
 
        while(waserror()) {
@@ -1021,23 +1038,22 @@ mountio(Mnt *m, Mntrpc *r)
 
        /* Transmit a file system rpc */
        n = sizeS2M(&r->request);
-       if(n > r->rpclen) {
-               free(r->rpc);
-               r->rpc = mallocz(((uint)n+127) & ~127, 0);
-               if(r->rpc == nil) {
-                       r->rpclen = 0;
-                       exhausted("mount rpc buffer");
-               }
-               r->rpclen = msize(r->rpc);
+       b = allocb(n);
+       if(waserror()){
+               freeb(b);
+               nexterror();
        }
-       n = convS2M(&r->request, r->rpc, r->rpclen);
+       n = convS2M(&r->request, b->wp, n);
        if(n <= 0 || n > m->msize) {
                print("mountio: proc %s %lud: convS2M returned %d for tag %d fid %d T%d\n",
                        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);
+       b->wp += n;
+       if(r->request.type == Twrite && cachedchan(r->c))
+               r->w = copyblock(b, n);
+       poperror();
+       devtab[m->c->type]->bwrite(m->c, b, 0);
 
        /* Gate readers onto the mount point one at a time */
        for(;;) {
@@ -1071,13 +1087,8 @@ doread(Mnt *m, int len)
 
        while(qlen(m->q) < len){
                b = devtab[m->c->type]->bread(m->c, m->msize, 0);
-               if(b == nil)
-                       return -1;
-               if(blocklen(b) == 0){
-                       freeblist(b);
+               if(b == nil || qaddlist(m->q, b) == 0)
                        return -1;
-               }
-               qaddlist(m->q, b);
        }
        return 0;
 }
@@ -1203,7 +1214,8 @@ mountmux(Mnt *m, Mntrpc *r)
                l = &q->list;
        }
        unlock(m);
-       print("unexpected reply tag %ud; type %d\n", r->reply.tag, r->reply.type);
+       print("mnt: unexpected reply from %s tag %ud; type %d\n",
+               chanpath(m->c), r->reply.tag, r->reply.type);
 }
 
 /*
@@ -1256,17 +1268,16 @@ static int
 alloctag(void)
 {
        int i, j;
-       ulong v;
+       u32int v;
 
        for(i = 0; i < NMASK; i++){
                v = mntalloc.tagmask[i];
-               if(v == ~0UL)
+               if(v == -1)
                        continue;
-               for(j = 0; j < 1<<TAGSHIFT; j++)
-                       if((v & (1<<j)) == 0){
-                               mntalloc.tagmask[i] |= 1<<j;
-                               return (i<<TAGSHIFT) + j;
-                       }
+               for(j = 0; (v & 1) != 0; j++)
+                       v >>= 1;
+               mntalloc.tagmask[i] |= 1<<j;
+               return i<<TAGSHIFT | j;
        }
        panic("no friggin tags left");
        return NOTAG;
@@ -1288,8 +1299,6 @@ mntralloc(Chan *c)
                new = malloc(sizeof(Mntrpc));
                if(new == nil)
                        exhausted("mount rpc header");
-               new->rpc = nil;
-               new->rpclen = 0;
                lock(&mntalloc);
                new->request.tag = alloctag();
        } else {
@@ -1308,12 +1317,14 @@ mntralloc(Chan *c)
        new->done = 0;
        new->flushed = nil;
        new->b = nil;
+       new->w = nil;
        return new;
 }
 
 static void
 mntfree(Mntrpc *r)
 {
+       freeb(r->w);
        freeblist(r->b);
        lock(&mntalloc);
        mntalloc.nrpcused--;
@@ -1326,7 +1337,6 @@ mntfree(Mntrpc *r)
        }
        freetag(r->request.tag);
        unlock(&mntalloc);
-       free(r->rpc);
        free(r);
 }