[BACK]Return to ffs_vfsops.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / ufs / ffs

Annotation of src/sys/ufs/ffs/ffs_vfsops.c, Revision 1.223.4.3

1.223.4.3! yamt        1: /*     $NetBSD: ffs_vfsops.c,v 1.223.4.2 2009/05/04 08:14:37 yamt Exp $        */
1.223.4.2  yamt        2:
                      3: /*-
                      4:  * Copyright (c) 2008, 2009 The NetBSD Foundation, Inc.
                      5:  * All rights reserved.
                      6:  *
                      7:  * This code is derived from software contributed to The NetBSD Foundation
                      8:  * by Wasabi Systems, Inc, and by Andrew Doran.
                      9:  *
                     10:  * Redistribution and use in source and binary forms, with or without
                     11:  * modification, are permitted provided that the following conditions
                     12:  * are met:
                     13:  * 1. Redistributions of source code must retain the above copyright
                     14:  *    notice, this list of conditions and the following disclaimer.
                     15:  * 2. Redistributions in binary form must reproduce the above copyright
                     16:  *    notice, this list of conditions and the following disclaimer in the
                     17:  *    documentation and/or other materials provided with the distribution.
                     18:  *
                     19:  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
                     20:  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
                     21:  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
                     22:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
                     23:  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
                     24:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
                     25:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
                     26:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
                     27:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
                     28:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
                     29:  * POSSIBILITY OF SUCH DAMAGE.
                     30:  */
1.4       cgd        31:
1.1       mycroft    32: /*
                     33:  * Copyright (c) 1989, 1991, 1993, 1994
                     34:  *     The Regents of the University of California.  All rights reserved.
                     35:  *
                     36:  * Redistribution and use in source and binary forms, with or without
                     37:  * modification, are permitted provided that the following conditions
                     38:  * are met:
                     39:  * 1. Redistributions of source code must retain the above copyright
                     40:  *    notice, this list of conditions and the following disclaimer.
                     41:  * 2. Redistributions in binary form must reproduce the above copyright
                     42:  *    notice, this list of conditions and the following disclaimer in the
                     43:  *    documentation and/or other materials provided with the distribution.
1.119     agc        44:  * 3. Neither the name of the University nor the names of its contributors
1.1       mycroft    45:  *    may be used to endorse or promote products derived from this software
                     46:  *    without specific prior written permission.
                     47:  *
                     48:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     49:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     50:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     51:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     52:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     53:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     54:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     55:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     56:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     57:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     58:  * SUCH DAMAGE.
                     59:  *
1.33      fvdl       60:  *     @(#)ffs_vfsops.c        8.31 (Berkeley) 5/20/95
1.1       mycroft    61:  */
1.88      lukem      62:
                     63: #include <sys/cdefs.h>
1.223.4.3! yamt       64: __KERNEL_RCSID(0, "$NetBSD: ffs_vfsops.c,v 1.223.4.2 2009/05/04 08:14:37 yamt Exp $");
1.36      scottr     65:
1.81      mrg        66: #if defined(_KERNEL_OPT)
1.45      thorpej    67: #include "opt_ffs.h"
1.36      scottr     68: #include "opt_quota.h"
1.223.4.2  yamt       69: #include "opt_wapbl.h"
1.37      scottr     70: #endif
1.1       mycroft    71:
                     72: #include <sys/param.h>
                     73: #include <sys/systm.h>
                     74: #include <sys/namei.h>
                     75: #include <sys/proc.h>
                     76: #include <sys/kernel.h>
                     77: #include <sys/vnode.h>
                     78: #include <sys/socket.h>
                     79: #include <sys/mount.h>
                     80: #include <sys/buf.h>
1.23      thorpej    81: #include <sys/device.h>
1.1       mycroft    82: #include <sys/mbuf.h>
                     83: #include <sys/file.h>
                     84: #include <sys/disklabel.h>
                     85: #include <sys/ioctl.h>
                     86: #include <sys/errno.h>
                     87: #include <sys/malloc.h>
1.43      thorpej    88: #include <sys/pool.h>
1.29      fvdl       89: #include <sys/lock.h>
1.33      fvdl       90: #include <sys/sysctl.h>
1.101     gehenna    91: #include <sys/conf.h>
1.181     elad       92: #include <sys/kauth.h>
1.223.4.2  yamt       93: #include <sys/wapbl.h>
1.193     hannken    94: #include <sys/fstrans.h>
1.223.4.1  yamt       95: #include <sys/module.h>
1.1       mycroft    96:
1.221     dholland   97: #include <miscfs/genfs/genfs.h>
1.1       mycroft    98: #include <miscfs/specfs/specdev.h>
                     99:
                    100: #include <ufs/ufs/quota.h>
                    101: #include <ufs/ufs/ufsmount.h>
                    102: #include <ufs/ufs/inode.h>
1.25      bouyer    103: #include <ufs/ufs/dir.h>
1.1       mycroft   104: #include <ufs/ufs/ufs_extern.h>
1.34      bouyer    105: #include <ufs/ufs/ufs_bswap.h>
1.223.4.2  yamt      106: #include <ufs/ufs/ufs_wapbl.h>
1.1       mycroft   107:
                    108: #include <ufs/ffs/fs.h>
                    109: #include <ufs/ffs/ffs_extern.h>
                    110:
1.223.4.1  yamt      111: MODULE(MODULE_CLASS_VFS, ffs, NULL);
                    112:
1.223.4.2  yamt      113: static int     ffs_vfs_fsync(vnode_t *, int);
                    114:
                    115: static struct sysctllog *ffs_sysctl_log;
                    116:
1.59      jdolecek  117: /* how many times ffs_init() was called */
                    118: int ffs_initcount = 0;
                    119:
1.195     ad        120: extern kmutex_t ufs_hashlock;
1.29      fvdl      121:
1.105     matt      122: extern const struct vnodeopv_desc ffs_vnodeop_opv_desc;
                    123: extern const struct vnodeopv_desc ffs_specop_opv_desc;
                    124: extern const struct vnodeopv_desc ffs_fifoop_opv_desc;
1.32      thorpej   125:
1.79      jdolecek  126: const struct vnodeopv_desc * const ffs_vnodeopv_descs[] = {
1.32      thorpej   127:        &ffs_vnodeop_opv_desc,
                    128:        &ffs_specop_opv_desc,
                    129:        &ffs_fifoop_opv_desc,
                    130:        NULL,
                    131: };
                    132:
1.17      mycroft   133: struct vfsops ffs_vfsops = {
                    134:        MOUNT_FFS,
1.204     dsl       135:        sizeof (struct ufs_args),
1.1       mycroft   136:        ffs_mount,
                    137:        ufs_start,
                    138:        ffs_unmount,
                    139:        ufs_root,
                    140:        ufs_quotactl,
1.143     christos  141:        ffs_statvfs,
1.1       mycroft   142:        ffs_sync,
                    143:        ffs_vget,
                    144:        ffs_fhtovp,
                    145:        ffs_vptofh,
                    146:        ffs_init,
1.86      chs       147:        ffs_reinit,
1.59      jdolecek  148:        ffs_done,
1.23      thorpej   149:        ffs_mountroot,
1.149     hannken   150:        ffs_snapshot,
1.170     thorpej   151:        ffs_extattrctl,
1.193     hannken   152:        ffs_suspendctl,
1.221     dholland  153:        genfs_renamelock_enter,
                    154:        genfs_renamelock_exit,
1.223.4.2  yamt      155:        ffs_vfs_fsync,
1.32      thorpej   156:        ffs_vnodeopv_descs,
1.185     christos  157:        0,
                    158:        { NULL, NULL },
1.1       mycroft   159: };
                    160:
1.165     yamt      161: static const struct genfs_ops ffs_genfsops = {
                    162:        .gop_size = ffs_gop_size,
                    163:        .gop_alloc = ufs_gop_alloc,
                    164:        .gop_write = genfs_gop_write,
1.167     yamt      165:        .gop_markupdate = ufs_gop_markupdate,
1.87      chs       166: };
                    167:
1.175     yamt      168: static const struct ufs_ops ffs_ufsops = {
                    169:        .uo_itimes = ffs_itimes,
1.176     yamt      170:        .uo_update = ffs_update,
                    171:        .uo_truncate = ffs_truncate,
                    172:        .uo_valloc = ffs_valloc,
                    173:        .uo_vfree = ffs_vfree,
                    174:        .uo_balloc = ffs_balloc,
1.223.4.2  yamt      175:        .uo_unmark_vnode = (void (*)(vnode_t *))nullop,
1.175     yamt      176: };
                    177:
1.223.4.1  yamt      178: static int
                    179: ffs_modcmd(modcmd_t cmd, void *arg)
                    180: {
1.223.4.2  yamt      181:        int error;
                    182:
                    183: #if 0
                    184:        extern int doasyncfree;
                    185: #endif
                    186:        extern int ffs_log_changeopt;
1.223.4.1  yamt      187:
                    188:        switch (cmd) {
                    189:        case MODULE_CMD_INIT:
1.223.4.2  yamt      190:                error = vfs_attach(&ffs_vfsops);
                    191:                if (error != 0)
                    192:                        break;
                    193:
                    194:                sysctl_createv(&ffs_sysctl_log, 0, NULL, NULL,
                    195:                               CTLFLAG_PERMANENT,
                    196:                               CTLTYPE_NODE, "vfs", NULL,
                    197:                               NULL, 0, NULL, 0,
                    198:                               CTL_VFS, CTL_EOL);
                    199:                sysctl_createv(&ffs_sysctl_log, 0, NULL, NULL,
                    200:                               CTLFLAG_PERMANENT,
                    201:                               CTLTYPE_NODE, "ffs",
                    202:                               SYSCTL_DESCR("Berkeley Fast File System"),
                    203:                               NULL, 0, NULL, 0,
                    204:                               CTL_VFS, 1, CTL_EOL);
                    205:
                    206:                /*
                    207:                 * @@@ should we even bother with these first three?
                    208:                 */
                    209:                sysctl_createv(&ffs_sysctl_log, 0, NULL, NULL,
                    210:                               CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
                    211:                               CTLTYPE_INT, "doclusterread", NULL,
                    212:                               sysctl_notavail, 0, NULL, 0,
                    213:                               CTL_VFS, 1, FFS_CLUSTERREAD, CTL_EOL);
                    214:                sysctl_createv(&ffs_sysctl_log, 0, NULL, NULL,
                    215:                               CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
                    216:                               CTLTYPE_INT, "doclusterwrite", NULL,
                    217:                               sysctl_notavail, 0, NULL, 0,
                    218:                               CTL_VFS, 1, FFS_CLUSTERWRITE, CTL_EOL);
                    219:                sysctl_createv(&ffs_sysctl_log, 0, NULL, NULL,
                    220:                               CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
                    221:                               CTLTYPE_INT, "doreallocblks", NULL,
                    222:                               sysctl_notavail, 0, NULL, 0,
                    223:                               CTL_VFS, 1, FFS_REALLOCBLKS, CTL_EOL);
                    224: #if 0
                    225:                sysctl_createv(&ffs_sysctl_log, 0, NULL, NULL,
                    226:                               CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
                    227:                               CTLTYPE_INT, "doasyncfree",
                    228:                               SYSCTL_DESCR("Release dirty blocks asynchronously"),
                    229:                               NULL, 0, &doasyncfree, 0,
                    230:                               CTL_VFS, 1, FFS_ASYNCFREE, CTL_EOL);
                    231: #endif
                    232:                sysctl_createv(&ffs_sysctl_log, 0, NULL, NULL,
                    233:                               CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
                    234:                               CTLTYPE_INT, "log_changeopt",
                    235:                               SYSCTL_DESCR("Log changes in optimization strategy"),
                    236:                               NULL, 0, &ffs_log_changeopt, 0,
                    237:                               CTL_VFS, 1, FFS_LOG_CHANGEOPT, CTL_EOL);
                    238:                break;
1.223.4.1  yamt      239:        case MODULE_CMD_FINI:
1.223.4.2  yamt      240:                error = vfs_detach(&ffs_vfsops);
                    241:                if (error != 0)
                    242:                        break;
                    243:                sysctl_teardown(&ffs_sysctl_log);
                    244:                break;
1.223.4.1  yamt      245:        default:
1.223.4.2  yamt      246:                error = ENOTTY;
                    247:                break;
1.223.4.1  yamt      248:        }
1.223.4.2  yamt      249:
                    250:        return (error);
1.223.4.1  yamt      251: }
                    252:
1.216     ad        253: pool_cache_t ffs_inode_cache;
                    254: pool_cache_t ffs_dinode1_cache;
                    255: pool_cache_t ffs_dinode2_cache;
1.110     fvdl      256:
1.146     simonb    257: static void ffs_oldfscompat_read(struct fs *, struct ufsmount *, daddr_t);
1.110     fvdl      258: static void ffs_oldfscompat_write(struct fs *, struct ufsmount *);
1.43      thorpej   259:
1.1       mycroft   260: /*
1.33      fvdl      261:  * Called by main() when ffs is going to be mounted as root.
1.1       mycroft   262:  */
                    263:
1.19      christos  264: int
1.166     thorpej   265: ffs_mountroot(void)
1.1       mycroft   266: {
1.33      fvdl      267:        struct fs *fs;
                    268:        struct mount *mp;
1.177     christos  269:        struct lwp *l = curlwp;                 /* XXX */
1.1       mycroft   270:        struct ufsmount *ump;
                    271:        int error;
1.23      thorpej   272:
1.180     thorpej   273:        if (device_class(root_device) != DV_DISK)
1.23      thorpej   274:                return (ENODEV);
                    275:
1.51      wrstuden  276:        if ((error = vfs_rootmountalloc(MOUNT_FFS, "root_device", &mp))) {
                    277:                vrele(rootvp);
1.33      fvdl      278:                return (error);
1.51      wrstuden  279:        }
1.223.4.2  yamt      280:
                    281:        /*
                    282:         * We always need to be able to mount the root file system.
                    283:         */
                    284:        mp->mnt_flag |= MNT_FORCE;
1.177     christos  285:        if ((error = ffs_mountfs(rootvp, mp, l)) != 0) {
1.223.4.1  yamt      286:                vfs_unbusy(mp, false, NULL);
1.210     ad        287:                vfs_destroy(mp);
1.1       mycroft   288:                return (error);
                    289:        }
1.223.4.2  yamt      290:        mp->mnt_flag &= ~MNT_FORCE;
1.210     ad        291:        mutex_enter(&mountlist_lock);
1.11      mycroft   292:        CIRCLEQ_INSERT_TAIL(&mountlist, mp, mnt_list);
1.210     ad        293:        mutex_exit(&mountlist_lock);
1.1       mycroft   294:        ump = VFSTOUFS(mp);
                    295:        fs = ump->um_fs;
1.42      perry     296:        memset(fs->fs_fsmnt, 0, sizeof(fs->fs_fsmnt));
1.33      fvdl      297:        (void)copystr(mp->mnt_stat.f_mntonname, fs->fs_fsmnt, MNAMELEN - 1, 0);
1.211     pooka     298:        (void)ffs_statvfs(mp, &mp->mnt_stat);
1.223.4.1  yamt      299:        vfs_unbusy(mp, false, NULL);
1.151     pk        300:        setrootfstime((time_t)fs->fs_time);
1.1       mycroft   301:        return (0);
                    302: }
                    303:
                    304: /*
                    305:  * VFS Operations.
                    306:  *
                    307:  * mount system call
                    308:  */
                    309: int
