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

1.1       root        1: /*
                      2:  * traditional disk filesystem
                      3:  */
                      4: #include "sys/param.h"
                      5: #include "sys/systm.h"
                      6: #include "sys/ino.h"
                      7: #include "sys/buf.h"
                      8: #include "sys/filsys.h"
                      9: #include "sys/mount.h"
                     10: #include "sys/dir.h"
                     11: #include "sys/user.h"
                     12: #include "sys/inode.h"
                     13: #include "sys/file.h"
                     14: #include "sys/conf.h"
                     15: #include "sys/vlimit.h"
                     16: #include "sys/stat.h"
                     17: #include "sys/filio.h"
                     18: #include "sys/cmap.h"
                     19: #include "sys/stream.h"
                     20: 
                     21: int fsput(), fsupdat(), fsread(), fswrite(), fstrunc(), fsstat();
                     22: int fsnami(), fsmount(), fsioctl(), fsdirread();
                     23: struct inode *fsopen();
                     24: struct fstypsw fsfs =
                     25: fsinit(fsput, fsupdat, fsread, fswrite, fstrunc, fsstat,
                     26:        fsnami, fsmount, fsioctl, fsopen, fsdirread);
                     27: 
                     28: extern struct mount fsmtab[];
                     29: extern int fscnt;
                     30: 
                     31: /*
                     32:  * silly mount/unmount routine for fs type 0
                     33:  */
                     34: 
                     35: fsmount(sip, ip, flag, mnt, fstyp)
                     36: register struct inode *ip, *sip;
                     37: int flag, mnt, fstyp;
                     38: {
                     39: 
                     40:        if (!suser())
                     41:                return;
                     42:        if (mnt)
                     43:                fson(sip, ip, flag, fstyp);
                     44:        else
                     45:                fsoff(ip, fstyp);
                     46: }
                     47: 
                     48: /*
                     49:  * mount a type 0 filesystem (sip on ip)
                     50:  * maintain the mount table for vm code's sake
                     51:  *
                     52:  * magic to help booting:
                     53:  * if rootdir == NULL, we are being called from iinit, so
                     54:  *     - allow s_valid == 0 on bitmapped filesystems so root may be mounted
                     55:  *     - call clkinit to set the clock from the super-block time
                     56:  */
                     57: 
                     58: fson(sip, ip, ronly, fstyp)
                     59: register struct inode *ip, *sip;
                     60: int ronly, fstyp;
                     61: {
                     62:        dev_t dev;
                     63:        register struct mount *mp;
                     64:        struct mount *emp;
                     65:        struct inode *rip;
                     66:        register struct filsys *fp;
                     67:        struct buf *bp;
                     68:        struct inode pi;        /* primer */
                     69: 
                     70:        if ((sip->i_mode&IFMT) != IFBLK) {
                     71:                u.u_error = EINVAL;
                     72:                return;
                     73:        }
                     74:        if (ip->i_fstyp == fstyp && ip->i_dev == sip->i_un.i_rdev) {
                     75:                u.u_error = EBUSY;
                     76:                return;
                     77:        }
                     78:        emp = NULL;
                     79:        for (mp = &fsmtab[fscnt-1]; mp >= fsmtab; mp--) {
                     80:                if (mp->m_dev == NULL)
                     81:                        emp = mp;
                     82:                else if (mp->m_dev == sip)
                     83:                        goto hopeless;
                     84:        }
                     85:        if (emp == NULL)
                     86:                goto hopeless;
                     87:        emp->m_dev = sip;
                     88:        dev = (dev_t)sip->i_un.i_rdev;
                     89:        bp = bread(dev, SUPERB);
                     90:        if(u.u_error) {
                     91:                emp->m_dev = NULL;
                     92:                brelse(bp);
                     93:                return;
                     94:        }
                     95:        bp->b_flags |= B_LOCKED;
                     96:        brelse(bp);
                     97:        fp = bp->b_un.b_filsys;
                     98:        fp->s_ilock = 0;
                     99:        fp->s_flock = 0;
                    100:        fp->s_ronly = ronly & 1;
                    101:        fp->s_nbehind = 0;
                    102:        fp->s_lasti = 1;
                    103:        if(fp->s_cylsize == 0)
                    104:                fp->s_cylsize = 40;     /* transition hack */
                    105:        if(fp->s_aspace == 0)
                    106:                fp->s_aspace = 4;       /* likewise */
                    107:        if(BITFS(dev) && !fp->s_valid && !fp->s_ronly && rootdir != NULL)
                    108:                goto failed;                    /* NOT IMPLEMENTED */
                    109:        if(BITFS(dev) && fp->U.N.S_flag) {
                    110:                if(fsbiton(dev, fp))
                    111:                        goto failed;
                    112:        /* hack until pjw fixes chuck */
                    113:        } else if (BITFS(dev) && fp->s_isize + BITMAP*BITCELL < fp->s_fsize)
                    114:                if(fsbiton(dev, fp))
                    115:                        goto failed;
                    116:        pi.i_dev = dev;
                    117:        pi.i_fstyp = fstyp;
                    118:        pi.i_un.i_bufp = bp;
                    119:        if ((rip = iget(&pi, dev, ROOTINO)) == NULL)
                    120:                goto failed;
                    121:        if (rip->i_count == 1 && fsiread(&pi, rip) < 0)
                    122:                goto failed;
                    123:        if (rip->i_count != 1) {        /* already mounted */
                    124:                iput(rip);
                    125:                goto failed;
                    126:        }
                    127:        emp->m_mroot = rip;
                    128:        ip->i_mroot = rip;
                    129:        rip->i_mpoint = ip;
                    130:        ip->i_count++;
                    131:        sip->i_count++;
                    132:        prele(rip);
                    133:        if (rootdir == NULL)
                    134:                clkinit(fp->s_time);
                    135:        return;
                    136: failed:
                    137:        bp->b_flags &= ~B_LOCKED;
                    138:        emp->m_dev = NULL;
                    139: hopeless:
                    140:        if (u.u_error == 0)
                    141:                u.u_error = EBUSY;
                    142: }
                    143: 
                    144: fsoff(mip, fstyp)
                    145: register struct inode *mip;
                    146: {
                    147:        dev_t dev;
                    148:        register struct mount *mp;
                    149:        register struct inode *rip;
                    150:        struct buf *bp;
                    151:        struct filsys *fp;
                    152: 
                    153:        rip = mip->i_mroot;
                    154:        for (mp = &fsmtab[fscnt-1]; mp >= fsmtab; mp--)
                    155:                if (mp->m_mroot == rip)
                    156:                        break;
                    157:        if (mp < fsmtab)
                    158:                panic("umount mp");
                    159:        plock(rip);
                    160:        xumount(rip);
                    161:        update();       /* silly */
                    162:        if (rip->i_count > 1 || ifsbusy(rip)) {
                    163:                u.u_error = EBUSY;
                    164:                prele(rip);
                    165:                return;
                    166:        }
                    167:        plock(mip);
                    168:        mip->i_mroot = NULL;
                    169:        iput(mip);
                    170:        dev = rip->i_dev;
                    171:        if ((bp = getblk(dev, SUPERB)) != rip->i_un.i_bufp)
                    172:                panic("umount");
                    173:        iput(rip);
                    174:        bp->b_flags &= ~(B_LOCKED|B_ASYNC);     /* ~async needed? */
                    175:        if (bp->b_un.b_filsys->s_ronly)
                    176:                brelse(bp);
                    177:        else {
                    178:                if (BITFS(dev)) {
                    179:                        fp = bp->b_un.b_filsys;
                    180:                        fp->s_valid = 1;
                    181:                        if(fp->U.N.S_flag)
                    182:                                fsbitoff(dev, fp, 1);
                    183:                }
                    184:                bwrite(bp);
                    185:        }
                    186:        mpurge(mp - fsmtab);
                    187:        idec(mp->m_dev);
                    188:        mp->m_dev = NULL;
                    189: }
                    190: 
                    191: fsbiton(dev, fp)
                    192: dev_t dev;
                    193: register struct filsys *fp;
                    194: {
                    195:        register int i, nf;
                    196:        register struct buf **bpp;
                    197:        register struct buf *bp;
                    198: 
                    199:        /* two chuck should do */
                    200:        fp->U.N.S_flag = 1;     /* bit map not in superblock */
                    201:        nf = fp->U.N.S_bsize = BSIZE(dev) * NBBY;
                    202:        if (fp->s_ronly)
                    203:                return (0);
                    204:        nf = (fp->s_fsize + nf - 1) / nf;
                    205:        bpp = fp->U.N.S_blk;
                    206:        for(i = 0; i < nf; i++)
                    207:                bpp[i] = 0;
                    208:        for(i = 0; i < nf; i++) {
                    209:                bp = bread(dev, fp->s_fsize-nf+i);
                    210:                if(u.u_error) {
                    211:                        brelse(bp);
                    212:                        goto failed;
                    213:                }
                    214:                bp->b_flags |= B_LOCKED;
                    215:                brelse(bp);
                    216:                bpp[i] = bp;
                    217:        }
                    218:        return(0);
                    219: failed:
                    220:        fsbitoff(dev, fp, 0);
                    221:        return(1);
                    222: }
                    223: 
                    224: fsbitoff(dev, fp, wrtflg)
                    225: dev_t dev;
                    226: struct filsys *fp;
                    227: {
                    228:        register struct buf **bpp;
                    229:        register struct buf *bp;
                    230:        register int i, nf;
                    231: 
                    232:        if (fp->s_ronly)
                    233:                return;
                    234:        nf = fp->U.N.S_bsize;
                    235:        nf = (fp->s_fsize + nf-1)/nf;
                    236:        bpp = fp->U.N.S_blk;
                    237:        for(i = 0; i < nf; i++)
                    238:                if(bpp[i]) {
                    239:                        if ((bp = getblk(dev, fp->s_fsize - nf + i)) != bpp[i])
                    240:                                panic("fsbitoff");
                    241:                        bp->b_flags &= ~B_LOCKED;
                    242:                        if(wrtflg)
                    243:                                bwrite(bp);
                    244:                        bpp[i] = 0;     /* safety first */
                    245:                }
                    246: }
                    247: 
                    248: /*
                    249:  * fill in inode ip from the disk copy
                    250:  * in filesystem fip
                    251:  * ip is an inode fresh from iget
                    252:  */
                    253: fsiread(fip, ip)
                    254: register struct inode *fip, *ip;
                    255: {
                    256:        register struct buf *bp;
                    257:        daddr_t bno;
                    258: 
                    259:        if (ip->i_number <= 0) {
                    260:                u.u_error = EINVAL;
                    261:                iput(ip);
                    262:                return (-1);
                    263:        }
                    264:        bno = itod(fip->i_dev, (ino_t)ip->i_number);
                    265:        if (bno >= getfs(fip)->s_isize) {
                    266:                u.u_error = EINVAL;
                    267:                iput(ip);
                    268:                return (-1);
                    269:        }
                    270:        bp = bread(fip->i_dev, bno);
                    271:        if((bp->b_flags&B_ERROR) != 0) {
                    272:                brelse(bp);
                    273:                iput(ip);
                    274:                return(-1);
                    275:        }
                    276:        iexpand(ip, bp->b_un.b_dino+itoo(fip->i_dev, (ino_t)ip->i_number));
                    277:        brelse(bp);
                    278:        ip->i_un.i_bufp = fip->i_un.i_bufp;
                    279:        ip->i_un.i_lastr = 0;
                    280:        return (0);
                    281: }
                    282: 
                    283: iexpand(ip, dp)
                    284: register struct inode *ip;
                    285: register struct dinode *dp;
                    286: {
                    287:        register char *p1, *p2;
                    288:        register int i;
                    289: 
                    290:        ip->i_mode = dp->di_mode;
                    291:        ip->i_nlink = dp->di_nlink;
                    292:        ip->i_uid = dp->di_uid;
                    293:        ip->i_gid = dp->di_gid;
                    294:        ip->i_size = dp->di_size;
                    295:        p1 = (char *)ip->i_un.i_addr;
                    296:        p2 = (char *)dp->di_addr;
                    297:        for(i=0; i<NADDR; i++) {
                    298:                *p1++ = *p2++;
                    299:                *p1++ = *p2++;
                    300:                *p1++ = *p2++;
                    301:                *p1++ = 0;
                    302:        }
                    303: }
                    304: 
                    305: fsput(ip)
                    306: struct inode *ip;
                    307: {
                    308:        if (ip->i_nlink == 0) {
                    309:                fstrunc(ip);
                    310:                ifree(ip);
                    311:                ip->i_mode = 0;
                    312:                ip->i_flag |= IUPD|ICHG;
                    313:        }
                    314:        if ((ip->i_flag&(IUPD|IACC|ICHG)) != 0)
                    315:                fsiupdat(ip, &time, &time, 0);
                    316: }
                    317: 
                    318: fsupdat(ip, ta, tm, waitfor)
                    319: register struct inode *ip;
                    320: time_t *ta, *tm;
                    321: {
                    322:        fsiupdat(ip, ta, tm, waitfor);
                    323:        if (ip->i_un.i_bufp->b_un.b_filsys->s_fmod)
                    324:                fsfupdat(ip);
                    325: }
                    326: 
                    327: /*
                    328:  * update the inode on disk
                    329:  * if the super-block is dirty, write it too
                    330:  */
                    331: 
                    332: fsiupdat(ip, ta, tm, waitfor)
                    333: register struct inode *ip;
                    334: time_t *ta, *tm;
                    335: {
                    336:        register struct buf *bp;
                    337:        struct dinode *dp;
                    338:        register char *p1, *p2;
                    339:        register int i;
                    340: 
                    341:        if (ip->i_un.i_bufp->b_un.b_filsys->s_ronly)
                    342:                return;
                    343:        bp = bread(ip->i_dev, itod(ip->i_dev, ip->i_number));
                    344:        if (bp->b_flags & B_ERROR) {
                    345:                brelse(bp);
                    346:                return;
                    347:        }
                    348:        dp = bp->b_un.b_dino;
                    349:        dp += itoo(ip->i_dev, ip->i_number);
                    350:        dp->di_mode = ip->i_mode;
                    351:        dp->di_nlink = ip->i_nlink;
                    352:        dp->di_uid = ip->i_uid;
                    353:        dp->di_gid = ip->i_gid;
                    354:        dp->di_size = ip->i_size;
                    355:        p1 = (char *)dp->di_addr;
                    356:        p2 = (char *)ip->i_un.i_addr;
                    357:        for(i=0; i<NADDR; i++) {
                    358:                *p1++ = *p2++;
                    359:                *p1++ = *p2++;
                    360:                *p1++ = *p2++;
                    361:                if(*p2++)
                    362:                        printf("ino %d dev #%x addr #%x\n", ip->i_number, ip->i_dev, ip->i_un.i_addr[i]);
                    363:        }
                    364:        if(ip->i_flag&IACC)
                    365:                dp->di_atime = *ta;
                    366:        if(ip->i_flag&IUPD)
                    367:                dp->di_mtime = *tm;
                    368:        if(ip->i_flag&ICHG)
                    369:                dp->di_ctime = time;
                    370:        ip->i_flag &= ~(IUPD|IACC|ICHG);
                    371:        if (waitfor)
                    372:                bwrite(bp);
                    373:        else
                    374:                bdwrite(bp);
                    375: }
                    376: 
                    377: /*
                    378:  * write the super-block
                    379:  */
                    380: 
                    381: fsfupdat(ip)
                    382: struct inode *ip;
                    383: {
                    384:        register struct filsys *fp;
                    385:        struct buf *bp;
                    386: 
                    387:        fp = ip->i_un.i_bufp->b_un.b_filsys;
                    388:        if (fp->s_fmod == 0 || fp->s_ilock || fp->s_flock || fp->s_ronly)
                    389:                return;
                    390:        bp = getblk(ip->i_dev, SUPERB);
                    391:        if (bp->b_un.b_filsys != fp)
                    392:                panic("fsfupdat");
                    393:        fp->s_fmod = 0;
                    394:        fp->s_time = time;
                    395:        bwrite(bp);
                    396: }
                    397: 
                    398: fsstat(ip, ub)
                    399: register struct inode *ip;
                    400: struct stat *ub;
                    401: {
                    402:        register struct dinode *dp;
                    403:        register struct buf *bp;
                    404:        struct stat ds;
                    405: 
                    406:        /*
                    407:         * first copy from inode table
                    408:         */
                    409:        ds.st_dev = ip->i_dev;
                    410:        ds.st_ino = ip->i_number;
                    411:        ds.st_mode = ip->i_mode;
                    412:        ds.st_nlink = ip->i_nlink;
                    413:        ds.st_uid = ip->i_uid;
                    414:        ds.st_gid = ip->i_gid;
                    415:        ds.st_rdev = (dev_t)ip->i_un.i_rdev;
                    416:        ds.st_size = ip->i_size;
                    417:        /*
                    418:         * next the dates in the disk
                    419:         */
                    420:        bp = bread(ip->i_dev, itod(ip->i_dev, ip->i_number));
                    421:        dp = bp->b_un.b_dino;
                    422:        dp += itoo(ip->i_dev, ip->i_number);
                    423:        ds.st_atime = dp->di_atime;
                    424:        ds.st_mtime = dp->di_mtime;
                    425:        ds.st_ctime = dp->di_ctime;
                    426:        brelse(bp);
                    427:        if (copyout((caddr_t)&ds, (caddr_t)ub, sizeof(ds)) < 0)
                    428:                u.u_error = EFAULT;
                    429: }
                    430: 
                    431: fstrunc(ip)
                    432: register struct inode *ip;
                    433: {
                    434:        register i;
                    435:        daddr_t bn;
                    436:        struct inode itmp;
                    437: 
                    438:        i = ip->i_mode & IFMT;
                    439:        if (i!=IFREG && i!=IFDIR && i!=IFLNK)
                    440:                return;
                    441:        /*
                    442:         * Clean inode on disk before freeing blocks
                    443:         * to insure no duplicates if system crashes.
                    444:         */
                    445:        itmp = *ip;
                    446:        itmp.i_size = 0;
                    447:        for (i = 0; i < NADDR; i++)
                    448:                itmp.i_un.i_addr[i] = 0;
                    449:        itmp.i_flag |= ICHG|IUPD;
                    450:        fsiupdat(&itmp, &time, &time, 1);
                    451:        ip->i_flag &= ~(IUPD|IACC|ICHG);
                    452: 
                    453:        /*
                    454:         * Now return blocks to free list... if machine
                    455:         * crashes, they will be harmless MISSING blocks.
                    456:         */
                    457:        for(i=NADDR-1; i>=0; i--) {
                    458:                bn = ip->i_un.i_addr[i];
                    459:                if(bn == (daddr_t)0)
                    460:                        continue;
                    461:                ip->i_un.i_addr[i] = (daddr_t)0;
                    462:                switch(i) {
                    463: 
                    464:                default:
                    465:                        free(ip, bn);
                    466:                        break;
                    467: 
                    468:                case NADDR-3:
                    469:                        tloop(ip, bn, 0, 0);
                    470:                        break;
                    471: 
                    472:                case NADDR-2:
                    473:                        tloop(ip, bn, 1, 0);
                    474:                        break;
                    475: 
                    476:                case NADDR-1:
                    477:                        tloop(ip, bn, 1, 1);
                    478:                }
                    479:        }
                    480:        ip->i_size = 0;
                    481:        /*
                    482:         * Inode was written and flags updated above.
                    483:         * No need to modify flags here.
                    484:         */
                    485: }
                    486: 
                    487: tloop(fip, bn, f1, f2)
                    488: register struct inode *fip;
                    489: daddr_t bn;
                    490: {
                    491:        register i;
                    492:        register struct buf *bp;
                    493:        register daddr_t *bap;
                    494:        daddr_t nb;
                    495: 
                    496:        bp = NULL;
                    497:        for(i=NINDIR(fip->i_dev)-1; i>=0; i--) {
                    498:                if(bp == NULL) {
                    499:                        bp = bread(fip->i_dev, bn);
                    500:                        if (bp->b_flags & B_ERROR) {
                    501:                                brelse(bp);
                    502:                                return;
                    503:                        }
                    504:                        bap = bp->b_un.b_daddr;
                    505:                }
                    506:                nb = bap[i];
                    507:                if(nb == (daddr_t)0)
                    508:                        continue;
                    509:                if(f1) {
                    510:                        brelse(bp);
                    511:                        bp = NULL;
                    512:                        tloop(fip, nb, f2, 0);
                    513:                } else
                    514:                        free(fip, nb);
                    515:        }
                    516:        if(bp != NULL)
                    517:                brelse(bp);
                    518:        free(fip, bn);
                    519: }
                    520: 
                    521: fsioctl(ip, cmd, cmarg, flag)
                    522: register struct inode *ip;
                    523: caddr_t cmarg;
                    524: {
                    525:        int fmt;
                    526:        register dev_t dev;
                    527: 
                    528:        fmt = ip->i_mode & IFMT;
                    529:        if (fmt != IFCHR) {
                    530:                if (cmd==FIONREAD && (fmt == IFREG || fmt == IFDIR)) {
                    531:                        off_t nread = ip->i_size; /* - fp->f_offset */
                    532:                        if (copyout((caddr_t)&nread, cmarg, sizeof(off_t)))
                    533:                                u.u_error = EFAULT;
                    534:                } else
                    535:                        u.u_error = ENOTTY;
                    536:                return;
                    537:        }
                    538:        dev = ip->i_un.i_rdev;
                    539:        u.u_r.r_val1 = 0;
                    540:        (*cdevsw[major(dev)]->d_ioctl)(dev, cmd, cmarg, flag);
                    541: }
                    542: 
                    543: struct inode *
                    544: fsopen(ip, rw)
                    545: register struct inode *ip;
                    546: {
                    547:        dev_t dev;
                    548:        register unsigned int maj;
                    549: 
                    550:        dev = (dev_t)ip->i_un.i_rdev;
                    551:        maj = major(dev);
                    552: 
                    553:        switch(ip->i_mode&IFMT) {
                    554:        case IFCHR:
                    555:                if(maj >= nchrdev || cdevsw[maj] == NULL)
                    556:                        goto bad;
                    557:                if (cdevsw[maj]->qinfo)         /* stream device */
                    558:                        return(stopen(cdevsw[major(dev)]->qinfo, dev, rw, ip));
                    559:                (*cdevsw[maj]->d_open)(dev, rw);
                    560:                break;
                    561: 
                    562:        case IFBLK:
                    563:                if(maj >= nblkdev || bdevsw[maj] == NULL)
                    564:                        goto bad;
                    565:                (*bdevsw[maj]->d_open)(dev, rw);
                    566:        }
                    567:        if (u.u_error) {
                    568:                iput(ip);
                    569:                return (NULL);
                    570:        }
                    571:        return (ip);
                    572: 
                    573: bad:
                    574:        u.u_error = ENXIO;
                    575:        iput(ip);
                    576:        return(NULL);
                    577: }
                    578: 
                    579: fsread(ip)
                    580: register struct inode *ip;
                    581: {
                    582:        struct buf *bp;
                    583:        dev_t dev;
                    584:        daddr_t lbn, bn;
                    585:        off_t diff;
                    586:        register int on, type;
                    587:        register unsigned n;
                    588: 
                    589:        dev = (dev_t)ip->i_un.i_rdev;
                    590:        type = ip->i_mode&IFMT;
                    591:        if (type==IFCHR) {
                    592:                (*cdevsw[major(dev)]->d_read)(dev);
                    593:                return;
                    594:        }
                    595:        if (Lsign(u.u_offset) < 0) {            /* and not IFCHR */
                    596:                u.u_error = EINVAL;
                    597:                return;
                    598:        }
                    599:        if (type != IFBLK) {    /* if offset >= size, avoid overflow */
                    600:                if (Lsign(Lladd(u.u_offset, -ip->i_size))>=0)
                    601:                        return;
                    602:                dev = ip->i_dev;
                    603:        }
                    604:        do {
                    605:                lbn = bn = Lshift(u.u_offset, BSHIFT(dev));
                    606:                on = Ltol(u.u_offset) & BMASK(dev);
                    607:                n = MIN((unsigned)(BSIZE(dev)-on), u.u_count);
                    608:                if (type!=IFBLK) {
                    609:                        diff = ip->i_size - Ltol(u.u_offset);
                    610:                        if (diff <= 0)
                    611:                                return;
                    612:                        if (diff < n)
                    613:                                n = diff;
                    614:                        bn = bmap(ip, bn, B_READ);
                    615:                        if (u.u_error)
                    616:                                return;
                    617:                } else
                    618:                        rablock = bn+1;
                    619:                if ((long)bn<0) {
                    620:                        bp = geteblk();
                    621:                        clrbuf(bp);
                    622:                } else if (ip->i_un.i_lastr+1==lbn)
                    623:                        bp = breada(dev, bn, rablock);
                    624:                else
                    625:                        bp = bread(dev, bn);
                    626:                ip->i_un.i_lastr = lbn;
                    627:                n = MIN(n, BSIZE(dev)-bp->b_resid);
                    628:                if (n!=0)
                    629:                        iomove(bp->b_un.b_addr+on, n, B_READ);
                    630:                brelse(bp);
                    631:        } while(u.u_error==0 && u.u_count!=0 && n!=0);
                    632: }
                    633: 
                    634: fsdirread(ip, len)
                    635: struct inode *ip;
                    636: {      struct buf *bp = 0, *outb;
                    637:        dev_t dev;
                    638:        daddr_t bn, lbn;
                    639:        int on, type, j, m, new = 0;
                    640:        char *p, *lp, *lastp;
                    641:        struct direct *dp;
                    642:        char ncvt[24];
                    643: 
                    644:        if(Lsign(u.u_offset) < 0) {
                    645:                u.u_error = EINVAL;
                    646:                return;
                    647:        }
                    648:        type = ip->i_mode & IFMT;
                    649:        if(type != IFDIR) {
                    650:                u.u_error = ENOTDIR;
                    651:                return;
                    652:        }
                    653:        dev = ip->i_dev;
                    654:        outb = geteblk();       /* to hold the stuff for the user */
                    655:        if(len > BSIZE(dev))
                    656:                len = BSIZE(dev);
                    657:        p = lp = outb->b_un.b_addr;
                    658:        lastp = p + len;
                    659: loop:
                    660:        if(new <= 0) {  /* get some goo */
                    661:                lbn = bn = Lshift(u.u_offset, BSHIFT(dev));
                    662:                on = Ltol(u.u_offset) & BMASK(dev);
                    663:                if(ip->i_size <= Ltol(u.u_offset))
                    664:                        goto done;
                    665:                bn = bmap(ip, bn, B_READ);
                    666:                if(u.u_error)
                    667:                        return;
                    668:                if((long)bn < 0) {      /* holes in dirs? */
                    669:                        u.u_offset = Lladd(u.u_offset, BSIZE(dev)-on);
                    670:                        goto loop;      /* try the next block */
                    671:                }
                    672:                if(bp)
                    673:                        brelse(bp);
                    674:                if(ip->i_un.i_lastr + 1 == lbn)
                    675:                        bp = breada(dev, bn, rablock);
                    676:                else
                    677:                        bp = bread(dev, bn);
                    678:                ip->i_un.i_lastr = lbn;
                    679:                new = BSIZE(dev) - on;
                    680:                if(new > BSIZE(dev) - bp->b_resid)      /* io error? */
                    681:                        new = BSIZE(dev) - bp->b_resid; /* or paranoia */
                    682:                if(new > ip->i_size - Ltol(u.u_offset))
                    683:                        new = ip->i_size - Ltol(u.u_offset);
                    684:                dp = (struct direct *) (bp->b_un.b_addr + on);
                    685:        }
                    686:        if(dp->d_ino == 0)
                    687:                goto incr;
                    688:        for(m = dp->d_ino, j = sizeof(ncvt)-1; m; j--) {
                    689:                ncvt[j] = m%10 + '0';
                    690:                m /= 10;
                    691:        }
                    692:        for(++j; j < sizeof(ncvt) && p < lastp; )
                    693:                *p++ = ncvt[j++];
                    694:        if(j != sizeof(ncvt) || p >= lastp)
                    695:                goto early;
                    696:        *p++ = '\t';
                    697:        for(j = 0; j < DIRSIZ && dp->d_name[j] && p < lastp; j++)
                    698:                *p++ = dp->d_name[j];
                    699:        if(p >= lastp)
                    700:                goto early;
                    701:        *p++ = 0;
                    702: incr:
                    703:        lp = p;
                    704:        new -= sizeof(*dp);
                    705:        u.u_offset = Lladd(u.u_offset, sizeof(*dp));
                    706:        dp++;
                    707:        if(p < lastp)
                    708:                goto loop;
                    709: done:
                    710:        j = lp - outb->b_un.b_addr;
                    711:        if(j > 0)
                    712:                if(copyout((caddr_t)outb->b_un.b_addr, u.u_base, j))
                    713:                        u.u_error = EFAULT;
                    714:        if(bp)
                    715:                brelse(bp);
                    716:        brelse(outb);
                    717:        u.u_r.r_val1 = j;
                    718:        return;
                    719: early:
                    720:        *lp = 0;
                    721:        if(lp > outb->b_un.b_addr)
                    722:                goto done;
                    723:        u.u_error = ENOSPC;
                    724:        if(bp)
                    725:                brelse(bp);
                    726:        brelse(outb);
                    727: }
                    728: 
                    729: fswrite(ip)
                    730: register struct inode *ip;
                    731: {
                    732:        struct buf *bp;
                    733:        dev_t dev;
                    734:        daddr_t bn;
                    735:        register int on, type;
                    736:        register unsigned n;
                    737:        register int i;
                    738: 
                    739:        dev = (dev_t)ip->i_un.i_rdev;
                    740:        type = ip->i_mode&IFMT;
                    741:        if (type==IFCHR) {
                    742:                ip->i_flag |= IUPD|ICHG;
                    743:                (*cdevsw[major(dev)]->d_write)(dev);
                    744:                return;
                    745:        }
                    746:        if (Lsign(u.u_offset) < 0) {            /* and not IFCHR */
                    747:                u.u_error = EINVAL;
                    748:                return;
                    749:        }
                    750:        if (u.u_count == 0)
                    751:                return;
                    752:        if ((ip->i_mode&IFMT)==IFREG &&
                    753:            (Lsign(Luadd(u.u_offset, u.u_count))!=0 || 
                    754:             Ltol(u.u_offset) + u.u_count > u.u_limit[LIM_FSIZE])) {
                    755:                u.u_error = EMFILE;
                    756:                return;
                    757:        }
                    758:        if (type != IFBLK)
                    759:                dev = ip->i_dev;
                    760:        do {
                    761:                bn = Lshift(u.u_offset, BSHIFT(dev));
                    762:                on = Ltol(u.u_offset) & BMASK(dev);
                    763:                n = MIN((unsigned)(BSIZE(dev)-on), u.u_count);
                    764:                if (type!=IFBLK) {
                    765:                        bn = bmap(ip, bn, B_WRITE);
                    766:                        if((long)bn<0)
                    767:                                return;
                    768:                }
                    769:                i = getfsx(dev);
                    770:                if (bn && mfind(i, bn))
                    771:                        munhash(i, bn);
                    772:                if(n == BSIZE(dev)) 
                    773:                        bp = getblk(dev, bn);
                    774:                else
                    775:                        bp = bread(dev, bn);
                    776:                iomove(bp->b_un.b_addr+on, n, B_WRITE);
                    777:                if(u.u_error != 0)
                    778:                        brelse(bp);
                    779:                else {
                    780:                        if ((ip->i_mode&IFMT) == IFDIR &&
                    781:                            ((struct direct *)(bp->b_un.b_addr+on))->d_ino == 0)
                    782:                                bwrite(bp);     /* consistency */
                    783:                        else if ((n+on) == BSIZE(dev))
                    784:                                bawrite(bp);
                    785:                        else
                    786:                                bdwrite(bp);
                    787:                }
                    788:                if(Ltol(u.u_offset) > ip->i_size &&
                    789:                   (type==IFDIR || type==IFREG || type==IFLNK))
                    790:                        ip->i_size = Ltol(u.u_offset);
                    791:                ip->i_flag |= IUPD|ICHG;
                    792:        } while(u.u_error==0 && u.u_count!=0);
                    793: }
                    794: 
                    795: /*
                    796:  * Getfsx returns the index in the file system
                    797:  * table of the specified device.  The swap device
                    798:  * is also assigned a pseudo-index.  The index may
                    799:  * be used as a compressed indication of the location
                    800:  * of a block, recording
                    801:  *     <getfsx(dev),blkno>
                    802:  * rather than
                    803:  *     <dev, blkno>
                    804:  * provided the information need remain valid only
                    805:  * as long as the file system is mounted.
                    806:  *
                    807:  * only the vm code calls this.
                    808:  */
                    809: getfsx(dev)
                    810:        dev_t dev;
                    811: {
                    812:        register struct mount *mp;
                    813: 
                    814:        if (dev == swapdev)
                    815:                return (MSWAPX);
                    816:        for (mp = &fsmtab[fscnt-1]; mp >= fsmtab; mp--) {
                    817:                if (mp->m_dev == NULL)
                    818:                        continue;
                    819:                if (mp->m_dev->i_un.i_rdev == dev)
                    820:                        return (mp - fsmtab);
                    821:        }
                    822:        return (-1);
                    823: }

unix.superglobalmegacorp.com

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