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

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

unix.superglobalmegacorp.com

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