1.211     pooka     310: ffs_mount(struct mount *mp, const char *path, void *data, size_t *data_len)
1.1       mycroft   311: {
1.211     pooka     312:        struct lwp *l = curlwp;
1.223.4.2  yamt      313:        struct vnode *devvp = NULL;
1.204     dsl       314:        struct ufs_args *args = data;
1.19      christos  315:        struct ufsmount *ump = NULL;
1.61      augustss  316:        struct fs *fs;
1.204     dsl       317:        int error = 0, flags, update;
1.9       mycroft   318:        mode_t accessmode;
1.1       mycroft   319:
1.204     dsl       320:        if (*data_len < sizeof *args)
                    321:                return EINVAL;
                    322:
1.102     christos  323:        if (mp->mnt_flag & MNT_GETARGS) {
                    324:                ump = VFSTOUFS(mp);
                    325:                if (ump == NULL)
                    326:                        return EIO;
1.204     dsl       327:                args->fspec = NULL;
                    328:                *data_len = sizeof *args;
                    329:                return 0;
1.102     christos  330:        }
1.66      matt      331:
1.95      christos  332:        update = mp->mnt_flag & MNT_UPDATE;
                    333:
                    334:        /* Check arguments */
1.204     dsl       335:        if (args->fspec != NULL) {
1.95      christos  336:                /*
                    337:                 * Look up the name and verify that it's sane.
                    338:                 */
1.223.4.3! yamt      339:                error = namei_simple_user(args->fspec,
        !           340:                                        NSM_FOLLOW_NOEMULROOT, &devvp);
        !           341:                if (error != 0)
1.95      christos  342:                        return (error);
                    343:
                    344:                if (!update) {
                    345:                        /*
                    346:                         * Be sure this is a valid block device
                    347:                         */
                    348:                        if (devvp->v_type != VBLK)
                    349:                                error = ENOTBLK;
1.101     gehenna   350:                        else if (bdevsw_lookup(devvp->v_rdev) == NULL)
1.95      christos  351:                                error = ENXIO;
                    352:                } else {
                    353:                        /*
                    354:                         * Be sure we're still naming the same device
                    355:                         * used for our initial mount
                    356:                         */
1.160     mycroft   357:                        ump = VFSTOUFS(mp);
1.186     jld       358:                        if (devvp != ump->um_devvp) {
                    359:                                if (devvp->v_rdev != ump->um_devvp->v_rdev)
                    360:                                        error = EINVAL;
                    361:                                else {
                    362:                                        vrele(devvp);
                    363:                                        devvp = ump->um_devvp;
                    364:                                        vref(devvp);
                    365:                                }
                    366:                        }
1.95      christos  367:                }
1.160     mycroft   368:        } else {
                    369:                if (!update) {
                    370:                        /* New mounts must have a filename for the device */
                    371:                        return (EINVAL);
                    372:                } else {
                    373:                        /* Use the extant mount */
                    374:                        ump = VFSTOUFS(mp);
                    375:                        devvp = ump->um_devvp;
                    376:                        vref(devvp);
                    377:                }
1.95      christos  378:        }
1.218     ad        379:
                    380:        /*
1.95      christos  381:         * If mount by non-root, then verify that user has necessary
                    382:         * permissions on the device.
1.223.4.2  yamt      383:         *
                    384:         * Permission to update a mount is checked higher, so here we presume
                    385:         * updating the mount is okay (for example, as far as securelevel goes)
                    386:         * which leaves us with the normal check.
                    387:         */
                    388:        accessmode = VREAD;
                    389:        if (update ?
                    390:            (mp->mnt_iflag & IMNT_WANTRDWR) != 0 :
                    391:            (mp->mnt_flag & MNT_RDONLY) == 0)
                    392:                accessmode |= VWRITE;
                    393:        vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY);
                    394:        error = genfs_can_mount(devvp, accessmode, l->l_cred);
                    395:        VOP_UNLOCK(devvp, 0);
1.95      christos  396:
                    397:        if (error) {
                    398:                vrele(devvp);
                    399:                return (error);
                    400:        }
                    401:
1.223.4.2  yamt      402: #ifdef WAPBL
                    403:        /* WAPBL can only be enabled on a r/w mount. */
                    404:        if ((mp->mnt_flag & MNT_RDONLY) && !(mp->mnt_iflag & IMNT_WANTRDWR)) {
                    405:                mp->mnt_flag &= ~MNT_LOG;
                    406:        }
                    407: #else /* !WAPBL */
                    408:        mp->mnt_flag &= ~MNT_LOG;
                    409: #endif /* !WAPBL */
                    410:
1.95      christos  411:        if (!update) {
1.164     christos  412:                int xflags;
1.159     mycroft   413:
                    414:                if (mp->mnt_flag & MNT_RDONLY)
1.164     christos  415:                        xflags = FREAD;
1.159     mycroft   416:                else
1.223.4.2  yamt      417:                        xflags = FREAD | FWRITE;
1.211     pooka     418:                error = VOP_OPEN(devvp, xflags, FSCRED);
1.159     mycroft   419:                if (error)
                    420:                        goto fail;
1.177     christos  421:                error = ffs_mountfs(devvp, mp, l);
1.95      christos  422:                if (error) {
1.159     mycroft   423:                        vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY);
1.211     pooka     424:                        (void)VOP_CLOSE(devvp, xflags, NOCRED);
1.159     mycroft   425:                        VOP_UNLOCK(devvp, 0);
                    426:                        goto fail;
1.95      christos  427:                }
                    428:
1.1       mycroft   429:                ump = VFSTOUFS(mp);
                    430:                fs = ump->um_fs;
1.95      christos  431:        } else {
                    432:                /*
1.96      christos  433:                 * Update the mount.
                    434:                 */
                    435:
                    436:                /*
                    437:                 * The initial mount got a reference on this
                    438:                 * device, so drop the one obtained via
                    439:                 * namei(), above.
1.95      christos  440:                 */
1.96      christos  441:                vrele(devvp);
                    442:
1.160     mycroft   443:                ump = VFSTOUFS(mp);
1.95      christos  444:                fs = ump->um_fs;
1.1       mycroft   445:                if (fs->fs_ronly == 0 && (mp->mnt_flag & MNT_RDONLY)) {
1.95      christos  446:                        /*
                    447:                         * Changing from r/w to r/o
                    448:                         */
1.1       mycroft   449:                        flags = WRITECLOSE;
                    450:                        if (mp->mnt_flag & MNT_FORCE)
                    451:                                flags |= FORCECLOSE;
1.223.4.2  yamt      452:                        error = ffs_flushfiles(mp, flags, l);
                    453:                        if (error == 0)
                    454:                                error = UFS_WAPBL_BEGIN(mp);
1.15      mycroft   455:                        if (error == 0 &&
                    456:                            ffs_cgupdate(ump, MNT_WAIT) == 0 &&
                    457:                            fs->fs_clean & FS_WASCLEAN) {
1.65      fvdl      458:                                if (mp->mnt_flag & MNT_SOFTDEP)
                    459:                                        fs->fs_flags &= ~FS_DOSOFTDEP;
1.15      mycroft   460:                                fs->fs_clean = FS_ISCLEAN;
                    461:                                (void) ffs_sbupdate(ump, MNT_WAIT);
                    462:                        }
1.223.4.2  yamt      463:                        if (error == 0)
                    464:                                UFS_WAPBL_END(mp);
1.15      mycroft   465:                        if (error)
                    466:                                return (error);
1.1       mycroft   467:                }
1.65      fvdl      468:
1.223.4.2  yamt      469: #ifdef WAPBL
                    470:                if ((mp->mnt_flag & MNT_LOG) == 0) {
                    471:                        error = ffs_wapbl_stop(mp, mp->mnt_flag & MNT_FORCE);
                    472:                        if (error)
                    473:                                return error;
1.65      fvdl      474:                }
1.223.4.2  yamt      475: #endif /* WAPBL */
1.65      fvdl      476:
1.223.4.2  yamt      477:                if (fs->fs_ronly == 0 && (mp->mnt_flag & MNT_RDONLY)) {
                    478:                        /*
                    479:                         * Finish change from r/w to r/o
                    480:                         */
                    481:                        fs->fs_ronly = 1;
                    482:                        fs->fs_fmod = 0;
1.65      fvdl      483:                }
                    484:
1.15      mycroft   485:                if (mp->mnt_flag & MNT_RELOAD) {
1.184     ad        486:                        error = ffs_reload(mp, l->l_cred, l);
1.15      mycroft   487:                        if (error)
                    488:                                return (error);
                    489:                }
1.95      christos  490:
1.124     dbj       491:                if (fs->fs_ronly && (mp->mnt_iflag & IMNT_WANTRDWR)) {
1.9       mycroft   492:                        /*
1.95      christos  493:                         * Changing from read-only to read/write
1.9       mycroft   494:                         */
1.1       mycroft   495:                        fs->fs_ronly = 0;
1.15      mycroft   496:                        fs->fs_clean <<= 1;
                    497:                        fs->fs_fmod = 1;
1.223.4.2  yamt      498: #ifdef WAPBL
                    499:                        if (fs->fs_flags & FS_DOWAPBL) {
                    500:                                printf("%s: replaying log to disk\n",
                    501:                                    fs->fs_fsmnt);
                    502:                                KDASSERT(mp->mnt_wapbl_replay);
                    503:                                error = wapbl_replay_write(mp->mnt_wapbl_replay,
                    504:                                                           devvp);
                    505:                                if (error) {
                    506:                                        return error;
                    507:                                }
                    508:                                wapbl_replay_stop(mp->mnt_wapbl_replay);
                    509:                                fs->fs_clean = FS_WASCLEAN;
1.65      fvdl      510:                        }
1.223.4.2  yamt      511: #endif /* WAPBL */
1.149     hannken   512:                        if (fs->fs_snapinum[0] != 0)
                    513:                                ffs_snapshot_mount(mp);
1.9       mycroft   514:                }
1.223.4.2  yamt      515:
                    516: #ifdef WAPBL
                    517:                error = ffs_wapbl_start(mp);
                    518:                if (error)
                    519:                        return error;
                    520: #endif /* WAPBL */
                    521:
1.204     dsl       522:                if (args->fspec == NULL)
1.223.4.3! yamt      523:                        return 0;
1.1       mycroft   524:        }
                    525:
1.204     dsl       526:        error = set_statvfs_info(path, UIO_USERSPACE, args->fspec,
1.205     pooka     527:            UIO_USERSPACE, mp->mnt_op->vfs_name, mp, l);
1.114     christos  528:        if (error == 0)
                    529:                (void)strncpy(fs->fs_fsmnt, mp->mnt_stat.f_mntonname,
                    530:                    sizeof(fs->fs_fsmnt));
1.223.4.2  yamt      531:        fs->fs_flags &= ~FS_DOSOFTDEP;
1.15      mycroft   532:        if (fs->fs_fmod != 0) { /* XXX */
1.223.4.2  yamt      533:                int err;
                    534:
1.15      mycroft   535:                fs->fs_fmod = 0;
                    536:                if (fs->fs_clean & FS_WASCLEAN)
1.182     kardel    537:                        fs->fs_time = time_second;
1.89      fvdl      538:                else {
1.223.4.2  yamt      539:                        printf("%s: file system not clean (fs_clean=%#x); "
                    540:                            "please fsck(8)\n", mp->mnt_stat.f_mntfromname,
                    541:                            fs->fs_clean);
1.110     fvdl      542:                        printf("%s: lost blocks %" PRId64 " files %d\n",
1.89      fvdl      543:                            mp->mnt_stat.f_mntfromname, fs->fs_pendingblocks,
                    544:                            fs->fs_pendinginodes);
                    545:                }
1.223.4.2  yamt      546:                err = UFS_WAPBL_BEGIN(mp);
                    547:                if (err == 0) {
                    548:                        (void) ffs_cgupdate(ump, MNT_WAIT);
                    549:                        UFS_WAPBL_END(mp);
                    550:                }
1.15      mycroft   551:        }
1.223.4.2  yamt      552:        if ((mp->mnt_flag & MNT_SOFTDEP) != 0) {
                    553:                printf("%s: `-o softdep' is no longer supported, "
                    554:                    "consider `-o log'\n", mp->mnt_stat.f_mntfromname);
                    555:                mp->mnt_flag &= ~MNT_SOFTDEP;
                    556:        }
                    557:
1.159     mycroft   558:        return (error);
                    559:
                    560: fail:
                    561:        vrele(devvp);
                    562:        return (error);
1.1       mycroft   563: }
                    564:
                    565: /*
                    566:  * Reload all incore data for a filesystem (used after running fsck on
                    567:  * the root filesystem and finding things to fix). The filesystem must
                    568:  * be mounted read-only.
                    569:  *
                    570:  * Things to do to update the mount:
                    571:  *     1) invalidate all cached meta-data.
                    572:  *     2) re-read superblock from disk.
                    573:  *     3) re-read summary information from disk.
                    574:  *     4) invalidate all inactive vnodes.
                    575:  *     5) invalidate all cached file data.
                    576:  *     6) re-read inode data for all active vnodes.
                    577:  */
