Annotation of Net2/ufs/ufs_vfsops.c, revision 1.1.1.3

1.1       root        1: /*
                      2:  * Copyright (c) 1989, 1991 The Regents of the University of California.
                      3:  * All rights reserved.
                      4:  *
                      5:  * Redistribution and use in source and binary forms, with or without
                      6:  * modification, are permitted provided that the following conditions
                      7:  * are met:
                      8:  * 1. Redistributions of source code must retain the above copyright
                      9:  *    notice, this list of conditions and the following disclaimer.
                     10:  * 2. Redistributions in binary form must reproduce the above copyright
                     11:  *    notice, this list of conditions and the following disclaimer in the
                     12:  *    documentation and/or other materials provided with the distribution.
                     13:  * 3. All advertising materials mentioning features or use of this software
                     14:  *    must display the following acknowledgement:
                     15:  *     This product includes software developed by the University of
                     16:  *     California, Berkeley and its contributors.
                     17:  * 4. Neither the name of the University nor the names of its contributors
                     18:  *    may be used to endorse or promote products derived from this software
                     19:  *    without specific prior written permission.
                     20:  *
                     21:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     22:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     23:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     24:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     25:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     26:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     27:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     28:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     29:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     30:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     31:  * SUCH DAMAGE.
                     32:  *
1.1.1.3 ! root       33:  *     from: @(#)ufs_vfsops.c  7.56 (Berkeley) 6/28/91
        !            34:  *     ufs_vfsops.c,v 1.2 1993/05/20 03:53:45 cgd Exp
1.1       root       35:  */
                     36: 
                     37: #include "param.h"
                     38: #include "systm.h"
                     39: #include "namei.h"
                     40: #include "proc.h"
                     41: #include "kernel.h"
                     42: #include "vnode.h"
                     43: #include "specdev.h"
                     44: #include "mount.h"
                     45: #include "buf.h"
                     46: #include "file.h"
