[BACK]Return to ffs_vfsops.c CVS log [TXT][DIR] Up to [local] / sys / ufs / ffs

Annotation of sys/ufs/ffs/ffs_vfsops.c, Revision 1.1.1.1

1.1       nbrk        1: /*     $OpenBSD: ffs_vfsops.c,v 1.109 2007/08/04 03:33:31 art Exp $    */
                      2: /*     $NetBSD: ffs_vfsops.c,v 1.19 1996/02/09 22:22:26 christos Exp $ */
                      3:
                      4: /*
                      5:  * Copyright (c) 1989, 1991, 1993, 1994
                      6:  *     The Regents of the University of California.  All rights reserved.
                      7:  *
                      8:  * Redistribution and use in source and binary forms, with or without
                      9:  * modification, are permitted provided that the following conditions
                     10:  * are met:
                     11:  * 1. Redistributions of source code must retain the above copyright
                     12:  *    notice, this list of conditions and the following disclaimer.
                     13:  * 2. Redistributions in binary form must reproduce the above copyright
                     14:  *    notice, this list of conditions and the following disclaimer in the
                     15:  *    documentation and/or other materials provided with the distribution.
                     16:  * 3. Neither the name of the University nor the names of its contributors
                     17:  *    may be used to endorse or promote products derived from this software
                     18:  *    without specific prior written permission.
                     19:  *
                     20:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     21:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     22:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     23:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     24:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     25:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     26:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     27:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     28:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     29:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     30:  * SUCH DAMAGE.
                     31:  *
                     32:  *     @(#)ffs_vfsops.c        8.14 (Berkeley) 11/28/94
                     33:  */
                     34:
                     35: #include <sys/param.h>
                     36: #include <sys/systm.h>
                     37: #include <sys/namei.h>
                     38: #include <sys/proc.h>
                     39: #include <sys/kernel.h>
                     40: #include <sys/vnode.h>
                     41: #include <sys/socket.h>
                     42: #include <sys/mount.h>
                     43: #include <sys/buf.h>
                     44: #include <sys/mbuf.h>
                     45: #include <sys/file.h>
                     46: #include <sys/disklabel.h>
                     47: #include <sys/ioctl.h>
                     48: #include <sys/errno.h>
                     49: #include <sys/malloc.h>
                     50: #include <sys/sysctl.h>
                     51: #include <sys/pool.h>
                     52:
                     53: #include <dev/rndvar.h>
                     54:
                     55: #include <miscfs/specfs/specdev.h>
                     56:
                     57: #include <ufs/ufs/quota.h>
                     58: #include <ufs/ufs/ufsmount.h>
                     59: #include <ufs/ufs/inode.h>
                     60: #include <ufs/ufs/dir.h>
                     61: #include <ufs/ufs/ufs_extern.h>
                     62: #include <ufs/ufs/dirhash.h>
                     63:
                     64: #include <ufs/ffs/fs.h>
                     65: #include <ufs/ffs/ffs_extern.h>
                     66:
                     67: int ffs_sbupdate(struct ufsmount *, int);
                     68: int ffs_reload_vnode(struct vnode *, void *);
                     69: int ffs_sync_vnode(struct vnode *, void *);
                     70: int ffs_validate(struct fs *);
                     71:
                     72: void ffs1_compat_read(struct fs *, struct ufsmount *, daddr64_t);
                     73: void ffs1_compat_write(struct fs *, struct ufsmount *);
                     74:
                     75: const struct vfsops ffs_vfsops = {
                     76:        ffs_mount,
                     77:        ufs_start,
                     78:        ffs_unmount,
                     79:        ufs_root,
                     80:        ufs_quotactl,
                     81:        ffs_statfs,
                     82:        ffs_sync,
                     83:        ffs_vget,
                     84:        ffs_fhtovp,
                     85:        ffs_vptofh,
                     86:        ffs_init,
                     87:        ffs_sysctl,
                     88:        ufs_check_export
                     89: };
                     90:
                     91: struct inode_vtbl ffs_vtbl = {
                     92:        ffs_truncate,
                     93:        ffs_update,
                     94:        ffs_inode_alloc,
                     95:        ffs_inode_free,
                     96:        ffs_balloc,
                     97:        ffs_bufatoff
                     98: };
                     99:
                    100:
                    101: /*
                    102:  * Called by main() when ufs is going to be mounted as root.
                    103:  */
                    104:
                    105: struct pool ffs_ino_pool;
                    106: struct pool ffs_dinode1_pool;
                    107: #ifdef FFS2
                    108: struct pool ffs_dinode2_pool;
                    109: #endif
                    110:
                    111: int
                    112: ffs_mountroot(void)
                    113: {
                    114:        struct fs *fs;
                    115:        struct mount *mp;
                    116:        struct proc *p = curproc;       /* XXX */
                    117:        struct ufsmount *ump;
                    118:        int error;
                    119:
                    120:        /*
                    121:         * Get vnodes for swapdev and rootdev.
                    122:         */
                    123:        swapdev_vp = NULL;
                    124:        if ((error = bdevvp(swapdev, &swapdev_vp)) ||
                    125:            (error = bdevvp(rootdev, &rootvp))) {
                    126:                printf("ffs_mountroot: can't setup bdevvp's\n");
                    127:                if (swapdev_vp)
                    128:                        vrele(swapdev_vp);
                    129:                return (error);
                    130:        }
                    131:
                    132:        if ((error = vfs_rootmountalloc("ffs", "root_device", &mp)) != 0) {
                    133:                vrele(swapdev_vp);
                    134:                vrele(rootvp);
                    135:                return (error);
                    136:        }
                    137:
                    138:        if ((error = ffs_mountfs(rootvp, mp, p)) != 0) {
                    139:                mp->mnt_vfc->vfc_refcount--;
                    140:                vfs_unbusy(mp);
                    141:                free(mp, M_MOUNT);
                    142:                vrele(swapdev_vp);
                    143:                vrele(rootvp);
                    144:                return (error);
                    145:        }
                    146:
                    147:        CIRCLEQ_INSERT_TAIL(&mountlist, mp, mnt_list);
                    148:        ump = VFSTOUFS(mp);
                    149:        fs = ump->um_fs;
                    150:        (void) copystr(mp->mnt_stat.f_mntonname, fs->fs_fsmnt, MNAMELEN - 1, 0);
                    151:        (void)ffs_statfs(mp, &mp->mnt_stat, p);
                    152:        vfs_unbusy(mp);
                    153:        inittodr(fs->fs_time);
                    154:
                    155:        return (0);
                    156: }
                    157:
                    158: /*
                    159:  * VFS Operations.
                    160:  *
                    161:  * mount system call
                    162:  */
                    163: int
                    164: ffs_mount(struct mount *mp, const char *path, void *data,
                    165:     struct nameidata *ndp, struct proc *p)
                    166: {
                    167:        struct vnode *devvp;
                    168:        struct ufs_args args;
                    169:        struct ufsmount *ump = NULL;
                    170:        struct fs *fs;
                    171:        int error = 0, flags;
                    172:        int ronly;
                    173:        mode_t accessmode;
                    174:        size_t size;
                    175:
                    176:        error = copyin(data, &args, sizeof (struct ufs_args));
                    177:        if (error)
                    178:                return (error);
                    179:
                    180: #ifndef FFS_SOFTUPDATES
                    181:        if (mp->mnt_flag & MNT_SOFTDEP) {
                    182:                printf("WARNING: soft updates isn't compiled in\n");
                    183:                mp->mnt_flag &= ~MNT_SOFTDEP;
                    184:        }
                    185: #endif
                    186:
                    187:        /*
                    188:         * Soft updates is incompatible with "async",
                    189:         * so if we are doing softupdates stop the user
                    190:         * from setting the async flag.
                    191:         */
                    192:        if ((mp->mnt_flag & (MNT_SOFTDEP | MNT_ASYNC)) ==
                    193:            (MNT_SOFTDEP | MNT_ASYNC)) {
                    194:                return (EINVAL);
                    195:        }
                    196:        /*
                    197:         * If updating, check whether changing from read-only to
                    198:         * read/write; if there is no device name, that's all we do.
                    199:         */
                    200:        if (mp->mnt_flag & MNT_UPDATE) {
                    201:                ump = VFSTOUFS(mp);
                    202:                fs = ump->um_fs;
                    203:                devvp = ump->um_devvp;
                    204:                error = 0;
                    205:                ronly = fs->fs_ronly;
                    206:
                    207:                if (ronly == 0 && (mp->mnt_flag & MNT_RDONLY)) {
                    208:                        /* Flush any dirty data */
                    209:                        mp->mnt_flag &= ~MNT_RDONLY;
                    210:                        VFS_SYNC(mp, MNT_WAIT, p->p_ucred, p);
                    211:                        mp->mnt_flag |= MNT_RDONLY;
                    212:
                    213:                        /*
                    214:                         * Get rid of files open for writing.
                    215:                         */
                    216:                        flags = WRITECLOSE;
                    217:                        if (mp->mnt_flag & MNT_FORCE)
                    218:                                flags |= FORCECLOSE;
                    219:                        if (fs->fs_flags & FS_DOSOFTDEP) {
                    220:                                error = softdep_flushfiles(mp, flags, p);
                    221:                                mp->mnt_flag &= ~MNT_SOFTDEP;
                    222:                        } else
                    223:                                error = ffs_flushfiles(mp, flags, p);
                    224:                        ronly = 1;
                    225:                }
                    226:
                    227:                /*
                    228:                 * Flush soft dependencies if disabling it via an update
                    229:                 * mount. This may leave some items to be processed,
                    230:                 * so don't do this yet XXX.
                    231:                 */
                    232:                if ((fs->fs_flags & FS_DOSOFTDEP) &&
                    233:                    !(mp->mnt_flag & MNT_SOFTDEP) &&
                    234:                    !(mp->mnt_flag & MNT_RDONLY) && fs->fs_ronly == 0) {
                    235: #if 0
                    236:                        flags = WRITECLOSE;
                    237:                        if (mp->mnt_flag & MNT_FORCE)
                    238:                                flags |= FORCECLOSE;
                    239:                        error = softdep_flushfiles(mp, flags, p);
                    240: #elif FFS_SOFTUPDATES
                    241:                        mp->mnt_flag |= MNT_SOFTDEP;
                    242: #endif
                    243:                }
                    244:                /*
                    245:                 * When upgrading to a softdep mount, we must first flush
                    246:                 * all vnodes. (not done yet -- see above)
                    247:                 */
                    248:                if (!(fs->fs_flags & FS_DOSOFTDEP) &&
                    249:                    (mp->mnt_flag & MNT_SOFTDEP) && fs->fs_ronly == 0) {
                    250: #if 0
                    251:                        flags = WRITECLOSE;
                    252:                        if (mp->mnt_flag & MNT_FORCE)
                    253:                                flags |= FORCECLOSE;
                    254:                        error = ffs_flushfiles(mp, flags, p);
                    255: #else
                    256:                        mp->mnt_flag &= ~MNT_SOFTDEP;
                    257: #endif
                    258:                }
                    259:
                    260:                if (!error && (mp->mnt_flag & MNT_RELOAD))
                    261:                        error = ffs_reload(mp, ndp->ni_cnd.cn_cred, p);
                    262:                if (error)
                    263:                        goto error_1;
                    264:
                    265:                if (ronly && (mp->mnt_flag & MNT_WANTRDWR)) {
                    266:                        /*
                    267:                         * If upgrade to read-write by non-root, then verify
                    268:                         * that user has necessary permissions on the device.
                    269:                         */
                    270:                        if (suser(p, 0)) {
                    271:                                vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, p);
                    272:                                error = VOP_ACCESS(devvp, VREAD | VWRITE,
                    273:                                                   p->p_ucred, p);
                    274:                                VOP_UNLOCK(devvp, 0, p);
                    275:                                if (error)
                    276:                                        goto error_1;
                    277:                        }
                    278:
                    279:                        if (fs->fs_clean == 0) {
                    280: #if 0
                    281:                                /*
                    282:                                 * It is safe mount unclean file system
                    283:                                 * if it was previously mounted with softdep
                    284:                                 * but we may loss space and must
                    285:                                 * sometimes run fsck manually.
                    286:                                 */
                    287:                                if (fs->fs_flags & FS_DOSOFTDEP)
                    288:                                        printf(
                    289: "WARNING: %s was not properly unmounted\n",
                    290:                                            fs->fs_fsmnt);
                    291:                                else
                    292: #endif
                    293:                                if (mp->mnt_flag & MNT_FORCE) {
                    294:                                        printf(
                    295: "WARNING: %s was not properly unmounted\n",
                    296:                                            fs->fs_fsmnt);
                    297:                                } else {
                    298:                                        printf(
                    299: "WARNING: R/W mount of %s denied.  Filesystem is not clean - run fsck\n",
                    300:                                            fs->fs_fsmnt);
                    301:                                        error = EROFS;
                    302:                                        goto error_1;
                    303:                                }
                    304:                        }
                    305:
                    306:                        if ((fs->fs_flags & FS_DOSOFTDEP)) {
                    307:                                error = softdep_mount(devvp, mp, fs,
                    308:                                                      p->p_ucred);
                    309:                                if (error)
                    310:                                        goto error_1;
                    311:                        }
                    312:                        fs->fs_contigdirs=(u_int8_t*)malloc((u_long)fs->fs_ncg,
                    313:                                                            M_UFSMNT, M_WAITOK);
                    314:                        bzero(fs->fs_contigdirs, fs->fs_ncg);
                    315:
                    316:                        ronly = 0;
                    317:                }
                    318:                if (args.fspec == 0) {
                    319:                        /*
                    320:                         * Process export requests.
                    321:                         */
                    322:                        error = vfs_export(mp, &ump->um_export,
                    323:                            &args.export_info);
                    324:                        if (error)
                    325:                                goto error_1;
                    326:                        else
                    327:                                goto success;
                    328:                }
                    329:        }
                    330:        /*
                    331:         * Not an update, or updating the name: look up the name
                    332:         * and verify that it refers to a sensible block device.
                    333:         */
                    334:        NDINIT(ndp, LOOKUP, FOLLOW, UIO_USERSPACE, args.fspec, p);
                    335:        if ((error = namei(ndp)) != 0)
                    336:                goto error_1;
                    337:
                    338:        devvp = ndp->ni_vp;
                    339:
                    340:        if (devvp->v_type != VBLK) {
                    341:                error = ENOTBLK;
                    342:                goto error_2;
                    343:        }
                    344:
                    345:        if (major(devvp->v_rdev) >= nblkdev) {
                    346:                error = ENXIO;
                    347:                goto error_2;
                    348:        }
                    349:
                    350:        /*
                    351:         * If mount by non-root, then verify that user has necessary
                    352:         * permissions on the device.
                    353:         */
                    354:        if (suser(p, 0)) {
                    355:                accessmode = VREAD;
                    356:                if ((mp->mnt_flag & MNT_RDONLY) == 0)
                    357:                        accessmode |= VWRITE;
                    358:                vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, p);
                    359:                error = VOP_ACCESS(devvp, accessmode, p->p_ucred, p);
                    360:                VOP_UNLOCK(devvp, 0, p);
                    361:                if (error)
                    362:                        goto error_2;
                    363:        }
                    364:
                    365:        if (mp->mnt_flag & MNT_UPDATE) {
                    366:                /*
                    367:                 * UPDATE
                    368:                 * If it's not the same vnode, or at least the same device
                    369:                 * then it's not correct.
                    370:                 */
                    371:
                    372:                if (devvp != ump->um_devvp) {
                    373:                        if (devvp->v_rdev == ump->um_devvp->v_rdev) {
                    374:                                vrele(devvp);
                    375:                        } else {
                    376:                                error = EINVAL; /* needs translation */
                    377:                        }
                    378:                } else
                    379:                        vrele(devvp);
                    380:                /*
                    381:                 * Update device name only on success
                    382:                 */
                    383:                if (!error) {
                    384:                        /*
                    385:                         * Save "mounted from" info for mount point (NULL pad)
                    386:                         */
                    387:                        copyinstr(args.fspec,
                    388:                                  mp->mnt_stat.f_mntfromname,
                    389:                                  MNAMELEN - 1,
                    390:                                  &size);
                    391:                        bzero(mp->mnt_stat.f_mntfromname + size,
                    392:                              MNAMELEN - size);
                    393:                }
                    394:        } else {
                    395:                /*
                    396:                 * Since this is a new mount, we want the names for
                    397:                 * the device and the mount point copied in.  If an
                    398:                 * error occurs,  the mountpoint is discarded by the
                    399:                 * upper level code.
                    400:                 */
                    401:                /* Save "last mounted on" info for mount point (NULL pad)*/
                    402:                copyinstr(path,                         /* mount point*/
                    403:                          mp->mnt_stat.f_mntonname,     /* save area*/
                    404:                          MNAMELEN - 1,                 /* max size*/
                    405:                          &size);                       /* real size*/
                    406:                bzero(mp->mnt_stat.f_mntonname + size, MNAMELEN - size);
                    407:
                    408:                /* Save "mounted from" info for mount point (NULL pad)*/
                    409:                copyinstr(args.fspec,                   /* device name*/
                    410:                          mp->mnt_stat.f_mntfromname,   /* save area*/
                    411:                          MNAMELEN - 1,                 /* max size*/
                    412:                          &size);                       /* real size*/
                    413:                bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size);
                    414:
                    415:                error = ffs_mountfs(devvp, mp, p);
                    416:        }
                    417:
                    418:        if (error)
                    419:                goto error_2;
                    420:
                    421:        /*
                    422:         * Initialize FS stat information in mount struct; uses both
                    423:         * mp->mnt_stat.f_mntonname and mp->mnt_stat.f_mntfromname
                    424:         *
                    425:         * This code is common to root and non-root mounts
                    426:         */
                    427:        bcopy(&args, &mp->mnt_stat.mount_info.ufs_args, sizeof(args));
                    428:        (void)VFS_STATFS(mp, &mp->mnt_stat, p);
                    429:
                    430: success:
                    431:        if (path && (mp->mnt_flag & MNT_UPDATE)) {
                    432:                /* Update clean flag after changing read-onlyness. */
                    433:                fs = ump->um_fs;
                    434:                if (ronly != fs->fs_ronly) {
                    435:                        fs->fs_ronly = ronly;
                    436:                        fs->fs_clean = ronly &&
                    437:                            (fs->fs_flags & FS_UNCLEAN) == 0 ? 1 : 0;
                    438:                        if (ronly)
                    439:                                free(fs->fs_contigdirs, M_UFSMNT);
                    440:                }
                    441:                if (!ronly) {
                    442:                        if (mp->mnt_flag & MNT_SOFTDEP)
                    443:                                fs->fs_flags |= FS_DOSOFTDEP;
                    444:                        else
                    445:                                fs->fs_flags &= ~FS_DOSOFTDEP;
                    446:                }
                    447:                ffs_sbupdate(ump, MNT_WAIT);
                    448:        }
                    449:        return (0);
                    450:
                    451: error_2:       /* error with devvp held */
                    452:        vrele (devvp);
                    453: error_1:       /* no state to back out */
                    454:        return (error);
                    455: }
                    456:
                    457: struct ffs_reload_args {
                    458:        struct fs *fs;
                    459:        struct proc *p;
                    460:        struct ucred *cred;
                    461:        struct vnode *devvp;
                    462: };
                    463:
                    464: int
                    465: ffs_reload_vnode(struct vnode *vp, void *args)
                    466: {
                    467:        struct ffs_reload_args *fra = args;
                    468:        struct inode *ip;
                    469:        struct buf *bp;
                    470:        int error;
                    471:
                    472:        /*
                    473:         * Step 4: invalidate all inactive vnodes.
                    474:         */
                    475:        if (vp->v_usecount == 0) {
                    476:                vgonel(vp, fra->p);
                    477:                return (0);
                    478:        }
                    479:
                    480:        /*
                    481:         * Step 5: invalidate all cached file data.
                    482:         */
                    483:        if (vget(vp, LK_EXCLUSIVE, fra->p))
                    484:                return (0);
                    485:
                    486:        if (vinvalbuf(vp, 0, fra->cred, fra->p, 0, 0))
                    487:                panic("ffs_reload: dirty2");
                    488:
                    489:        /*
                    490:         * Step 6: re-read inode data for all active vnodes.
                    491:         */
                    492:        ip = VTOI(vp);
                    493:
                    494:        error = bread(fra->devvp,
                    495:            fsbtodb(fra->fs, ino_to_fsba(fra->fs, ip->i_number)),
                    496:            (int)fra->fs->fs_bsize, NOCRED, &bp);
                    497:        if (error) {
                    498:                brelse(bp);
                    499:                vput(vp);
                    500:                return (error);
                    501:        }
                    502:
                    503:        *ip->i_din1 = *((struct ufs1_dinode *)bp->b_data +
                    504:            ino_to_fsbo(fra->fs, ip->i_number));
                    505:        ip->i_effnlink = DIP(ip, nlink);
                    506:        brelse(bp);
                    507:        vput(vp);
                    508:        return (0);
                    509: }
                    510:
                    511: /*
                    512:  * Reload all incore data for a filesystem (used after running fsck on
                    513:  * the root filesystem and finding things to fix). The filesystem must
                    514:  * be mounted read-only.
                    515:  *
                    516:  * Things to do to update the mount:
                    517:  *     1) invalidate all cached meta-data.
                    518:  *     2) re-read superblock from disk.
                    519:  *     3) re-read summary information from disk.
                    520:  *     4) invalidate all inactive vnodes.
                    521:  *     5) invalidate all cached file data.
                    522:  *     6) re-read inode data for all active vnodes.
                    523:  */
                    524: int
                    525: ffs_reload(struct mount *mountp, struct ucred *cred, struct proc *p)
                    526: {
                    527:        struct vnode *devvp;
                    528:        caddr_t space;
                    529:        struct fs *fs, *newfs;
                    530:        struct partinfo dpart;
                    531:        int i, blks, size, error;
                    532:        int32_t *lp;
                    533:        struct buf *bp = NULL;
                    534:        struct ffs_reload_args fra;
                    535:
                    536:        if ((mountp->mnt_flag & MNT_RDONLY) == 0)
                    537:                return (EINVAL);
                    538:        /*
                    539:         * Step 1: invalidate all cached meta-data.
                    540:         */
                    541:        devvp = VFSTOUFS(mountp)->um_devvp;
                    542:        vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, p);
                    543:        error = vinvalbuf(devvp, 0, cred, p, 0, 0);
                    544:        VOP_UNLOCK(devvp, 0, p);
                    545:        if (error)
                    546:                panic("ffs_reload: dirty1");
                    547:
                    548:        /*
                    549:         * Step 2: re-read superblock from disk.
                    550:         */
                    551:        if (VOP_IOCTL(devvp, DIOCGPART, (caddr_t)&dpart, FREAD, NOCRED, p) != 0)
                    552:                size = DEV_BSIZE;
                    553:        else
                    554:                size = dpart.disklab->d_secsize;
                    555:
                    556:        fs = VFSTOUFS(mountp)->um_fs;
                    557:
                    558:        error = bread(devvp, (daddr_t)(fs->fs_sblockloc / size), SBSIZE,
                    559:            NOCRED, &bp);
                    560:        if (error) {
                    561:                brelse(bp);
                    562:                return (error);
                    563:        }
                    564:
                    565:        newfs = (struct fs *)bp->b_data;
                    566:        if (ffs_validate(newfs) == 0) {
                    567:                brelse(bp);
                    568:                return (EINVAL);
                    569:        }
                    570:
                    571:        /*
                    572:         * Copy pointer fields back into superblock before copying in   XXX
                    573:         * new superblock. These should really be in the ufsmount.      XXX
                    574:         * Note that important parameters (eg fs_ncg) are unchanged.
                    575:         */
                    576:        newfs->fs_csp = fs->fs_csp;
                    577:        newfs->fs_maxcluster = fs->fs_maxcluster;
                    578:        newfs->fs_ronly = fs->fs_ronly;
                    579:        bcopy(newfs, fs, (u_int)fs->fs_sbsize);
                    580:        if (fs->fs_sbsize < SBSIZE)
                    581:                bp->b_flags |= B_INVAL;
                    582:        brelse(bp);
                    583:        mountp->mnt_maxsymlinklen = fs->fs_maxsymlinklen;
                    584:        ffs1_compat_read(fs, VFSTOUFS(mountp), fs->fs_sblockloc);
                    585:        ffs_oldfscompat(fs);
                    586:        (void)ffs_statfs(mountp, &mountp->mnt_stat, p);
                    587:        /*
                    588:         * Step 3: re-read summary information from disk.
                    589:         */
                    590:        blks = howmany(fs->fs_cssize, fs->fs_fsize);
                    591:        space = (caddr_t)fs->fs_csp;
                    592:        for (i = 0; i < blks; i += fs->fs_frag) {
                    593:                size = fs->fs_bsize;
                    594:                if (i + fs->fs_frag > blks)
                    595:                        size = (blks - i) * fs->fs_fsize;
                    596:                error = bread(devvp, fsbtodb(fs, fs->fs_csaddr + i), size,
                    597:                              NOCRED, &bp);
                    598:                if (error) {
                    599:                        brelse(bp);
                    600:                        return (error);
                    601:                }
                    602:                bcopy(bp->b_data, space, (u_int)size);
                    603:                space += size;
                    604:                brelse(bp);
                    605:        }
                    606:        if ((fs->fs_flags & FS_DOSOFTDEP))
                    607:                (void) softdep_mount(devvp, mountp, fs, cred);
                    608:        /*
                    609:         * We no longer know anything about clusters per cylinder group.
                    610:         */
                    611:        if (fs->fs_contigsumsize > 0) {
                    612:                lp = fs->fs_maxcluster;
                    613:                for (i = 0; i < fs->fs_ncg; i++)
                    614:                        *lp++ = fs->fs_contigsumsize;
                    615:        }
                    616:
                    617:        fra.p = p;
                    618:        fra.cred = cred;
                    619:        fra.fs = fs;
                    620:        fra.devvp = devvp;
                    621:
                    622:        error = vfs_mount_foreach_vnode(mountp, ffs_reload_vnode, &fra);
                    623:
                    624:        return (error);
                    625: }
                    626:
                    627: /*
                    628:  * Checks if a super block is sane enough to be mounted.
                    629:  */
                    630: int
                    631: ffs_validate(struct fs *fsp)
                    632: {
                    633: #ifdef FFS2
                    634:        if (fsp->fs_magic != FS_UFS2_MAGIC && fsp->fs_magic != FS_UFS1_MAGIC)
                    635:                return (0); /* Invalid magic */
                    636: #else
                    637:        if (fsp->fs_magic != FS_UFS1_MAGIC)
                    638:                return (0); /* Invalid magic */
                    639: #endif /* FFS2 */
                    640:
                    641:        if ((u_int)fsp->fs_bsize > MAXBSIZE)
                    642:                return (0); /* Invalid block size */
                    643:
                    644:        if ((u_int)fsp->fs_bsize < sizeof(struct fs))
                    645:                return (0); /* Invalid block size */
                    646:
                    647:        if ((u_int)fsp->fs_sbsize > SBSIZE)
                    648:                return (0); /* Invalid super block size */
                    649:
                    650:        if ((u_int)fsp->fs_frag > MAXFRAG || fragtbl[fsp->fs_frag] == NULL)
                    651:                return (0); /* Invalid number of fragments */
                    652:
                    653:        return (1); /* Super block is okay */
                    654: }
                    655:
                    656: /*
                    657:  * Possible locations for the super-block.
                    658:  */
                    659: const int sbtry[] = SBLOCKSEARCH;
                    660:
                    661: /*
                    662:  * Common code for mount and mountroot
                    663:  */
                    664: int
                    665: ffs_mountfs(struct vnode *devvp, struct mount *mp, struct proc *p)
                    666: {
                    667:        struct ufsmount *ump;
                    668:        struct buf *bp;
                    669:        struct fs *fs;
                    670:        dev_t dev;
                    671:        struct partinfo dpart;
                    672:        caddr_t space;
                    673:        daddr64_t sbloc;
                    674:        int error, i, blks, size, ronly;
                    675:        int32_t *lp;
                    676:        size_t strsize;
                    677:        struct ucred *cred;
                    678:        u_int64_t maxfilesize;                                  /* XXX */
                    679:
                    680:        dev = devvp->v_rdev;
                    681:        cred = p ? p->p_ucred : NOCRED;
                    682:        /*
                    683:         * Disallow multiple mounts of the same device.
                    684:         * Disallow mounting of a device that is currently in use
                    685:         * (except for root, which might share swap device for miniroot).
                    686:         * Flush out any old buffers remaining from a previous use.
                    687:         */
                    688:        if ((error = vfs_mountedon(devvp)) != 0)
                    689:                return (error);
                    690:        if (vcount(devvp) > 1 && devvp != rootvp)
                    691:                return (EBUSY);
                    692:        vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, p);
                    693:        error = vinvalbuf(devvp, V_SAVE, cred, p, 0, 0);
                    694:        VOP_UNLOCK(devvp, 0, p);
                    695:        if (error)
                    696:                return (error);
                    697:
                    698:        ronly = (mp->mnt_flag & MNT_RDONLY) != 0;
                    699:        error = VOP_OPEN(devvp, ronly ? FREAD : FREAD|FWRITE, FSCRED, p);
                    700:        if (error)
                    701:                return (error);
                    702:        if (VOP_IOCTL(devvp, DIOCGPART, (caddr_t)&dpart, FREAD, cred, p) != 0)
                    703:                size = DEV_BSIZE;
                    704:        else
                    705:                size = dpart.disklab->d_secsize;
                    706:
                    707:        bp = NULL;
                    708:        ump = NULL;
                    709:
                    710:        /*
                    711:         * Try reading the super-block in each of its possible locations.
                    712:         */
                    713:        for (i = 0; sbtry[i] != -1; i++) {
                    714:                if (bp != NULL) {
                    715:                        bp->b_flags |= B_NOCACHE;
                    716:                        brelse(bp);
                    717:                        bp = NULL;
                    718:                }
                    719:
                    720:                error = bread(devvp, sbtry[i] / size, SBSIZE, cred, &bp);
                    721:                if (error)
                    722:                        goto out;
                    723:
                    724:                fs = (struct fs *) bp->b_data;
                    725:                sbloc = sbtry[i];
                    726:
                    727: #if 0
                    728:                if (fs->fs_magic == FS_UFS2_MAGIC) {
                    729:                        printf("ffs_mountfs(): Sorry, no UFS2 support (yet)\n");
                    730:                        error = EFTYPE;
                    731:                        goto out;
                    732:                }
                    733: #endif
                    734:
                    735:                /*
                    736:                 * Do not look for an FFS1 file system at SBLOCK_UFS2. Doing so
                    737:                 * will find the wrong super-block for file systems with 64k
                    738:                 * block size.
                    739:                 */
                    740:                if (fs->fs_magic == FS_UFS1_MAGIC && sbloc == SBLOCK_UFS2)
                    741:                        continue;
                    742:
                    743:                if (ffs_validate(fs))
                    744:                        break; /* Super block validated */
                    745:        }
                    746:
                    747:        if (sbtry[i] == -1) {
                    748:                error = EINVAL;
                    749:                goto out;
                    750:        }
                    751:
                    752:        fs->fs_fmod = 0;
                    753:        fs->fs_flags &= ~FS_UNCLEAN;
                    754:        if (fs->fs_clean == 0) {
                    755: #if 0
                    756:                /*
                    757:                 * It is safe mount unclean file system
                    758:                 * if it was previously mounted with softdep
                    759:                 * but we may loss space and must
                    760:                 * sometimes run fsck manually.
                    761:                 */
                    762:                if (fs->fs_flags & FS_DOSOFTDEP)
                    763:                        printf(
                    764: "WARNING: %s was not properly unmounted\n",
                    765:                            fs->fs_fsmnt);
                    766:                else
                    767: #endif
                    768:                if (ronly || (mp->mnt_flag & MNT_FORCE)) {
                    769:                        printf(
                    770: "WARNING: %s was not properly unmounted\n",
                    771:                            fs->fs_fsmnt);
                    772:                } else {
                    773:                        printf(
                    774: "WARNING: R/W mount of %s denied.  Filesystem is not clean - run fsck\n",
                    775:                            fs->fs_fsmnt);
                    776:                        error = EROFS;
                    777:                        goto out;
                    778:                }
                    779:        }
                    780:
                    781:        if (fs->fs_postblformat == FS_42POSTBLFMT && !ronly) {
                    782: #ifndef SMALL_KERNEL
                    783:                printf("ffs_mountfs(): obsolete rotational table format, "
                    784:                    "please use fsck_ffs(8) -c 1\n");
                    785: #endif
                    786:                error = EFTYPE;
                    787:                goto out;
                    788:        }
                    789:
                    790:        ump = malloc(sizeof *ump, M_UFSMNT, M_WAITOK);
                    791:        bzero(ump, sizeof *ump);
                    792:        ump->um_fs = malloc((u_long)fs->fs_sbsize, M_UFSMNT,
                    793:            M_WAITOK);
                    794:
                    795:        if (fs->fs_magic == FS_UFS1_MAGIC)
                    796:                ump->um_fstype = UM_UFS1;
                    797: #ifdef FFS2
                    798:        else
                    799:                ump->um_fstype = UM_UFS2;
                    800: #endif
                    801:
                    802:        bcopy(bp->b_data, ump->um_fs, (u_int)fs->fs_sbsize);
                    803:        if (fs->fs_sbsize < SBSIZE)
                    804:                bp->b_flags |= B_INVAL;
                    805:        brelse(bp);
                    806:        bp = NULL;
                    807:        fs = ump->um_fs;
                    808:
                    809:        ffs1_compat_read(fs, ump, sbloc);
                    810:
                    811:        if (fs->fs_clean == 0)
                    812:                fs->fs_flags |= FS_UNCLEAN;
                    813:        fs->fs_ronly = ronly;
                    814:        size = fs->fs_cssize;
                    815:        blks = howmany(size, fs->fs_fsize);
                    816:        if (fs->fs_contigsumsize > 0)
                    817:                size += fs->fs_ncg * sizeof(int32_t);
                    818:        space = malloc((u_long)size, M_UFSMNT, M_WAITOK);
                    819:        fs->fs_csp = (struct csum *)space;
                    820:        for (i = 0; i < blks; i += fs->fs_frag) {
                    821:                size = fs->fs_bsize;
                    822:                if (i + fs->fs_frag > blks)
                    823:                        size = (blks - i) * fs->fs_fsize;
                    824:                error = bread(devvp, fsbtodb(fs, fs->fs_csaddr + i), size,
                    825:                              cred, &bp);
                    826:                if (error) {
                    827:                        free(fs->fs_csp, M_UFSMNT);
                    828:                        goto out;
                    829:                }
                    830:                bcopy(bp->b_data, space, (u_int)size);
                    831:                space += size;
                    832:                brelse(bp);
                    833:                bp = NULL;
                    834:        }
                    835:        if (fs->fs_contigsumsize > 0) {
                    836:                fs->fs_maxcluster = lp = (int32_t *)space;
                    837:                for (i = 0; i < fs->fs_ncg; i++)
                    838:                        *lp++ = fs->fs_contigsumsize;
                    839:        }
                    840:        mp->mnt_data = (qaddr_t)ump;
                    841:        mp->mnt_stat.f_fsid.val[0] = (long)dev;
                    842:        /* Use on-disk fsid if it exists, else fake it */
                    843:        if (fs->fs_id[0] != 0 && fs->fs_id[1] != 0)
                    844:                mp->mnt_stat.f_fsid.val[1] = fs->fs_id[1];
                    845:        else
                    846:                mp->mnt_stat.f_fsid.val[1] = mp->mnt_vfc->vfc_typenum;
                    847:        mp->mnt_maxsymlinklen = fs->fs_maxsymlinklen;
                    848:        mp->mnt_flag |= MNT_LOCAL;
                    849:        ump->um_mountp = mp;
                    850:        ump->um_dev = dev;
                    851:        ump->um_devvp = devvp;
                    852:        ump->um_nindir = fs->fs_nindir;
                    853:        ump->um_bptrtodb = fs->fs_fsbtodb;
                    854:        ump->um_seqinc = fs->fs_frag;
                    855:        for (i = 0; i < MAXQUOTAS; i++)
                    856:                ump->um_quotas[i] = NULLVP;
                    857:
                    858:        devvp->v_specmountpoint = mp;
                    859:        ffs_oldfscompat(fs);
                    860:
                    861:        if (ronly)
                    862:                fs->fs_contigdirs = NULL;
                    863:        else {
                    864:                fs->fs_contigdirs = (u_int8_t*)malloc((u_long)fs->fs_ncg,
                    865:                                                      M_UFSMNT, M_WAITOK);
                    866:                bzero(fs->fs_contigdirs, fs->fs_ncg);
                    867:        }
                    868:
                    869:        /*
                    870:         * Set FS local "last mounted on" information (NULL pad)
                    871:         */
                    872:        copystr(mp->mnt_stat.f_mntonname,       /* mount point*/
                    873:                fs->fs_fsmnt,                   /* copy area*/
                    874:                sizeof(fs->fs_fsmnt) - 1,       /* max size*/
                    875:                &strsize);                      /* real size*/
                    876:        bzero(fs->fs_fsmnt + strsize, sizeof(fs->fs_fsmnt) - strsize);
                    877:
                    878: #if 0
                    879:        if( mp->mnt_flag & MNT_ROOTFS) {
                    880:                /*
                    881:                 * Root mount; update timestamp in mount structure.
                    882:                 * this will be used by the common root mount code
                    883:                 * to update the system clock.
                    884:                 */
                    885:                mp->mnt_time = fs->fs_time;
                    886:        }
                    887: #endif
                    888:
                    889:        /*
                    890:         * XXX
                    891:         * Limit max file size.  Even though ffs can handle files up to 16TB,
                    892:         * we do limit the max file to 2^31 pages to prevent overflow of
                    893:         * a 32-bit unsigned int.  The buffer cache has its own checks but
                    894:         * a little added paranoia never hurts.
                    895:         */
                    896:        ump->um_savedmaxfilesize = fs->fs_maxfilesize;          /* XXX */
                    897:        maxfilesize = (u_int64_t)0x80000000 * MIN(PAGE_SIZE, fs->fs_bsize) - 1;
                    898:        if (fs->fs_maxfilesize > maxfilesize)                   /* XXX */
                    899:                fs->fs_maxfilesize = maxfilesize;               /* XXX */
                    900:        if (ronly == 0) {
                    901:                if ((fs->fs_flags & FS_DOSOFTDEP) &&
                    902:                    (error = softdep_mount(devvp, mp, fs, cred)) != 0) {
                    903:                        free(fs->fs_csp, M_UFSMNT);
                    904:                        free(fs->fs_contigdirs, M_UFSMNT);
                    905:                        goto out;
                    906:                }
                    907:                fs->fs_fmod = 1;
                    908:                fs->fs_clean = 0;
                    909:                if (mp->mnt_flag & MNT_SOFTDEP)
                    910:                        fs->fs_flags |= FS_DOSOFTDEP;
                    911:                else
                    912:                        fs->fs_flags &= ~FS_DOSOFTDEP;
                    913:                (void) ffs_sbupdate(ump, MNT_WAIT);
                    914:        }
                    915:        return (0);
                    916: out:
                    917:        devvp->v_specmountpoint = NULL;
                    918:        if (bp)
                    919:                brelse(bp);
                    920:        (void)VOP_CLOSE(devvp, ronly ? FREAD : FREAD|FWRITE, cred, p);
                    921:        if (ump) {
                    922:                free(ump->um_fs, M_UFSMNT);
                    923:                free(ump, M_UFSMNT);
                    924:                mp->mnt_data = (qaddr_t)0;
                    925:        }
                    926:        return (error);
                    927: }
                    928:
                    929: /*
                    930:  * Sanity checks for old file systems.
                    931:  */
                    932: int
                    933: ffs_oldfscompat(struct fs *fs)
                    934: {
                    935:        int i;
                    936:
                    937:        fs->fs_npsect = max(fs->fs_npsect, fs->fs_nsect);       /* XXX */
                    938:        fs->fs_interleave = max(fs->fs_interleave, 1);          /* XXX */
                    939:        if (fs->fs_postblformat == FS_42POSTBLFMT)              /* XXX */
                    940:                fs->fs_nrpos = 8;                               /* XXX */
                    941:        if (fs->fs_inodefmt < FS_44INODEFMT) {                  /* XXX */
                    942:                u_int64_t sizepb = fs->fs_bsize;                /* XXX */
                    943:                                                                /* XXX */
                    944:                fs->fs_maxfilesize = fs->fs_bsize * NDADDR - 1; /* XXX */
                    945:                for (i = 0; i < NIADDR; i++) {                  /* XXX */
                    946:                        sizepb *= NINDIR(fs);                   /* XXX */
                    947:                        fs->fs_maxfilesize += sizepb;           /* XXX */
                    948:                }                                               /* XXX */
                    949:                fs->fs_qbmask = ~fs->fs_bmask;                  /* XXX */
                    950:                fs->fs_qfmask = ~fs->fs_fmask;                  /* XXX */
                    951:        }                                                       /* XXX */
                    952:        if (fs->fs_avgfilesize <= 0)                            /* XXX */
                    953:                fs->fs_avgfilesize = AVFILESIZ;                 /* XXX */
                    954:        if (fs->fs_avgfpdir <= 0)                               /* XXX */
                    955:                fs->fs_avgfpdir = AFPDIR;                       /* XXX */
                    956:        return (0);
                    957: }
                    958:
                    959: /*
                    960:  * Auxiliary function for reading FFS1 super blocks.
                    961:  */
                    962: void
                    963: ffs1_compat_read(struct fs *fs, struct ufsmount *ump, daddr64_t sbloc)
                    964: {
                    965:        if (fs->fs_magic == FS_UFS2_MAGIC)
                    966:                return; /* UFS2 */
                    967: #if 0
                    968:        if (fs->fs_ffs1_flags & FS_FLAGS_UPDATED)
                    969:                return; /* Already updated */
                    970: #endif
                    971:        fs->fs_flags = fs->fs_ffs1_flags;
                    972:        fs->fs_sblockloc = sbloc;
                    973:        fs->fs_maxbsize = fs->fs_bsize;
                    974:        fs->fs_time = fs->fs_ffs1_time;
                    975:        fs->fs_size = fs->fs_ffs1_size;
                    976:        fs->fs_dsize = fs->fs_ffs1_dsize;
                    977:        fs->fs_csaddr = fs->fs_ffs1_csaddr;
                    978:        fs->fs_cstotal.cs_ndir = fs->fs_ffs1_cstotal.cs_ndir;
                    979:        fs->fs_cstotal.cs_nbfree = fs->fs_ffs1_cstotal.cs_nbfree;
                    980:        fs->fs_cstotal.cs_nifree = fs->fs_ffs1_cstotal.cs_nifree;
                    981:        fs->fs_cstotal.cs_nffree = fs->fs_ffs1_cstotal.cs_nffree;
                    982:        fs->fs_ffs1_flags |= FS_FLAGS_UPDATED;
                    983: }
                    984:
                    985: /*
                    986:  * Auxiliary function for writing FFS1 super blocks.
                    987:  */
                    988: void
                    989: ffs1_compat_write(struct fs *fs, struct ufsmount *ump)
                    990: {
                    991:        if (fs->fs_magic != FS_UFS1_MAGIC)
                    992:                return; /* UFS2 */
                    993:
                    994:        fs->fs_ffs1_time = fs->fs_time;
                    995:        fs->fs_ffs1_cstotal.cs_ndir = fs->fs_cstotal.cs_ndir;
                    996:        fs->fs_ffs1_cstotal.cs_nbfree = fs->fs_cstotal.cs_nbfree;
                    997:        fs->fs_ffs1_cstotal.cs_nifree = fs->fs_cstotal.cs_nifree;
                    998:        fs->fs_ffs1_cstotal.cs_nffree = fs->fs_cstotal.cs_nffree;
                    999: }
                   1000:
                   1001: /*
                   1002:  * unmount system call
                   1003:  */
                   1004: int
                   1005: ffs_unmount(struct mount *mp, int mntflags, struct proc *p)
                   1006: {
                   1007:        struct ufsmount *ump;
                   1008:        struct fs *fs;
                   1009:        int error, flags;
                   1010:
                   1011:        flags = 0;
                   1012:        if (mntflags & MNT_FORCE)
                   1013:                flags |= FORCECLOSE;
                   1014:
                   1015:        ump = VFSTOUFS(mp);
                   1016:        fs = ump->um_fs;
                   1017:        if (mp->mnt_flag & MNT_SOFTDEP)
                   1018:                error = softdep_flushfiles(mp, flags, p);
                   1019:        else
                   1020:                error = ffs_flushfiles(mp, flags, p);
                   1021:        if (error != 0)
                   1022:                return (error);
                   1023:
                   1024:        if (fs->fs_ronly == 0) {
                   1025:                fs->fs_clean = (fs->fs_flags & FS_UNCLEAN) ? 0 : 1;
                   1026:                error = ffs_sbupdate(ump, MNT_WAIT);
                   1027:                /* ignore write errors if mounted RW on read-only device */
                   1028:                if (error && error != EROFS) {
                   1029:                        fs->fs_clean = 0;
                   1030:                        return (error);
                   1031:                }
                   1032:                free(fs->fs_contigdirs, M_UFSMNT);
                   1033:        }
                   1034:        ump->um_devvp->v_specmountpoint = NULL;
                   1035:
                   1036:        vinvalbuf(ump->um_devvp, V_SAVE, NOCRED, p, 0, 0);
                   1037:        error = VOP_CLOSE(ump->um_devvp, fs->fs_ronly ? FREAD : FREAD|FWRITE,
                   1038:                NOCRED, p);
                   1039:        vrele(ump->um_devvp);
                   1040:        free(fs->fs_csp, M_UFSMNT);
                   1041:        free(fs, M_UFSMNT);
                   1042:        free(ump, M_UFSMNT);
                   1043:        mp->mnt_data = (qaddr_t)0;
                   1044:        mp->mnt_flag &= ~MNT_LOCAL;
                   1045:        return (error);
                   1046: }
                   1047:
                   1048: /*
                   1049:  * Flush out all the files in a filesystem.
                   1050:  */
                   1051: int
                   1052: ffs_flushfiles(struct mount *mp, int flags, struct proc *p)
                   1053: {
                   1054:        struct ufsmount *ump;
                   1055:        int error;
                   1056:
                   1057:        ump = VFSTOUFS(mp);
                   1058:        if (mp->mnt_flag & MNT_QUOTA) {
                   1059:                int i;
                   1060:                if ((error = vflush(mp, NULLVP, SKIPSYSTEM|flags)) != 0)
                   1061:                        return (error);
                   1062:                for (i = 0; i < MAXQUOTAS; i++) {
                   1063:                        if (ump->um_quotas[i] == NULLVP)
                   1064:                                continue;
                   1065:                        quotaoff(p, mp, i);
                   1066:                }
                   1067:                /*
                   1068:                 * Here we fall through to vflush again to ensure
                   1069:                 * that we have gotten rid of all the system vnodes.
                   1070:                 */
                   1071:        }
                   1072:
                   1073:        /*
                   1074:         * Flush all the files.
                   1075:         */
                   1076:        if ((error = vflush(mp, NULL, flags)) != 0)
                   1077:                return (error);
                   1078:        /*
                   1079:         * Flush filesystem metadata.
                   1080:         */
                   1081:        vn_lock(ump->um_devvp, LK_EXCLUSIVE | LK_RETRY, p);
                   1082:        error = VOP_FSYNC(ump->um_devvp, p->p_ucred, MNT_WAIT, p);
                   1083:        VOP_UNLOCK(ump->um_devvp, 0, p);
                   1084:        return (error);
                   1085: }
                   1086:
                   1087: /*
                   1088:  * Get file system statistics.
                   1089:  */
                   1090: int
                   1091: ffs_statfs(struct mount *mp, struct statfs *sbp, struct proc *p)
                   1092: {
                   1093:        struct ufsmount *ump;
                   1094:        struct fs *fs;
                   1095:
                   1096:        ump = VFSTOUFS(mp);
                   1097:        fs = ump->um_fs;
                   1098:
                   1099: #ifdef FFS2
                   1100:        if (fs->fs_magic != FS_MAGIC && fs->fs_magic != FS_UFS2_MAGIC)
                   1101:                panic("ffs_statfs");
                   1102: #else
                   1103:        if (fs->fs_magic != FS_MAGIC)
                   1104:                panic("ffs_statfs");
                   1105: #endif /* FFS2 */
                   1106:
                   1107:        sbp->f_bsize = fs->fs_fsize;
                   1108:        sbp->f_iosize = fs->fs_bsize;
                   1109:        sbp->f_blocks = fs->fs_dsize;
                   1110:        sbp->f_bfree = fs->fs_cstotal.cs_nbfree * fs->fs_frag +
                   1111:                fs->fs_cstotal.cs_nffree;
                   1112:        sbp->f_bavail = sbp->f_bfree - ((int64_t)fs->fs_dsize * fs->fs_minfree / 100);
                   1113:        sbp->f_files = fs->fs_ncg * fs->fs_ipg - ROOTINO;
                   1114:        sbp->f_ffree = fs->fs_cstotal.cs_nifree;
                   1115:        if (sbp != &mp->mnt_stat) {
                   1116:                bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN);
                   1117:                bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN);
                   1118:                bcopy(&mp->mnt_stat.mount_info.ufs_args,
                   1119:                    &sbp->mount_info.ufs_args, sizeof(struct ufs_args));
                   1120:        }
                   1121:        strncpy(sbp->f_fstypename, mp->mnt_vfc->vfc_name, MFSNAMELEN);
                   1122:
                   1123:        return (0);
                   1124: }
                   1125:
                   1126: struct ffs_sync_args {
                   1127:        int allerror;
                   1128:        struct proc *p;
                   1129:        int waitfor;
                   1130:        struct ucred *cred;
                   1131: };
                   1132:
                   1133: int
                   1134: ffs_sync_vnode(struct vnode *vp, void *arg) {
                   1135:        struct ffs_sync_args *fsa = arg;
                   1136:        struct inode *ip;
                   1137:        int error;
                   1138:
                   1139:        ip = VTOI(vp);
                   1140:        if (vp->v_type == VNON ||
                   1141:            ((ip->i_flag &
                   1142:                (IN_ACCESS | IN_CHANGE | IN_MODIFIED | IN_UPDATE)) == 0 &&
                   1143:                LIST_EMPTY(&vp->v_dirtyblkhd)) ) {
                   1144:                return (0);
                   1145:        }
                   1146:
                   1147:        if (vget(vp, LK_EXCLUSIVE | LK_NOWAIT, fsa->p))
                   1148:                return (0);
                   1149:
                   1150:        if ((error = VOP_FSYNC(vp, fsa->cred, fsa->waitfor, fsa->p)))
                   1151:                fsa->allerror = error;
                   1152:        VOP_UNLOCK(vp, 0, fsa->p);
                   1153:        vrele(vp);
                   1154:
                   1155:        return (0);
                   1156: }
                   1157:
                   1158: /*
                   1159:  * Go through the disk queues to initiate sandbagged IO;
                   1160:  * go through the inodes to write those that have been modified;
                   1161:  * initiate the writing of the super block if it has been modified.
                   1162:  *
                   1163:  * Should always be called with the mount point locked.
                   1164:  */
                   1165: int
                   1166: ffs_sync(struct mount *mp, int waitfor, struct ucred *cred, struct proc *p)
                   1167: {
                   1168:        struct ufsmount *ump = VFSTOUFS(mp);
                   1169:        struct fs *fs;
                   1170:        int error, allerror = 0, count;
                   1171:        struct ffs_sync_args fsa;
                   1172:
                   1173:        fs = ump->um_fs;
                   1174:        /*
                   1175:         * Write back modified superblock.
                   1176:         * Consistency check that the superblock
                   1177:         * is still in the buffer cache.
                   1178:         */
                   1179:        if (fs->fs_fmod != 0 && fs->fs_ronly != 0) {
                   1180:                printf("fs = %s\n", fs->fs_fsmnt);
                   1181:                panic("update: rofs mod");
                   1182:        }
                   1183:  loop:
                   1184:        /*
                   1185:         * Write back each (modified) inode.
                   1186:         */
                   1187:        fsa.allerror = 0;
                   1188:        fsa.p = p;
                   1189:        fsa.cred = cred;
                   1190:        fsa.waitfor = waitfor;
                   1191:
                   1192:        /*
                   1193:         * Don't traverse the vnode list if we want to skip all of them.
                   1194:         */
                   1195:        if (waitfor != MNT_LAZY) {
                   1196:                vfs_mount_foreach_vnode(mp, ffs_sync_vnode, &fsa);
                   1197:                allerror = fsa.allerror;
                   1198:        }
                   1199:
                   1200:        /*
                   1201:         * Force stale file system control information to be flushed.
                   1202:         */
                   1203:        if ((ump->um_mountp->mnt_flag & MNT_SOFTDEP) && waitfor == MNT_WAIT) {
                   1204:                if ((error = softdep_flushworklist(ump->um_mountp, &count, p)))
                   1205:                        allerror = error;
                   1206:                /* Flushed work items may create new vnodes to clean */
                   1207:                if (count)
                   1208:                        goto loop;
                   1209:        }
                   1210:        if (waitfor != MNT_LAZY) {
                   1211:                vn_lock(ump->um_devvp, LK_EXCLUSIVE | LK_RETRY, p);
                   1212:                if ((error = VOP_FSYNC(ump->um_devvp, cred, waitfor, p)) != 0)
                   1213:                        allerror = error;
                   1214:                VOP_UNLOCK(ump->um_devvp, 0, p);
                   1215:        }
                   1216:        qsync(mp);
                   1217:        /*
                   1218:         * Write back modified superblock.
                   1219:         */
                   1220:
                   1221:        if (fs->fs_fmod != 0 && (error = ffs_sbupdate(ump, waitfor)) != 0)
                   1222:                allerror = error;
                   1223:
                   1224:        return (allerror);
                   1225: }
                   1226:
                   1227: /*
                   1228:  * Look up a FFS dinode number to find its incore vnode, otherwise read it
                   1229:  * in from disk.  If it is in core, wait for the lock bit to clear, then
                   1230:  * return the inode locked.  Detection and handling of mount points must be
                   1231:  * done by the calling routine.
                   1232:  */
                   1233: int
                   1234: ffs_vget(struct mount *mp, ino_t ino, struct vnode **vpp)
                   1235: {
                   1236:        struct fs *fs;
                   1237:        struct inode *ip;
                   1238:        struct ufs1_dinode *dp1;
                   1239: #ifdef FFS2
                   1240:        struct ufs2_dinode *dp2;
                   1241: #endif
                   1242:        struct ufsmount *ump;
                   1243:        struct buf *bp;
                   1244:        struct vnode *vp;
                   1245:        dev_t dev;
                   1246:        int error;
                   1247:
                   1248:        ump = VFSTOUFS(mp);
                   1249:        dev = ump->um_dev;
                   1250: retry:
                   1251:        if ((*vpp = ufs_ihashget(dev, ino)) != NULL)
                   1252:                return (0);
                   1253:
                   1254:        /* Allocate a new vnode/inode. */
                   1255:        if ((error = getnewvnode(VT_UFS, mp, ffs_vnodeop_p, &vp)) != 0) {
                   1256:                *vpp = NULL;
                   1257:                return (error);
                   1258:        }
                   1259: #ifdef VFSDEBUG
                   1260:        vp->v_flag |= VLOCKSWORK;
                   1261: #endif
                   1262:        /* XXX - we use the same pool for ffs and mfs */
                   1263:        ip = pool_get(&ffs_ino_pool, PR_WAITOK);
                   1264:        bzero((caddr_t)ip, sizeof(struct inode));
                   1265:        lockinit(&ip->i_lock, PINOD, "inode", 0, 0);
                   1266:        ip->i_ump = ump;
                   1267:        VREF(ip->i_devvp);
                   1268:        vp->v_data = ip;
                   1269:        ip->i_vnode = vp;
                   1270:        ip->i_fs = fs = ump->um_fs;
                   1271:        ip->i_dev = dev;
                   1272:        ip->i_number = ino;
                   1273:        ip->i_vtbl = &ffs_vtbl;
                   1274:
                   1275:        /*
                   1276:         * Put it onto its hash chain and lock it so that other requests for
                   1277:         * this inode will block if they arrive while we are sleeping waiting
                   1278:         * for old data structures to be purged or for the contents of the
                   1279:         * disk portion of this inode to be read.
                   1280:         */
                   1281:        error = ufs_ihashins(ip);
                   1282:
                   1283:        if (error) {
                   1284:                /*
                   1285:                 * VOP_INACTIVE will treat this as a stale file
                   1286:                 * and recycle it quickly
                   1287:                 */
                   1288:                vrele(vp);
                   1289:
                   1290:                if (error == EEXIST)
                   1291:                        goto retry;
                   1292:
                   1293:                return (error);
                   1294:        }
                   1295:
                   1296:
                   1297:        /* Read in the disk contents for the inode, copy into the inode. */
                   1298:        error = bread(ump->um_devvp, fsbtodb(fs, ino_to_fsba(fs, ino)),
                   1299:                      (int)fs->fs_bsize, NOCRED, &bp);
                   1300:        if (error) {
                   1301:                /*
                   1302:                 * The inode does not contain anything useful, so it would
                   1303:                 * be misleading to leave it on its hash chain. With mode
                   1304:                 * still zero, it will be unlinked and returned to the free
                   1305:                 * list by vput().
                   1306:                 */
                   1307:                vput(vp);
                   1308:                brelse(bp);
                   1309:                *vpp = NULL;
                   1310:                return (error);
                   1311:        }
                   1312:
                   1313: #ifdef FFS2
                   1314:        if (ip->i_ump->um_fstype == UM_UFS2) {
                   1315:                ip->i_din2 = pool_get(&ffs_dinode2_pool, PR_WAITOK);
                   1316:                dp2 = (struct ufs2_dinode *) bp->b_data + ino_to_fsbo(fs, ino);
                   1317:                *ip->i_din2 = *dp2;
                   1318:        } else
                   1319: #endif
                   1320:        {
                   1321:                ip->i_din1 = pool_get(&ffs_dinode1_pool, PR_WAITOK);
                   1322:                dp1 = (struct ufs1_dinode *) bp->b_data + ino_to_fsbo(fs, ino);
                   1323:                *ip->i_din1 = *dp1;
                   1324:        }
                   1325:
                   1326:        brelse(bp);
                   1327:
                   1328:        if (DOINGSOFTDEP(vp))
                   1329:                softdep_load_inodeblock(ip);
                   1330:        else
                   1331:                ip->i_effnlink = DIP(ip, nlink);
                   1332:
                   1333:        /*
                   1334:         * Initialize the vnode from the inode, check for aliases.
                   1335:         * Note that the underlying vnode may have changed.
                   1336:         */
                   1337:        error = ufs_vinit(mp, ffs_specop_p, FFS_FIFOOPS, &vp);
                   1338:        if (error) {
                   1339:                vput(vp);
                   1340:                *vpp = NULL;
                   1341:                return (error);
                   1342:        }
                   1343:
                   1344:        /*
                   1345:         * Set up a generation number for this inode if it does not
                   1346:         * already have one. This should only happen on old filesystems.
                   1347:         */
                   1348:        if (DIP(ip, gen) == 0) {
                   1349:                DIP_ASSIGN(ip, gen, arc4random() & INT_MAX);
                   1350:                if (DIP(ip, gen) == 0 || DIP(ip, gen) == -1)
                   1351:                        DIP_ASSIGN(ip, gen, 1); /* Shouldn't happen */
                   1352:                if ((vp->v_mount->mnt_flag & MNT_RDONLY) == 0)
                   1353:                        ip->i_flag |= IN_MODIFIED;
                   1354:        }
                   1355:
                   1356:        /*
                   1357:         * Ensure that uid and gid are correct. This is a temporary
                   1358:         * fix until fsck has been changed to do the update.
                   1359:         */
                   1360:        if (fs->fs_magic == FS_UFS1_MAGIC && fs->fs_inodefmt < FS_44INODEFMT) {
                   1361:                ip->i_ffs1_uid = ip->i_din1->di_ouid;
                   1362:                ip->i_ffs1_gid = ip->i_din1->di_ogid;
                   1363:        }
                   1364:
                   1365:        *vpp = vp;
                   1366:
                   1367:        return (0);
                   1368: }
                   1369:
                   1370: /*
                   1371:  * File handle to vnode
                   1372:  *
                   1373:  * Have to be really careful about stale file handles:
                   1374:  * - check that the inode number is valid
                   1375:  * - call ffs_vget() to get the locked inode
                   1376:  * - check for an unallocated inode (i_mode == 0)
                   1377:  */
                   1378: int
                   1379: ffs_fhtovp(struct mount *mp, struct fid *fhp, struct vnode **vpp)
                   1380: {
                   1381:        struct ufid *ufhp;
                   1382:        struct fs *fs;
                   1383:
                   1384:        ufhp = (struct ufid *)fhp;
                   1385:        fs = VFSTOUFS(mp)->um_fs;
                   1386:        if (ufhp->ufid_ino < ROOTINO ||
                   1387:            ufhp->ufid_ino >= fs->fs_ncg * fs->fs_ipg)
                   1388:                return (ESTALE);
                   1389:        return (ufs_fhtovp(mp, ufhp, vpp));
                   1390: }
                   1391:
                   1392: /*
                   1393:  * Vnode pointer to File handle
                   1394:  */
                   1395: /* ARGSUSED */
                   1396: int
                   1397: ffs_vptofh(struct vnode *vp, struct fid *fhp)
                   1398: {
                   1399:        struct inode *ip;
                   1400:        struct ufid *ufhp;
                   1401:
                   1402:        ip = VTOI(vp);
                   1403:        ufhp = (struct ufid *)fhp;
                   1404:        ufhp->ufid_len = sizeof(struct ufid);
                   1405:        ufhp->ufid_ino = ip->i_number;
                   1406:        ufhp->ufid_gen = DIP(ip, gen);
                   1407:
                   1408:        return (0);
                   1409: }
                   1410:
                   1411: /*
                   1412:  * Write a superblock and associated information back to disk.
                   1413:  */
                   1414: int
                   1415: ffs_sbupdate(struct ufsmount *mp, int waitfor)
                   1416: {
                   1417:        struct fs *dfs, *fs = mp->um_fs;
                   1418:        struct buf *bp;
                   1419:        int blks;
                   1420:        caddr_t space;
                   1421:        int i, size, error, allerror = 0;
                   1422:
                   1423:        /*
                   1424:         * First write back the summary information.
                   1425:         */
                   1426:        blks = howmany(fs->fs_cssize, fs->fs_fsize);
                   1427:        space = (caddr_t)fs->fs_csp;
                   1428:        for (i = 0; i < blks; i += fs->fs_frag) {
                   1429:                size = fs->fs_bsize;
                   1430:                if (i + fs->fs_frag > blks)
                   1431:                        size = (blks - i) * fs->fs_fsize;
                   1432:                bp = getblk(mp->um_devvp, fsbtodb(fs, fs->fs_csaddr + i),
                   1433:                            size, 0, 0);
                   1434:                bcopy(space, bp->b_data, (u_int)size);
                   1435:                space += size;
                   1436:                if (waitfor != MNT_WAIT)
                   1437:                        bawrite(bp);
                   1438:                else if ((error = bwrite(bp)))
                   1439:                        allerror = error;
                   1440:        }
                   1441:
                   1442:        /*
                   1443:         * Now write back the superblock itself. If any errors occurred
                   1444:         * up to this point, then fail so that the superblock avoids
                   1445:         * being written out as clean.
                   1446:         */
                   1447:        if (allerror) {
                   1448:                return (allerror);
                   1449:        }
                   1450:
                   1451:        bp = getblk(mp->um_devvp,
                   1452:            fs->fs_sblockloc >> (fs->fs_fshift - fs->fs_fsbtodb),
                   1453:            (int)fs->fs_sbsize, 0, 0);
                   1454:        fs->fs_fmod = 0;
                   1455:        fs->fs_time = time_second;
                   1456:        bcopy((caddr_t)fs, bp->b_data, (u_int)fs->fs_sbsize);
                   1457:        /* Restore compatibility to old file systems.              XXX */
                   1458:        dfs = (struct fs *)bp->b_data;                          /* XXX */
                   1459:        if (fs->fs_postblformat == FS_42POSTBLFMT)              /* XXX */
                   1460:                dfs->fs_nrpos = -1;                             /* XXX */
                   1461:        if (fs->fs_inodefmt < FS_44INODEFMT) {                  /* XXX */
                   1462:                int32_t *lp, tmp;                               /* XXX */
                   1463:                                                                /* XXX */
                   1464:                lp = (int32_t *)&dfs->fs_qbmask;                /* XXX */
                   1465:                tmp = lp[4];                                    /* XXX */
                   1466:                for (i = 4; i > 0; i--)                         /* XXX */
                   1467:                        lp[i] = lp[i-1];                        /* XXX */
                   1468:                lp[0] = tmp;                                    /* XXX */
                   1469:        }                                                       /* XXX */
                   1470:        dfs->fs_maxfilesize = mp->um_savedmaxfilesize;          /* XXX */
                   1471:
                   1472:        ffs1_compat_write(dfs, mp);
                   1473:
                   1474:        if (waitfor != MNT_WAIT)
                   1475:                bawrite(bp);
                   1476:        else if ((error = bwrite(bp)))
                   1477:                allerror = error;
                   1478:
                   1479:        return (allerror);
                   1480: }
                   1481:
                   1482: int
                   1483: ffs_init(struct vfsconf *vfsp)
                   1484: {
                   1485:        static int done;
                   1486:
                   1487:        if (done)
                   1488:                return (0);
                   1489:
                   1490:        done = 1;
                   1491:
                   1492:        pool_init(&ffs_ino_pool, sizeof(struct inode), 0, 0, 0, "ffsino",
                   1493:            &pool_allocator_nointr);
                   1494:        pool_init(&ffs_dinode1_pool, sizeof(struct ufs1_dinode), 0, 0, 0,
                   1495:            "dino1pl", &pool_allocator_nointr);
                   1496: #ifdef FFS2
                   1497:        pool_init(&ffs_dinode2_pool, sizeof(struct ufs2_dinode), 0, 0, 0,
                   1498:            "dino2pl", &pool_allocator_nointr);
                   1499: #endif
                   1500:
                   1501:        softdep_initialize();
                   1502:
                   1503:        return (ufs_init(vfsp));
                   1504: }
                   1505:
                   1506: /*
                   1507:  * fast filesystem related variables.
                   1508:  */
                   1509: int
                   1510: ffs_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp,
                   1511:     size_t newlen, struct proc *p)
                   1512: {
                   1513:        extern int doclusterread, doclusterwrite, doreallocblks, doasyncfree;
                   1514: #ifdef FFS_SOFTUPDATES
                   1515:        extern int max_softdeps, tickdelay, stat_worklist_push;
                   1516:        extern int stat_blk_limit_push, stat_ino_limit_push, stat_blk_limit_hit;
                   1517:        extern int stat_ino_limit_hit, stat_sync_limit_hit, stat_indir_blk_ptrs;
                   1518:        extern int stat_inode_bitmap, stat_direct_blk_ptrs, stat_dir_entry;
                   1519: #endif
                   1520:
                   1521:        /* all sysctl names at this level are terminal */
                   1522:        if (namelen != 1)
                   1523:                return (ENOTDIR);               /* overloaded */
                   1524:
                   1525:        switch (name[0]) {
                   1526:        case FFS_CLUSTERREAD:
                   1527:                return (sysctl_int(oldp, oldlenp, newp, newlen,
                   1528:                    &doclusterread));
                   1529:        case FFS_CLUSTERWRITE:
                   1530:                return (sysctl_int(oldp, oldlenp, newp, newlen,
                   1531:                    &doclusterwrite));
                   1532:        case FFS_REALLOCBLKS:
                   1533:                return (sysctl_int(oldp, oldlenp, newp, newlen,
                   1534:                    &doreallocblks));
                   1535:        case FFS_ASYNCFREE:
                   1536:                return (sysctl_int(oldp, oldlenp, newp, newlen, &doasyncfree));
                   1537: #ifdef FFS_SOFTUPDATES
                   1538:        case FFS_MAX_SOFTDEPS:
                   1539:                return (sysctl_int(oldp, oldlenp, newp, newlen, &max_softdeps));
                   1540:        case FFS_SD_TICKDELAY:
                   1541:                return (sysctl_int(oldp, oldlenp, newp, newlen, &tickdelay));
                   1542:        case FFS_SD_WORKLIST_PUSH:
                   1543:                return (sysctl_rdint(oldp, oldlenp, newp, stat_worklist_push));
                   1544:        case FFS_SD_BLK_LIMIT_PUSH:
                   1545:                return (sysctl_rdint(oldp, oldlenp, newp, stat_blk_limit_push));
                   1546:        case FFS_SD_INO_LIMIT_PUSH:
                   1547:                return (sysctl_rdint(oldp, oldlenp, newp, stat_ino_limit_push));
                   1548:        case FFS_SD_BLK_LIMIT_HIT:
                   1549:                return (sysctl_rdint(oldp, oldlenp, newp, stat_blk_limit_hit));
                   1550:        case FFS_SD_INO_LIMIT_HIT:
                   1551:                return (sysctl_rdint(oldp, oldlenp, newp, stat_ino_limit_hit));
                   1552:        case FFS_SD_SYNC_LIMIT_HIT:
                   1553:                return (sysctl_rdint(oldp, oldlenp, newp, stat_sync_limit_hit));
                   1554:        case FFS_SD_INDIR_BLK_PTRS:
                   1555:                return (sysctl_rdint(oldp, oldlenp, newp, stat_indir_blk_ptrs));
                   1556:        case FFS_SD_INODE_BITMAP:
                   1557:                return (sysctl_rdint(oldp, oldlenp, newp, stat_inode_bitmap));
                   1558:        case FFS_SD_DIRECT_BLK_PTRS:
                   1559:                return (sysctl_rdint(oldp, oldlenp, newp, stat_direct_blk_ptrs));
                   1560:        case FFS_SD_DIR_ENTRY:
                   1561:                return (sysctl_rdint(oldp, oldlenp, newp, stat_dir_entry));
                   1562: #endif
                   1563: #ifdef UFS_DIRHASH
                   1564:        case FFS_DIRHASH_DIRSIZE:
                   1565:                return (sysctl_int(oldp, oldlenp, newp, newlen,
                   1566:                    &ufs_mindirhashsize));
                   1567:        case FFS_DIRHASH_MAXMEM:
                   1568:                return (sysctl_int(oldp, oldlenp, newp, newlen,
                   1569:                    &ufs_dirhashmaxmem));
                   1570:        case FFS_DIRHASH_MEM:
                   1571:                return (sysctl_rdint(oldp, oldlenp, newp, ufs_dirhashmem));
                   1572: #endif
                   1573:
                   1574:        default:
                   1575:                return (EOPNOTSUPP);
                   1576:        }
                   1577:        /* NOTREACHED */
                   1578: }

CVSweb