1.19      christos  578: int
1.181     elad      579: ffs_reload(struct mount *mp, kauth_cred_t cred, struct lwp *l)
1.1       mycroft   580: {
1.214     ad        581:        struct vnode *vp, *mvp, *devvp;
1.1       mycroft   582:        struct inode *ip;
1.84      lukem     583:        void *space;
1.1       mycroft   584:        struct buf *bp;
1.18      cgd       585:        struct fs *fs, *newfs;
1.1       mycroft   586:        struct partinfo dpart;
                    587:        int i, blks, size, error;
1.18      cgd       588:        int32_t *lp;
1.111     fvdl      589:        struct ufsmount *ump;
1.141     dbj       590:        daddr_t sblockloc;
1.1       mycroft   591:
1.153     mycroft   592:        if ((mp->mnt_flag & MNT_RDONLY) == 0)
1.1       mycroft   593:                return (EINVAL);
1.111     fvdl      594:
1.153     mycroft   595:        ump = VFSTOUFS(mp);
1.1       mycroft   596:        /*
                    597:         * Step 1: invalidate all cached meta-data.
                    598:         */
1.111     fvdl      599:        devvp = ump->um_devvp;
1.55      fvdl      600:        vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY);
1.177     christos  601:        error = vinvalbuf(devvp, 0, cred, l, 0, 0);
1.55      fvdl      602:        VOP_UNLOCK(devvp, 0);
                    603:        if (error)
1.1       mycroft   604:                panic("ffs_reload: dirty1");
                    605:        /*
                    606:         * Step 2: re-read superblock from disk.
                    607:         */
1.111     fvdl      608:        fs = ump->um_fs;
1.211     pooka     609:        if (VOP_IOCTL(devvp, DIOCGPART, &dpart, FREAD, NOCRED) != 0)
1.1       mycroft   610:                size = DEV_BSIZE;
                    611:        else
                    612:                size = dpart.disklab->d_secsize;
1.141     dbj       613:        /* XXX we don't handle possibility that superblock moved. */
1.110     fvdl      614:        error = bread(devvp, fs->fs_sblockloc / size, fs->fs_sbsize,
1.223.4.2  yamt      615:                      NOCRED, 0, &bp);
1.47      bouyer    616:        if (error) {
1.209     ad        617:                brelse(bp, 0);
1.1       mycroft   618:                return (error);
1.47      bouyer    619:        }
1.34      bouyer    620:        newfs = malloc(fs->fs_sbsize, M_UFSMNT, M_WAITOK);
1.42      perry     621:        memcpy(newfs, bp->b_data, fs->fs_sbsize);
1.34      bouyer    622: #ifdef FFS_EI
1.111     fvdl      623:        if (ump->um_flags & UFS_NEEDSWAP) {
1.83      lukem     624:                ffs_sb_swap((struct fs*)bp->b_data, newfs);
1.55      fvdl      625:                fs->fs_flags |= FS_SWAPPED;
1.121     bouyer    626:        } else
1.34      bouyer    627: #endif
1.121     bouyer    628:                fs->fs_flags &= ~FS_SWAPPED;
1.161     perry     629:        if ((newfs->fs_magic != FS_UFS1_MAGIC &&
1.110     fvdl      630:             newfs->fs_magic != FS_UFS2_MAGIC)||
                    631:             newfs->fs_bsize > MAXBSIZE ||
                    632:             newfs->fs_bsize < sizeof(struct fs)) {
1.209     ad        633:                brelse(bp, 0);
1.34      bouyer    634:                free(newfs, M_UFSMNT);
1.1       mycroft   635:                return (EIO);           /* XXX needs translation */
                    636:        }
1.141     dbj       637:        /* Store off old fs_sblockloc for fs_oldfscompat_read. */
                    638:        sblockloc = fs->fs_sblockloc;
1.161     perry     639:        /*
1.18      cgd       640:         * Copy pointer fields back into superblock before copying in   XXX
                    641:         * new superblock. These should really be in the ufsmount.      XXX
                    642:         * Note that important parameters (eg fs_ncg) are unchanged.
                    643:         */
1.84      lukem     644:        newfs->fs_csp = fs->fs_csp;
1.18      cgd       645:        newfs->fs_maxcluster = fs->fs_maxcluster;
1.85      lukem     646:        newfs->fs_contigdirs = fs->fs_contigdirs;
1.76      mycroft   647:        newfs->fs_ronly = fs->fs_ronly;
1.110     fvdl      648:        newfs->fs_active = fs->fs_active;
1.42      perry     649:        memcpy(fs, newfs, (u_int)fs->fs_sbsize);
1.209     ad        650:        brelse(bp, 0);
1.34      bouyer    651:        free(newfs, M_UFSMNT);
1.103     dbj       652:
                    653:        /* Recheck for apple UFS filesystem */
1.153     mycroft   654:        ump->um_flags &= ~UFS_ISAPPLEUFS;
1.103     dbj       655:        /* First check to see if this is tagged as an Apple UFS filesystem
                    656:         * in the disklabel
                    657:         */
1.211     pooka     658:        if ((VOP_IOCTL(devvp, DIOCGPART, &dpart, FREAD, cred) == 0) &&
1.103     dbj       659:                (dpart.part->p_fstype == FS_APPLEUFS)) {
1.153     mycroft   660:                ump->um_flags |= UFS_ISAPPLEUFS;
1.103     dbj       661:        }
                    662: #ifdef APPLE_UFS
                    663:        else {
                    664:                /* Manually look for an apple ufs label, and if a valid one
                    665:                 * is found, then treat it like an Apple UFS filesystem anyway
                    666:                 */
1.106     fvdl      667:                error = bread(devvp, (daddr_t)(APPLEUFS_LABEL_OFFSET / size),
1.223.4.2  yamt      668:                        APPLEUFS_LABEL_SIZE, cred, 0, &bp);
1.103     dbj       669:                if (error) {
1.209     ad        670:                        brelse(bp, 0);
1.103     dbj       671:                        return (error);
                    672:                }
                    673:                error = ffs_appleufs_validate(fs->fs_fsmnt,
1.223.4.2  yamt      674:                        (struct appleufslabel *)bp->b_data, NULL);
1.153     mycroft   675:                if (error == 0)
                    676:                        ump->um_flags |= UFS_ISAPPLEUFS;
1.209     ad        677:                brelse(bp, 0);
1.103     dbj       678:                bp = NULL;
                    679:        }
                    680: #else
1.153     mycroft   681:        if (ump->um_flags & UFS_ISAPPLEUFS)
1.103     dbj       682:                return (EIO);
                    683: #endif
                    684:
1.153     mycroft   685:        if (UFS_MPISAPPLEUFS(ump)) {
1.103     dbj       686:                /* see comment about NeXT below */
1.153     mycroft   687:                ump->um_maxsymlinklen = APPLEUFS_MAXSYMLINKLEN;
                    688:                ump->um_dirblksiz = APPLEUFS_DIRBLKSIZ;
                    689:                mp->mnt_iflag |= IMNT_DTYPE;
                    690:        } else {
                    691:                ump->um_maxsymlinklen = fs->fs_maxsymlinklen;
                    692:                ump->um_dirblksiz = DIRBLKSIZ;
                    693:                if (ump->um_maxsymlinklen > 0)
                    694:                        mp->mnt_iflag |= IMNT_DTYPE;
                    695:                else
                    696:                        mp->mnt_iflag &= ~IMNT_DTYPE;
1.103     dbj       697:        }
1.154     yamt      698:        ffs_oldfscompat_read(fs, ump, sblockloc);
1.223.4.2  yamt      699:
1.209     ad        700:        mutex_enter(&ump->um_lock);
1.153     mycroft   701:        ump->um_maxfilesize = fs->fs_maxfilesize;
1.223.4.2  yamt      702:        if (fs->fs_flags & ~(FS_KNOWN_FLAGS | FS_INTERNAL)) {
                    703:                uprintf("%s: unknown ufs flags: 0x%08"PRIx32"%s\n",
                    704:                    mp->mnt_stat.f_mntonname, fs->fs_flags,
                    705:                    (mp->mnt_flag & MNT_FORCE) ? "" : ", not mounting");
                    706:                if ((mp->mnt_flag & MNT_FORCE) == 0) {
                    707:                        mutex_exit(&ump->um_lock);
                    708:                        return (EINVAL);
                    709:                }
                    710:        }
1.89      fvdl      711:        if (fs->fs_pendingblocks != 0 || fs->fs_pendinginodes != 0) {
                    712:                fs->fs_pendingblocks = 0;
                    713:                fs->fs_pendinginodes = 0;
                    714:        }
1.209     ad        715:        mutex_exit(&ump->um_lock);
1.85      lukem     716:
1.211     pooka     717:        ffs_statvfs(mp, &mp->mnt_stat);
1.1       mycroft   718:        /*
                    719:         * Step 3: re-read summary information from disk.
                    720:         */
                    721:        blks = howmany(fs->fs_cssize, fs->fs_fsize);
1.84      lukem     722:        space = fs->fs_csp;
1.1       mycroft   723:        for (i = 0; i < blks; i += fs->fs_frag) {
                    724:                size = fs->fs_bsize;
                    725:                if (i + fs->fs_frag > blks)
                    726:                        size = (blks - i) * fs->fs_fsize;
1.19      christos  727:                error = bread(devvp, fsbtodb(fs, fs->fs_csaddr + i), size,
1.223.4.2  yamt      728:                              NOCRED, 0, &bp);
1.47      bouyer    729:                if (error) {
1.209     ad        730:                        brelse(bp, 0);
1.1       mycroft   731:                        return (error);
1.47      bouyer    732:                }
1.34      bouyer    733: #ifdef FFS_EI
1.55      fvdl      734:                if (UFS_FSNEEDSWAP(fs))
1.84      lukem     735:                        ffs_csum_swap((struct csum *)bp->b_data,
                    736:                            (struct csum *)space, size);
1.34      bouyer    737:                else
                    738: #endif
1.84      lukem     739:                        memcpy(space, bp->b_data, (size_t)size);
                    740:                space = (char *)space + size;
1.209     ad        741:                brelse(bp, 0);
1.1       mycroft   742:        }
1.149     hannken   743:        if (fs->fs_snapinum[0] != 0)
1.153     mycroft   744:                ffs_snapshot_mount(mp);
1.18      cgd       745:        /*
                    746:         * We no longer know anything about clusters per cylinder group.
                    747:         */
                    748:        if (fs->fs_contigsumsize > 0) {
                    749:                lp = fs->fs_maxcluster;
                    750:                for (i = 0; i < fs->fs_ncg; i++)
                    751:                        *lp++ = fs->fs_contigsumsize;
                    752:        }
                    753:
1.214     ad        754:        /* Allocate a marker vnode. */
1.215     pooka     755:        if ((mvp = vnalloc(mp)) == NULL)
1.214     ad        756:                return ENOMEM;
1.189     reinoud   757:        /*
                    758:         * NOTE: not using the TAILQ_FOREACH here since in this loop vgone()
                    759:         * and vclean() can be called indirectly
                    760:         */
1.214     ad        761:        mutex_enter(&mntvnode_lock);
                    762:  loop:
                    763:        for (vp = TAILQ_FIRST(&mp->mnt_vnodelist); vp; vp = vunmark(mvp)) {
                    764:                vmark(mvp, vp);
                    765:                if (vp->v_mount != mp || vismarker(vp))
                    766:                        continue;
1.1       mycroft   767:                /*
                    768:                 * Step 4: invalidate all inactive vnodes.
                    769:                 */
1.214     ad        770:                if (vrecycle(vp, &mntvnode_lock, l)) {
                    771:                        mutex_enter(&mntvnode_lock);
                    772:                        (void)vunmark(mvp);
1.33      fvdl      773:                        goto loop;
1.214     ad        774:                }
1.1       mycroft   775:                /*
                    776:                 * Step 5: invalidate all cached file data.
                    777:                 */
1.214     ad        778:                mutex_enter(&vp->v_interlock);
                    779:                mutex_exit(&mntvnode_lock);
                    780:                if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK)) {
                    781:                        (void)vunmark(mvp);
1.1       mycroft   782:                        goto loop;
1.214     ad        783:                }
1.177     christos  784:                if (vinvalbuf(vp, 0, cred, l, 0, 0))
1.1       mycroft   785:                        panic("ffs_reload: dirty2");
                    786:                /*
                    787:                 * Step 6: re-read inode data for all active vnodes.
                    788:                 */
                    789:                ip = VTOI(vp);
1.19      christos  790:                error = bread(devvp, fsbtodb(fs, ino_to_fsba(fs, ip->i_number)),
1.223.4.2  yamt      791:                              (int)fs->fs_bsize, NOCRED, 0, &bp);
1.19      christos  792:                if (error) {
1.209     ad        793:                        brelse(bp, 0);
1.1       mycroft   794:                        vput(vp);
1.214     ad        795:                        (void)vunmark(mvp);
                    796:                        break;
1.1       mycroft   797:                }
1.110     fvdl      798:                ffs_load_inode(bp, ip, fs, ip->i_number);
1.209     ad        799:                brelse(bp, 0);
1.1       mycroft   800:                vput(vp);
1.214     ad        801:                mutex_enter(&mntvnode_lock);
1.1       mycroft   802:        }
1.214     ad        803:        mutex_exit(&mntvnode_lock);
1.215     pooka     804:        vnfree(mvp);
1.214     ad        805:        return (error);
1.1       mycroft   806: }
                    807:
                    808: /*
1.110     fvdl      809:  * Possible superblock locations ordered from most to least likely.
                    810:  */
1.135     jdolecek  811: static const int sblock_try[] = SBLOCKSEARCH;
1.110     fvdl      812:
                    813: /*
1.1       mycroft   814:  * Common code for mount and mountroot
                    815:  */
                    816: int
