]> git.lizzy.rs Git - plan9front.git/blobdiff - sys/src/cmd/sshfs.c
fix ref822 again: remove uniqarray(), fix case with many entries in 'n'.
[plan9front.git] / sys / src / cmd / sshfs.c
index f6267ed852666e90541140176767eeff95402f72..30638ddb6400f9dea88e354793ed25ebe2e20a53 100644 (file)
@@ -103,7 +103,6 @@ struct SFid {
 struct SReq {
        Req *req;
        SFid *closefid;
-       int reqid;
        SReq *next;
 };
 
@@ -193,10 +192,30 @@ namelookup(IDEnt **tab, char *name)
        return -1;
 }
 
+int
+allocsreqid(SReq *r)
+{
+       int i;
+
+       qlock(&sreqidlock);
+       for(;;){
+               for(i = 0; i < MAXREQID; i++)
+                       if(sreqrd[i] == nil){
+                               sreqrd[i] = r;
+                               goto out;
+                       }
+               rsleep(&sreqidrend);
+       }
+out:
+       qunlock(&sreqidlock);
+       return i;
+}
+
 int
 vpack(uchar *p, int n, char *fmt, va_list a)
 {
        uchar *p0 = p, *e = p+n;
+       SReq *sr = nil;
        u32int u;
        u64int v;
        void *s;
@@ -205,6 +224,10 @@ vpack(uchar *p, int n, char *fmt, va_list a)
        for(;;){
                switch(c = *fmt++){
                case '\0':
+                       if(sr != nil){
+                               u = allocsreqid(sr);
+                               PUT4(p0+1, u);
+                       }
                        return p - p0;
                case '_':
                        if(++p > e) goto err;
@@ -228,6 +251,11 @@ vpack(uchar *p, int n, char *fmt, va_list a)
                        memmove(p, s, u);
                        p += u;
                        break;
+               case 'q':
+                       p += 4;
+                       if(p != p0+5 || p > e) goto err;
+                       sr = va_arg(a, SReq*);
+                       break;
                case 'u':
                        u = va_arg(a, int);
                        if(p+4 > e) goto err;
@@ -389,11 +417,14 @@ freedir(SFid *s)
        s->dirpos = 0;
 }
 
-
 void
 putsfid(SFid *s)
 {
        if(s == nil) return;
+
+       wlock(s);
+       wunlock(s);
+
        free(s->fn);
        free(s->hand);
        freedir(s);
@@ -403,14 +434,6 @@ putsfid(SFid *s)
 void
 putsreq(SReq *s)
 {
-       if(s == nil) return;
-       if(s->reqid != -1){
-               qlock(&sreqidlock);
-               sreqrd[s->reqid] = nil;
-               rwakeup(&sreqidrend);
-               qunlock(&sreqidlock);
-       }
-       putsfid(s->closefid);
        free(s);
 }
 
@@ -424,14 +447,12 @@ submitsreq(SReq *s)
        qunlock(&sreqwrlock);
 }
 
-
 void
 submitreq(Req *r)
 {
        SReq *s;
        
        s = emalloc9p(sizeof(SReq));
-       s->reqid = -1;
        s->req = r;
        submitsreq(s);
 }
@@ -548,7 +569,7 @@ dir2attrib(Dir *d, uchar **rp)
        int uid, gid;
 
        werrstr("phase error");
-       r = emalloc9p(MAXATTRIB);
+       *rp = r = emalloc9p(MAXATTRIB);
        e = r + MAXATTRIB;
        fl = 0;
        p = r + 4;
@@ -583,7 +604,6 @@ dir2attrib(Dir *d, uchar **rp)
                rc = pack(p, e - p, "uu", d->atime, d->mtime); if(rc < 0) return -1; p += rc;
        }
        PUT4(r, fl);
-       *rp = r;
        return p - r;
 }
 
