Annotation of researchv10no/sys/fs/netb.c, revision 1.1.1.1

1.1       root        1: #include "sys/param.h"
                      2: #include "sys/user.h"
                      3: #include "sys/netb.h"
                      4: #include "sys/inode.h"
                      5: #include "sys/buf.h"
                      6: #include "sys/systm.h"
                      7: #include "sys/stat.h"
                      8: #include "sys/file.h"
                      9: #include "sys/conf.h"
                     10: #include "sys/nbio.h"
                     11: 
                     12: static long nbtrannum;
                     13: static int nbfstyp;
                     14: int nbdebug;
                     15: int nbput(), nbupdat(), nbread(), nbwrite(), nbtrunc(), nbstat();
                     16: int nbnami(), nbioctl(), nbmount(), nbdirread();
                     17: struct fstypsw nbfs =
                     18: fsinit(nbput, nbupdat, nbread, nbwrite, nbtrunc, nbstat,
                     19:        nbnami, nbmount, nbioctl, nullopen, nbdirread);
                     20: unsigned char *getnbbuf();
                     21: #define        NBMAXMSG        (5*1024)        /* probably enough */
                     22: int nbbsz = NBMAXMSG;
                     23: 
                     24: /*
                     25:  * flags in i_un.i_fsflags
                     26:  * valid only in the root inode
                     27:  */
                     28: #define        NBUSY   01              /* already a message outstanding */
                     29: #define        NWANT   02              /* someone waiting for BUSY */
                     30: #define        NDEAD   04              /* communication line assumed dead */
                     31: 
                     32: /*
                     33:  * flags valid in any netb inode
                     34:  */
                     35: #define        NSTOK   010             /* inode data is fresh; skip next stat message */
                     36: 
                     37: nbput(ip)
                     38: register struct inode *ip;
                     39: {
                     40:        unsigned char sbuf[SNBSIZE];
                     41:        unsigned char rbuf[RNBSIZE];
                     42:        register unsigned char *sp;
                     43: 
                     44: 
                     45:        /* don't put root, as optimization.  pointless? */
                     46:        if (ip->i_mpoint->i_mroot == ip)
                     47:                return;
                     48:        if(ip->i_flag & ICHG)   /* this is an extra message, but not often? */
                     49:                nbupdat(ip, &time, &time, 0);
                     50:        sp = sbuf;
                     51:        bzero(sp, sizeof(sbuf));
                     52:        tonetchar(sp, SNB_VERSION, NETB);
                     53:        tonetchar(sp, SNB_CMD, NBPUT);
                     54:        tonetlong(sp, SNB_LEN, sizeof(sbuf));
                     55:        tonetlong(sp, SNB_TAG, ip->i_un.i_tag);
                     56:        nbsend(ip, sp, rbuf, sizeof(rbuf));
                     57: }
                     58: 
                     59: nbtrunc(ip)
                     60: register struct inode *ip;
                     61: {
                     62:        unsigned char sbuf[SNBSIZE];
                     63:        unsigned char rbuf[RNBSIZE];
                     64:        register unsigned char *sp;
                     65: 
                     66:        ip->i_un.i_fsflags &=~ NSTOK;
                     67:        sp = sbuf;
                     68:        bzero(sp, sizeof(sbuf));
                     69:        tonetchar(sp, SNB_VERSION, NETB);
                     70:        tonetchar(sp, SNB_CMD, NBTRNC);
                     71:        tonetlong(sp, SNB_LEN, sizeof(sbuf));
                     72:        tonetlong(sp, SNB_TAG, ip->i_un.i_tag);
                     73:        nbsend(ip, sp, rbuf, sizeof(rbuf));
                     74: }
                     75: 
                     76: /*
                     77:  * the only times we're interested in are those which have waitfor == 0
                     78:  * (or those which have ta or tb != &time)
                     79:  */
                     80: nbupdat(ip, ta, tb, waitfor)
                     81: register time_t *ta, *tb;
                     82: register struct inode *ip;
                     83: {
                     84:        unsigned char sbuf[SUPSIZE];
                     85:        unsigned char rbuf[RNBSIZE];
                     86:        register unsigned char *sp;
                     87: 
                     88:        ip->i_un.i_fsflags &=~ NSTOK;
                     89:        sp = sbuf;
                     90:        bzero(sp, sizeof(sbuf));
                     91:        tonetchar(sp, SNB_VERSION, NETB);
                     92:        tonetchar(sp, SNB_CMD, NBUPD);
                     93:        tonetlong(sp, SNB_LEN, sizeof(sbuf));
                     94:        tonetlong(sp, SNB_TAG, ip->i_un.i_tag);
                     95:        tonetshort(sp, SUP_MODE, ip->i_mode);
                     96:        /*
                     97:         * in theory *ta or *tb could be incremented
                     98:         * while we are copying them char-by-char
                     99:         * in practice, it doesn't matter,
                    100:         * as *t? != &time
                    101:         */
                    102:        if((ta != &time) && (ip->i_flag & IACC))
                    103:                tonetlong(sp, SUP_ATIME, *ta);
                    104:        if((tb != &time) && (ip->i_flag & IUPD))
                    105:                tonetlong(sp, SUP_MTIME, *tb);
                    106:        nbsend(ip, sp, rbuf, sizeof(rbuf));
                    107:        ip->i_flag &= ~(IUPD|IACC|ICHG);
                    108: }
                    109: 
                    110: /*
                    111:  * if NSTOK is set,
                    112:  * the inode is full of stat data from a recent namei
                    113:  * for stat, NSTOK always set, because we just called namei
                    114:  * (except for the root, for which namei isn't called)
                    115:  * for fstat, it is probably not set
                    116:  */
                    117: nbstat(ip, ub)
                    118: register struct inode *ip;
                    119: struct stat *ub;
                    120: {
                    121:        unsigned char sbuf[SSTSIZE];
                    122:        unsigned char rbuf[RSTSIZE];
                    123:        struct stat ds;
                    124:        register unsigned char *p;
                    125:        long now;
                    126: 
                    127:        if ((ip->i_un.i_fsflags & NSTOK) == 0) {
                    128:                p = sbuf;
                    129:                bzero(p, sizeof(sbuf));
                    130:                tonetchar(p, SNB_VERSION, NETB);
                    131:                tonetchar(p, SNB_CMD, NBSTAT);
                    132:                tonetlong(p, SNB_LEN, sizeof(sbuf));
                    133:                tonetlong(p, SNB_TAG, ip->i_un.i_tag);
                    134:                now = time;             /* in case clock ticks */
                    135:                tonetlong(p, SST_TIME, now);
                    136:                nbsend(ip, p, rbuf, sizeof(rbuf));
                    137:                if(u.u_error)
                    138:                        return;
                    139:                p = rbuf;
                    140:                ip->i_mode = frnetshort(p, RST_MODE);
                    141:                ip->i_nlink = frnetshort(p, RST_NLINK);
                    142:                ip->i_uid = frnetshort(p, RST_UID);
                    143:                ip->i_gid = frnetshort(p, RST_GID);
                    144:                ip->i_size = frnetlong(p, RST_SIZE);
                    145:                ip->i_un.i_netatime = frnetlong(p, RST_ATIME);
                    146:                ip->i_un.i_netmtime = frnetlong(p, RST_MTIME);
                    147:                ip->i_un.i_netctime = frnetlong(p, RST_CTIME);
                    148:                ip->i_un.i_netrdev = frnetlong(p, RST_RDEV);
                    149:        }
                    150:        ds.st_dev = ip->i_dev;
                    151:        ds.st_ino = ip->i_number;
                    152:        ds.st_mode = ip->i_mode;
                    153:        ds.st_nlink = ip->i_nlink;
                    154:        ds.st_uid = ip->i_uid;
                    155:        ds.st_gid = ip->i_gid;
                    156:        ds.st_size = ip->i_size;
                    157:        ds.st_atime = ip->i_un.i_netatime;
                    158:        ds.st_mtime = ip->i_un.i_netmtime;
                    159:        ds.st_ctime = ip->i_un.i_netctime;
                    160:        ds.st_rdev = ip->i_un.i_netrdev;
                    161:        if(copyout((caddr_t)&ds, (caddr_t)ub, sizeof(ds)))
                    162:                u.u_error = EFAULT;
                    163:        ip->i_un.i_fsflags &=~ NSTOK;   /* so repeated fstats check for changes */
                    164: }
                    165: 
                    166: /*
                    167:  * here and in nbwrite, `tonetlong(..., Ltol(u.u_offset))' is OK.
                    168:  * it looks like four function calls, one per byte,
                    169:  * but Ltol is a macro without side effects.
                    170:  * maybe there should just be a temporary for clarity
                    171:  */
                    172: nbread(ip)
                    173: register struct inode *ip;
                    174: {
                    175:        unsigned char sbuf[SRDSIZE];
                    176:        register unsigned char *rp;
                    177:        register unsigned char *sp;
                    178:        register int n;
                    179: 
                    180:        ip->i_un.i_fsflags &=~ NSTOK;
                    181:        rp = getnbbuf();
                    182:        sp = sbuf;
                    183:        bzero(sp, sizeof(sbuf));
                    184:        tonetchar(sp, SNB_VERSION, NETB);
                    185:        tonetchar(sp, SNB_CMD, NBREAD);
                    186:        tonetlong(sp, SNB_LEN, sizeof(sbuf));
                    187:        tonetlong(sp, SNB_TAG, ip->i_un.i_tag);
                    188:        do {
                    189:                n = u.u_count;
                    190:                if(n > nbbsz - RNBSIZE)
                    191:                        n = nbbsz - RNBSIZE;
                    192:                tonetlong(sp, SRD_LEN, n);
                    193:                tonetlong(sp, SRD_OFFSET, Ltol(u.u_offset));
                    194:                nbsend(ip, sp, rp, nbbsz);
                    195:                if (u.u_error)
                    196:                        break;
                    197:                n = frnetlong(rp, RNB_LEN) - RNBSIZE;
                    198:                if(n > 0 && n <= nbbsz) /* give it to user */
                    199:                        iomove(rp + RNBSIZE, n, B_READ);
                    200:        } while (u.u_error == 0 && u.u_count > 0 && n > 0
                    201:          &&  frnetchar(rp, RNB_FLAGS) != NBEND);
                    202:        putnbbuf(rp);
                    203: }
                    204: 
                    205: nbdirread(ip, len)
                    206: register struct inode *ip;
                    207: {
                    208:        unsigned char sbuf[SRDSIZE];
                    209:        register unsigned char *sp;
                    210:        register unsigned char *rp;     /* RDISIZE */
                    211:        int n;
                    212:        llong_t oldoff;
                    213:        long netoff;    /* just the 32-bit part */
                    214: 
                    215:        ip->i_un.i_fsflags &=~ NSTOK;
                    216:        rp = getnbbuf();
                    217:        sp = sbuf;
                    218:        bzero(sp, sizeof(sbuf));
                    219:        tonetchar(sp, SNB_VERSION, NETB);
                    220:        tonetchar(sp, SNB_CMD, NBDIR);
                    221:        tonetlong(sp, SNB_LEN, sizeof(sbuf));
                    222:        tonetlong(sp, SNB_TAG, ip->i_un.i_tag);
                    223:        if(len > nbbsz - RDISIZE)
                    224:                len = nbbsz - RDISIZE;
                    225:        tonetlong(sp, SRD_LEN, len);
                    226:        oldoff = u.u_offset;
                    227:        netoff = Ltol(u.u_offset);
                    228:        tonetlong(sp, SRD_OFFSET, netoff);
                    229:        nbsend(ip, sp, rp, nbbsz);
                    230:        if(u.u_error)
                    231:                goto out;
                    232:        n = frnetlong(rp, RNB_LEN) - RDISIZE;
                    233:        if (n > 0 && n <= nbbsz)
                    234:                iomove(rp + RDISIZE, n, B_READ);
                    235:        if (u.u_error)
                    236:                goto out;
                    237:        u.u_offset = Lladd(oldoff, frnetlong(rp, RDI_USED));
                    238:        u.u_r.r_val1 = n;
                    239: out:
                    240:        putnbbuf(rp);
                    241: }
                    242: 
                    243: nbwrite(ip)
                    244: register struct inode *ip;
                    245: {
                    246:        register unsigned char *sp;
                    247:        unsigned char rbuf[RNBSIZE];
                    248:        int n;
                    249: 
                    250:        ip->i_un.i_fsflags &=~ NSTOK;
                    251:        sp = getnbbuf();
                    252:        bzero(sp, SWRSIZE);
                    253:        tonetchar(sp, SNB_VERSION, NETB);
                    254:        tonetchar(sp, SNB_CMD, NBWRT);
                    255:        tonetlong(sp, SNB_TAG, ip->i_un.i_tag);
                    256:        do {
                    257:                n = u.u_count;
                    258:                if(n > nbbsz - SWRSIZE)
                    259:                        n = nbbsz - SWRSIZE;
                    260:                tonetlong(sp, SNB_LEN, n + SWRSIZE);
                    261:                tonetlong(sp, SWR_LEN, n);
                    262:                tonetlong(sp, SWR_OFFSET, Ltol(u.u_offset));
                    263:                iomove(sp + SWRSIZE, n, B_WRITE);
                    264:                if (u.u_error)
                    265:                        break;
                    266:                nbsend(ip, sp, rbuf, sizeof(rbuf));
                    267:                if (u.u_error)
                    268:                        break;
                    269:                ip->i_flag |= IUPD|ICHG;
                    270:        } while(u.u_count > 0);
                    271:        if(u.u_error == 0)
                    272:                ip->i_size = frnetlong(rbuf, RNB_FSIZE);
                    273:        putnbbuf(sp);
                    274: }
                    275: 
                    276: nbioctl(ip, cmd, addr, flag)   /* fp->f_flag */
                    277: register struct inode *ip;
                    278: caddr_t addr;
                    279: {
                    280:        register unsigned char *p;
                    281:        int size;
                    282: 
                    283:        switch(cmd) {
                    284:        case NBIOCON:
                    285:                nbdebug = 1;
                    286:                return;
                    287:        case NBIOCOFF:
                    288:                nbdebug = 0;
                    289:                return;
                    290:        case NBIOCBSZ:
                    291:                if (copyin(addr, (caddr_t)&size, sizeof(size))) {
                    292:                        u.u_error = EFAULT;
                    293:                        return;
                    294:                }
                    295:                if (size > 1024 && size <= NBMAXMSG)
                    296:                        nbbsz = size & ~1023;   /* round to even 1K */
                    297:                if (copyout(addr, (caddr_t)&nbbsz, sizeof(nbbsz)))
                    298:                        u.u_error = EFAULT;
                    299:                return;
                    300:        }
                    301:        /*
                    302:         * one buffer, used first for sbuf, then for rbuf
                    303:         */
                    304:        p = getnbbuf();
                    305:        bzero(p, SIOSIZE);
                    306:        tonetchar(p, SNB_VERSION, NETB);
                    307:        tonetchar(p, SNB_CMD, NBIOCTL);
                    308:        tonetlong(p, SNB_LEN, SIOSIZE + SIODATA);
                    309:        tonetlong(p, SNB_TAG, ip->i_un.i_tag);
                    310:        tonetlong(p, SIO_CMD, cmd);
                    311:        tonetshort(p, SIO_FLAG, flag);
                    312:        if(copyin(addr, p + SIOSIZE, SIODATA)) {
                    313:                u.u_error = EFAULT;
                    314:                goto out;
                    315:        }
                    316:        nbsend(ip, p, p, RNBSIZE + SIODATA);
                    317:        if (u.u_error)
                    318:                goto out;
                    319:        if(frnetlong(p, RNB_LEN) != RNBSIZE + SIODATA) {
                    320:                printf("netb: nbioc got %d, not %d\n",
                    321:                        frnetlong(p, RNB_LEN), RNBSIZE+SIODATA);
                    322:                u.u_error = EIO;
                    323:                goto out;
                    324:        }
                    325:        if(copyout(p+RNBSIZE, addr, SIODATA))
                    326:                u.u_error = EFAULT;
                    327: out:
                    328:        putnbbuf(p);
                    329: }
                    330: 
                    331: /*
                    332:  * namei:
                    333:  * send the whole pathname
                    334:  * wrong if another filesystem is mounted
                    335:  * atop some file in this one
                    336:  */
                    337: nbnami(p, flagp, follow)
                    338: register struct nx *p;
                    339: register struct argnamei *flagp;
                    340: {
                    341:        register char *cp;
                    342:        register struct inode *dp;
                    343:        register unsigned char *pp;
                    344:        register int nlen;
                    345:        int used;
                    346:        dev_t dev;
                    347: 
                    348:        dp = p->dp;
                    349:        /*
                    350:         * special case:
                    351:         * if simple lookup of "" in the root,
                    352:         * and the connection is dead,
                    353:         * return OK even though dead so it's possible to unmount
                    354:         */
                    355:        if (dp->i_mpoint->i_mroot == dp
                    356:        &&  dp->i_un.i_fsflags & NDEAD
                    357:        &&  flagp->flag == NI_SEARCH && *p->cp == 0)
                    358:                return (0);     /* with the same dp and cp */
                    359:        /*
                    360:         * one buffer for rbuf and sbuf
                    361:         */
                    362:        pp = getnbbuf();
                    363:        bzero(pp, SNMSIZE);
                    364:        tonetchar(pp, SNB_VERSION, NETB);
                    365:        tonetchar(pp, SNB_CMD, NBNAMI);
                    366:        tonetlong(pp, SNB_TAG, dp->i_un.i_tag);
                    367:        cp = p->cp;
                    368:        while (*cp++)
                    369:                ;
                    370:        nlen = cp - p->cp;      /* length of name, including NUL */
                    371:        if (nlen + SNMSIZE >= nbbsz) {
                    372:                u.u_error = ENOENT;
                    373:                goto outnull;
                    374:        }
                    375:        used = nlen + SNMSIZE - 1;      /* temporary to improve code */
                    376:        tonetlong(pp, SNB_LEN, used);
                    377:        bcopy(p->cp, pp + SNMSIZE, nlen);
                    378:        tonetchar(pp, SNB_FLAGS, flagp->flag);
                    379:        switch (flagp->flag) {
                    380: 
                    381:        case NI_CREAT:
                    382:        case NI_NXCREAT:
                    383:        case NI_MKDIR:
                    384:                tonetshort(pp, SNM_MODE, flagp->un.mode);
                    385:                break;
                    386: 
                    387:        case NI_LINK:
                    388:                tonetlong(pp, SNM_INO, flagp->un.il->i_un.i_tag);
                    389:                break;
                    390:        }
                    391:        nbsend(dp, pp, pp, RNMSIZE);
                    392:        if(u.u_error)
                    393:                goto outnull;
                    394:        if (frnetchar(pp, RNB_FLAGS) == NBROOT) {
                    395:                /* find my root */
                    396:                dp = dp->i_mpoint;
                    397:                iput(p->dp);
                    398:                if(dp == NULL) {
                    399:                        u.u_error = EGREG;
                    400:                        goto out;
                    401:                }
                    402:                plock(dp);
                    403:                dp->i_count++;
                    404:                used = frnetlong(pp, RNM_USED);
                    405:                if (used < 2 || used >= nlen) {
                    406:                        u.u_error = EGREG;
                    407:                        goto outnull;
                    408:                }
                    409:                cp = p->cp + used;
                    410:                *--cp == '.';
                    411:                *--cp == '.';
                    412:                p->cp = cp;
                    413:                goto outmore;
                    414:        }
                    415:        switch(flagp->flag) {
                    416: 
                    417:        default:
                    418:                panic("nbnami");
                    419: 
                    420:        case NI_CREAT:  /* only case where flagp is used later (creat()) */
                    421:        case NI_NXCREAT:        /* return an inode, like search */
                    422:                flagp->un.mode = ~flagp->un.mode;       /* obscure side-effects! */
                    423:        case NI_SEARCH:
                    424:                break;
                    425: 
                    426:        case NI_DEL:    /* nothing returned */
                    427:        case NI_LINK:   /* nothing returned */
                    428:        case NI_MKDIR:  /* nothing returned */
                    429:        case NI_RMDIR:  /* nothing returned */
                    430:                goto outnull;
                    431:        }
                    432:        /*
                    433:         * release directory inode, construct a new one
                    434:         * fill in the attributes even if inode was already in core;
                    435:         * the new data is more correct (server gets priority)
                    436:         */
                    437:        prele(dp);      /* in case new == old */
                    438:        /* cheat: first character of RNM_DEV == minor */
                    439:        dev = makedev(major(dp->i_dev), frnetchar(pp, RNM_DEV));
                    440:        dp = iget(dp, dev, frnetlong(pp, RNM_INO));
                    441:        /* p->dp == dp before iget was called */
                    442:        if (dp == NULL) {
                    443:                idec(p->dp);
                    444:                goto out;
                    445:        }
                    446:        if (p->dp->i_mpoint != dp->i_mpoint) {  /* something mounted here */
                    447:                idec(p->dp);
                    448:                p->cp += nlen - 1;      /* point to NUL at the end */
                    449:                goto outmore;
                    450:        }
                    451:        dp->i_un.i_cip = p->dp->i_un.i_cip;
                    452:        idec(p->dp);
                    453:        nbunpack(dp, pp);
                    454:        /*
                    455:         * no filename to save for accounting; oh well
                    456:         */
                    457:        if(flagp->flag == NI_SEARCH && flagp->un.buf)
                    458:                bcopy("netb exec", flagp->un.buf, flagp->len);
                    459: 
                    460:        /*
                    461:         * return the inode in dp
                    462:         */
                    463: out:
                    464:        p->dp = dp;
                    465:        putnbbuf(pp);
                    466:        return (0);
                    467: 
                    468:        /*
                    469:         * discard dp, return NULL
                    470:         */
                    471: outnull:
                    472:        iput(dp);
                    473:        p->dp = NULL;
                    474:        putnbbuf(pp);
                    475:        return (0);
                    476: 
                    477:        /*
                    478:         * crossed to a different filesystem;
                    479:         * return cp and dp
                    480:         */
                    481: outmore:
                    482:        p->dp = dp;
                    483:        putnbbuf(pp);
                    484:        return (1);
                    485: }
                    486: 
                    487: nbmount(cip, dip, flag, mnt, fstyp)
                    488: struct inode *cip, *dip;
                    489: {
                    490: 
                    491:        nbfstyp = fstyp;
                    492:        if (mnt)
                    493:                nbon(cip, dip, flag, fstyp);
                    494:        else
                    495:                nboff(dip);
                    496: }
                    497: 
                    498: /*
                    499:  * data structures for keeping track of device numbers in use
                    500:  */
                    501: #define        NDEVS   256
                    502: static char nbdevs[NDEVS];
                    503: 
                    504: #define        D_SET(dev)      nbdevs[dev] = 1
                    505: #define        D_CLR(dev)      nbdevs[dev] = 0
                    506: #define        D_ISSET(dev)    nbdevs[dev]
                    507: 
                    508: /*
                    509:  * mount the filesystem
                    510:  * fake up a namei message to fetch the root
                    511:  * don't call nbnami because it's too hard to get
                    512:  * all the first-time error checks right
                    513:  */
                    514: 
                    515: nbon(cip, dip, flag, fstyp)
                    516: struct inode *cip;
                    517: struct inode *dip;
                    518: {
                    519:        register struct inode *rip;
                    520:        struct inode pi;
                    521:        register unsigned char *pp;
                    522:        unsigned char sbuf[SNMSIZE+1];
                    523:        unsigned char rbuf[RNMSIZE];
                    524:        register int dmaj;
                    525: 
                    526:        if(cip->i_sptr == NULL) {       /* shouting into the storm */
                    527:                u.u_error = ENXIO;
                    528:                return;
                    529:        }
                    530:        for (dmaj = 0; dmaj < NDEVS; dmaj++)
                    531:                if (D_ISSET(dmaj) == 0)
                    532:                        break;
                    533:        if (dmaj >= NDEVS) {
                    534:                u.u_error = EMFILE;
                    535:                return;
                    536:        }
                    537:        D_SET(dmaj);
                    538:        /*
                    539:         * fake up an inode to represent the connection
                    540:         * to nbsend and iget
                    541:         */
                    542:        pi.i_fstyp = fstyp;
                    543:        pi.i_mpoint = &pi;
                    544:        pi.i_mroot = &pi;       /* pi.i_mpoint->i_mroot == &pi */
                    545:        pi.i_un.i_cip = cip;
                    546:        pi.i_un.i_fsflags = 0;
                    547:        pp = sbuf;
                    548:        bzero(pp, sizeof(sbuf));
                    549:        tonetchar(pp, SNB_VERSION, NETB);
                    550:        tonetchar(pp, SNB_CMD, NBNAMI);
                    551:        tonetlong(pp, SNB_TAG, NBROOTTAG);      /* lookup in the root */
                    552:        tonetlong(pp, SNB_LEN, SNMSIZE+1);      /* one char of filename */
                    553:        /* tonetchar(pp, SNMSIZE, 0);           /* "" */
                    554:        tonetchar(pp, SNB_FLAGS, NI_SEARCH);
                    555:        nbsend(&pi, pp, rbuf, sizeof(rbuf));
                    556:        if (u.u_error) {
                    557:                D_CLR(dmaj);
                    558:                return;
                    559:        }
                    560:        pp = rbuf;
                    561:        if (frnetchar(pp, RNB_FLAGS) != 0) {
                    562:                D_CLR(dmaj);
                    563:                u.u_error = EINVAL;
                    564:                return;
                    565:        }
                    566:        if ((rip = iget(&pi, makedev(dmaj, frnetchar(pp, RNM_DEV)), frnetlong(pp, RNM_INO))) == NULL) {
                    567:                D_CLR(dmaj);
                    568:                return;
                    569:        }
                    570:        if (rip->i_count != 1) {
                    571:                printf("nbon busy, dev %d\n", dmaj);    /* shouldn't happen */
                    572:                iput(rip);
                    573:                D_CLR(dmaj);
                    574:                u.u_error = EBUSY;
                    575:                return;
                    576:        }
                    577:        nbunpack(rip, pp);
                    578:        rip->i_un.i_cip = cip;
                    579:        dip->i_mroot = rip;
                    580:        rip->i_mpoint = dip;
                    581:        prele(rip);
                    582:        dip->i_count++;
                    583:        cip->i_count++;
                    584: }
                    585: 
                    586: /*
                    587:  * unpack inode info from namei response
                    588:  * a pity stat can't use this too,
                    589:  * but the stat response isn't quite the same format
                    590:  */
                    591: nbunpack(dp, pp)
                    592: register struct inode *dp;
                    593: register unsigned char *pp;
                    594: {
                    595: 
                    596:        dp->i_un.i_tag = frnetlong(pp, RNM_TAG);
                    597:        dp->i_mode = frnetshort(pp, RNM_MODE);
                    598:        dp->i_nlink = frnetshort(pp, RNM_NLINK);
                    599:        dp->i_uid = frnetshort(pp, RNM_UID);
                    600:        dp->i_gid = frnetshort(pp, RNM_GID);
                    601:        dp->i_size = frnetlong(pp, RNM_SIZE);
                    602:        dp->i_un.i_netatime = frnetlong(pp, RNM_ATIME);
                    603:        dp->i_un.i_netmtime = frnetlong(pp, RNM_MTIME);
                    604:        dp->i_un.i_netctime = frnetlong(pp, RNM_CTIME);
                    605:        dp->i_un.i_netrdev = frnetlong(pp, RNM_RDEV);
                    606:        if (dp->i_count == 1)
                    607:                dp->i_un.i_fsflags = 0;
                    608:        dp->i_un.i_fsflags |= NSTOK;
                    609: }
                    610: 
                    611: /*
                    612:  * unmount a netb--
                    613:  * mip is the mount point
                    614:  * locking needs some thought
                    615:  */
                    616: nboff(mip)
                    617: register struct inode *mip;
                    618: {
                    619:        register struct inode *rip;
                    620: 
                    621:        rip = mip->i_mroot;
                    622:        plock(rip);
                    623:        if (rip->i_mpoint != mip) {     /* already unmounted */
                    624:                prele(rip);
                    625:                return;
                    626:        }
                    627:        xumount(rip);
                    628:        iupdat(rip, &time, &time, 1);
                    629:        ifsinacc(rip);  /* turn all, including rip, to errfs */
                    630:        plock(mip);             
                    631:        mip->i_mroot = NULL;
                    632:        iput(mip);
                    633:        if (rip->i_un.i_cip == NULL)
                    634:                panic("nboff");
                    635:        iput(rip->i_un.i_cip);
                    636:        D_CLR(major(rip->i_dev));
                    637:        iput(rip);      /* errput, not nbput */
                    638: }
                    639: 
                    640: nbsend(ip, sp, rp, size)
                    641: struct inode *ip;
                    642: register unsigned char *sp;
                    643: unsigned char *rp;
                    644: {
                    645:        int bad;
                    646:        long tn;
                    647:        struct inode *cip;
                    648:        register struct inode *rip;
                    649: 
                    650:        cip = ip->i_un.i_cip;
                    651:        rip = ip->i_mpoint->i_mroot;
                    652:        if (rip == NULL || rip->i_fstyp != ip->i_fstyp) {
                    653:                u.u_error = EIO;
                    654:                return;
                    655:        }
                    656:        while ((rip->i_un.i_fsflags & (NBUSY|NDEAD)) == NBUSY
                    657:        &&  ip->i_fstyp == nbfstyp) {
                    658:                rip->i_un.i_fsflags |= NWANT;
                    659:                if (tsleep((caddr_t)cip, PZERO+1, 0) != TS_OK) {
                    660:                        u.u_error = EIO;
                    661:                        return;
                    662:                }
                    663:        }
                    664:        if (ip->i_fstyp != nbfstyp      /* unmounted under us */
                    665:        ||  rip->i_un.i_fsflags & NDEAD) {      /* or connection fell down */
                    666:                u.u_error = EIO;
                    667:                return;
                    668:        }
                    669:        rip->i_un.i_fsflags |= NBUSY;
                    670:        tonetshort(sp, SNB_UID, u.u_uid);
                    671:        tonetshort(sp, SNB_GID, u.u_gid);
                    672:        tn = nbtrannum++;
                    673:        tonetlong(sp, SNB_TRANNUM, tn);
                    674:        if (istwrite(cip, sp, frnetlong(sp, SNB_LEN)) >= 0
                    675:        &&  nbrecv(cip, rp, size, tn) >= 0)
                    676:                bad = 0;
                    677:        else
                    678:                bad = 1;
                    679:        if (ip->i_fstyp == nbfstyp) {   /* in case unmounted while asleep */
                    680:                rip->i_un.i_fsflags &=~ NBUSY;
                    681:                if (rip->i_un.i_fsflags & NWANT) {
                    682:                        wakeup((caddr_t)cip);
                    683:                        rip->i_un.i_fsflags &=~ NWANT;
                    684:                }
                    685:                if (bad)
                    686:                        rip->i_un.i_fsflags |= NDEAD;
                    687:        }
                    688:        if (bad)
                    689:                u.u_error = EIO;
                    690:        else if ((bad = frnetshort(rp, RNB_ERRNO)) != 0)
                    691:                u.u_error = bad;
                    692: }
                    693: 
                    694: /*
                    695:  * read an answer,
                    696:  * and make sure it smells like one of ours
                    697:  */
                    698: 
                    699: int
                    700: nbrecv(cip, rp, size, tn)
                    701: struct inode *cip;
                    702: register unsigned char *rp;
                    703: int size;
                    704: long tn;
                    705: {
                    706:        unsigned char *p;
                    707:        register int n, len, netlen;
                    708: 
                    709: loop:
                    710:        p = rp;
                    711:        len = 0;
                    712:        /*
                    713:         * header
                    714:         */
                    715:        while (len < RNBSIZE) {
                    716:                n = istread(cip, p, size - len, 0);
                    717:                if (n <= 0)
                    718:                        return (-1);
                    719:                len += n;
                    720:                p += n;
                    721:        }
                    722:        netlen = frnetlong(rp, RNB_LEN);
                    723:        if (netlen > size || netlen < RNBSIZE) {
                    724:                printf("netb: rcv len %d\n", netlen);
                    725:                return (-1);
                    726:        }
                    727:        /*
                    728:         * following data, if any
                    729:         */
                    730:        while (len < netlen) {
                    731:                n = istread(cip, p, size - len, 0);
                    732:                if (n <= 0)
                    733:                        return (-1);
                    734:                len += n;
                    735:                p += n;
                    736:        }
                    737:        if (frnetlong(rp, RNB_TRANNUM) != tn) {
                    738:                if (frnetlong(rp, RNB_TRANNUM) < tn)    /* echo from the past */
                    739:                        goto loop;
                    740:                printf("netb: exp tran %d, got %d\n", tn, frnetlong(rp, RNB_TRANNUM));
                    741:                return (-1);
                    742:        }
                    743:        return (len);
                    744: }
                    745: 
                    746: /* oh no, it's got its own tiny buffer pool: want to avoid breakage on
                    747:        normal (4k reads for now).  we could replace this with a real
                    748:        memory manager in the kernel */
                    749: #define        NBUF    7       /* who knows? */
                    750: char nb_lock;
                    751: char nbflgs[NBUF];
                    752: unsigned char nbbuf[NBUF][NBMAXMSG];
                    753: 
                    754: unsigned char *
                    755: getnbbuf()
                    756: {
                    757:        register int i;
                    758: 
                    759: loop:
                    760:        for(i = 0; i < NBUF; i++)
                    761:                if(!nbflgs[i]) {
                    762:                        nbflgs[i] = 1;
                    763:                        return(nbbuf[i]);
                    764:                }
                    765:        nb_lock = 1;
                    766:        sleep((caddr_t)&nb_lock, PZERO);
                    767:        goto loop;
                    768: }
                    769: 
                    770: putnbbuf(s)
                    771: unsigned char *s;
                    772: {
                    773:        register int i;
                    774: 
                    775:        for(i = 0; i < NBUF; i++)
                    776:                if(nbbuf[i] == s) {
                    777:                        nbflgs[i] = 0;
                    778:                        if(nb_lock) {
                    779:                                nb_lock = 0;
                    780:                                wakeup((caddr_t) &nb_lock);
                    781:                        }
                    782:                        return;
                    783:                }
                    784:        panic("putnbbuf");
                    785: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.