1.177     christos  817: ffs_mountfs(struct vnode *devvp, struct mount *mp, struct lwp *l)
1.1       mycroft   818: {
1.34      bouyer    819:        struct ufsmount *ump;
1.1       mycroft   820:        struct buf *bp;
1.34      bouyer    821:        struct fs *fs;
1.9       mycroft   822:        dev_t dev;
1.1       mycroft   823:        struct partinfo dpart;
1.84      lukem     824:        void *space;
1.110     fvdl      825:        daddr_t sblockloc, fsblockloc;
                    826:        int blks, fstype;
1.209     ad        827:        int error, i, size, ronly, bset = 0;
1.52      drochner  828: #ifdef FFS_EI
1.110     fvdl      829:        int needswap = 0;               /* keep gcc happy */
1.52      drochner  830: #endif
1.9       mycroft   831:        int32_t *lp;
1.181     elad      832:        kauth_cred_t cred;
1.110     fvdl      833:        u_int32_t sbsize = 8192;        /* keep gcc happy*/
1.1       mycroft   834:
1.9       mycroft   835:        dev = devvp->v_rdev;
1.184     ad        836:        cred = l ? l->l_cred : NOCRED;
1.159     mycroft   837:
                    838:        /* Flush out any old buffers remaining from a previous use. */
1.55      fvdl      839:        vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY);
1.177     christos  840:        error = vinvalbuf(devvp, V_SAVE, cred, l, 0, 0);
1.55      fvdl      841:        VOP_UNLOCK(devvp, 0);
                    842:        if (error)
1.1       mycroft   843:                return (error);
                    844:
                    845:        ronly = (mp->mnt_flag & MNT_RDONLY) != 0;
1.211     pooka     846:        if (VOP_IOCTL(devvp, DIOCGPART, &dpart, FREAD, cred) != 0)
1.1       mycroft   847:                size = DEV_BSIZE;
                    848:        else
                    849:                size = dpart.disklab->d_secsize;
                    850:
                    851:        bp = NULL;
                    852:        ump = NULL;
1.110     fvdl      853:        fs = NULL;
1.138     dsl       854:        sblockloc = 0;
1.110     fvdl      855:        fstype = 0;
1.34      bouyer    856:
1.214     ad        857:        error = fstrans_mount(mp);
                    858:        if (error)
                    859:                return error;
                    860:
1.223.4.2  yamt      861:        ump = malloc(sizeof *ump, M_UFSMNT, M_WAITOK);
                    862:        memset(ump, 0, sizeof *ump);
                    863:        mutex_init(&ump->um_lock, MUTEX_DEFAULT, IPL_NONE);
                    864:        error = ffs_snapshot_init(ump);
                    865:        if (error)
                    866:                goto out;
                    867:        ump->um_ops = &ffs_ufsops;
                    868:
                    869: #ifdef WAPBL
                    870:  sbagain:
                    871: #endif
1.110     fvdl      872:        /*
1.192     isaki     873:         * Try reading the superblock in each of its possible locations.
                    874:         */
1.138     dsl       875:        for (i = 0; ; i++) {
                    876:                if (bp != NULL) {
1.209     ad        877:                        brelse(bp, BC_NOCACHE);
1.138     dsl       878:                        bp = NULL;
                    879:                }
                    880:                if (sblock_try[i] == -1) {
                    881:                        error = EINVAL;
                    882:                        fs = NULL;
                    883:                        goto out;
                    884:                }
1.110     fvdl      885:                error = bread(devvp, sblock_try[i] / size, SBLOCKSIZE, cred,
1.223.4.2  yamt      886:                              0, &bp);
1.168     drochner  887:                if (error) {
                    888:                        fs = NULL;
1.110     fvdl      889:                        goto out;
1.168     drochner  890:                }
1.110     fvdl      891:                fs = (struct fs*)bp->b_data;
                    892:                fsblockloc = sblockloc = sblock_try[i];
                    893:                if (fs->fs_magic == FS_UFS1_MAGIC) {
                    894:                        sbsize = fs->fs_sbsize;
                    895:                        fstype = UFS1;
1.34      bouyer    896: #ifdef FFS_EI
1.110     fvdl      897:                        needswap = 0;
                    898:                } else if (fs->fs_magic == bswap32(FS_UFS1_MAGIC)) {
                    899:                        sbsize = bswap32(fs->fs_sbsize);
                    900:                        fstype = UFS1;
                    901:                        needswap = 1;
1.34      bouyer    902: #endif
1.110     fvdl      903:                } else if (fs->fs_magic == FS_UFS2_MAGIC) {
                    904:                        sbsize = fs->fs_sbsize;
                    905:                        fstype = UFS2;
                    906: #ifdef FFS_EI
                    907:                        needswap = 0;
                    908:                } else if (fs->fs_magic == bswap32(FS_UFS2_MAGIC)) {
                    909:                        sbsize = bswap32(fs->fs_sbsize);
                    910:                        fstype = UFS2;
                    911:                        needswap = 1;
                    912: #endif
1.112     fvdl      913:                } else
1.138     dsl       914:                        continue;
                    915:
                    916:
                    917:                /* fs->fs_sblockloc isn't defined for old filesystems */
1.140     dsl       918:                if (fstype == UFS1 && !(fs->fs_old_flags & FS_FLAGS_UPDATED)) {
                    919:                        if (sblockloc == SBLOCK_UFS2)
1.138     dsl       920:                                /*
                    921:                                 * This is likely to be the first alternate
                    922:                                 * in a filesystem with 64k blocks.
                    923:                                 * Don't use it.
                    924:                                 */
                    925:                                continue;
                    926:                        fsblockloc = sblockloc;
                    927:                } else {
                    928:                        fsblockloc = fs->fs_sblockloc;
                    929: #ifdef FFS_EI
                    930:                        if (needswap)
                    931:                                fsblockloc = bswap64(fsblockloc);
                    932: #endif
                    933:                }
1.110     fvdl      934:
1.138     dsl       935:                /* Check we haven't found an alternate superblock */
                    936:                if (fsblockloc != sblockloc)
                    937:                        continue;
1.112     fvdl      938:
1.138     dsl       939:                /* Validate size of superblock */
                    940:                if (sbsize > MAXBSIZE || sbsize < sizeof(struct fs))
                    941:                        continue;
1.110     fvdl      942:
1.138     dsl       943:                /* Ok seems to be a good superblock */
                    944:                break;
1.34      bouyer    945:        }
                    946:
                    947:        fs = malloc((u_long)sbsize, M_UFSMNT, M_WAITOK);
1.42      perry     948:        memcpy(fs, bp->b_data, sbsize);
1.111     fvdl      949:        ump->um_fs = fs;
                    950:
1.34      bouyer    951: #ifdef FFS_EI
1.55      fvdl      952:        if (needswap) {
1.83      lukem     953:                ffs_sb_swap((struct fs*)bp->b_data, fs);
1.55      fvdl      954:                fs->fs_flags |= FS_SWAPPED;
1.121     bouyer    955:        } else
1.34      bouyer    956: #endif
1.121     bouyer    957:                fs->fs_flags &= ~FS_SWAPPED;
1.56      drochner  958:
1.223.4.2  yamt      959: #ifdef WAPBL
                    960:        if ((mp->mnt_wapbl_replay == 0) && (fs->fs_flags & FS_DOWAPBL)) {
                    961:                error = ffs_wapbl_replay_start(mp, fs, devvp);
                    962:                if (error)
                    963:                        goto out;
                    964:
                    965:                if (!ronly) {
                    966:                        /* XXX fsmnt may be stale. */
                    967:                        printf("%s: replaying log to disk\n", fs->fs_fsmnt);
                    968:                        error = wapbl_replay_write(mp->mnt_wapbl_replay, devvp);
                    969:                        if (error)
                    970:                                goto out;
                    971:                        wapbl_replay_stop(mp->mnt_wapbl_replay);
                    972:                        fs->fs_clean = FS_WASCLEAN;
                    973:                } else {
                    974:                        /* XXX fsmnt may be stale */
                    975:                        printf("%s: replaying log to memory\n", fs->fs_fsmnt);
                    976:                }
                    977:
                    978:                /* Force a re-read of the superblock */
                    979:                brelse(bp, BC_INVAL);
                    980:                bp = NULL;
                    981:                free(fs, M_UFSMNT);
                    982:                fs = NULL;
                    983:                goto sbagain;
                    984:        }
                    985: #else /* !WAPBL */
                    986:        if ((fs->fs_flags & FS_DOWAPBL) && (mp->mnt_flag & MNT_FORCE) == 0) {
                    987:                error = EPERM;
                    988:                goto out;
                    989:        }
                    990: #endif /* !WAPBL */
                    991:
1.154     yamt      992:        ffs_oldfscompat_read(fs, ump, sblockloc);
1.153     mycroft   993:        ump->um_maxfilesize = fs->fs_maxfilesize;
1.131     dbj       994:
1.223.4.2  yamt      995:        if (fs->fs_flags & ~(FS_KNOWN_FLAGS | FS_INTERNAL)) {
                    996:                uprintf("%s: unknown ufs flags: 0x%08"PRIx32"%s\n",
                    997:                    mp->mnt_stat.f_mntonname, fs->fs_flags,
                    998:                    (mp->mnt_flag & MNT_FORCE) ? "" : ", not mounting");
                    999:                if ((mp->mnt_flag & MNT_FORCE) == 0) {
                   1000:                        error = EINVAL;
                   1001:                        goto out;
                   1002:                }
                   1003:        }
                   1004:
1.89      fvdl     1005:        if (fs->fs_pendingblocks != 0 || fs->fs_pendinginodes != 0) {
                   1006:                fs->fs_pendingblocks = 0;
                   1007:                fs->fs_pendinginodes = 0;
                   1008:        }
1.56      drochner 1009:
1.110     fvdl     1010:        ump->um_fstype = fstype;
                   1011:        if (fs->fs_sbsize < SBLOCKSIZE)
1.209     ad       1012:                brelse(bp, BC_INVAL);
                   1013:        else
                   1014:                brelse(bp, 0);
1.1       mycroft  1015:        bp = NULL;
1.94      chs      1016:
1.103     dbj      1017:        /* First check to see if this is tagged as an Apple UFS filesystem
                   1018:         * in the disklabel
                   1019:         */
1.211     pooka    1020:        if ((VOP_IOCTL(devvp, DIOCGPART, &dpart, FREAD, cred) == 0) &&
1.103     dbj      1021:                (dpart.part->p_fstype == FS_APPLEUFS)) {
                   1022:                ump->um_flags |= UFS_ISAPPLEUFS;
                   1023:        }
                   1024: #ifdef APPLE_UFS
                   1025:        else {
                   1026:                /* Manually look for an apple ufs label, and if a valid one
                   1027:                 * is found, then treat it like an Apple UFS filesystem anyway
                   1028:                 */
1.106     fvdl     1029:                error = bread(devvp, (daddr_t)(APPLEUFS_LABEL_OFFSET / size),
1.223.4.2  yamt     1030:                        APPLEUFS_LABEL_SIZE, cred, 0, &bp);
1.103     dbj      1031:                if (error)
                   1032:                        goto out;
                   1033:                error = ffs_appleufs_validate(fs->fs_fsmnt,
1.223.4.2  yamt     1034:                        (struct appleufslabel *)bp->b_data, NULL);
1.103     dbj      1035:                if (error == 0) {
                   1036:                        ump->um_flags |= UFS_ISAPPLEUFS;
                   1037:                }
1.209     ad       1038:                brelse(bp, 0);
1.103     dbj      1039:                bp = NULL;
                   1040:        }
                   1041: #else
                   1042:        if (ump->um_flags & UFS_ISAPPLEUFS) {
                   1043:                error = EINVAL;
                   1044:                goto out;
                   1045:        }
                   1046: #endif
                   1047:
1.223.4.2  yamt     1048: #if 0
                   1049: /*
                   1050:  * XXX This code changes the behaviour of mounting dirty filesystems, to
                   1051:  * XXX require "mount -f ..." to mount them.  This doesn't match what
                   1052:  * XXX mount(8) describes and is disabled for now.
                   1053:  */
                   1054:        /*
                   1055:         * If the file system is not clean, don't allow it to be mounted
                   1056:         * unless MNT_FORCE is specified.  (Note: MNT_FORCE is always set
                   1057:         * for the root file system.)
                   1058:         */
                   1059:        if (fs->fs_flags & FS_DOWAPBL) {
                   1060:                /*
                   1061:                 * wapbl normally expects to be FS_WASCLEAN when the FS_DOWAPBL
                   1062:                 * bit is set, although there's a window in unmount where it
                   1063:                 * could be FS_ISCLEAN
                   1064:                 */
                   1065:                if ((mp->mnt_flag & MNT_FORCE) == 0 &&
                   1066:                    (fs->fs_clean & (FS_WASCLEAN | FS_ISCLEAN)) == 0) {
                   1067:                        error = EPERM;
                   1068:                        goto out;
                   1069:                }
                   1070:        } else
                   1071:                if ((fs->fs_clean & FS_ISCLEAN) == 0 &&
                   1072:                    (mp->mnt_flag & MNT_FORCE) == 0) {
                   1073:                        error = EPERM;
                   1074:                        goto out;
                   1075:                }
                   1076: #endif
                   1077:
1.94      chs      1078:        /*
1.99      chs      1079:         * verify that we can access the last block in the fs
                   1080:         * if we're mounting read/write.
1.94      chs      1081:         */
                   1082:
1.99      chs      1083:        if (!ronly) {
                   1084:                error = bread(devvp, fsbtodb(fs, fs->fs_size - 1), fs->fs_fsize,
1.223.4.2  yamt     1085:                    cred, 0, &bp);
1.99      chs      1086:                if (bp->b_bcount != fs->fs_fsize)
                   1087:                        error = EINVAL;
1.209     ad       1088:                if (error) {
                   1089:                        bset = BC_INVAL;
1.99      chs      1090:                        goto out;
1.209     ad       1091:                }
                   1092:                brelse(bp, BC_INVAL);
1.99      chs      1093:                bp = NULL;
                   1094:        }
1.94      chs      1095:
1.1       mycroft  1096:        fs->fs_ronly = ronly;
1.223.4.2  yamt     1097:        /* Don't bump fs_clean if we're replaying journal */
                   1098:        if (!((fs->fs_flags & FS_DOWAPBL) && (fs->fs_clean & FS_WASCLEAN)))
                   1099:                if (ronly == 0) {
                   1100:                        fs->fs_clean <<= 1;
                   1101:                        fs->fs_fmod = 1;
                   1102:                }
1.9       mycroft  1103:        size = fs->fs_cssize;
                   1104:        blks = howmany(size, fs->fs_fsize);
                   1105:        if (fs->fs_contigsumsize > 0)
                   1106:                size += fs->fs_ncg * sizeof(int32_t);
