]> git.lizzy.rs Git - plan9front.git/blobdiff - sys/src/9/port/chan.c
kernel: fix fairshare formula in comment (thanks erik)
[plan9front.git] / sys / src / 9 / port / chan.c
index a50565ba0bb0b0a34a2cd20b0da2032fbcadcc4d..c74fb5d51d485e760f60b2d394e100ede48dfb00 100644 (file)
@@ -14,7 +14,7 @@ enum
        PATHMSLOP       = 20,
 };
 
-struct
+static struct Chanalloc
 {
        Lock;
        int     fid;
@@ -114,7 +114,6 @@ decref(Ref *r)
        unlock(r);
        if(x < 0)
                panic("decref pc=%#p", getcallerpc(&r));
-
        return x;
 }
 
@@ -130,20 +129,19 @@ kstrcpy(char *s, char *t, int ns)
        int nt;
 
        nt = strlen(t);
-       if(nt+1 <= ns){
-               memmove(s, t, nt+1);
-               return;
-       }
-       /* too long */
-       if(ns < 4){
-               /* but very short! */
-               strncpy(s, t, ns);
+       if(nt < ns){
+               memmove(s, t, nt);
+               s[nt] = '\0';
                return;
        }
-       /* truncate with ... at character boundary (very rare case) */
-       memmove(s, t, ns-4);
+       /* too long, truncate */
+       nt = ns-1;
+       memmove(s, t, nt);
+       s[nt] = '\0';
+       /* append ... if there is space */
        ns -= 4;
-       s[ns] = '\0';
+       if(ns < 0)
+               return;
        /* look for first byte of UTF-8 sequence by skipping continuation bytes */
        while(ns>0 && (s[--ns]&0xC0)==0x80)
                ;
@@ -169,17 +167,18 @@ kstrdup(char **p, char *s)
        int n;
        char *t, *prev;
 
-       n = strlen(s)+1;
+       n = strlen(s);
        /* if it's a user, we can wait for memory; if not, something's very wrong */
-       if(up){
-               t = smalloc(n);
-               setmalloctag(t, getcallerpc(&p));
-       }else{
-               t = malloc(n);
+       if(up != nil)
+               t = smalloc(n+1);
+       else{
+               t = malloc(n+1);
                if(t == nil)
                        panic("kstrdup: no memory");
        }
+       setmalloctag(t, getcallerpc(&p));
        memmove(t, s, n);
+       t[n] = '\0';
        prev = *p;
        *p = t;
        free(prev);
@@ -195,6 +194,8 @@ chandevreset(void)
                devtab[i]->reset();
 }
 
+static void closeproc(void*);
+
 void
 chandevinit(void)
 {
@@ -202,6 +203,7 @@ chandevinit(void)
 
        for(i=0; devtab[i] != nil; i++)
                devtab[i]->init();
+       kproc("closeproc", closeproc, nil);
 }
 
 void
@@ -223,8 +225,10 @@ newchan(void)
 
        lock(&chanalloc);
        c = chanalloc.free;
-       if(c != 0)
+       if(c != 0){
                chanalloc.free = c->next;
+               c->next = 0;
+       }
        unlock(&chanalloc);
 
        if(c == nil){
@@ -469,48 +473,28 @@ chanfree(Chan *c)
        unlock(&chanalloc);
 }
 
-void
-cclose(Chan *c)
-{
-       if(c == nil || c->ref < 1 || c->flag&CFREE)
-               panic("cclose %#p", getcallerpc(&c));
-
-       DBG("cclose %p name=%s ref=%ld\n", c, chanpath(c), c->ref);
-       if(decref(c))
-               return;
-
-       if(!waserror()){
-               devtab[c->type]->close(c);
-               poperror();
-       }
-       chanfree(c);
-}
-
 /*
  * Queue a chan to be closed by one of the clunk procs.
  */
 struct {
        Chan *head;
        Chan *tail;
-       int nqueued;
-       int nclosed;
+       ulong nqueued;
+       ulong nclosed;  
        Lock l;
        QLock q;
        Rendez r;
 } clunkq;
-void closeproc(void*);
 
-void
-ccloseq(Chan *c)
+static int
+clunkwork(void*)
 {
-       if(c == nil || c->ref < 1 || c->flag&CFREE)
-               panic("ccloseq %#p", getcallerpc(&c));
-
-       DBG("ccloseq %p name=%s ref=%ld\n", c, chanpath(c), c->ref);
-
-       if(decref(c))
-               return;
+       return clunkq.head != nil;
+}
 
+static void
+closechanq(Chan *c)
+{
        lock(&clunkq.l);
        clunkq.nqueued++;
        c->next = nil;
@@ -520,40 +504,54 @@ ccloseq(Chan *c)
                clunkq.head = c;
        clunkq.tail = c;
        unlock(&clunkq.l);
-
-       if(!wakeup(&clunkq.r))
-               kproc("closeproc", closeproc, nil);     
+       wakeup(&clunkq.r);
 }
 
-static int
-clunkwork(void*)
+static Chan*
+closechandeq(void)
 {
-       return clunkq.head != nil;
+       Chan *c;
+
+       lock(&clunkq.l);
+       c = clunkq.head;
+       if(c != nil) {
+               clunkq.head = c->next;
+               clunkq.nclosed++;
+       }
+       unlock(&clunkq.l);
+       return c;
 }
 
-void
-closeproc(void*)
+static void
+closeproc(void *)
 {
        Chan *c;
 
        for(;;){
-               qlock(&clunkq.q);
-               if(clunkq.head == nil){
-                       if(!waserror()){
-                               tsleep(&clunkq.r, clunkwork, nil, 5000);
+               c = closechandeq();
+               if(c == nil) {
+                       qlock(&clunkq.q);
+                       if(!waserror()) {
+                               tsleep(&clunkq.r, clunkwork, nil, 500);
                                poperror();
                        }
-                       if(clunkq.head == nil){
+                       c = closechandeq();
+                       if(c == nil) {
+                               if(clunkq.q.head != nil) {
+                                       qunlock(&clunkq.q);
+                                       pexit("no work", 1);
+                               }
                                qunlock(&clunkq.q);
-                               pexit("no work", 1);
+                               continue;
                        }
+                       if(clunkq.q.head == nil) {
+                               if(!waserror()) {
+                                       kproc("closeproc", closeproc, nil);
+                                       poperror();
+                               }
+                       }
+                       qunlock(&clunkq.q);
                }
-               lock(&clunkq.l);
-               c = clunkq.head;
-               clunkq.head = c->next;
-               clunkq.nclosed++;
-               unlock(&clunkq.l);
-               qunlock(&clunkq.q);
                if(!waserror()){
                        devtab[c->type]->close(c);
                        poperror();
@@ -562,6 +560,46 @@ closeproc(void*)
        }
 }
 
+void
+cclose(Chan *c)
+{
+       if(c == nil || c->ref < 1 || c->flag&CFREE)
+               panic("cclose %#p", getcallerpc(&c));
+
+       DBG("cclose %p name=%s ref=%ld\n", c, chanpath(c), c->ref);
+
+       if(decref(c))
+               return;
+
+       if(devtab[c->type]->dc == L'M')
+       if((c->flag&(CRCLOSE|CCACHE)) == CCACHE)
+       if((c->qid.type&(QTEXCL|QTMOUNT|QTAUTH)) == 0)
+       if((clunkq.nqueued - clunkq.nclosed) < 64){
+               closechanq(c);
+               return;
+       }
+
+       if(!waserror()){
+               devtab[c->type]->close(c);
+               poperror();
+       }
+       chanfree(c);
+}
+
+void
+ccloseq(Chan *c)
+{
+       if(c == nil || c->ref < 1 || c->flag&CFREE)
+               panic("ccloseq %#p", getcallerpc(&c));
+
+       DBG("ccloseq %p name=%s ref=%ld\n", c, chanpath(c), c->ref);
+
+       if(decref(c))
+               return;
+
+       closechanq(c);
+}
+
 /*
  * Make sure we have the only copy of c.  (Copy on write.)
  */
@@ -982,7 +1020,7 @@ walk(Chan **cp, char **names, int nnames, int nomount, int *nerror)
                                *nerror = nhave;
                        pathclose(path);
                        cclose(c);
-                       strcpy(up->errstr, Enotdir);
+                       kstrcpy(up->errstr, Enotdir, ERRMAX);
                        if(mh != nil)
                                putmhead(mh);
                        return -1;
@@ -1015,15 +1053,15 @@ walk(Chan **cp, char **names, int nnames, int nomount, int *nerror)
                                 * mh->mount->to == c, so start at mh->mount->next
                                 */
                                rlock(&mh->lock);
-                               f = mh->mount;
-                               for(f = (f? f->next: f); f; f = f->next)
-                                       if((wq = ewalk(f->to, nil, names+nhave, ntry)) != nil)
+                               if((f = mh->mount) != nil)
+                                       f = f->next;
+                               for(; f != nil; f = f->next)
+                                       if((wq = ewalk(f->to, nil, names+nhave, ntry)) != nil){
+                                               type = f->to->type;
+                                               dev = f->to->dev;
                                                break;
+                                       }
                                runlock(&mh->lock);
-                               if(f != nil){
-                                       type = f->to->type;
-                                       dev = f->to->dev;
-                               }
                        }
                        if(wq == nil){
                                cclose(c);
@@ -1063,11 +1101,11 @@ walk(Chan **cp, char **names, int nnames, int nomount, int *nerror)
                                        if(wq->nqid==0 || (wq->qid[wq->nqid-1].type&QTDIR)){
                                                if(nerror)
                                                        *nerror = nhave+wq->nqid+1;
-                                               strcpy(up->errstr, Edoesnotexist);
+                                               kstrcpy(up->errstr, Edoesnotexist, ERRMAX);
                                        }else{
                                                if(nerror)
                                                        *nerror = nhave+wq->nqid;
-                                               strcpy(up->errstr, Enotdir);
+                                               kstrcpy(up->errstr, Enotdir, ERRMAX);
                                        }
                                        free(wq);
                                        if(mh != nil)
@@ -1133,7 +1171,7 @@ createdir(Chan *c, Mhead *m)
                nexterror();
        }
        for(f = m->mount; f; f = f->next){
-               if(f->mflag&MCREATE){
+               if(f->to != nil && (f->mflag&MCREATE) != 0){
                        nc = cclone(f->to);
                        runlock(&m->lock);
                        poperror();
@@ -1452,6 +1490,10 @@ namec(char *aname, int amode, int omode, ulong perm)
                /* save&update the name; domount might change c */
                path = c->path;
                incref(path);
+               if(waserror()){
+                       pathclose(path);
+                       nexterror();
+               }
                m = nil;
                if(!nomount)
                        domount(&c, &m, &path);
@@ -1462,6 +1504,7 @@ namec(char *aname, int amode, int omode, ulong perm)
                /* now it's our copy anyway, we can put the name back */
                pathclose(c->path);
                c->path = path;
+               poperror();
 
                /* record whether c is on a mount point */
                c->ismtpt = m!=nil;
@@ -1624,7 +1667,7 @@ if(c->umh != nil){
                goto Open;
 
        default:
-               panic("unknown namec access %d\n", amode);
+               panic("unknown namec access %d", amode);
        }
 
        /* place final element in genbuf for e.g. exec */