@@ -697,20 +717,18 @@ readprocess(Req *r)
 void
 sshfsread(Req *r)
 {
-       SFid *sf;
-
        if((r->fid->qid.type & QTDIR) == 0){
                submitreq(r);
                return;
        }
-       sf = r->fid->aux;       
        if(r->ifcall.offset == 0){
+               SFid *sf = r->fid->aux;
                wlock(sf);
                freedir(sf);
                if(sf->dirreads > 0){
+                       wunlock(sf);
                        r->aux = (void*)-1;
                        submitreq(r);
-                       wunlock(sf);
                        return;
                }
                wunlock(sf);
@@ -764,7 +782,6 @@ sendproc(void *)
 {
        SReq *r;
        SFid *sf;
-       int i;
        int x, y;
        char *s, *t;
 
@@ -778,41 +795,33 @@ sendproc(void *)
                sreqwr = r->next;
                if(sreqwr == nil) sreqlast = &sreqwr;
                qunlock(&sreqwrlock);
-               
-               qlock(&sreqidlock);
-       idagain:
-               for(i = 0; i < MAXREQID; i++)
-                       if(sreqrd[i] == nil){
-                               sreqrd[i] = r;
-                               r->reqid = i;
-                               break;
-                       }
-               if(i == MAXREQID){
-                       rsleep(&sreqidrend);
-                       goto idagain;
-               }
-               qunlock(&sreqidlock);
 
-               if(r->closefid != nil){
-                       sendpkt("bus", SSH_FXP_CLOSE, r->reqid, r->closefid->hand, r->closefid->handn);
+               sf = r->closefid;
+               if(sf != nil){
+                       rlock(sf);
+                       sendpkt("bqs", SSH_FXP_CLOSE, r, sf->hand, sf->handn);
+                       runlock(sf);
                        continue;
                }
                if(r->req == nil)
                        sysfatal("nil request in queue");
 
-               sf = r->req->fid != nil ? r->req->fid->aux : nil;
+               sf = r->req->fid->aux;
                switch(r->req->ifcall.type){
                case Tattach:
-                       sendpkt("bus", SSH_FXP_STAT, r->reqid, sf->fn, strlen(sf->fn));
+                       rlock(sf);
+                       sendpkt("bqs", SSH_FXP_STAT, r, sf->fn, strlen(sf->fn));
+                       runlock(sf);
                        break;
                case Twalk:
-                       sendpkt("bus", SSH_FXP_STAT, r->reqid, r->req->aux, strlen(r->req->aux));
+                       sendpkt("bqs", SSH_FXP_STAT, r, r->req->aux, strlen(r->req->aux));
                        break;
                case Topen:
-                       rlock(sf);
-                       if((r->req->ofcall.qid.type & QTDIR) != 0)
-                               sendpkt("bus", SSH_FXP_OPENDIR, r->reqid, sf->fn, strlen(sf->fn));
-                       else{
+                       if((r->req->ofcall.qid.type & QTDIR) != 0){
+                               rlock(sf);
+                               sendpkt("bqs", SSH_FXP_OPENDIR, r, sf->fn, strlen(sf->fn));
+                               runlock(sf);
+                       }else{
                                x = r->req->ifcall.mode;
                                y = 0;
                                switch(x & 3){
@@ -822,15 +831,15 @@ sendproc(void *)
                                }
                                if(readonly && (y & SSH_FXF_WRITE) != 0){
                                        respond(r->req, "mounted read-only");
-                                       runlock(sf);
                                        putsreq(r);
                                        break;
                                }
                                if((x & OTRUNC) != 0)
                                        y |= SSH_FXF_TRUNC;
-                               sendpkt("busuu", SSH_FXP_OPEN, r->reqid, sf->fn, strlen(sf->fn), y, 0);
+                               rlock(sf);
+                               sendpkt("bqsuu", SSH_FXP_OPEN, r, sf->fn, strlen(sf->fn), y, 0);
+                               runlock(sf);
                        }
-                       runlock(sf);
                        break;
                case Tcreate:
                        rlock(sf);
@@ -838,12 +847,12 @@ sendproc(void *)
                        runlock(sf);
                        if((r->req->ifcall.perm & DMDIR) != 0){
                                if(r->req->aux == nil){
-                                       sendpkt("busuu", SSH_FXP_MKDIR, r->reqid, s, strlen(s),
-                                               SSH_FILEXFER_ATTR_PERMISSIONS, r->req->ifcall.perm & 0777);
                                        r->req->aux = (void*)-1;
+                                       sendpkt("bqsuu", SSH_FXP_MKDIR, r, s, strlen(s),
+                                               SSH_FILEXFER_ATTR_PERMISSIONS, r->req->ifcall.perm & 0777);
                                }else{
-                                       sendpkt("bus", SSH_FXP_OPENDIR, r->reqid, s, strlen(s));
                                        r->req->aux = (void*)-2;
+                                       sendpkt("bqs", SSH_FXP_OPENDIR, r, s, strlen(s));
                                }
                                free(s);
                                break;
@@ -855,7 +864,7 @@ sendproc(void *)
                        case OWRITE: y |= SSH_FXF_WRITE; break;
                        case ORDWR: y |= SSH_FXF_READ | SSH_FXF_WRITE; break;
                        }
-                       sendpkt("busuuu", SSH_FXP_OPEN, r->reqid, s, strlen(s), y,
+                       sendpkt("bqsuuu", SSH_FXP_OPEN, r, s, strlen(s), y,
                                SSH_FILEXFER_ATTR_PERMISSIONS, r->req->ifcall.perm & 0777);
                        free(s);
                        break;
@@ -863,22 +872,22 @@ sendproc(void *)
                        if((r->req->fid->qid.type & QTDIR) != 0){
                                wlock(sf);
                                if(r->req->aux == (void*)-1){
-                                       sendpkt("bus", SSH_FXP_CLOSE, r->reqid, sf->hand, sf->handn);
+                                       sendpkt("bqs", SSH_FXP_CLOSE, r, sf->hand, sf->handn);
                                        free(sf->hand);
                                        sf->hand = nil;
                                        sf->handn = 0;
                                        sf->direof = 0;
                                        sf->dirreads = 0;
                                }else if(r->req->aux == (void*)-2){
-                                       sendpkt("bus", SSH_FXP_OPENDIR, r->reqid, sf->fn, strlen(sf->fn));
+                                       sendpkt("bqs", SSH_FXP_OPENDIR, r, sf->fn, strlen(sf->fn));
                                }else{
                                        sf->dirreads++;
-                                       sendpkt("bus", SSH_FXP_READDIR, r->reqid, sf->hand, sf->handn);
+                                       sendpkt("bqs", SSH_FXP_READDIR, r, sf->hand, sf->handn);
                                }
                                wunlock(sf);
                        }else{
                                rlock(sf);
-                               sendpkt("busvuu", SSH_FXP_READ, r->reqid, sf->hand, sf->handn,
+                               sendpkt("bqsvuu", SSH_FXP_READ, r, sf->hand, sf->handn,
                                        r->req->ifcall.offset, r->req->ifcall.count);
                                runlock(sf);
                        }
@@ -886,55 +895,56 @@ sendproc(void *)
                case Twrite:
                        x = r->req->ifcall.count - r->req->ofcall.count;
                        if(x >= MAXWRITE) x = MAXWRITE;
+                       r->req->ofcall.offset = x;
                        rlock(sf);
-                       sendpkt("busvs", SSH_FXP_WRITE, r->reqid, sf->hand, sf->handn,
+                       sendpkt("bqsvs", SSH_FXP_WRITE, r, sf->hand, sf->handn,
                                r->req->ifcall.offset + r->req->ofcall.count,
                                r->req->ifcall.data + r->req->ofcall.count,
                                x);
                        runlock(sf);
-                       r->req->ofcall.offset = x;
                        break;
                case Tstat:
                        rlock(sf);
                        r->req->d.name = finalelem(sf->fn);
                        r->req->d.qid = sf->qid;
                        if(sf->handn > 0 && (sf->qid.type & QTDIR) == 0)
-                               sendpkt("bus", SSH_FXP_FSTAT, r->reqid, sf->hand, sf->handn);
+                               sendpkt("bqs", SSH_FXP_FSTAT, r, sf->hand, sf->handn);
                        else
-                               sendpkt("bus", SSH_FXP_STAT, r->reqid, sf->fn, strlen(sf->fn));
+                               sendpkt("bqs", SSH_FXP_STAT, r, sf->fn, strlen(sf->fn));
                        runlock(sf);
                        break;
                case Twstat:
-                       if(r->req->aux == (void *) -1){
+                       if(r->req->aux == (void*)-1){
                                rlock(sf);
                                s = parentdir(sf->fn);
                                t = pathcat(s, r->req->d.name);
-                               free(s);
                                r->req->aux = t;
-                               sendpkt("buss", SSH_FXP_RENAME, r->reqid, sf->fn, strlen(sf->fn), t, strlen(t));
+                               sendpkt("bqss", SSH_FXP_RENAME, r, sf->fn, strlen(sf->fn), t, strlen(t));
                                runlock(sf);
+                               free(s);
                                break;
                        }
                        x = dir2attrib(&r->req->d, (uchar **) &s);
                        if(x < 0){
                                responderror(r->req);
                                putsreq(r);
+                               free(s);
                                break;
                        }
                        rlock(sf);
                        if(sf->handn > 0)
-                               sendpkt("bus[", SSH_FXP_FSETSTAT, r->reqid, sf->hand, sf->handn, s, x);
+                               sendpkt("bqs[", SSH_FXP_FSETSTAT, r, sf->hand, sf->handn, s, x);
                        else
-                               sendpkt("bus[", SSH_FXP_SETSTAT, r->reqid, sf->fn, strlen(sf->fn), s, x);
+                               sendpkt("bqs[", SSH_FXP_SETSTAT, r, sf->fn, strlen(sf->fn), s, x);
                        runlock(sf);
                        free(s);
                        break;
                case Tremove:
                        rlock(sf);
                        if((sf->qid.type & QTDIR) != 0)
-                               sendpkt("bus", SSH_FXP_RMDIR, r->reqid, sf->fn, strlen(sf->fn));
+                               sendpkt("bqs", SSH_FXP_RMDIR, r, sf->fn, strlen(sf->fn));
                        else
-                               sendpkt("bus", SSH_FXP_REMOVE, r->reqid, sf->fn, strlen(sf->fn));
+                               sendpkt("bqs", SSH_FXP_REMOVE, r, sf->fn, strlen(sf->fn));
                        runlock(sf);
                        break;
                default:
@@ -983,7 +993,6 @@ recvproc(void *)
                r = sreqrd[id];
                if(r != nil){
                        sreqrd[id] = nil;
-                       r->reqid = -1;
                        rwakeup(&sreqidrend);
                }
                qunlock(&sreqidlock);
@@ -992,13 +1001,14 @@ recvproc(void *)
                        continue;
                }
                if(r->closefid != nil){
+                       putsfid(r->closefid);
                        putsreq(r);
                        continue;
                }
                if(r->req == nil)
                        sysfatal("recvproc: r->req == nil");
 
-               sf = r->req->fid != nil ? r->req->fid->aux : nil;
+               sf = r->req->fid->aux;
                okresp = rxlen >= 9 && t == SSH_FXP_STATUS && GET4(rxpkt+5) == SSH_FX_OK;
                switch(r->req->ifcall.type){
                case Tattach:
@@ -1094,7 +1104,7 @@ recvproc(void *)
                                break;
                        }
                        if(r->req->aux == nil){
-                               r->req->aux = (void *) -1;
+                               r->req->aux = (void*)-1;
                                submitreq(r->req);
                        }else{
                                wlock(sf);
@@ -1199,7 +1209,6 @@ sshfsdestroyfid(Fid *f)
                return;
        if(sf->hand != nil){
                sr = emalloc9p(sizeof(SReq));
-               sr->reqid = -1;
                sr->closefid = sf;
                submitsreq(sr);
        }else