1.85      lukem    1107:        size += fs->fs_ncg * sizeof(*fs->fs_contigdirs);
1.84      lukem    1108:        space = malloc((u_long)size, M_UFSMNT, M_WAITOK);
                   1109:        fs->fs_csp = space;
1.1       mycroft  1110:        for (i = 0; i < blks; i += fs->fs_frag) {
                   1111:                size = fs->fs_bsize;
                   1112:                if (i + fs->fs_frag > blks)
                   1113:                        size = (blks - i) * fs->fs_fsize;
1.19      christos 1114:                error = bread(devvp, fsbtodb(fs, fs->fs_csaddr + i), size,
1.223.4.2  yamt     1115:                              cred, 0, &bp);
1.19      christos 1116:                if (error) {
1.84      lukem    1117:                        free(fs->fs_csp, M_UFSMNT);
1.128     dbj      1118:                        goto out;
1.1       mycroft  1119:                }
1.34      bouyer   1120: #ifdef FFS_EI
                   1121:                if (needswap)
1.84      lukem    1122:                        ffs_csum_swap((struct csum *)bp->b_data,
                   1123:                                (struct csum *)space, size);
1.34      bouyer   1124:                else
                   1125: #endif
1.42      perry    1126:                        memcpy(space, bp->b_data, (u_int)size);
1.161     perry    1127:
1.84      lukem    1128:                space = (char *)space + size;
1.209     ad       1129:                brelse(bp, 0);
1.1       mycroft  1130:                bp = NULL;
                   1131:        }
1.9       mycroft  1132:        if (fs->fs_contigsumsize > 0) {
1.85      lukem    1133:                fs->fs_maxcluster = lp = space;
1.9       mycroft  1134:                for (i = 0; i < fs->fs_ncg; i++)
                   1135:                        *lp++ = fs->fs_contigsumsize;
1.85      lukem    1136:                space = lp;
1.9       mycroft  1137:        }
1.85      lukem    1138:        size = fs->fs_ncg * sizeof(*fs->fs_contigdirs);
                   1139:        fs->fs_contigdirs = space;
                   1140:        space = (char *)space + size;
                   1141:        memset(fs->fs_contigdirs, 0, size);
                   1142:                /* Compatibility for old filesystems - XXX */
                   1143:        if (fs->fs_avgfilesize <= 0)
                   1144:                fs->fs_avgfilesize = AVFILESIZ;
                   1145:        if (fs->fs_avgfpdir <= 0)
                   1146:                fs->fs_avgfpdir = AFPDIR;
1.150     hannken  1147:        fs->fs_active = NULL;
1.100     soren    1148:        mp->mnt_data = ump;
1.143     christos 1149:        mp->mnt_stat.f_fsidx.__fsid_val[0] = (long)dev;
                   1150:        mp->mnt_stat.f_fsidx.__fsid_val[1] = makefstype(MOUNT_FFS);
                   1151:        mp->mnt_stat.f_fsid = mp->mnt_stat.f_fsidx.__fsid_val[0];
1.169     christos 1152:        mp->mnt_stat.f_namemax = FFS_MAXNAMLEN;
1.153     mycroft  1153:        if (UFS_MPISAPPLEUFS(ump)) {
1.103     dbj      1154:                /* NeXT used to keep short symlinks in the inode even
                   1155:                 * when using FS_42INODEFMT.  In that case fs->fs_maxsymlinklen
                   1156:                 * is probably -1, but we still need to be able to identify
                   1157:                 * short symlinks.
                   1158:                 */
1.153     mycroft  1159:                ump->um_maxsymlinklen = APPLEUFS_MAXSYMLINKLEN;
                   1160:                ump->um_dirblksiz = APPLEUFS_DIRBLKSIZ;
                   1161:                mp->mnt_iflag |= IMNT_DTYPE;
                   1162:        } else {
                   1163:                ump->um_maxsymlinklen = fs->fs_maxsymlinklen;
                   1164:                ump->um_dirblksiz = DIRBLKSIZ;
                   1165:                if (ump->um_maxsymlinklen > 0)
                   1166:                        mp->mnt_iflag |= IMNT_DTYPE;
                   1167:                else
                   1168:                        mp->mnt_iflag &= ~IMNT_DTYPE;
1.103     dbj      1169:        }
1.73      chs      1170:        mp->mnt_fs_bshift = fs->fs_bshift;
                   1171:        mp->mnt_dev_bshift = DEV_BSHIFT;        /* XXX */
1.1       mycroft  1172:        mp->mnt_flag |= MNT_LOCAL;
1.214     ad       1173:        mp->mnt_iflag |= IMNT_MPSAFE;
1.34      bouyer   1174: #ifdef FFS_EI
                   1175:        if (needswap)
                   1176:                ump->um_flags |= UFS_NEEDSWAP;
                   1177: #endif
1.1       mycroft  1178:        ump->um_mountp = mp;
                   1179:        ump->um_dev = dev;
                   1180:        ump->um_devvp = devvp;
                   1181:        ump->um_nindir = fs->fs_nindir;
1.73      chs      1182:        ump->um_lognindir = ffs(fs->fs_nindir) - 1;
1.1       mycroft  1183:        ump->um_bptrtodb = fs->fs_fsbtodb;
                   1184:        ump->um_seqinc = fs->fs_frag;
                   1185:        for (i = 0; i < MAXQUOTAS; i++)
                   1186:                ump->um_quotas[i] = NULLVP;
1.55      fvdl     1187:        devvp->v_specmountpoint = mp;
1.223.4.2  yamt     1188:        if (ronly == 0 && fs->fs_snapinum[0] != 0)
                   1189:                ffs_snapshot_mount(mp);
                   1190:
                   1191: #ifdef WAPBL
                   1192:        if (!ronly) {
                   1193:                KDASSERT(fs->fs_ronly == 0);
                   1194:                /*
                   1195:                 * ffs_wapbl_start() needs mp->mnt_stat initialised if it
                   1196:                 * needs to create a new log file in-filesystem.
                   1197:                 */
                   1198:                ffs_statvfs(mp, &mp->mnt_stat);
                   1199:
                   1200:                error = ffs_wapbl_start(mp);
1.55      fvdl     1201:                if (error) {
1.84      lukem    1202:                        free(fs->fs_csp, M_UFSMNT);
1.55      fvdl     1203:                        goto out;
                   1204:                }
                   1205:        }
1.223.4.2  yamt     1206: #endif /* WAPBL */
1.170     thorpej  1207: #ifdef UFS_EXTATTR
                   1208:        /*
                   1209:         * Initialize file-backed extended attributes on UFS1 file
                   1210:         * systems.
                   1211:         */
                   1212:        if (ump->um_fstype == UFS1) {
                   1213:                ufs_extattr_uepm_init(&ump->um_extattr);
                   1214: #ifdef UFS_EXTATTR_AUTOSTART
                   1215:                /*
                   1216:                 * XXX Just ignore errors.  Not clear that we should
                   1217:                 * XXX fail the mount in this case.
                   1218:                 */
1.178     rpaulo   1219:                (void) ufs_extattr_autostart(mp, l);
1.170     thorpej  1220: #endif
                   1221:        }
                   1222: #endif /* UFS_EXTATTR */
1.1       mycroft  1223:        return (0);
                   1224: out:
1.223.4.2  yamt     1225: #ifdef WAPBL
                   1226:        if (mp->mnt_wapbl_replay) {
                   1227:                wapbl_replay_stop(mp->mnt_wapbl_replay);
                   1228:                wapbl_replay_free(mp->mnt_wapbl_replay);
                   1229:                mp->mnt_wapbl_replay = 0;
                   1230:        }
                   1231: #endif
                   1232:
1.214     ad       1233:        fstrans_unmount(mp);
1.128     dbj      1234:        if (fs)
                   1235:                free(fs, M_UFSMNT);
1.55      fvdl     1236:        devvp->v_specmountpoint = NULL;
1.1       mycroft  1237:        if (bp)
1.209     ad       1238:                brelse(bp, bset);
1.1       mycroft  1239:        if (ump) {
1.131     dbj      1240:                if (ump->um_oldfscompat)
                   1241:                        free(ump->um_oldfscompat, M_UFSMNT);
1.209     ad       1242:                mutex_destroy(&ump->um_lock);
1.1       mycroft  1243:                free(ump, M_UFSMNT);
1.100     soren    1244:                mp->mnt_data = NULL;
1.1       mycroft  1245:        }
                   1246:        return (error);
                   1247: }
                   1248:
                   1249: /*
1.110     fvdl     1250:  * Sanity checks for loading old filesystem superblocks.
                   1251:  * See ffs_oldfscompat_write below for unwound actions.
1.1       mycroft  1252:  *
1.110     fvdl     1253:  * XXX - Parts get retired eventually.
                   1254:  * Unfortunately new bits get added.
1.1       mycroft  1255:  */
1.110     fvdl     1256: static void
1.166     thorpej  1257: ffs_oldfscompat_read(struct fs *fs, struct ufsmount *ump, daddr_t sblockloc)
1.110     fvdl     1258: {
                   1259:        off_t maxfilesize;
1.131     dbj      1260:        int32_t *extrasave;
1.110     fvdl     1261:
1.131     dbj      1262:        if ((fs->fs_magic != FS_UFS1_MAGIC) ||
                   1263:            (fs->fs_old_flags & FS_FLAGS_UPDATED))
1.111     fvdl     1264:                return;
                   1265:
1.131     dbj      1266:        if (!ump->um_oldfscompat)
                   1267:                ump->um_oldfscompat = malloc(512 + 3*sizeof(int32_t),
                   1268:                    M_UFSMNT, M_WAITOK);
                   1269:
                   1270:        memcpy(ump->um_oldfscompat, &fs->fs_old_postbl_start, 512);
                   1271:        extrasave = ump->um_oldfscompat;
                   1272:        extrasave += 512/sizeof(int32_t);
                   1273:        extrasave[0] = fs->fs_old_npsect;
                   1274:        extrasave[1] = fs->fs_old_interleave;
                   1275:        extrasave[2] = fs->fs_old_trackskew;
                   1276:
                   1277:        /* These fields will be overwritten by their
                   1278:         * original values in fs_oldfscompat_write, so it is harmless
                   1279:         * to modify them here.
                   1280:         */
                   1281:        fs->fs_cstotal.cs_ndir = fs->fs_old_cstotal.cs_ndir;
                   1282:        fs->fs_cstotal.cs_nbfree = fs->fs_old_cstotal.cs_nbfree;
                   1283:        fs->fs_cstotal.cs_nifree = fs->fs_old_cstotal.cs_nifree;
                   1284:        fs->fs_cstotal.cs_nffree = fs->fs_old_cstotal.cs_nffree;
                   1285:
                   1286:        fs->fs_maxbsize = fs->fs_bsize;
                   1287:        fs->fs_time = fs->fs_old_time;
                   1288:        fs->fs_size = fs->fs_old_size;
                   1289:        fs->fs_dsize = fs->fs_old_dsize;
                   1290:        fs->fs_csaddr = fs->fs_old_csaddr;
                   1291:        fs->fs_sblockloc = sblockloc;
                   1292:
1.223.4.2  yamt     1293:        fs->fs_flags = fs->fs_old_flags | (fs->fs_flags & FS_INTERNAL);
1.122     enami    1294:
1.131     dbj      1295:        if (fs->fs_old_postblformat == FS_42POSTBLFMT) {
                   1296:                fs->fs_old_nrpos = 8;
                   1297:                fs->fs_old_npsect = fs->fs_old_nsect;
                   1298:                fs->fs_old_interleave = 1;
                   1299:                fs->fs_old_trackskew = 0;
1.111     fvdl     1300:        }
                   1301:
                   1302:        if (fs->fs_old_inodefmt < FS_44INODEFMT) {
1.201     tsutsui  1303:                fs->fs_maxfilesize = (u_quad_t) 1LL << 39;
1.110     fvdl     1304:                fs->fs_qbmask = ~fs->fs_bmask;
                   1305:                fs->fs_qfmask = ~fs->fs_fmask;
                   1306:        }
1.111     fvdl     1307:
                   1308:        maxfilesize = (u_int64_t)0x80000000 * fs->fs_bsize - 1;
1.201     tsutsui  1309:        if (fs->fs_maxfilesize > maxfilesize)
                   1310:                fs->fs_maxfilesize = maxfilesize;
1.111     fvdl     1311:
1.110     fvdl     1312:        /* Compatibility for old filesystems */
                   1313:        if (fs->fs_avgfilesize <= 0)
                   1314:                fs->fs_avgfilesize = AVFILESIZ;
                   1315:        if (fs->fs_avgfpdir <= 0)
                   1316:                fs->fs_avgfpdir = AFPDIR;
1.131     dbj      1317:
1.110     fvdl     1318: #if 0
                   1319:        if (bigcgs) {
                   1320:                fs->fs_save_cgsize = fs->fs_cgsize;
                   1321:                fs->fs_cgsize = fs->fs_bsize;
                   1322:        }
                   1323: #endif
                   1324: }
                   1325:
                   1326: /*
                   1327:  * Unwinding superblock updates for old filesystems.
                   1328:  * See ffs_oldfscompat_read above for details.
                   1329:  *
                   1330:  * XXX - Parts get retired eventually.
                   1331:  * Unfortunately new bits get added.
                   1332:  */
                   1333: static void