1.1.1.2   root       47: #include "dkbad.h"     /* XXX */
1.1       root       48: #include "disklabel.h"
                     49: #include "ioctl.h"
                     50: #include "errno.h"
                     51: #include "malloc.h"
                     52: 
                     53: #include "quota.h"
                     54: #include "fs.h"
                     55: #include "ufsmount.h"
                     56: #include "inode.h"
                     57: 
                     58: struct vfsops ufs_vfsops = {
                     59:        ufs_mount,
                     60:        ufs_start,
                     61:        ufs_unmount,
                     62:        ufs_root,
                     63:        ufs_quotactl,
                     64:        ufs_statfs,
                     65:        ufs_sync,
                     66:        ufs_fhtovp,
                     67:        ufs_vptofh,
                     68:        ufs_init
                     69: };
                     70: 
                     71: /*
                     72:  * Flag to allow forcible unmounting.
                     73:  */
                     74: int doforce = 1;
                     75: 
                     76: /*
                     77:  * Called by vfs_mountroot when ufs is going to be mounted as root.
                     78:  *
                     79:  * Name is updated by mount(8) after booting.
                     80:  */
                     81: #define ROOTNAME       "root_device"
                     82: 
                     83: ufs_mountroot()
                     84: {
                     85:        register struct mount *mp;
                     86:        extern struct vnode *rootvp;
                     87:        struct proc *p = curproc;       /* XXX */
                     88:        struct ufsmount *ump;
                     89:        register struct fs *fs;
                     90:        u_int size;
                     91:        int error;
                     92: 
                     93:        mp = (struct mount *)malloc((u_long)sizeof(struct mount),
                     94:                M_MOUNT, M_WAITOK);
                     95:        mp->mnt_op = &ufs_vfsops;
                     96:        mp->mnt_flag = MNT_RDONLY;
                     97:        mp->mnt_exroot = 0;
                     98:        mp->mnt_mounth = NULLVP;
                     99:        error = mountfs(rootvp, mp, p);
                    100:        if (error) {
                    101:                free((caddr_t)mp, M_MOUNT);
                    102:                return (error);
                    103:        }
                    104:        if (error = vfs_lock(mp)) {
                    105:                (void)ufs_unmount(mp, 0, p);
                    106:                free((caddr_t)mp, M_MOUNT);
                    107:                return (error);
                    108:        }
                    109:        rootfs = mp;
                    110:        mp->mnt_next = mp;
                    111:        mp->mnt_prev = mp;
                    112:        mp->mnt_vnodecovered = NULLVP;
                    113:        ump = VFSTOUFS(mp);
                    114:        fs = ump->um_fs;
                    115:        bzero(fs->fs_fsmnt, sizeof(fs->fs_fsmnt));
                    116:        fs->fs_fsmnt[0] = '/';
                    117:        bcopy((caddr_t)fs->fs_fsmnt, (caddr_t)mp->mnt_stat.f_mntonname,
                    118:            MNAMELEN);
                    119:        (void) copystr(ROOTNAME, mp->mnt_stat.f_mntfromname, MNAMELEN - 1,
                    120:            &size);
                    121:        bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size);
                    122:        (void) ufs_statfs(mp, &mp->mnt_stat, p);
                    123:        vfs_unlock(mp);
                    124:        inittodr(fs->fs_time);
                    125:        return (0);
                    126: }
                    127: 
                    128: /*
                    129:  * VFS Operations.
                    130:  *
                    131:  * mount system call
                    132:  */
                    133: ufs_mount(mp, path, data, ndp, p)
                    134:        register struct mount *mp;
                    135:        char *path;
                    136:        caddr_t data;
                    137:        struct nameidata *ndp;
                    138:        struct proc *p;
                    139: {
                    140:        struct vnode *devvp;
                    141:        struct ufs_args args;
                    142:        struct ufsmount *ump;
                    143:        register struct fs *fs;
                    144:        u_int size;
                    145:        int error;
                    146: 
                    147:        if (error = copyin(data, (caddr_t)&args, sizeof (struct ufs_args)))
                    148:                return (error);
                    149:        /*
                    150:         * Process export requests.
                    151:         */
                    152:        if ((args.exflags & MNT_EXPORTED) || (mp->mnt_flag & MNT_EXPORTED)) {
                    153:                if (args.exflags & MNT_EXPORTED)
                    154:                        mp->mnt_flag |= MNT_EXPORTED;
                    155:                else
                    156:                        mp->mnt_flag &= ~MNT_EXPORTED;
                    157:                if (args.exflags & MNT_EXRDONLY)
                    158:                        mp->mnt_flag |= MNT_EXRDONLY;
                    159:                else
                    160:                        mp->mnt_flag &= ~MNT_EXRDONLY;
                    161:                mp->mnt_exroot = args.exroot;
                    162:        }
                    163:        /*
                    164:         * If updating, check whether changing from read-only to
                    165:         * read/write; if there is no device name, that's all we do.
                    166:         */
                    167:        if (mp->mnt_flag & MNT_UPDATE) {
                    168:                ump = VFSTOUFS(mp);
                    169:                fs = ump->um_fs;
                    170:                if (fs->fs_ronly && (mp->mnt_flag & MNT_RDONLY) == 0)
                    171:                        fs->fs_ronly = 0;
                    172:                if (args.fspec == 0)
                    173:                        return (0);
                    174:        }
                    175:        /*
                    176:         * Not an update, or updating the name: look up the name
                    177:         * and verify that it refers to a sensible block device.
                    178:         */
                    179:        ndp->ni_nameiop = LOOKUP | FOLLOW;
                    180:        ndp->ni_segflg = UIO_USERSPACE;
                    181:        ndp->ni_dirp = args.fspec;
                    182:        if (error = namei(ndp, p))
                    183:                return (error);
                    184:        devvp = ndp->ni_vp;
                    185:        if (devvp->v_type != VBLK) {
                    186:                vrele(devvp);
                    187:                return (ENOTBLK);
                    188:        }
                    189:        if (major(devvp->v_rdev) >= nblkdev) {
                    190:                vrele(devvp);
                    191:                return (ENXIO);
                    192:        }
                    193:        if ((mp->mnt_flag & MNT_UPDATE) == 0)
                    194:                error = mountfs(devvp, mp, p);
                    195:        else {
                    196:                if (devvp != ump->um_devvp)
                    197:                        error = EINVAL; /* needs translation */
                    198:                else
                    199:                        vrele(devvp);
                    200:        }
                    201:        if (error) {
                    202:                vrele(devvp);
                    203:                return (error);
                    204:        }
                    205:        ump = VFSTOUFS(mp);
                    206:        fs = ump->um_fs;
                    207:        (void) copyinstr(path, fs->fs_fsmnt, sizeof(fs->fs_fsmnt) - 1, &size);
                    208:        bzero(fs->fs_fsmnt + size, sizeof(fs->fs_fsmnt) - size);
                    209:        bcopy((caddr_t)fs->fs_fsmnt, (caddr_t)mp->mnt_stat.f_mntonname,
                    210:            MNAMELEN);
                    211:        (void) copyinstr(args.fspec, mp->mnt_stat.f_mntfromname, MNAMELEN - 1, 
                    212:            &size);
                    213:        bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size);
                    214:        (void) ufs_statfs(mp, &mp->mnt_stat, p);
                    215:        return (0);
                    216: }
                    217: 
                    218: /*
                    219:  * Common code for mount and mountroot
                    220:  */
                    221: mountfs(devvp, mp, p)
                    222:        register struct vnode *devvp;
                    223:        struct mount *mp;
                    224:        struct proc *p;
                    225: {
                    226:        register struct ufsmount *ump = (struct ufsmount *)0;
                    227:        struct buf *bp = NULL;
                    228:        register struct fs *fs;
                    229:        dev_t dev = devvp->v_rdev;
                    230:        struct partinfo dpart;
                    231:        caddr_t base, space;
                    232:        int havepart = 0, blks;
                    233:        int error, i, size;
                    234:        int needclose = 0;
                    235:        int ronly = (mp->mnt_flag & MNT_RDONLY) != 0;
                    236:        extern struct vnode *rootvp;
                    237: 
                    238:        /*
                    239:         * Disallow multiple mounts of the same device.
                    240:         * Disallow mounting of a device that is currently in use
                    241:         * (except for root, which might share swap device for miniroot).
                    242:         * Flush out any old buffers remaining from a previous use.
                    243:         */
                    244:        if (error = mountedon(devvp))
                    245:                return (error);
                    246:        if (vcount(devvp) > 1 && devvp != rootvp)
                    247:                return (EBUSY);
                    248:        vinvalbuf(devvp, 1);
                    249:        if (error = VOP_OPEN(devvp, ronly ? FREAD : FREAD|FWRITE, NOCRED, p))
                    250:                return (error);
                    251:        needclose = 1;
                    252:        if (VOP_IOCTL(devvp, DIOCGPART, (caddr_t)&dpart, FREAD, NOCRED, p) != 0)
                    253:                size = DEV_BSIZE;
                    254:        else {
                    255:                havepart = 1;
                    256:                size = dpart.disklab->d_secsize;
                    257:        }
                    258:        if (error = bread(devvp, SBLOCK, SBSIZE, NOCRED, &bp))
                    259:                goto out;
                    260:        fs = bp->b_un.b_fs;
                    261:        if (fs->fs_magic != FS_MAGIC || fs->fs_bsize > MAXBSIZE ||
                    262:            fs->fs_bsize < sizeof(struct fs)) {
                    263:                error = EINVAL;         /* XXX needs translation */
                    264:                goto out;
                    265:        }
                    266:        ump = (struct ufsmount *)malloc(sizeof *ump, M_UFSMNT, M_WAITOK);
                    267:        ump->um_fs = (struct fs *)malloc((u_long)fs->fs_sbsize, M_SUPERBLK,
                    268:            M_WAITOK);
                    269:        bcopy((caddr_t)bp->b_un.b_addr, (caddr_t)ump->um_fs,
                    270:           (u_int)fs->fs_sbsize);
                    271:        if (fs->fs_sbsize < SBSIZE)
                    272:                bp->b_flags |= B_INVAL;
                    273:        brelse(bp);
                    274:        bp = NULL;
                    275:        fs = ump->um_fs;
                    276:        fs->fs_ronly = ronly;
                    277:        if (ronly == 0)
                    278:                fs->fs_fmod = 1;
                    279:        if (havepart) {
                    280:                dpart.part->p_fstype = FS_BSDFFS;
                    281:                dpart.part->p_fsize = fs->fs_fsize;
                    282:                dpart.part->p_frag = fs->fs_frag;
                    283:                dpart.part->p_cpg = fs->fs_cpg;
                    284:        }
                    285:        blks = howmany(fs->fs_cssize, fs->fs_fsize);
                    286:        base = space = (caddr_t)malloc((u_long)fs->fs_cssize, M_SUPERBLK,
                    287:            M_WAITOK);
                    288:        for (i = 0; i < blks; i += fs->fs_frag) {
                    289:                size = fs->fs_bsize;
                    290:                if (i + fs->fs_frag > blks)
                    291:                        size = (blks - i) * fs->fs_fsize;
                    292:                error = bread(devvp, fsbtodb(fs, fs->fs_csaddr + i), size,
                    293:                        NOCRED, &bp);
                    294:                if (error) {
                    295:                        free((caddr_t)base, M_SUPERBLK);
                    296:                        goto out;
                    297:                }
                    298:                bcopy((caddr_t)bp->b_un.b_addr, space, (u_int)size);
                    299:                fs->fs_csp[fragstoblks(fs, i)] = (struct csum *)space;
                    300:                space += size;
                    301:                brelse(bp);
                    302:                bp = NULL;
                    303:        }
                    304:        mp->mnt_data = (qaddr_t)ump;
                    305:        mp->mnt_stat.f_fsid.val[0] = (long)dev;
                    306:        mp->mnt_stat.f_fsid.val[1] = MOUNT_UFS;
                    307:        mp->mnt_flag |= MNT_LOCAL;
                    308:        ump->um_mountp = mp;
                    309:        ump->um_dev = dev;
                    310:        ump->um_devvp = devvp;
                    311:        for (i = 0; i < MAXQUOTAS; i++)
                    312:                ump->um_quotas[i] = NULLVP;
                    313:        devvp->v_specflags |= SI_MOUNTEDON;
                    314: 
                    315:        /* Sanity checks for old file systems.                     XXX */
                    316:        fs->fs_npsect = MAX(fs->fs_npsect, fs->fs_nsect);       /* XXX */
                    317:        fs->fs_interleave = MAX(fs->fs_interleave, 1);          /* XXX */
                    318:        if (fs->fs_postblformat == FS_42POSTBLFMT)              /* XXX */
                    319:                fs->fs_nrpos = 8;                               /* XXX */
                    320:        return (0);
                    321: out:
                    322:        if (bp)
                    323:                brelse(bp);
                    324:        if (needclose)
                    325:                (void)VOP_CLOSE(devvp, ronly ? FREAD : FREAD|FWRITE, NOCRED, p);
                    326:        if (ump) {
                    327:                free((caddr_t)ump->um_fs, M_SUPERBLK);
                    328:                free((caddr_t)ump, M_UFSMNT);
                    329:                mp->mnt_data = (qaddr_t)0;
                    330:        }
                    331:        return (error);
                    332: }
                    333: 
                    334: /*
                    335:  * Make a filesystem operational.
                    336:  * Nothing to do at the moment.
                    337:  */
                    338: /* ARGSUSED */
                    339: ufs_start(mp, flags, p)
                    340:        struct mount *mp;
                    341:        int flags;
                    342:        struct proc *p;
                    343: {
                    344: 
                    345:        return (0);
                    346: }
                    347: 
                    348: /*
                    349:  * unmount system call
                    350:  */
                    351: ufs_unmount(mp, mntflags, p)
                    352:        struct mount *mp;
                    353:        int mntflags;
                    354:        struct proc *p;
                    355: {
                    356:        register struct ufsmount *ump;
                    357:        register struct fs *fs;
                    358:        int i, error, ronly, flags = 0;
                    359: 
                    360:        if (mntflags & MNT_FORCE) {
                    361:                if (!doforce || mp == rootfs)
                    362:                        return (EINVAL);
                    363:                flags |= FORCECLOSE;
                    364:        }
                    365:        mntflushbuf(mp, 0);
                    366:        if (mntinvalbuf(mp))
                    367:                return (EBUSY);
                    368:        ump = VFSTOUFS(mp);
                    369: #ifdef QUOTA
                    370:        if (mp->mnt_flag & MNT_QUOTA) {
                    371:                if (error = vflush(mp, NULLVP, SKIPSYSTEM|flags))
                    372:                        return (error);
                    373:                for (i = 0; i < MAXQUOTAS; i++) {
                    374:                        if (ump->um_quotas[i] == NULLVP)
                    375:                                continue;
                    376:                        quotaoff(p, mp, i);
                    377:                }
                    378:                /*
                    379:                 * Here we fall through to vflush again to ensure
                    380:                 * that we have gotten rid of all the system vnodes.
                    381:                 */
                    382:        }
                    383: #endif
                    384:        if (error = vflush(mp, NULLVP, flags))
                    385:                return (error);
                    386:        fs = ump->um_fs;
                    387:        ronly = !fs->fs_ronly;
                    388:        ump->um_devvp->v_specflags &= ~SI_MOUNTEDON;
                    389:        error = VOP_CLOSE(ump->um_devvp, ronly ? FREAD : FREAD|FWRITE,
                    390:                NOCRED, p);
                    391:        vrele(ump->um_devvp);
                    392:        free((caddr_t)fs->fs_csp[0], M_SUPERBLK);
                    393:        free((caddr_t)fs, M_SUPERBLK);
                    394:        free((caddr_t)ump, M_UFSMNT);
                    395:        mp->mnt_data = (qaddr_t)0;
                    396:        mp->mnt_flag &= ~MNT_LOCAL;
                    397:        return (error);
                    398: }
                    399: 
                    400: /*
                    401:  * Check to see if a filesystem is mounted on a block device.
                    402:  */
                    403: mountedon(vp)
                    404:        register struct vnode *vp;
                    405: {
                    406:        register struct vnode *vq;
                    407: 
                    408:        if (vp->v_specflags & SI_MOUNTEDON)
                    409:                return (EBUSY);
                    410:        if (vp->v_flag & VALIASED) {
                    411:                for (vq = *vp->v_hashchain; vq; vq = vq->v_specnext) {
                    412:                        if (vq->v_rdev != vp->v_rdev ||
                    413:                            vq->v_type != vp->v_type)
                    414:                                continue;
                    415:                        if (vq->v_specflags & SI_MOUNTEDON)
                    416:                                return (EBUSY);
                    417:                }
                    418:        }
                    419:        return (0);
                    420: }
                    421: 
                    422: /*
                    423:  * Return root of a filesystem
                    424:  */
                    425: ufs_root(mp, vpp)
                    426:        struct mount *mp;
                    427:        struct vnode **vpp;
                    428: {
                    429:        register struct inode *ip;
                    430:        struct inode *nip;
                    431:        struct vnode tvp;
                    432:        int error;
                    433: 
                    434:        tvp.v_mount = mp;
                    435:        ip = VTOI(&tvp);
                    436:        ip->i_vnode = &tvp;
                    437:        ip->i_dev = VFSTOUFS(mp)->um_dev;
                    438:        error = iget(ip, (ino_t)ROOTINO, &nip);
                    439:        if (error)
                    440:                return (error);
                    441:        *vpp = ITOV(nip);
                    442:        return (0);
                    443: }
                    444: 
                    445: /*
                    446:  * Do operations associated with quotas
                    447:  */
                    448: ufs_quotactl(mp, cmds, uid, arg, p)
                    449:        struct mount *mp;
                    450:        int cmds;
                    451:        uid_t uid;
                    452:        caddr_t arg;
                    453:        struct proc *p;
                    454: {
                    455:        struct ufsmount *ump = VFSTOUFS(mp);
                    456:        int cmd, type, error;
                    457: 
                    458: #ifndef QUOTA
                    459:        return (EOPNOTSUPP);
                    460: #else
                    461:        if (uid == -1)
                    462:                uid = p->p_cred->p_ruid;
                    463:        cmd = cmds >> SUBCMDSHIFT;
                    464: 
                    465:        switch (cmd) {
                    466:        case Q_GETQUOTA:
                    467:        case Q_SYNC:
                    468:                if (uid == p->p_cred->p_ruid)
                    469:                        break;
                    470:                /* fall through */
                    471:        default:
                    472:                if (error = suser(p->p_ucred, &p->p_acflag))
                    473:                        return (error);
                    474:        }
                    475: 
                    476:        type = cmd & SUBCMDMASK;
                    477:        if ((u_int)type >= MAXQUOTAS)
                    478:                return (EINVAL);
                    479: 
                    480:        switch (cmd) {
                    481: 
                    482:        case Q_QUOTAON:
                    483:                return (quotaon(p, mp, type, arg));
                    484: 
                    485:        case Q_QUOTAOFF:
                    486:                if (vfs_busy(mp))
                    487:                        return (0);
                    488:                error = quotaoff(p, mp, type);
                    489:                vfs_unbusy(mp);
                    490:                return (error);
                    491: 
                    492:        case Q_SETQUOTA:
                    493:                return (setquota(mp, uid, type, arg));
                    494: 
                    495:        case Q_SETUSE:
                    496:                return (setuse(mp, uid, type, arg));
                    497: 
                    498:        case Q_GETQUOTA:
                    499:                return (getquota(mp, uid, type, arg));
                    500: 
                    501:        case Q_SYNC:
                    502:                if (vfs_busy(mp))
                    503:                        return (0);
                    504:                error = qsync(mp);
                    505:                vfs_unbusy(mp);
                    506:                return (error);
                    507: 
                    508:        default:
                    509:                return (EINVAL);
                    510:        }
                    511:        /* NOTREACHED */
                    512: #endif
                    513: }
                    514: 
                    515: /*
                    516:  * Get file system statistics.
                    517:  */
                    518: ufs_statfs(mp, sbp, p)
                    519:        struct mount *mp;
                    520:        register struct statfs *sbp;
                    521:        struct proc *p;
                    522: {
                    523:        register struct ufsmount *ump;
                    524:        register struct fs *fs;
                    525: 
                    526:        ump = VFSTOUFS(mp);
                    527:        fs = ump->um_fs;
                    528:        if (fs->fs_magic != FS_MAGIC)
                    529:                panic("ufs_statfs");
                    530:        sbp->f_type = MOUNT_UFS;
                    531:        sbp->f_fsize = fs->fs_fsize;
                    532:        sbp->f_bsize = fs->fs_bsize;
                    533:        sbp->f_blocks = fs->fs_dsize;
                    534:        sbp->f_bfree = fs->fs_cstotal.cs_nbfree * fs->fs_frag +
                    535:                fs->fs_cstotal.cs_nffree;
                    536:        sbp->f_bavail = (fs->fs_dsize * (100 - fs->fs_minfree) / 100) -
                    537:                (fs->fs_dsize - sbp->f_bfree);
                    538:        sbp->f_files =  fs->fs_ncg * fs->fs_ipg - ROOTINO;
                    539:        sbp->f_ffree = fs->fs_cstotal.cs_nifree;
                    540:        if (sbp != &mp->mnt_stat) {
                    541:                bcopy((caddr_t)mp->mnt_stat.f_mntonname,
                    542:                        (caddr_t)&sbp->f_mntonname[0], MNAMELEN);
                    543:                bcopy((caddr_t)mp->mnt_stat.f_mntfromname,
                    544:                        (caddr_t)&sbp->f_mntfromname[0], MNAMELEN);
                    545:        }
                    546:        return (0);
                    547: }
                    548: 
                    549: int    syncprt = 0;
                    550: 
                    551: /*
                    552:  * Go through the disk queues to initiate sandbagged IO;
                    553:  * go through the inodes to write those that have been modified;
                    554:  * initiate the writing of the super block if it has been modified.
                    555:  *
                    556:  * Note: we are always called with the filesystem marked `MPBUSY'.
                    557:  */
                    558: ufs_sync(mp, waitfor)
                    559:        struct mount *mp;
                    560:        int waitfor;
                    561: {
                    562:        register struct vnode *vp;
                    563:        register struct inode *ip;
                    564:        register struct ufsmount *ump = VFSTOUFS(mp);
                    565:        register struct fs *fs;
                    566:        int error, allerror = 0;
                    567: 
                    568:        if (syncprt)
                    569:                bufstats();
                    570:        fs = ump->um_fs;
                    571:        /*
                    572:         * Write back modified superblock.
                    573:         * Consistency check that the superblock
                    574:         * is still in the buffer cache.
                    575:         */
                    576:        if (fs->fs_fmod != 0) {
                    577:                if (fs->fs_ronly != 0) {                /* XXX */
                    578:                        printf("fs = %s\n", fs->fs_fsmnt);
                    579:                        panic("update: rofs mod");
                    580:                }
                    581:                fs->fs_fmod = 0;
                    582:                fs->fs_time = time.tv_sec;
                    583:                allerror = sbupdate(ump, waitfor);
                    584:        }
                    585:        /*
                    586:         * Write back each (modified) inode.
                    587:         */
                    588: loop:
                    589:        for (vp = mp->mnt_mounth; vp; vp = vp->v_mountf) {
                    590:                /*
                    591:                 * If the vnode that we are about to sync is no longer
                    592:                 * associated with this mount point, start over.
                    593:                 */
                    594:                if (vp->v_mount != mp)
                    595:                        goto loop;
                    596:                if (VOP_ISLOCKED(vp))
                    597:                        continue;
                    598:                ip = VTOI(vp);
                    599:                if ((ip->i_flag & (IMOD|IACC|IUPD|ICHG)) == 0 &&
                    600:                    vp->v_dirtyblkhd == NULL)
                    601:                        continue;
                    602:                if (vget(vp))
                    603:                        goto loop;
                    604:                if (vp->v_dirtyblkhd)
                    605:                        vflushbuf(vp, 0);
                    606:                if ((ip->i_flag & (IMOD|IACC|IUPD|ICHG)) &&
                    607:                    (error = iupdat(ip, &time, &time, 0)))
                    608:                        allerror = error;
                    609:                vput(vp);
                    610:        }
                    611:        /*
                    612:         * Force stale file system control information to be flushed.
                    613:         */
                    614:        vflushbuf(ump->um_devvp, waitfor == MNT_WAIT ? B_SYNC : 0);
                    615: #ifdef QUOTA
                    616:        qsync(mp);
                    617: #endif
                    618:        return (allerror);
                    619: }
                    620: 
                    621: /*
                    622:  * Write a superblock and associated information back to disk.
                    623:  */
                    624: sbupdate(mp, waitfor)
                    625:        struct ufsmount *mp;
                    626:        int waitfor;
                    627: {
                    628:        register struct fs *fs = mp->um_fs;
                    629:        register struct buf *bp;
                    630:        int blks;
                    631:        caddr_t space;
                    632:        int i, size, error = 0;
                    633: 
                    634:        bp = getblk(mp->um_devvp, SBLOCK, (int)fs->fs_sbsize);
                    635:        bcopy((caddr_t)fs, bp->b_un.b_addr, (u_int)fs->fs_sbsize);
                    636:        /* Restore compatibility to old file systems.              XXX */
                    637:        if (fs->fs_postblformat == FS_42POSTBLFMT)              /* XXX */
                    638:                bp->b_un.b_fs->fs_nrpos = -1;                   /* XXX */
                    639:        if (waitfor == MNT_WAIT)
                    640:                error = bwrite(bp);
                    641:        else
                    642:                bawrite(bp);
                    643:        blks = howmany(fs->fs_cssize, fs->fs_fsize);
                    644:        space = (caddr_t)fs->fs_csp[0];
                    645:        for (i = 0; i < blks; i += fs->fs_frag) {
                    646:                size = fs->fs_bsize;
                    647:                if (i + fs->fs_frag > blks)
                    648:                        size = (blks - i) * fs->fs_fsize;
                    649:                bp = getblk(mp->um_devvp, fsbtodb(fs, fs->fs_csaddr + i), size);
                    650:                bcopy(space, bp->b_un.b_addr, (u_int)size);
                    651:                space += size;
                    652:                if (waitfor == MNT_WAIT)
                    653:                        error = bwrite(bp);
                    654:                else
                    655:                        bawrite(bp);
                    656:        }
                    657:        return (error);
                    658: }
                    659: 
                    660: /*
                    661:  * Print out statistics on the current allocation of the buffer pool.
                    662:  * Can be enabled to print out on every ``sync'' by setting "syncprt"
                    663:  * above.
                    664:  */
                    665: bufstats()
                    666: {
                    667:        int s, i, j, count;
                    668:        register struct buf *bp, *dp;
                    669:        int counts[MAXBSIZE/CLBYTES+1];
                    670:        static char *bname[BQUEUES] = { "LOCKED", "LRU", "AGE", "EMPTY" };
                    671: 
                    672:        for (bp = bfreelist, i = 0; bp < &bfreelist[BQUEUES]; bp++, i++) {
                    673:                count = 0;
                    674:                for (j = 0; j <= MAXBSIZE/CLBYTES; j++)
                    675:                        counts[j] = 0;
                    676:                s = splbio();
                    677:                for (dp = bp->av_forw; dp != bp; dp = dp->av_forw) {
                    678:                        counts[dp->b_bufsize/CLBYTES]++;
                    679:                        count++;
                    680:                }
                    681:                splx(s);
                    682:                printf("%s: total-%d", bname[i], count);
                    683:                for (j = 0; j <= MAXBSIZE/CLBYTES; j++)
                    684:                        if (counts[j] != 0)
                    685:                                printf(", %d-%d", j * CLBYTES, counts[j]);
                    686:                printf("\n");
                    687:        }
                    688: }
                    689: 
                    690: /*
                    691:  * File handle to vnode
                    692:  *
                    693:  * Have to be really careful about stale file handles:
                    694:  * - check that the inode number is in range
                    695:  * - call iget() to get the locked inode
                    696:  * - check for an unallocated inode (i_mode == 0)
                    697:  * - check that the generation number matches
                    698:  */
                    699: ufs_fhtovp(mp, fhp, vpp)
                    700:        register struct mount *mp;
                    701:        struct fid *fhp;
                    702:        struct vnode **vpp;
                    703: {
                    704:        register struct ufid *ufhp;
                    705:        register struct fs *fs;
                    706:        register struct inode *ip;
                    707:        struct inode *nip;
                    708:        struct vnode tvp;
                    709:        int error;
                    710: 
                    711:        ufhp = (struct ufid *)fhp;
                    712:        fs = VFSTOUFS(mp)->um_fs;
                    713:        if (ufhp->ufid_ino < ROOTINO ||
                    714:            ufhp->ufid_ino >= fs->fs_ncg * fs->fs_ipg) {
                    715:                *vpp = NULLVP;
                    716:                return (EINVAL);
                    717:        }
                    718:        tvp.v_mount = mp;
                    719:        ip = VTOI(&tvp);
                    720:        ip->i_vnode = &tvp;
                    721:        ip->i_dev = VFSTOUFS(mp)->um_dev;
                    722:        if (error = iget(ip, ufhp->ufid_ino, &nip)) {
                    723:                *vpp = NULLVP;
                    724:                return (error);
                    725:        }
                    726:        ip = nip;
                    727:        if (ip->i_mode == 0) {
                    728:                iput(ip);
                    729:                *vpp = NULLVP;
                    730:                return (EINVAL);
                    731:        }
                    732:        if (ip->i_gen != ufhp->ufid_gen) {
                    733:                iput(ip);
                    734:                *vpp = NULLVP;
                    735:                return (EINVAL);
                    736:        }
                    737:        *vpp = ITOV(ip);
                    738:        return (0);
                    739: }
                    740: 
                    741: /*
                    742:  * Vnode pointer to File handle
                    743:  */
                    744: /* ARGSUSED */
                    745: ufs_vptofh(vp, fhp)
                    746:        struct vnode *vp;
                    747:        struct fid *fhp;
                    748: {
                    749:        register struct inode *ip = VTOI(vp);
                    750:        register struct ufid *ufhp;
                    751: 
                    752:        ufhp = (struct ufid *)fhp;
                    753:        ufhp->ufid_len = sizeof(struct ufid);
                    754:        ufhp->ufid_ino = ip->i_number;
                    755:        ufhp->ufid_gen = ip->i_gen;
                    756:        return (0);
                    757: }

unix.superglobalmegacorp.com

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