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

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

unix.superglobalmegacorp.com

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