1.166     thorpej  1334: ffs_oldfscompat_write(struct fs *fs, struct ufsmount *ump)
1.1       mycroft  1335: {
1.131     dbj      1336:        int32_t *extrasave;
                   1337:
                   1338:        if ((fs->fs_magic != FS_UFS1_MAGIC) ||
                   1339:            (fs->fs_old_flags & FS_FLAGS_UPDATED))
1.111     fvdl     1340:                return;
1.115     fvdl     1341:
1.111     fvdl     1342:        fs->fs_old_time = fs->fs_time;
                   1343:        fs->fs_old_cstotal.cs_ndir = fs->fs_cstotal.cs_ndir;
                   1344:        fs->fs_old_cstotal.cs_nbfree = fs->fs_cstotal.cs_nbfree;
                   1345:        fs->fs_old_cstotal.cs_nifree = fs->fs_cstotal.cs_nifree;
                   1346:        fs->fs_old_cstotal.cs_nffree = fs->fs_cstotal.cs_nffree;
1.131     dbj      1347:        fs->fs_old_flags = fs->fs_flags;
1.111     fvdl     1348:
1.110     fvdl     1349: #if 0
                   1350:        if (bigcgs) {
                   1351:                fs->fs_cgsize = fs->fs_save_cgsize;
                   1352:        }
                   1353: #endif
1.131     dbj      1354:
                   1355:        memcpy(&fs->fs_old_postbl_start, ump->um_oldfscompat, 512);
                   1356:        extrasave = ump->um_oldfscompat;
                   1357:        extrasave += 512/sizeof(int32_t);
                   1358:        fs->fs_old_npsect = extrasave[0];
                   1359:        fs->fs_old_interleave = extrasave[1];
                   1360:        fs->fs_old_trackskew = extrasave[2];
                   1361:
1.1       mycroft  1362: }
                   1363:
                   1364: /*
                   1365:  * unmount system call
                   1366:  */
                   1367: int
1.211     pooka    1368: ffs_unmount(struct mount *mp, int mntflags)
1.1       mycroft  1369: {
1.211     pooka    1370:        struct lwp *l = curlwp;
1.170     thorpej  1371:        struct ufsmount *ump = VFSTOUFS(mp);
                   1372:        struct fs *fs = ump->um_fs;
1.223.4.2  yamt     1373:        int error, flags;
                   1374: #ifdef WAPBL
                   1375:        extern int doforce;
                   1376: #endif
1.1       mycroft  1377:
                   1378:        flags = 0;
1.11      mycroft  1379:        if (mntflags & MNT_FORCE)
1.1       mycroft  1380:                flags |= FORCECLOSE;
1.170     thorpej  1381: #ifdef UFS_EXTATTR
                   1382:        if (ump->um_fstype == UFS1) {
1.220     pooka    1383:                ufs_extattr_stop(mp, l);
                   1384:                ufs_extattr_uepm_destroy(&ump->um_extattr);
1.170     thorpej  1385:        }
                   1386: #endif /* UFS_EXTATTR */
1.223.4.2  yamt     1387:        if ((error = ffs_flushfiles(mp, flags, l)) != 0)
                   1388:                return (error);
                   1389:        error = UFS_WAPBL_BEGIN(mp);
                   1390:        if (error == 0)
                   1391:                if (fs->fs_ronly == 0 &&
                   1392:                    ffs_cgupdate(ump, MNT_WAIT) == 0 &&
                   1393:                    fs->fs_clean & FS_WASCLEAN) {
1.91      fvdl     1394:                        fs->fs_clean = FS_ISCLEAN;
1.223.4.2  yamt     1395:                        fs->fs_fmod = 0;
                   1396:                        (void) ffs_sbupdate(ump, MNT_WAIT);
1.91      fvdl     1397:                }
1.223.4.2  yamt     1398:        if (error == 0)
                   1399:                UFS_WAPBL_END(mp);
                   1400: #ifdef WAPBL
                   1401:        KASSERT(!(mp->mnt_wapbl_replay && mp->mnt_wapbl));
                   1402:        if (mp->mnt_wapbl_replay) {
                   1403:                KDASSERT(fs->fs_ronly);
                   1404:                wapbl_replay_stop(mp->mnt_wapbl_replay);
                   1405:                wapbl_replay_free(mp->mnt_wapbl_replay);
                   1406:                mp->mnt_wapbl_replay = 0;
1.15      mycroft  1407:        }
1.223.4.2  yamt     1408:        error = ffs_wapbl_stop(mp, doforce && (mntflags & MNT_FORCE));
                   1409:        if (error) {
                   1410:                return error;
                   1411:        }
                   1412: #endif /* WAPBL */
1.54      enami    1413:        if (ump->um_devvp->v_type != VBAD)
1.55      fvdl     1414:                ump->um_devvp->v_specmountpoint = NULL;
1.53      wrstuden 1415:        vn_lock(ump->um_devvp, LK_EXCLUSIVE | LK_RETRY);
1.223.4.2  yamt     1416:        (void)VOP_CLOSE(ump->um_devvp, fs->fs_ronly ? FREAD : FREAD | FWRITE,
1.211     pooka    1417:                NOCRED);
1.53      wrstuden 1418:        vput(ump->um_devvp);
1.84      lukem    1419:        free(fs->fs_csp, M_UFSMNT);
1.1       mycroft  1420:        free(fs, M_UFSMNT);
1.131     dbj      1421:        if (ump->um_oldfscompat != NULL)
                   1422:                free(ump->um_oldfscompat, M_UFSMNT);
1.209     ad       1423:        mutex_destroy(&ump->um_lock);
1.223     hannken  1424:        ffs_snapshot_fini(ump);
1.1       mycroft  1425:        free(ump, M_UFSMNT);
1.100     soren    1426:        mp->mnt_data = NULL;
1.1       mycroft  1427:        mp->mnt_flag &= ~MNT_LOCAL;
1.214     ad       1428:        fstrans_unmount(mp);
1.129     dbj      1429:        return (0);
1.1       mycroft  1430: }
                   1431:
                   1432: /*
                   1433:  * Flush out all the files in a filesystem.
                   1434:  */
1.19      christos 1435: int
1.177     christos 1436: ffs_flushfiles(struct mount *mp, int flags, struct lwp *l)
1.1       mycroft  1437: {
                   1438:        extern int doforce;
1.61      augustss 1439:        struct ufsmount *ump;
1.19      christos 1440:        int error;
1.1       mycroft  1441:
                   1442:        if (!doforce)
                   1443:                flags &= ~FORCECLOSE;
                   1444:        ump = VFSTOUFS(mp);
                   1445: #ifdef QUOTA
                   1446:        if (mp->mnt_flag & MNT_QUOTA) {
1.19      christos 1447:                int i;
1.223.4.2  yamt     1448:                if ((error = vflush(mp, NULLVP, SKIPSYSTEM | flags)) != 0)
1.1       mycroft  1449:                        return (error);
                   1450:                for (i = 0; i < MAXQUOTAS; i++) {
                   1451:                        if (ump->um_quotas[i] == NULLVP)
                   1452:                                continue;
1.177     christos 1453:                        quotaoff(l, mp, i);
1.1       mycroft  1454:                }
                   1455:                /*
                   1456:                 * Here we fall through to vflush again to ensure
                   1457:                 * that we have gotten rid of all the system vnodes.
                   1458:                 */
                   1459:        }
                   1460: #endif
1.149     hannken  1461:        if ((error = vflush(mp, 0, SKIPSYSTEM | flags)) != 0)
                   1462:                return (error);
                   1463:        ffs_snapshot_unmount(mp);
1.55      fvdl     1464:        /*
                   1465:         * Flush all the files.
                   1466:         */
1.1       mycroft  1467:        error = vflush(mp, NULLVP, flags);
1.55      fvdl     1468:        if (error)
                   1469:                return (error);
                   1470:        /*
                   1471:         * Flush filesystem metadata.
                   1472:         */
                   1473:        vn_lock(ump->um_devvp, LK_EXCLUSIVE | LK_RETRY);
1.211     pooka    1474:        error = VOP_FSYNC(ump->um_devvp, l->l_cred, FSYNC_WAIT, 0, 0);
1.55      fvdl     1475:        VOP_UNLOCK(ump->um_devvp, 0);
1.223.4.2  yamt     1476:        if (flags & FORCECLOSE) /* XXXDBJ */
                   1477:                error = 0;
                   1478:
                   1479: #ifdef WAPBL
                   1480:        if (error)
                   1481:                return error;
                   1482:        if (mp->mnt_wapbl) {
                   1483:                error = wapbl_flush(mp->mnt_wapbl, 1);
                   1484:                if (flags & FORCECLOSE)
                   1485:                        error = 0;
                   1486:        }
                   1487: #endif
                   1488:
1.1       mycroft  1489:        return (error);
                   1490: }
                   1491:
                   1492: /*
                   1493:  * Get file system statistics.
                   1494:  */
                   1495: int
1.211     pooka    1496: ffs_statvfs(struct mount *mp, struct statvfs *sbp)
1.1       mycroft  1497: {
1.61      augustss 1498:        struct ufsmount *ump;
                   1499:        struct fs *fs;
1.1       mycroft  1500:
                   1501:        ump = VFSTOUFS(mp);
                   1502:        fs = ump->um_fs;
1.209     ad       1503:        mutex_enter(&ump->um_lock);
1.143     christos 1504:        sbp->f_bsize = fs->fs_bsize;
                   1505:        sbp->f_frsize = fs->fs_fsize;
1.1       mycroft  1506:        sbp->f_iosize = fs->fs_bsize;
                   1507:        sbp->f_blocks = fs->fs_dsize;
1.98      mycroft  1508:        sbp->f_bfree = blkstofrags(fs, fs->fs_cstotal.cs_nbfree) +
1.223.4.2  yamt     1509:            fs->fs_cstotal.cs_nffree + dbtofsb(fs, fs->fs_pendingblocks);
1.143     christos 1510:        sbp->f_bresvd = ((u_int64_t) fs->fs_dsize * (u_int64_t)
                   1511:            fs->fs_minfree) / (u_int64_t) 100;
                   1512:        if (sbp->f_bfree > sbp->f_bresvd)
                   1513:                sbp->f_bavail = sbp->f_bfree - sbp->f_bresvd;
                   1514:        else
                   1515:                sbp->f_bavail = 0;
1.1       mycroft  1516:        sbp->f_files =  fs->fs_ncg * fs->fs_ipg - ROOTINO;
1.89      fvdl     1517:        sbp->f_ffree = fs->fs_cstotal.cs_nifree + fs->fs_pendinginodes;
1.143     christos 1518:        sbp->f_favail = sbp->f_ffree;
                   1519:        sbp->f_fresvd = 0;
1.209     ad       1520:        mutex_exit(&ump->um_lock);
1.143     christos 1521:        copy_statvfs_info(sbp, mp);
1.209     ad       1522:
1.1       mycroft  1523:        return (0);
                   1524: }
                   1525:
                   1526: /*
                   1527:  * Go through the disk queues to initiate sandbagged IO;
                   1528:  * go through the inodes to write those that have been modified;
                   1529:  * initiate the writing of the super block if it has been modified.
                   1530:  *
                   1531:  * Note: we are always called with the filesystem marked `MPBUSY'.
                   1532:  */
                   1533: int
