[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.239

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

CVSweb <webmaster@jp.NetBSD.org>