Annotation of 43BSDReno/sys/ufs/ufs_vfsops.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

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