1.211     pooka    1534: ffs_sync(struct mount *mp, int waitfor, kauth_cred_t cred)
1.1       mycroft  1535: {
1.223.4.2  yamt     1536:        struct vnode *vp, *mvp, *nvp;
1.33      fvdl     1537:        struct inode *ip;
                   1538:        struct ufsmount *ump = VFSTOUFS(mp);
                   1539:        struct fs *fs;
1.223.4.2  yamt     1540:        int error, allerror = 0;
1.1       mycroft  1541:
                   1542:        fs = ump->um_fs;
1.33      fvdl     1543:        if (fs->fs_fmod != 0 && fs->fs_ronly != 0) {            /* XXX */
                   1544:                printf("fs = %s\n", fs->fs_fsmnt);
                   1545:                panic("update: rofs mod");
1.1       mycroft  1546:        }
1.214     ad       1547:
                   1548:        /* Allocate a marker vnode. */
1.215     pooka    1549:        if ((mvp = vnalloc(mp)) == NULL)
1.214     ad       1550:                return (ENOMEM);
                   1551:
1.199     hannken  1552:        fstrans_start(mp, FSTRANS_SHARED);
1.1       mycroft  1553:        /*
                   1554:         * Write back each (modified) inode.
                   1555:         */
1.214     ad       1556:        mutex_enter(&mntvnode_lock);
1.1       mycroft  1557: loop:
1.189     reinoud  1558:        /*
                   1559:         * NOTE: not using the TAILQ_FOREACH here since in this loop vgone()
                   1560:         * and vclean() can be called indirectly
                   1561:         */
1.223.4.2  yamt     1562:        for (vp = TAILQ_FIRST(&mp->mnt_vnodelist); vp; vp = nvp) {
                   1563:                nvp = TAILQ_NEXT(vp, v_mntvnodes);
1.1       mycroft  1564:                /*
                   1565:                 * If the vnode that we are about to sync is no longer
                   1566:                 * associated with this mount point, start over.
                   1567:                 */
1.223.4.2  yamt     1568:                if (vp->v_mount != mp)
                   1569:                        goto loop;
                   1570:                /*
                   1571:                 * Don't interfere with concurrent scans of this FS.
                   1572:                 */
                   1573:                if (vismarker(vp))
1.214     ad       1574:                        continue;
                   1575:                mutex_enter(&vp->v_interlock);
1.1       mycroft  1576:                ip = VTOI(vp);
1.223.4.2  yamt     1577:
                   1578:                /*
                   1579:                 * Skip the vnode/inode if inaccessible.
                   1580:                 */
                   1581:                if (ip == NULL || (vp->v_iflag & (VI_XLOCK | VI_CLEAN)) != 0 ||
                   1582:                    vp->v_type == VNON) {
                   1583:                        mutex_exit(&vp->v_interlock);
                   1584:                        continue;
                   1585:                }
                   1586:
                   1587:                /*
                   1588:                 * We deliberately update inode times here.  This will
                   1589:                 * prevent a massive queue of updates accumulating, only
                   1590:                 * to be handled by a call to unmount.
                   1591:                 *
                   1592:                 * XXX It would be better to have the syncer trickle these
                   1593:                 * out.  Adjustment needed to allow registering vnodes for
                   1594:                 * sync when the vnode is clean, but the inode dirty.  Or
                   1595:                 * have ufs itself trickle out inode updates.
                   1596:                 *
                   1597:                 * If doing a lazy sync, we don't care about metadata or
                   1598:                 * data updates, because they are handled by each vnode's
                   1599:                 * synclist entry.  In this case we are only interested in
                   1600:                 * writing back modified inodes.
                   1601:                 */
                   1602:                if ((ip->i_flag & (IN_ACCESS | IN_CHANGE | IN_UPDATE |
                   1603:                    IN_MODIFY | IN_MODIFIED | IN_ACCESSED)) == 0 &&
                   1604:                    (waitfor == MNT_LAZY || (LIST_EMPTY(&vp->v_dirtyblkhd) &&
                   1605:                    UVM_OBJ_IS_CLEAN(&vp->v_uobj)))) {
1.214     ad       1606:                        mutex_exit(&vp->v_interlock);
1.33      fvdl     1607:                        continue;
                   1608:                }
1.193     hannken  1609:                if (vp->v_type == VBLK &&
1.194     hannken  1610:                    fstrans_getstate(mp) == FSTRANS_SUSPENDING) {
1.214     ad       1611:                        mutex_exit(&vp->v_interlock);
1.193     hannken  1612:                        continue;
                   1613:                }
1.223.4.2  yamt     1614:                vmark(mvp, vp);
1.214     ad       1615:                mutex_exit(&mntvnode_lock);
1.117     thorpej  1616:                error = vget(vp, LK_EXCLUSIVE | LK_NOWAIT | LK_INTERLOCK);
1.33      fvdl     1617:                if (error) {
1.214     ad       1618:                        mutex_enter(&mntvnode_lock);
1.223.4.2  yamt     1619:                        nvp = vunmark(mvp);
1.214     ad       1620:                        if (error == ENOENT) {
1.33      fvdl     1621:                                goto loop;
1.214     ad       1622:                        }
1.1       mycroft  1623:                        continue;
1.33      fvdl     1624:                }
1.223.4.2  yamt     1625:                if (waitfor == MNT_LAZY) {
                   1626:                        error = UFS_WAPBL_BEGIN(vp->v_mount);
                   1627:                        if (!error) {
                   1628:                                error = ffs_update(vp, NULL, NULL,
                   1629:                                    UPDATE_CLOSE);
                   1630:                                UFS_WAPBL_END(vp->v_mount);
                   1631:                        }
                   1632:                } else {
                   1633:                        error = VOP_FSYNC(vp, cred, FSYNC_NOLOG |
                   1634:                            (waitfor == MNT_WAIT ? FSYNC_WAIT : 0), 0, 0);
                   1635:                }
1.152     mycroft  1636:                if (error)
1.1       mycroft  1637:                        allerror = error;
                   1638:                vput(vp);
1.214     ad       1639:                mutex_enter(&mntvnode_lock);
1.223.4.2  yamt     1640:                nvp = vunmark(mvp);
1.1       mycroft  1641:        }
1.214     ad       1642:        mutex_exit(&mntvnode_lock);
1.1       mycroft  1643:        /*
                   1644:         * Force stale file system control information to be flushed.
                   1645:         */
1.132     hannken  1646:        if (waitfor != MNT_LAZY && (ump->um_devvp->v_numoutput > 0 ||
                   1647:            !LIST_EMPTY(&ump->um_devvp->v_dirtyblkhd))) {
1.55      fvdl     1648:                vn_lock(ump->um_devvp, LK_EXCLUSIVE | LK_RETRY);
                   1649:                if ((error = VOP_FSYNC(ump->um_devvp, cred,
1.223.4.2  yamt     1650:                    (waitfor == MNT_WAIT ? FSYNC_WAIT : 0) | FSYNC_NOLOG,
                   1651:                    0, 0)) != 0)
1.55      fvdl     1652:                        allerror = error;
                   1653:                VOP_UNLOCK(ump->um_devvp, 0);
1.223.4.2  yamt     1654:                if (allerror == 0 && waitfor == MNT_WAIT && !mp->mnt_wapbl) {
1.214     ad       1655:                        mutex_enter(&mntvnode_lock);
1.132     hannken  1656:                        goto loop;
                   1657:                }
1.55      fvdl     1658:        }
1.1       mycroft  1659: #ifdef QUOTA
1.118     fvdl     1660:        qsync(mp);
1.1       mycroft  1661: #endif
1.33      fvdl     1662:        /*
                   1663:         * Write back modified superblock.
                   1664:         */
                   1665:        if (fs->fs_fmod != 0) {
                   1666:                fs->fs_fmod = 0;
1.182     kardel   1667:                fs->fs_time = time_second;
1.223.4.2  yamt     1668:                error = UFS_WAPBL_BEGIN(mp);
                   1669:                if (error)
                   1670:                        allerror = error;
                   1671:                else {
                   1672:                        if ((error = ffs_cgupdate(ump, waitfor)))
                   1673:                                allerror = error;
                   1674:                        UFS_WAPBL_END(mp);
                   1675:                }
                   1676:        }
                   1677:
                   1678: #ifdef WAPBL
                   1679:        if (mp->mnt_wapbl) {
                   1680:                error = wapbl_flush(mp->mnt_wapbl, 0);
                   1681:                if (error)
1.64      mycroft  1682:                        allerror = error;
1.33      fvdl     1683:        }
1.223.4.2  yamt     1684: #endif
                   1685:
1.193     hannken  1686:        fstrans_done(mp);
1.215     pooka    1687:        vnfree(mvp);
1.1       mycroft  1688:        return (allerror);
                   1689: }
                   1690:
                   1691: /*
                   1692:  * Look up a FFS dinode number to find its incore vnode, otherwise read it
                   1693:  * in from disk.  If it is in core, wait for the lock bit to clear, then
                   1694:  * return the inode locked.  Detection and handling of mount points must be
                   1695:  * done by the calling routine.
                   1696:  */
                   1697: int
1.166     thorpej  1698: ffs_vget(struct mount *mp, ino_t ino, struct vnode **vpp)
1.1       mycroft  1699: {
1.33      fvdl     1700:        struct fs *fs;
                   1701:        struct inode *ip;
1.1       mycroft  1702:        struct ufsmount *ump;
                   1703:        struct buf *bp;
                   1704:        struct vnode *vp;
                   1705:        dev_t dev;
1.43      thorpej  1706:        int error;
1.1       mycroft  1707:
                   1708:        ump = VFSTOUFS(mp);
                   1709:        dev = ump->um_dev;
1.68      fvdl     1710:
1.200     ad       1711:  retry:
1.117     thorpej  1712:        if ((*vpp = ufs_ihashget(dev, ino, LK_EXCLUSIVE)) != NULL)
1.68      fvdl     1713:                return (0);
1.1       mycroft  1714:
                   1715:        /* Allocate a new vnode/inode. */
1.19      christos 1716:        if ((error = getnewvnode(VT_UFS, mp, ffs_vnodeop_p, &vp)) != 0) {
1.1       mycroft  1717:                *vpp = NULL;
                   1718:                return (error);
                   1719:        }
1.216     ad       1720:        ip = pool_cache_get(ffs_inode_cache, PR_WAITOK);
1.68      fvdl     1721:
                   1722:        /*
1.200     ad       1723:         * If someone beat us to it, put back the freshly allocated
                   1724:         * vnode/inode pair and retry.
1.68      fvdl     1725:         */
1.195     ad       1726:        mutex_enter(&ufs_hashlock);
1.200     ad       1727:        if (ufs_ihashget(dev, ino, 0) != NULL) {
1.195     ad       1728:                mutex_exit(&ufs_hashlock);
                   1729:                ungetnewvnode(vp);
1.216     ad       1730:                pool_cache_put(ffs_inode_cache, ip);
1.200     ad       1731:                goto retry;
1.195     ad       1732:        }
1.68      fvdl     1733:
1.210     ad       1734:        vp->v_vflag |= VV_LOCKSWORK;
1.155     thorpej  1735:
1.43      thorpej  1736:        /*
                   1737:         * XXX MFS ends up here, too, to allocate an inode.  Should we
                   1738:         * XXX create another pool for MFS inodes?
                   1739:         */
1.87      chs      1740:
                   1741:        memset(ip, 0, sizeof(struct inode));
1.1       mycroft  1742:        vp->v_data = ip;
                   1743:        ip->i_vnode = vp;
1.110     fvdl     1744:        ip->i_ump = ump;
1.1       mycroft  1745:        ip->i_fs = fs = ump->um_fs;
                   1746:        ip->i_dev = dev;
                   1747:        ip->i_number = ino;
                   1748: #ifdef QUOTA
1.203     hannken  1749:        ufsquota_init(ip);
1.1       mycroft  1750: #endif
1.86      chs      1751:
1.1       mycroft  1752:        /*
1.213     dyoung   1753:         * Initialize genfs node, we might proceed to destroy it in
                   1754:         * error branches.
                   1755:         */
                   1756:        genfs_node_init(vp, &ffs_genfsops);
                   1757:
                   1758:        /*
1.1       mycroft  1759:         * Put it onto its hash chain and lock it so that other requests for
                   1760:         * this inode will block if they arrive while we are sleeping waiting
                   1761:         * for old data structures to be purged or for the contents of the
                   1762:         * disk portion of this inode to be read.
                   1763:         */
1.87      chs      1764:
1.1       mycroft  1765:        ufs_ihashins(ip);
1.195     ad       1766:        mutex_exit(&ufs_hashlock);
1.1       mycroft  1767:
                   1768:        /* Read in the disk contents for the inode, copy into the inode. */
1.19      christos 1769:        error = bread(ump->um_devvp, fsbtodb(fs, ino_to_fsba(fs, ino)),
1.223.4.2  yamt     1770:                      (int)fs->fs_bsize, NOCRED, 0, &bp);
1.19      christos 1771:        if (error) {
1.87      chs      1772:
1.1       mycroft  1773:                /*
                   1774:                 * The inode does not contain anything useful, so it would
                   1775:                 * be misleading to leave it on its hash chain. With mode
                   1776:                 * still zero, it will be unlinked and returned to the free
                   1777:                 * list by vput().
                   1778:                 */
1.87      chs      1779:
1.1       mycroft  1780:                vput(vp);
1.209     ad       1781:                brelse(bp, 0);
1.1       mycroft  1782:                *vpp = NULL;
                   1783:                return (error);
                   1784:        }
1.110     fvdl     1785:        if (ip->i_ump->um_fstype == UFS1)
1.216     ad       1786:                ip->i_din.ffs1_din = pool_cache_get(ffs_dinode1_cache,
                   1787:                    PR_WAITOK);
1.110     fvdl     1788:        else
1.216     ad       1789:                ip->i_din.ffs2_din = pool_cache_get(ffs_dinode2_cache,
                   1790:                    PR_WAITOK);
1.110     fvdl     1791:        ffs_load_inode(bp, ip, fs, ino);
1.209     ad       1792:        brelse(bp, 0);
1.1       mycroft  1793:
                   1794:        /*
                   1795:         * Initialize the vnode from the inode, check for aliases.
                   1796:         * Note that the underlying vnode may have changed.
                   1797:         */
1.87      chs      1798:
                   1799:        ufs_vinit(mp, ffs_specop_p, ffs_fifoop_p, &vp);
                   1800:
1.1       mycroft  1801:        /*
                   1802:         * Finish inode initialization now that aliasing has been resolved.
                   1803:         */
1.87      chs      1804:
1.1       mycroft  1805:        ip->i_devvp = ump->um_devvp;
                   1806:        VREF(ip->i_devvp);
1.87      chs      1807:
1.1       mycroft  1808:        /*
                   1809:         * Ensure that uid and gid are correct. This is a temporary
                   1810:         * fix until fsck has been changed to do the update.
                   1811:         */
1.87      chs      1812:
1.110     fvdl     1813:        if (fs->fs_old_inodefmt < FS_44INODEFMT) {              /* XXX */
                   1814:                ip->i_uid = ip->i_ffs1_ouid;                    /* XXX */
                   1815:                ip->i_gid = ip->i_ffs1_ogid;                    /* XXX */
1.38      kleink   1816:        }                                                       /* XXX */
1.110     fvdl     1817:        uvm_vnp_setsize(vp, ip->i_size);
1.1       mycroft  1818:        *vpp = vp;
                   1819:        return (0);
                   1820: }
                   1821:
                   1822: /*
                   1823:  * File handle to vnode
                   1824:  *
                   1825:  * Have to be really careful about stale file handles:
                   1826:  * - check that the inode number is valid
                   1827:  * - call ffs_vget() to get the locked inode
                   1828:  * - check for an unallocated inode (i_mode == 0)
                   1829:  * - check that the given client host has export rights and return
                   1830:  *   those rights via. exflagsp and credanonp
                   1831:  */
                   1832: int
1.166     thorpej  1833: ffs_fhtovp(struct mount *mp, struct fid *fhp, struct vnode **vpp)
1.1       mycroft  1834: {
1.183     martin   1835:        struct ufid ufh;
1.1       mycroft  1836:        struct fs *fs;
                   1837:
1.183     martin   1838:        if (fhp->fid_len != sizeof(struct ufid))
                   1839:                return EINVAL;
                   1840:
                   1841:        memcpy(&ufh, fhp, sizeof(ufh));
1.1       mycroft  1842:        fs = VFSTOUFS(mp)->um_fs;
1.183     martin   1843:        if (ufh.ufid_ino < ROOTINO ||
                   1844:            ufh.ufid_ino >= fs->fs_ncg * fs->fs_ipg)
1.1       mycroft  1845:                return (ESTALE);
1.183     martin   1846:        return (ufs_fhtovp(mp, &ufh, vpp));
1.1       mycroft  1847: }
                   1848:
                   1849: /*
                   1850:  * Vnode pointer to File handle
                   1851:  */
                   1852: /* ARGSUSED */
1.19      christos 1853: int
1.183     martin   1854: ffs_vptofh(struct vnode *vp, struct fid *fhp, size_t *fh_size)
1.1       mycroft  1855: {
1.61      augustss 1856:        struct inode *ip;
1.183     martin   1857:        struct ufid ufh;
1.1       mycroft  1858:
1.183     martin   1859:        if (*fh_size < sizeof(struct ufid)) {
                   1860:                *fh_size = sizeof(struct ufid);
                   1861:                return E2BIG;
                   1862:        }
1.1       mycroft  1863:        ip = VTOI(vp);
1.183     martin   1864:        *fh_size = sizeof(struct ufid);
                   1865:        memset(&ufh, 0, sizeof(ufh));
                   1866:        ufh.ufid_len = sizeof(struct ufid);
                   1867:        ufh.ufid_ino = ip->i_number;
                   1868:        ufh.ufid_gen = ip->i_gen;
                   1869:        memcpy(fhp, &ufh, sizeof(ufh));
1.1       mycroft  1870:        return (0);
1.33      fvdl     1871: }
                   1872:
                   1873: void
1.166     thorpej  1874: ffs_init(void)
1.33      fvdl     1875: {
1.59      jdolecek 1876:        if (ffs_initcount++ > 0)
                   1877:                return;
                   1878:
1.216     ad       1879:        ffs_inode_cache = pool_cache_init(sizeof(struct inode), 0, 0, 0,
                   1880:            "ffsino", NULL, IPL_NONE, NULL, NULL, NULL);
                   1881:        ffs_dinode1_cache = pool_cache_init(sizeof(struct ufs1_dinode), 0, 0, 0,
                   1882:            "ffsdino1", NULL, IPL_NONE, NULL, NULL, NULL);
                   1883:        ffs_dinode2_cache = pool_cache_init(sizeof(struct ufs2_dinode), 0, 0, 0,
                   1884:            "ffsdino2", NULL, IPL_NONE, NULL, NULL, NULL);
1.33      fvdl     1885:        ufs_init();
1.86      chs      1886: }
                   1887:
                   1888: void
1.166     thorpej  1889: ffs_reinit(void)
1.86      chs      1890: {
1.223.4.2  yamt     1891:
1.86      chs      1892:        ufs_reinit();
1.59      jdolecek 1893: }
                   1894:
                   1895: void
1.166     thorpej  1896: ffs_done(void)
1.59      jdolecek 1897: {
                   1898:        if (--ffs_initcount > 0)
                   1899:                return;
                   1900:
                   1901:        ufs_done();
1.216     ad       1902:        pool_cache_destroy(ffs_dinode2_cache);
                   1903:        pool_cache_destroy(ffs_dinode1_cache);
                   1904:        pool_cache_destroy(ffs_inode_cache);
1.33      fvdl     1905: }
                   1906:
1.1       mycroft  1907: /*
                   1908:  * Write a superblock and associated information back to disk.
                   1909:  */
                   1910: int
1.166     thorpej  1911: ffs_sbupdate(struct ufsmount *mp, int waitfor)
1.1       mycroft  1912: {
1.61      augustss 1913:        struct fs *fs = mp->um_fs;
                   1914:        struct buf *bp;
1.110     fvdl     1915:        int error = 0;
                   1916:        u_int32_t saveflag;
1.34      bouyer   1917:
1.223.4.2  yamt     1918:        error = ffs_getblk(mp->um_devvp,
                   1919:            fs->fs_sblockloc >> (fs->fs_fshift - fs->fs_fsbtodb), FFS_NOBLK,
                   1920:            fs->fs_sbsize, false, &bp);
                   1921:        if (error)
                   1922:                return error;
1.55      fvdl     1923:        saveflag = fs->fs_flags & FS_INTERNAL;
                   1924:        fs->fs_flags &= ~FS_INTERNAL;
1.161     perry    1925:
1.42      perry    1926:        memcpy(bp->b_data, fs, fs->fs_sbsize);
1.110     fvdl     1927:
                   1928:        ffs_oldfscompat_write((struct fs *)bp->b_data, mp);
1.34      bouyer   1929: #ifdef FFS_EI
                   1930:        if (mp->um_flags & UFS_NEEDSWAP)
1.123     enami    1931:                ffs_sb_swap((struct fs *)bp->b_data, (struct fs *)bp->b_data);
1.111     fvdl     1932: #endif
1.55      fvdl     1933:        fs->fs_flags |= saveflag;
1.34      bouyer   1934:
1.1       mycroft  1935:        if (waitfor == MNT_WAIT)
                   1936:                error = bwrite(bp);
                   1937:        else
                   1938:                bawrite(bp);
1.15      mycroft  1939:        return (error);
                   1940: }
                   1941:
                   1942: int
1.166     thorpej  1943: ffs_cgupdate(struct ufsmount *mp, int waitfor)
1.15      mycroft  1944: {
1.61      augustss 1945:        struct fs *fs = mp->um_fs;
                   1946:        struct buf *bp;
1.15      mycroft  1947:        int blks;
1.84      lukem    1948:        void *space;
1.15      mycroft  1949:        int i, size, error = 0, allerror = 0;
                   1950:
                   1951:        allerror = ffs_sbupdate(mp, waitfor);
1.1       mycroft  1952:        blks = howmany(fs->fs_cssize, fs->fs_fsize);
1.84      lukem    1953:        space = fs->fs_csp;
1.1       mycroft  1954:        for (i = 0; i < blks; i += fs->fs_frag) {
                   1955:                size = fs->fs_bsize;
                   1956:                if (i + fs->fs_frag > blks)
                   1957:                        size = (blks - i) * fs->fs_fsize;
1.223.4.2  yamt     1958:                error = ffs_getblk(mp->um_devvp, fsbtodb(fs, fs->fs_csaddr + i),
                   1959:                    FFS_NOBLK, size, false, &bp);
                   1960:                if (error)
                   1961:                        break;
1.34      bouyer   1962: #ifdef FFS_EI
                   1963:                if (mp->um_flags & UFS_NEEDSWAP)
                   1964:                        ffs_csum_swap((struct csum*)space,
1.38      kleink   1965:                            (struct csum*)bp->b_data, size);
1.34      bouyer   1966:                else
                   1967: #endif
1.42      perry    1968:                        memcpy(bp->b_data, space, (u_int)size);
1.84      lukem    1969:                space = (char *)space + size;
1.1       mycroft  1970:                if (waitfor == MNT_WAIT)
                   1971:                        error = bwrite(bp);
                   1972:                else
                   1973:                        bawrite(bp);
                   1974:        }
1.15      mycroft  1975:        if (!allerror && error)
                   1976:                allerror = error;
                   1977:        return (allerror);
1.1       mycroft  1978: }
1.170     thorpej  1979:
                   1980: int
                   1981: ffs_extattrctl(struct mount *mp, int cmd, struct vnode *vp,
1.211     pooka    1982:     int attrnamespace, const char *attrname)
1.170     thorpej  1983: {
                   1984: #ifdef UFS_EXTATTR
                   1985:        /*
                   1986:         * File-backed extended attributes are only supported on UFS1.
                   1987:         * UFS2 has native extended attributes.
                   1988:         */
                   1989:        if (VFSTOUFS(mp)->um_fstype == UFS1)
1.211     pooka    1990:                return (ufs_extattrctl(mp, cmd, vp, attrnamespace, attrname));
1.170     thorpej  1991: #endif
1.211     pooka    1992:        return (vfs_stdextattrctl(mp, cmd, vp, attrnamespace, attrname));
1.170     thorpej  1993: }
1.193     hannken  1994:
                   1995: int
                   1996: ffs_suspendctl(struct mount *mp, int cmd)
                   1997: {
                   1998:        int error;
                   1999:        struct lwp *l = curlwp;
                   2000:
                   2001:        switch (cmd) {
                   2002:        case SUSPEND_SUSPEND:
1.194     hannken  2003:                if ((error = fstrans_setstate(mp, FSTRANS_SUSPENDING)) != 0)
1.193     hannken  2004:                        return error;
1.211     pooka    2005:                error = ffs_sync(mp, MNT_WAIT, l->l_proc->p_cred);
1.193     hannken  2006:                if (error == 0)
1.194     hannken  2007:                        error = fstrans_setstate(mp, FSTRANS_SUSPENDED);
1.223.4.2  yamt     2008: #ifdef WAPBL
                   2009:                if (error == 0 && mp->mnt_wapbl)
                   2010:                        error = wapbl_flush(mp->mnt_wapbl, 1);
                   2011: #endif
1.193     hannken  2012:                if (error != 0) {
1.194     hannken  2013:                        (void) fstrans_setstate(mp, FSTRANS_NORMAL);
1.193     hannken  2014:                        return error;
                   2015:                }
                   2016:                return 0;
                   2017:
                   2018:        case SUSPEND_RESUME:
1.194     hannken  2019:                return fstrans_setstate(mp, FSTRANS_NORMAL);
1.193     hannken  2020:
                   2021:        default:
                   2022:                return EINVAL;
                   2023:        }
                   2024: }
1.223.4.2  yamt     2025:
                   2026: /*
                   2027:  * Synch vnode for a mounted file system.  This is called for foreign
                   2028:  * vnodes, i.e. non-ffs.
                   2029:  */
                   2030: static int
                   2031: ffs_vfs_fsync(vnode_t *vp, int flags)
                   2032: {
                   2033:        int error, passes, skipmeta, i, pflags;
                   2034:        buf_t *bp, *nbp;
                   2035: #ifdef WAPBL
                   2036:        struct mount *mp;
                   2037: #endif
                   2038:
                   2039:        KASSERT(vp->v_type == VBLK);
                   2040:        KASSERT(vp->v_specmountpoint != NULL);
                   2041:
                   2042:        /*
                   2043:         * Flush all dirty data associated with the vnode.
                   2044:         */
                   2045:        pflags = PGO_ALLPAGES | PGO_CLEANIT;
                   2046:        if ((flags & FSYNC_WAIT) != 0)
                   2047:                pflags |= PGO_SYNCIO;
                   2048:        mutex_enter(&vp->v_interlock);
                   2049:        error = VOP_PUTPAGES(vp, 0, 0, pflags);
                   2050:        if (error)
                   2051:                return error;
                   2052:
                   2053: #ifdef WAPBL
                   2054:        mp = vp->v_specmountpoint;
                   2055:        if (mp && mp->mnt_wapbl) {
                   2056:                /*
                   2057:                 * Don't bother writing out metadata if the syncer is
                   2058:                 * making the request.  We will let the sync vnode
                   2059:                 * write it out in a single burst through a call to
                   2060:                 * VFS_SYNC().
                   2061:                 */
                   2062:                if ((flags & (FSYNC_DATAONLY | FSYNC_LAZY | FSYNC_NOLOG)) != 0)
                   2063:                        return 0;
                   2064:
                   2065:                /*
                   2066:                 * Don't flush the log if the vnode being flushed
                   2067:                 * contains no dirty buffers that could be in the log.
                   2068:                 */
                   2069:                if (!LIST_EMPTY(&vp->v_dirtyblkhd)) {
                   2070:                        error = wapbl_flush(mp->mnt_wapbl, 0);
                   2071:                        if (error)
                   2072:                                return error;
                   2073:                }
                   2074:
                   2075:                if ((flags & FSYNC_WAIT) != 0) {
                   2076:                        mutex_enter(&vp->v_interlock);
                   2077:                        while (vp->v_numoutput)
                   2078:                                cv_wait(&vp->v_cv, &vp->v_interlock);
                   2079:                        mutex_exit(&vp->v_interlock);
                   2080:                }
                   2081:
                   2082:                return 0;
                   2083:        }
                   2084: #endif /* WAPBL */
                   2085:
                   2086:        /*
                   2087:         * Write out metadata for non-logging file systems. XXX This block
                   2088:         * should be simplified now that softdep is gone.
                   2089:         */
                   2090:        passes = NIADDR + 1;
                   2091:        skipmeta = 0;
                   2092:        if (flags & FSYNC_WAIT)
                   2093:                skipmeta = 1;
                   2094:
                   2095: loop:
                   2096:        mutex_enter(&bufcache_lock);
                   2097:        LIST_FOREACH(bp, &vp->v_dirtyblkhd, b_vnbufs) {
                   2098:                bp->b_cflags &= ~BC_SCANNED;
                   2099:        }
                   2100:        for (bp = LIST_FIRST(&vp->v_dirtyblkhd); bp; bp = nbp) {
                   2101:                nbp = LIST_NEXT(bp, b_vnbufs);
                   2102:                if (bp->b_cflags & (BC_BUSY | BC_SCANNED))
                   2103:                        continue;
                   2104:                if ((bp->b_oflags & BO_DELWRI) == 0)
                   2105:                        panic("ffs_fsync: not dirty");
                   2106:                if (skipmeta && bp->b_lblkno < 0)
                   2107:                        continue;
                   2108:                bp->b_cflags |= BC_BUSY | BC_VFLUSH | BC_SCANNED;
                   2109:                mutex_exit(&bufcache_lock);
                   2110:                /*
                   2111:                 * On our final pass through, do all I/O synchronously
                   2112:                 * so that we can find out if our flush is failing
                   2113:                 * because of write errors.
                   2114:                 */
                   2115:                if (passes > 0 || !(flags & FSYNC_WAIT))
                   2116:                        (void) bawrite(bp);
                   2117:                else if ((error = bwrite(bp)) != 0)
                   2118:                        return (error);
                   2119:                /*
                   2120:                 * Since we unlocked during the I/O, we need
                   2121:                 * to start from a known point.
                   2122:                 */
                   2123:                mutex_enter(&bufcache_lock);
                   2124:                nbp = LIST_FIRST(&vp->v_dirtyblkhd);
                   2125:        }
                   2126:        mutex_exit(&bufcache_lock);
                   2127:        if (skipmeta) {
                   2128:                skipmeta = 0;
                   2129:                goto loop;
                   2130:        }
                   2131:
                   2132:        if ((flags & FSYNC_WAIT) != 0) {
                   2133:                mutex_enter(&vp->v_interlock);
                   2134:                while (vp->v_numoutput) {
                   2135:                        cv_wait(&vp->v_cv, &vp->v_interlock);
                   2136:                }
                   2137:                mutex_exit(&vp->v_interlock);
                   2138:
                   2139:                if (!LIST_EMPTY(&vp->v_dirtyblkhd)) {
                   2140:                        /*
                   2141:                        * Block devices associated with filesystems may
                   2142:                        * have new I/O requests posted for them even if
                   2143:                        * the vnode is locked, so no amount of trying will
                   2144:                        * get them clean. Thus we give block devices a
                   2145:                        * good effort, then just give up. For all other file
                   2146:                        * types, go around and try again until it is clean.
                   2147:                        */
                   2148:                        if (passes > 0) {
                   2149:                                passes--;
                   2150:                                goto loop;
                   2151:                        }
                   2152: #ifdef DIAGNOSTIC
                   2153:                        if (vp->v_type != VBLK)
                   2154:                                vprint("ffs_fsync: dirty", vp);
                   2155: #endif
                   2156:                }
                   2157:        }
                   2158:
                   2159:        if (error == 0 && (flags & FSYNC_CACHE) != 0) {
                   2160:                (void)VOP_IOCTL(vp, DIOCCACHESYNC, &i, FWRITE,
                   2161:                    kauth_cred_get());
                   2162:        }
                   2163:
                   2164:        return error;
                   2165: }

CVSweb <webmaster@jp.NetBSD.org>