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

1.329   ! maxv        1: /*     $NetBSD: ffs_vfsops.c,v 1.328 2015/04/04 06:00:12 maxv Exp $    */
1.231     simonb      2:
                      3: /*-
1.245     ad          4:  * Copyright (c) 2008, 2009 The NetBSD Foundation, Inc.
1.231     simonb      5:  * All rights reserved.
                      6:  *
                      7:  * This code is derived from software contributed to The NetBSD Foundation
1.245     ad          8:  * by Wasabi Systems, Inc, and by Andrew Doran.
1.231     simonb      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.329   ! maxv       64: __KERNEL_RCSID(0, "$NetBSD: ffs_vfsops.c,v 1.328 2015/04/04 06:00:12 maxv 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.231     simonb     69: #include "opt_wapbl.h"
1.37      scottr     70: #endif
1.1       mycroft    71:
                     72: #include <sys/param.h>
                     73: #include <sys/systm.h>
                     74: #include <sys/namei.h>
                     75: #include <sys/proc.h>
                     76: #include <sys/kernel.h>
                     77: #include <sys/vnode.h>
                     78: #include <sys/socket.h>
                     79: #include <sys/mount.h>
                     80: #include <sys/buf.h>
1.23      thorpej    81: #include <sys/device.h>
1.270     christos   82: #include <sys/disk.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>
1.273     para       88: #include <sys/kmem.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.317     maxv      114: static int ffs_vfs_fsync(vnode_t *, int);
                    115: static int ffs_superblock_validate(struct fs *);
1.329   ! maxv      116: static int ffs_is_appleufs(struct vnode *, struct fs *);
1.242     ad        117:
1.325     hannken   118: static int ffs_init_vnode(struct ufsmount *, struct vnode *, ino_t);
                    119: static void ffs_deinit_vnode(struct ufsmount *, struct vnode *);
                    120:
1.230     rumble    121: static struct sysctllog *ffs_sysctl_log;
                    122:
1.276     elad      123: static kauth_listener_t ffs_snapshot_listener;
                    124:
1.59      jdolecek  125: /* how many times ffs_init() was called */
                    126: int ffs_initcount = 0;
                    127:
1.303     christos  128: #ifdef DEBUG_FFS_MOUNT
1.319     maxv      129: #define DPRINTF(_fmt, args...) printf("%s: " _fmt "\n", __func__, ##args)
1.303     christos  130: #else
1.319     maxv      131: #define DPRINTF(_fmt, args...) do {} while (/*CONSTCOND*/0)
1.303     christos  132: #endif
                    133:
1.105     matt      134: extern const struct vnodeopv_desc ffs_vnodeop_opv_desc;
                    135: extern const struct vnodeopv_desc ffs_specop_opv_desc;
                    136: extern const struct vnodeopv_desc ffs_fifoop_opv_desc;
1.32      thorpej   137:
1.79      jdolecek  138: const struct vnodeopv_desc * const ffs_vnodeopv_descs[] = {
1.32      thorpej   139:        &ffs_vnodeop_opv_desc,
                    140:        &ffs_specop_opv_desc,
                    141:        &ffs_fifoop_opv_desc,
                    142:        NULL,
                    143: };
                    144:
1.17      mycroft   145: struct vfsops ffs_vfsops = {
1.295     hannken   146:        .vfs_name = MOUNT_FFS,
                    147:        .vfs_min_mount_data = sizeof (struct ufs_args),
                    148:        .vfs_mount = ffs_mount,
                    149:        .vfs_start = ufs_start,
                    150:        .vfs_unmount = ffs_unmount,
                    151:        .vfs_root = ufs_root,
                    152:        .vfs_quotactl = ufs_quotactl,
                    153:        .vfs_statvfs = ffs_statvfs,
                    154:        .vfs_sync = ffs_sync,
1.298     hannken   155:        .vfs_vget = ufs_vget,
                    156:        .vfs_loadvnode = ffs_loadvnode,
1.325     hannken   157:        .vfs_newvnode = ffs_newvnode,
1.295     hannken   158:        .vfs_fhtovp = ffs_fhtovp,
                    159:        .vfs_vptofh = ffs_vptofh,
                    160:        .vfs_init = ffs_init,
                    161:        .vfs_reinit = ffs_reinit,
                    162:        .vfs_done = ffs_done,
                    163:        .vfs_mountroot = ffs_mountroot,
                    164:        .vfs_snapshot = ffs_snapshot,
                    165:        .vfs_extattrctl = ffs_extattrctl,
                    166:        .vfs_suspendctl = ffs_suspendctl,
                    167:        .vfs_renamelock_enter = genfs_renamelock_enter,
                    168:        .vfs_renamelock_exit = genfs_renamelock_exit,
                    169:        .vfs_fsync = ffs_vfs_fsync,
                    170:        .vfs_opv_descs = ffs_vnodeopv_descs
1.1       mycroft   171: };
                    172:
1.165     yamt      173: static const struct genfs_ops ffs_genfsops = {
                    174:        .gop_size = ffs_gop_size,
                    175:        .gop_alloc = ufs_gop_alloc,
1.238     hannken   176:        .gop_write = genfs_gop_write,
1.167     yamt      177:        .gop_markupdate = ufs_gop_markupdate,
1.87      chs       178: };
                    179:
1.175     yamt      180: static const struct ufs_ops ffs_ufsops = {
                    181:        .uo_itimes = ffs_itimes,
1.176     yamt      182:        .uo_update = ffs_update,
                    183:        .uo_truncate = ffs_truncate,
                    184:        .uo_balloc = ffs_balloc,
1.284     hannken   185:        .uo_snapgone = ffs_snapgone,
1.326     riastrad  186:        .uo_bufrd = ffs_bufrd,
                    187:        .uo_bufwr = ffs_bufwr,
1.175     yamt      188: };
                    189:
1.227     rumble    190: static int
1.276     elad      191: ffs_snapshot_cb(kauth_cred_t cred, kauth_action_t action, void *cookie,
                    192:     void *arg0, void *arg1, void *arg2, void *arg3)
                    193: {
                    194:        vnode_t *vp = arg2;
1.300     njoly     195:        int result = KAUTH_RESULT_DEFER;
1.276     elad      196:
                    197:        if (action != KAUTH_SYSTEM_FS_SNAPSHOT)
                    198:                return result;
                    199:
                    200:        if (VTOI(vp)->i_uid == kauth_cred_geteuid(cred))
                    201:                result = KAUTH_RESULT_ALLOW;
                    202:
                    203:        return result;
                    204: }
                    205:
                    206: static int
1.227     rumble    207: ffs_modcmd(modcmd_t cmd, void *arg)
                    208: {
1.230     rumble    209:        int error;
                    210:
                    211: #if 0
                    212:        extern int doasyncfree;
                    213: #endif
1.268     manu      214: #ifdef UFS_EXTATTR
                    215:        extern int ufs_extattr_autocreate;
                    216: #endif
1.230     rumble    217:        extern int ffs_log_changeopt;
1.227     rumble    218:
                    219:        switch (cmd) {
                    220:        case MODULE_CMD_INIT:
1.230     rumble    221:                error = vfs_attach(&ffs_vfsops);
                    222:                if (error != 0)
                    223:                        break;
                    224:
                    225:                sysctl_createv(&ffs_sysctl_log, 0, NULL, NULL,
                    226:                               CTLFLAG_PERMANENT,
                    227:                               CTLTYPE_NODE, "ffs",
                    228:                               SYSCTL_DESCR("Berkeley Fast File System"),
                    229:                               NULL, 0, NULL, 0,
                    230:                               CTL_VFS, 1, CTL_EOL);
                    231:                /*
                    232:                 * @@@ should we even bother with these first three?
                    233:                 */
                    234:                sysctl_createv(&ffs_sysctl_log, 0, NULL, NULL,
                    235:                               CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
                    236:                               CTLTYPE_INT, "doclusterread", NULL,
                    237:                               sysctl_notavail, 0, NULL, 0,
                    238:                               CTL_VFS, 1, FFS_CLUSTERREAD, CTL_EOL);
                    239:                sysctl_createv(&ffs_sysctl_log, 0, NULL, NULL,
                    240:                               CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
                    241:                               CTLTYPE_INT, "doclusterwrite", NULL,
                    242:                               sysctl_notavail, 0, NULL, 0,
                    243:                               CTL_VFS, 1, FFS_CLUSTERWRITE, CTL_EOL);
                    244:                sysctl_createv(&ffs_sysctl_log, 0, NULL, NULL,
                    245:                               CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
                    246:                               CTLTYPE_INT, "doreallocblks", NULL,
                    247:                               sysctl_notavail, 0, NULL, 0,
                    248:                               CTL_VFS, 1, FFS_REALLOCBLKS, CTL_EOL);
                    249: #if 0
                    250:                sysctl_createv(&ffs_sysctl_log, 0, NULL, NULL,
                    251:                               CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
                    252:                               CTLTYPE_INT, "doasyncfree",
                    253:                               SYSCTL_DESCR("Release dirty blocks asynchronously"),
                    254:                               NULL, 0, &doasyncfree, 0,
                    255:                               CTL_VFS, 1, FFS_ASYNCFREE, CTL_EOL);
                    256: #endif
                    257:                sysctl_createv(&ffs_sysctl_log, 0, NULL, NULL,
                    258:                               CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
                    259:                               CTLTYPE_INT, "log_changeopt",
                    260:                               SYSCTL_DESCR("Log changes in optimization strategy"),
                    261:                               NULL, 0, &ffs_log_changeopt, 0,
                    262:                               CTL_VFS, 1, FFS_LOG_CHANGEOPT, CTL_EOL);
1.268     manu      263: #ifdef UFS_EXTATTR
                    264:                sysctl_createv(&ffs_sysctl_log, 0, NULL, NULL,
                    265:                               CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
                    266:                               CTLTYPE_INT, "extattr_autocreate",
                    267:                               SYSCTL_DESCR("Size of attribute for "
                    268:                                            "backing file autocreation"),
                    269:                               NULL, 0, &ufs_extattr_autocreate, 0,
                    270:                               CTL_VFS, 1, FFS_EXTATTR_AUTOCREATE, CTL_EOL);
                    271:
                    272: #endif /* UFS_EXTATTR */
                    273:
1.276     elad      274:                ffs_snapshot_listener = kauth_listen_scope(KAUTH_SCOPE_SYSTEM,
                    275:                    ffs_snapshot_cb, NULL);
                    276:                if (ffs_snapshot_listener == NULL)
                    277:                        printf("ffs_modcmd: can't listen on system scope.\n");
                    278:
1.230     rumble    279:                break;
1.227     rumble    280:        case MODULE_CMD_FINI:
1.230     rumble    281:                error = vfs_detach(&ffs_vfsops);
                    282:                if (error != 0)
                    283:                        break;
                    284:                sysctl_teardown(&ffs_sysctl_log);
1.276     elad      285:                if (ffs_snapshot_listener != NULL)
                    286:                        kauth_unlisten_scope(ffs_snapshot_listener);
1.230     rumble    287:                break;
1.227     rumble    288:        default:
1.230     rumble    289:                error = ENOTTY;
                    290:                break;
1.227     rumble    291:        }
1.230     rumble    292:
                    293:        return (error);
1.227     rumble    294: }
                    295:
1.216     ad        296: pool_cache_t ffs_inode_cache;
                    297: pool_cache_t ffs_dinode1_cache;
                    298: pool_cache_t ffs_dinode2_cache;
1.110     fvdl      299:
1.146     simonb    300: static void ffs_oldfscompat_read(struct fs *, struct ufsmount *, daddr_t);
1.110     fvdl      301: static void ffs_oldfscompat_write(struct fs *, struct ufsmount *);
1.43      thorpej   302:
1.1       mycroft   303: /*
1.33      fvdl      304:  * Called by main() when ffs is going to be mounted as root.
1.1       mycroft   305:  */
                    306:
1.19      christos  307: int
1.166     thorpej   308: ffs_mountroot(void)
1.1       mycroft   309: {
1.33      fvdl      310:        struct fs *fs;
                    311:        struct mount *mp;
1.177     christos  312:        struct lwp *l = curlwp;                 /* XXX */
1.1       mycroft   313:        struct ufsmount *ump;
                    314:        int error;
1.23      thorpej   315:
1.180     thorpej   316:        if (device_class(root_device) != DV_DISK)
1.23      thorpej   317:                return (ENODEV);
                    318:
1.51      wrstuden  319:        if ((error = vfs_rootmountalloc(MOUNT_FFS, "root_device", &mp))) {
                    320:                vrele(rootvp);
1.33      fvdl      321:                return (error);
1.51      wrstuden  322:        }
1.231     simonb    323:
                    324:        /*
                    325:         * We always need to be able to mount the root file system.
                    326:         */
                    327:        mp->mnt_flag |= MNT_FORCE;
1.177     christos  328:        if ((error = ffs_mountfs(rootvp, mp, l)) != 0) {
1.225     ad        329:                vfs_unbusy(mp, false, NULL);
1.226     ad        330:                vfs_destroy(mp);
1.1       mycroft   331:                return (error);
                    332:        }
1.231     simonb    333:        mp->mnt_flag &= ~MNT_FORCE;
1.291     christos  334:        mountlist_append(mp);
1.1       mycroft   335:        ump = VFSTOUFS(mp);
                    336:        fs = ump->um_fs;
1.42      perry     337:        memset(fs->fs_fsmnt, 0, sizeof(fs->fs_fsmnt));
1.33      fvdl      338:        (void)copystr(mp->mnt_stat.f_mntonname, fs->fs_fsmnt, MNAMELEN - 1, 0);
1.211     pooka     339:        (void)ffs_statvfs(mp, &mp->mnt_stat);
1.225     ad        340:        vfs_unbusy(mp, false, NULL);
1.151     pk        341:        setrootfstime((time_t)fs->fs_time);
1.1       mycroft   342:        return (0);
                    343: }
                    344:
                    345: /*
                    346:  * VFS Operations.
                    347:  *
                    348:  * mount system call
                    349:  */
                    350: int
1.211     pooka     351: ffs_mount(struct mount *mp, const char *path, void *data, size_t *data_len)
1.1       mycroft   352: {
1.211     pooka     353:        struct lwp *l = curlwp;
1.243     ad        354:        struct vnode *devvp = NULL;
1.204     dsl       355:        struct ufs_args *args = data;
1.19      christos  356:        struct ufsmount *ump = NULL;
1.61      augustss  357:        struct fs *fs;
1.204     dsl       358:        int error = 0, flags, update;
1.9       mycroft   359:        mode_t accessmode;
1.1       mycroft   360:
1.303     christos  361:        if (args == NULL) {
1.319     maxv      362:                DPRINTF("NULL args");
1.297     maxv      363:                return EINVAL;
1.303     christos  364:        }
                    365:        if (*data_len < sizeof(*args)) {
1.319     maxv      366:                DPRINTF("bad size args %zu != %zu", *data_len, sizeof(*args));
1.204     dsl       367:                return EINVAL;
1.303     christos  368:        }
1.204     dsl       369:
1.102     christos  370:        if (mp->mnt_flag & MNT_GETARGS) {
                    371:                ump = VFSTOUFS(mp);
1.303     christos  372:                if (ump == NULL) {
1.319     maxv      373:                        DPRINTF("no ump");
1.102     christos  374:                        return EIO;
1.303     christos  375:                }
1.204     dsl       376:                args->fspec = NULL;
                    377:                *data_len = sizeof *args;
                    378:                return 0;
1.102     christos  379:        }
1.66      matt      380:
1.95      christos  381:        update = mp->mnt_flag & MNT_UPDATE;
                    382:
                    383:        /* Check arguments */
1.204     dsl       384:        if (args->fspec != NULL) {
1.95      christos  385:                /*
                    386:                 * Look up the name and verify that it's sane.
                    387:                 */
1.247     dholland  388:                error = namei_simple_user(args->fspec,
1.303     christos  389:                    NSM_FOLLOW_NOEMULROOT, &devvp);
                    390:                if (error != 0) {
1.319     maxv      391:                        DPRINTF("namei_simple_user returned %d", error);
1.303     christos  392:                        return error;
                    393:                }
1.95      christos  394:
                    395:                if (!update) {
                    396:                        /*
                    397:                         * Be sure this is a valid block device
                    398:                         */
1.303     christos  399:                        if (devvp->v_type != VBLK) {
1.319     maxv      400:                                DPRINTF("non block device %d", devvp->v_type);
1.95      christos  401:                                error = ENOTBLK;
1.303     christos  402:                        } else if (bdevsw_lookup(devvp->v_rdev) == NULL) {
1.319     maxv      403:                                DPRINTF("can't find block device 0x%jx",
                    404:                                    devvp->v_rdev);
1.95      christos  405:                                error = ENXIO;
1.303     christos  406:                        }
1.95      christos  407:                } else {
                    408:                        /*
                    409:                         * Be sure we're still naming the same device
                    410:                         * used for our initial mount
                    411:                         */
1.160     mycroft   412:                        ump = VFSTOUFS(mp);
1.186     jld       413:                        if (devvp != ump->um_devvp) {
1.303     christos  414:                                if (devvp->v_rdev != ump->um_devvp->v_rdev) {
1.319     maxv      415:                                        DPRINTF("wrong device 0x%jx != 0x%jx",
1.303     christos  416:                                            (uintmax_t)devvp->v_rdev,
1.319     maxv      417:                                            (uintmax_t)ump->um_devvp->v_rdev);
1.186     jld       418:                                        error = EINVAL;
1.303     christos  419:                                } else {
1.186     jld       420:                                        vrele(devvp);
                    421:                                        devvp = ump->um_devvp;
                    422:                                        vref(devvp);
                    423:                                }
                    424:                        }
1.95      christos  425:                }
1.160     mycroft   426:        } else {
                    427:                if (!update) {
                    428:                        /* New mounts must have a filename for the device */
1.319     maxv      429:                        DPRINTF("no filename for mount");
1.303     christos  430:                        return EINVAL;
1.160     mycroft   431:                } else {
                    432:                        /* Use the extant mount */
                    433:                        ump = VFSTOUFS(mp);
                    434:                        devvp = ump->um_devvp;
                    435:                        vref(devvp);
                    436:                }
1.95      christos  437:        }
1.218     ad        438:
                    439:        /*
1.95      christos  440:         * If mount by non-root, then verify that user has necessary
                    441:         * permissions on the device.
1.246     elad      442:         *
                    443:         * Permission to update a mount is checked higher, so here we presume
                    444:         * updating the mount is okay (for example, as far as securelevel goes)
                    445:         * which leaves us with the normal check.
                    446:         */
1.249     pooka     447:        if (error == 0) {
                    448:                accessmode = VREAD;
                    449:                if (update ?
                    450:                    (mp->mnt_iflag & IMNT_WANTRDWR) != 0 :
                    451:                    (mp->mnt_flag & MNT_RDONLY) == 0)
                    452:                        accessmode |= VWRITE;
                    453:                vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY);
1.276     elad      454:                error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_MOUNT,
                    455:                    KAUTH_REQ_SYSTEM_MOUNT_DEVICE, mp, devvp,
                    456:                    KAUTH_ARG(accessmode));
1.303     christos  457:                if (error) {
1.319     maxv      458:                        DPRINTF("kauth returned %d", error);
1.303     christos  459:                }
1.259     hannken   460:                VOP_UNLOCK(devvp);
1.249     pooka     461:        }
1.95      christos  462:
                    463:        if (error) {
                    464:                vrele(devvp);
                    465:                return (error);
                    466:        }
                    467:
1.231     simonb    468: #ifdef WAPBL
1.243     ad        469:        /* WAPBL can only be enabled on a r/w mount. */
1.231     simonb    470:        if ((mp->mnt_flag & MNT_RDONLY) && !(mp->mnt_iflag & IMNT_WANTRDWR)) {
                    471:                mp->mnt_flag &= ~MNT_LOG;
                    472:        }
                    473: #else /* !WAPBL */
                    474:        mp->mnt_flag &= ~MNT_LOG;
                    475: #endif /* !WAPBL */
                    476:
1.95      christos  477:        if (!update) {
1.164     christos  478:                int xflags;
1.159     mycroft   479:
                    480:                if (mp->mnt_flag & MNT_RDONLY)
1.164     christos  481:                        xflags = FREAD;
1.159     mycroft   482:                else
1.231     simonb    483:                        xflags = FREAD | FWRITE;
1.271     hannken   484:                vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY);
1.211     pooka     485:                error = VOP_OPEN(devvp, xflags, FSCRED);
1.271     hannken   486:                VOP_UNLOCK(devvp);
1.303     christos  487:                if (error) {
1.319     maxv      488:                        DPRINTF("VOP_OPEN returned %d", error);
1.159     mycroft   489:                        goto fail;
1.303     christos  490:                }
1.177     christos  491:                error = ffs_mountfs(devvp, mp, l);
1.95      christos  492:                if (error) {
1.319     maxv      493:                        DPRINTF("ffs_mountfs returned %d", error);
1.159     mycroft   494:                        vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY);
1.211     pooka     495:                        (void)VOP_CLOSE(devvp, xflags, NOCRED);
1.259     hannken   496:                        VOP_UNLOCK(devvp);
1.159     mycroft   497:                        goto fail;
1.95      christos  498:                }
                    499:
1.1       mycroft   500:                ump = VFSTOUFS(mp);
                    501:                fs = ump->um_fs;
1.95      christos  502:        } else {
                    503:                /*
1.96      christos  504:                 * Update the mount.
                    505:                 */
                    506:
                    507:                /*
                    508:                 * The initial mount got a reference on this
                    509:                 * device, so drop the one obtained via
                    510:                 * namei(), above.
1.95      christos  511:                 */
1.96      christos  512:                vrele(devvp);
                    513:
1.160     mycroft   514:                ump = VFSTOUFS(mp);
1.95      christos  515:                fs = ump->um_fs;
1.1       mycroft   516:                if (fs->fs_ronly == 0 && (mp->mnt_flag & MNT_RDONLY)) {
1.95      christos  517:                        /*
                    518:                         * Changing from r/w to r/o
                    519:                         */
1.1       mycroft   520:                        flags = WRITECLOSE;
                    521:                        if (mp->mnt_flag & MNT_FORCE)
                    522:                                flags |= FORCECLOSE;
1.243     ad        523:                        error = ffs_flushfiles(mp, flags, l);
1.231     simonb    524:                        if (error == 0)
                    525:                                error = UFS_WAPBL_BEGIN(mp);
1.15      mycroft   526:                        if (error == 0 &&
                    527:                            ffs_cgupdate(ump, MNT_WAIT) == 0 &&
                    528:                            fs->fs_clean & FS_WASCLEAN) {
1.65      fvdl      529:                                if (mp->mnt_flag & MNT_SOFTDEP)
                    530:                                        fs->fs_flags &= ~FS_DOSOFTDEP;
1.15      mycroft   531:                                fs->fs_clean = FS_ISCLEAN;
                    532:                                (void) ffs_sbupdate(ump, MNT_WAIT);
                    533:                        }
1.303     christos  534:                        if (error) {
1.319     maxv      535:                                DPRINTF("wapbl %d", error);
1.303     christos  536:                                return error;
                    537:                        }
                    538:                        UFS_WAPBL_END(mp);
1.231     simonb    539:                }
                    540:
                    541: #ifdef WAPBL
                    542:                if ((mp->mnt_flag & MNT_LOG) == 0) {
                    543:                        error = ffs_wapbl_stop(mp, mp->mnt_flag & MNT_FORCE);
1.303     christos  544:                        if (error) {
1.319     maxv      545:                                DPRINTF("ffs_wapbl_stop returned %d", error);
1.231     simonb    546:                                return error;
1.303     christos  547:                        }
1.231     simonb    548:                }
                    549: #endif /* WAPBL */
                    550:
                    551:                if (fs->fs_ronly == 0 && (mp->mnt_flag & MNT_RDONLY)) {
                    552:                        /*
                    553:                         * Finish change from r/w to r/o
                    554:                         */
1.15      mycroft   555:                        fs->fs_ronly = 1;
1.78      mycroft   556:                        fs->fs_fmod = 0;
1.1       mycroft   557:                }
1.65      fvdl      558:
1.15      mycroft   559:                if (mp->mnt_flag & MNT_RELOAD) {
1.184     ad        560:                        error = ffs_reload(mp, l->l_cred, l);
1.303     christos  561:                        if (error) {
1.319     maxv      562:                                DPRINTF("ffs_reload returned %d", error);
1.303     christos  563:                                return error;
                    564:                        }
1.15      mycroft   565:                }
1.95      christos  566:
1.124     dbj       567:                if (fs->fs_ronly && (mp->mnt_iflag & IMNT_WANTRDWR)) {
1.9       mycroft   568:                        /*
1.95      christos  569:                         * Changing from read-only to read/write
1.9       mycroft   570:                         */
1.264     bouyer    571: #ifndef QUOTA2
                    572:                        if (fs->fs_flags & FS_DOQUOTA2) {
                    573:                                ump->um_flags |= UFS_QUOTA2;
                    574:                                uprintf("%s: options QUOTA2 not enabled%s\n",
                    575:                                    mp->mnt_stat.f_mntonname,
                    576:                                    (mp->mnt_flag & MNT_FORCE) ? "" :
                    577:                                    ", not mounting");
1.319     maxv      578:                                DPRINTF("ffs_quota2 %d", EINVAL);
1.264     bouyer    579:                                return EINVAL;
                    580:                        }
                    581: #endif
1.1       mycroft   582:                        fs->fs_ronly = 0;
1.15      mycroft   583:                        fs->fs_clean <<= 1;
                    584:                        fs->fs_fmod = 1;
1.231     simonb    585: #ifdef WAPBL
                    586:                        if (fs->fs_flags & FS_DOWAPBL) {
1.305     christos  587:                                const char *nm = mp->mnt_stat.f_mntonname;
                    588:                                if (!mp->mnt_wapbl_replay) {
                    589:                                        printf("%s: log corrupted;"
                    590:                                            " replay cancelled\n", nm);
                    591:                                        return EFTYPE;
                    592:                                }
                    593:                                printf("%s: replaying log to disk\n", nm);
1.231     simonb    594:                                error = wapbl_replay_write(mp->mnt_wapbl_replay,
1.305     christos  595:                                    devvp);
1.231     simonb    596:                                if (error) {
1.319     maxv      597:                                        DPRINTF("%s: wapbl_replay_write %d",
                    598:                                            nm, error);
1.231     simonb    599:                                        return error;
                    600:                                }
                    601:                                wapbl_replay_stop(mp->mnt_wapbl_replay);
                    602:                                fs->fs_clean = FS_WASCLEAN;
                    603:                        }
                    604: #endif /* WAPBL */
1.149     hannken   605:                        if (fs->fs_snapinum[0] != 0)
                    606:                                ffs_snapshot_mount(mp);
1.9       mycroft   607:                }
1.231     simonb    608:
                    609: #ifdef WAPBL
                    610:                error = ffs_wapbl_start(mp);
1.303     christos  611:                if (error) {
1.319     maxv      612:                        DPRINTF("ffs_wapbl_start returned %d", error);
1.231     simonb    613:                        return error;
1.303     christos  614:                }
1.231     simonb    615: #endif /* WAPBL */
                    616:
1.264     bouyer    617: #ifdef QUOTA2
                    618:                if (!fs->fs_ronly) {
                    619:                        error = ffs_quota2_mount(mp);
                    620:                        if (error) {
1.319     maxv      621:                                DPRINTF("ffs_quota2_mount returned %d", error);
1.264     bouyer    622:                                return error;
                    623:                        }
                    624:                }
                    625: #endif
1.280     drochner  626:
                    627:                if ((mp->mnt_flag & MNT_DISCARD) && !(ump->um_discarddata))
                    628:                        ump->um_discarddata = ffs_discard_init(devvp, fs);
                    629:
1.204     dsl       630:                if (args->fspec == NULL)
1.248     christos  631:                        return 0;
1.1       mycroft   632:        }
                    633:
1.204     dsl       634:        error = set_statvfs_info(path, UIO_USERSPACE, args->fspec,
1.205     pooka     635:            UIO_USERSPACE, mp->mnt_op->vfs_name, mp, l);
1.114     christos  636:        if (error == 0)
                    637:                (void)strncpy(fs->fs_fsmnt, mp->mnt_stat.f_mntonname,
                    638:                    sizeof(fs->fs_fsmnt));
1.303     christos  639:        else {
1.319     maxv      640:            DPRINTF("set_statvfs_info returned %d", error);
1.303     christos  641:        }
1.243     ad        642:        fs->fs_flags &= ~FS_DOSOFTDEP;
1.15      mycroft   643:        if (fs->fs_fmod != 0) { /* XXX */
1.231     simonb    644:                int err;
                    645:
1.15      mycroft   646:                fs->fs_fmod = 0;
                    647:                if (fs->fs_clean & FS_WASCLEAN)
1.182     kardel    648:                        fs->fs_time = time_second;
1.89      fvdl      649:                else {
1.231     simonb    650:                        printf("%s: file system not clean (fs_clean=%#x); "
                    651:                            "please fsck(8)\n", mp->mnt_stat.f_mntfromname,
                    652:                            fs->fs_clean);
1.110     fvdl      653:                        printf("%s: lost blocks %" PRId64 " files %d\n",
1.89      fvdl      654:                            mp->mnt_stat.f_mntfromname, fs->fs_pendingblocks,
                    655:                            fs->fs_pendinginodes);
                    656:                }
1.231     simonb    657:                err = UFS_WAPBL_BEGIN(mp);
                    658:                if (err == 0) {
                    659:                        (void) ffs_cgupdate(ump, MNT_WAIT);
                    660:                        UFS_WAPBL_END(mp);
                    661:                }
1.15      mycroft   662:        }
1.243     ad        663:        if ((mp->mnt_flag & MNT_SOFTDEP) != 0) {
                    664:                printf("%s: `-o softdep' is no longer supported, "
                    665:                    "consider `-o log'\n", mp->mnt_stat.f_mntfromname);
                    666:                mp->mnt_flag &= ~MNT_SOFTDEP;
                    667:        }
                    668:
1.159     mycroft   669:        return (error);
                    670:
                    671: fail:
                    672:        vrele(devvp);
                    673:        return (error);
1.1       mycroft   674: }
                    675:
                    676: /*
                    677:  * Reload all incore data for a filesystem (used after running fsck on
                    678:  * the root filesystem and finding things to fix). The filesystem must
                    679:  * be mounted read-only.
                    680:  *
                    681:  * Things to do to update the mount:
                    682:  *     1) invalidate all cached meta-data.
                    683:  *     2) re-read superblock from disk.
                    684:  *     3) re-read summary information from disk.
                    685:  *     4) invalidate all inactive vnodes.
                    686:  *     5) invalidate all cached file data.
                    687:  *     6) re-read inode data for all active vnodes.
                    688:  */
1.19      christos  689: int
1.181     elad      690: ffs_reload(struct mount *mp, kauth_cred_t cred, struct lwp *l)
1.1       mycroft   691: {
1.293     hannken   692:        struct vnode *vp, *devvp;
1.1       mycroft   693:        struct inode *ip;
1.84      lukem     694:        void *space;
1.1       mycroft   695:        struct buf *bp;
1.18      cgd       696:        struct fs *fs, *newfs;
1.255     mlelstv   697:        int i, bsize, blks, error;
1.312     maxv      698:        int32_t *lp, fs_sbsize;
1.111     fvdl      699:        struct ufsmount *ump;
1.141     dbj       700:        daddr_t sblockloc;
1.293     hannken   701:        struct vnode_iterator *marker;
1.1       mycroft   702:
1.153     mycroft   703:        if ((mp->mnt_flag & MNT_RDONLY) == 0)
1.1       mycroft   704:                return (EINVAL);
1.111     fvdl      705:
1.153     mycroft   706:        ump = VFSTOUFS(mp);
1.311     maxv      707:
1.1       mycroft   708:        /*
                    709:         * Step 1: invalidate all cached meta-data.
                    710:         */
1.111     fvdl      711:        devvp = ump->um_devvp;
1.55      fvdl      712:        vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY);
1.177     christos  713:        error = vinvalbuf(devvp, 0, cred, l, 0, 0);
1.259     hannken   714:        VOP_UNLOCK(devvp);
1.55      fvdl      715:        if (error)
1.1       mycroft   716:                panic("ffs_reload: dirty1");
1.311     maxv      717:
1.1       mycroft   718:        /*
1.311     maxv      719:         * Step 2: re-read superblock from disk. XXX: We don't handle
1.312     maxv      720:         * possibility that superblock moved. Which implies that we don't
                    721:         * want its size to change either.
1.1       mycroft   722:         */
1.111     fvdl      723:        fs = ump->um_fs;
1.312     maxv      724:        fs_sbsize = fs->fs_sbsize;
                    725:        error = bread(devvp, fs->fs_sblockloc / DEV_BSIZE, fs_sbsize,
1.327     maxv      726:                      0, &bp);
1.311     maxv      727:        if (error)
1.1       mycroft   728:                return (error);
1.312     maxv      729:        newfs = kmem_alloc(fs_sbsize, KM_SLEEP);
                    730:        memcpy(newfs, bp->b_data, fs_sbsize);
1.311     maxv      731:
1.34      bouyer    732: #ifdef FFS_EI
1.111     fvdl      733:        if (ump->um_flags & UFS_NEEDSWAP) {
1.324     maxv      734:                ffs_sb_swap((struct fs *)bp->b_data, newfs);
                    735:                newfs->fs_flags |= FS_SWAPPED;
1.121     bouyer    736:        } else
1.34      bouyer    737: #endif
1.324     maxv      738:                newfs->fs_flags &= ~FS_SWAPPED;
1.310     maxv      739:
1.321     maxv      740:        brelse(bp, 0);
                    741:
1.324     maxv      742:        if ((newfs->fs_magic != FS_UFS1_MAGIC) &&
                    743:            (newfs->fs_magic != FS_UFS2_MAGIC)) {
1.312     maxv      744:                kmem_free(newfs, fs_sbsize);
1.1       mycroft   745:                return (EIO);           /* XXX needs translation */
                    746:        }
1.314     maxv      747:        if (!ffs_superblock_validate(newfs)) {
1.312     maxv      748:                kmem_free(newfs, fs_sbsize);
1.310     maxv      749:                return (EINVAL);
                    750:        }
                    751:
1.320     maxv      752:        /*
                    753:         * The current implementation doesn't handle the possibility that
                    754:         * these values may have changed.
                    755:         */
                    756:        if ((newfs->fs_sbsize != fs_sbsize) ||
                    757:            (newfs->fs_cssize != fs->fs_cssize) ||
                    758:            (newfs->fs_contigsumsize != fs->fs_contigsumsize) ||
                    759:            (newfs->fs_ncg != fs->fs_ncg)) {
                    760:                kmem_free(newfs, fs_sbsize);
                    761:                return (EINVAL);
                    762:        }
                    763:
1.141     dbj       764:        /* Store off old fs_sblockloc for fs_oldfscompat_read. */
                    765:        sblockloc = fs->fs_sblockloc;
1.161     perry     766:        /*
1.18      cgd       767:         * Copy pointer fields back into superblock before copying in   XXX
                    768:         * new superblock. These should really be in the ufsmount.      XXX
                    769:         * Note that important parameters (eg fs_ncg) are unchanged.
                    770:         */
1.84      lukem     771:        newfs->fs_csp = fs->fs_csp;
1.18      cgd       772:        newfs->fs_maxcluster = fs->fs_maxcluster;
1.85      lukem     773:        newfs->fs_contigdirs = fs->fs_contigdirs;
1.76      mycroft   774:        newfs->fs_ronly = fs->fs_ronly;
1.110     fvdl      775:        newfs->fs_active = fs->fs_active;
1.312     maxv      776:        memcpy(fs, newfs, (u_int)fs_sbsize);
                    777:        kmem_free(newfs, fs_sbsize);
1.103     dbj       778:
1.329   ! maxv      779:        /*
        !           780:         * Recheck for Apple UFS filesystem.
        !           781:         */
1.153     mycroft   782:        ump->um_flags &= ~UFS_ISAPPLEUFS;
1.329   ! maxv      783:        if (ffs_is_appleufs(devvp, fs)) {
        !           784: #ifdef APPLE_UFS
1.153     mycroft   785:                ump->um_flags |= UFS_ISAPPLEUFS;
1.103     dbj       786: #else
1.329   ! maxv      787:                DPRINTF("AppleUFS not supported");
        !           788:                return (EIO); /* XXX: really? */
1.103     dbj       789: #endif
1.329   ! maxv      790:        }
1.103     dbj       791:
1.153     mycroft   792:        if (UFS_MPISAPPLEUFS(ump)) {
1.103     dbj       793:                /* see comment about NeXT below */
1.153     mycroft   794:                ump->um_maxsymlinklen = APPLEUFS_MAXSYMLINKLEN;
                    795:                ump->um_dirblksiz = APPLEUFS_DIRBLKSIZ;
                    796:                mp->mnt_iflag |= IMNT_DTYPE;
                    797:        } else {
                    798:                ump->um_maxsymlinklen = fs->fs_maxsymlinklen;
1.283     dholland  799:                ump->um_dirblksiz = UFS_DIRBLKSIZ;
1.153     mycroft   800:                if (ump->um_maxsymlinklen > 0)
                    801:                        mp->mnt_iflag |= IMNT_DTYPE;
                    802:                else
                    803:                        mp->mnt_iflag &= ~IMNT_DTYPE;
1.103     dbj       804:        }
1.154     yamt      805:        ffs_oldfscompat_read(fs, ump, sblockloc);
1.243     ad        806:
1.209     ad        807:        mutex_enter(&ump->um_lock);
1.153     mycroft   808:        ump->um_maxfilesize = fs->fs_maxfilesize;
1.231     simonb    809:        if (fs->fs_flags & ~(FS_KNOWN_FLAGS | FS_INTERNAL)) {
                    810:                uprintf("%s: unknown ufs flags: 0x%08"PRIx32"%s\n",
                    811:                    mp->mnt_stat.f_mntonname, fs->fs_flags,
                    812:                    (mp->mnt_flag & MNT_FORCE) ? "" : ", not mounting");
                    813:                if ((mp->mnt_flag & MNT_FORCE) == 0) {
                    814:                        mutex_exit(&ump->um_lock);
                    815:                        return (EINVAL);
                    816:                }
                    817:        }
1.89      fvdl      818:        if (fs->fs_pendingblocks != 0 || fs->fs_pendinginodes != 0) {
                    819:                fs->fs_pendingblocks = 0;
                    820:                fs->fs_pendinginodes = 0;
                    821:        }
1.209     ad        822:        mutex_exit(&ump->um_lock);
1.85      lukem     823:
1.211     pooka     824:        ffs_statvfs(mp, &mp->mnt_stat);
1.1       mycroft   825:        /*
                    826:         * Step 3: re-read summary information from disk.
                    827:         */
                    828:        blks = howmany(fs->fs_cssize, fs->fs_fsize);
1.84      lukem     829:        space = fs->fs_csp;
1.1       mycroft   830:        for (i = 0; i < blks; i += fs->fs_frag) {
1.255     mlelstv   831:                bsize = fs->fs_bsize;
1.1       mycroft   832:                if (i + fs->fs_frag > blks)
1.255     mlelstv   833:                        bsize = (blks - i) * fs->fs_fsize;
1.285     dholland  834:                error = bread(devvp, FFS_FSBTODB(fs, fs->fs_csaddr + i), bsize,
1.327     maxv      835:                              0, &bp);
1.47      bouyer    836:                if (error) {
1.1       mycroft   837:                        return (error);
1.47      bouyer    838:                }
1.34      bouyer    839: #ifdef FFS_EI
1.55      fvdl      840:                if (UFS_FSNEEDSWAP(fs))
1.84      lukem     841:                        ffs_csum_swap((struct csum *)bp->b_data,
1.255     mlelstv   842:                            (struct csum *)space, bsize);
1.34      bouyer    843:                else
                    844: #endif
1.255     mlelstv   845:                        memcpy(space, bp->b_data, (size_t)bsize);
                    846:                space = (char *)space + bsize;
1.209     ad        847:                brelse(bp, 0);
1.1       mycroft   848:        }
1.18      cgd       849:        /*
                    850:         * We no longer know anything about clusters per cylinder group.
                    851:         */
                    852:        if (fs->fs_contigsumsize > 0) {
                    853:                lp = fs->fs_maxcluster;
                    854:                for (i = 0; i < fs->fs_ncg; i++)
                    855:                        *lp++ = fs->fs_contigsumsize;
                    856:        }
                    857:
1.293     hannken   858:        vfs_vnode_iterator_init(mp, &marker);
1.299     christos  859:        while ((vp = vfs_vnode_iterator_next(marker, NULL, NULL))) {
1.1       mycroft   860:                /*
                    861:                 * Step 4: invalidate all inactive vnodes.
                    862:                 */
1.293     hannken   863:                if (vrecycle(vp))
                    864:                        continue;
1.1       mycroft   865:                /*
                    866:                 * Step 5: invalidate all cached file data.
                    867:                 */
1.293     hannken   868:                if (vn_lock(vp, LK_EXCLUSIVE)) {
                    869:                        vrele(vp);
                    870:                        continue;
1.214     ad        871:                }
1.177     christos  872:                if (vinvalbuf(vp, 0, cred, l, 0, 0))
1.1       mycroft   873:                        panic("ffs_reload: dirty2");
                    874:                /*
                    875:                 * Step 6: re-read inode data for all active vnodes.
                    876:                 */
                    877:                ip = VTOI(vp);
1.285     dholland  878:                error = bread(devvp, FFS_FSBTODB(fs, ino_to_fsba(fs, ip->i_number)),
1.327     maxv      879:                              (int)fs->fs_bsize, 0, &bp);
1.19      christos  880:                if (error) {
1.1       mycroft   881:                        vput(vp);
1.214     ad        882:                        break;
1.1       mycroft   883:                }
1.110     fvdl      884:                ffs_load_inode(bp, ip, fs, ip->i_number);
1.209     ad        885:                brelse(bp, 0);
1.1       mycroft   886:                vput(vp);
                    887:        }
1.293     hannken   888:        vfs_vnode_iterator_destroy(marker);
1.214     ad        889:        return (error);
1.1       mycroft   890: }
                    891:
                    892: /*
1.110     fvdl      893:  * Possible superblock locations ordered from most to least likely.
                    894:  */
1.135     jdolecek  895: static const int sblock_try[] = SBLOCKSEARCH;
1.110     fvdl      896:
1.307     maxv      897:
                    898: static int
1.314     maxv      899: ffs_superblock_validate(struct fs *fs)
1.307     maxv      900: {
1.318     maxv      901:        int32_t i, fs_bshift = 0, fs_fshift = 0, fs_fragshift = 0, fs_frag;
1.322     maxv      902:        int32_t fs_inopb;
1.315     maxv      903:
1.307     maxv      904:        /* Check the superblock size */
1.314     maxv      905:        if (fs->fs_sbsize > SBLOCKSIZE || fs->fs_sbsize < sizeof(struct fs))
1.307     maxv      906:                return 0;
                    907:
                    908:        /* Check the file system blocksize */
1.314     maxv      909:        if (fs->fs_bsize > MAXBSIZE || fs->fs_bsize < MINBSIZE)
1.308     maxv      910:                return 0;
1.314     maxv      911:        if (!powerof2(fs->fs_bsize))
1.308     maxv      912:                return 0;
                    913:
                    914:        /* Check the size of frag blocks */
                    915:        if (!powerof2(fs->fs_fsize))
1.307     maxv      916:                return 0;
1.318     maxv      917:        if (fs->fs_fsize == 0)
                    918:                return 0;
1.307     maxv      919:
1.323     maxv      920:        /*
                    921:         * XXX: these values are just zero-checked to prevent obvious
                    922:         * bugs. We need more strict checks.
                    923:         */
1.307     maxv      924:        if (fs->fs_size == 0)
                    925:                return 0;
1.309     maxv      926:        if (fs->fs_cssize == 0)
                    927:                return 0;
1.323     maxv      928:        if (fs->fs_ipg == 0)
                    929:                return 0;
                    930:        if (fs->fs_fpg == 0)
                    931:                return 0;
1.328     maxv      932:        if (fs->fs_ncg == 0)
                    933:                return 0;
                    934:        if (fs->fs_maxbpg == 0)
                    935:                return 0;
1.307     maxv      936:
1.322     maxv      937:        /* Check the number of inodes per block */
                    938:        if (fs->fs_magic == FS_UFS1_MAGIC)
                    939:                fs_inopb = fs->fs_bsize / sizeof(struct ufs1_dinode);
                    940:        else /* fs->fs_magic == FS_UFS2_MAGIC */
                    941:                fs_inopb = fs->fs_bsize / sizeof(struct ufs2_dinode);
                    942:        if (fs->fs_inopb != fs_inopb)
                    943:                return 0;
                    944:
1.308     maxv      945:        /* Block size cannot be smaller than fragment size */
1.314     maxv      946:        if (fs->fs_bsize < fs->fs_fsize)
1.308     maxv      947:                return 0;
                    948:
1.315     maxv      949:        /* Compute fs_bshift and ensure it is consistent */
                    950:        for (i = fs->fs_bsize; i > 1; i >>= 1)
                    951:                fs_bshift++;
                    952:        if (fs->fs_bshift != fs_bshift)
                    953:                return 0;
                    954:
                    955:        /* Compute fs_fshift and ensure it is consistent */
                    956:        for (i = fs->fs_fsize; i > 1; i >>= 1)
                    957:                fs_fshift++;
                    958:        if (fs->fs_fshift != fs_fshift)
                    959:                return 0;
                    960:
1.318     maxv      961:        /* Compute fs_fragshift and ensure it is consistent */
                    962:        for (i = fs->fs_frag; i > 1; i >>= 1)
                    963:                fs_fragshift++;
                    964:        if (fs->fs_fragshift != fs_fragshift)
                    965:                return 0;
                    966:
                    967:        /* Check the masks */
                    968:        if (fs->fs_bmask != ~(fs->fs_bsize - 1))
                    969:                return 0;
                    970:        if (fs->fs_fmask != ~(fs->fs_fsize - 1))
                    971:                return 0;
                    972:
                    973:        /*
                    974:         * Now that the shifts and masks are sanitized, we can use the ffs_ API.
                    975:         */
1.315     maxv      976:
1.313     maxv      977:        /* Check the number of frag blocks */
1.316     maxv      978:        if ((fs_frag = ffs_numfrags(fs, fs->fs_bsize)) > MAXFRAG)
                    979:                return 0;
                    980:        if (fs->fs_frag != fs_frag)
1.313     maxv      981:                return 0;
                    982:
1.307     maxv      983:        return 1;
                    984: }
                    985:
1.329   ! maxv      986: static int
        !           987: ffs_is_appleufs(struct vnode *devvp, struct fs *fs)
        !           988: {
        !           989:        struct dkwedge_info dkw;
        !           990:        int ret = 0;
        !           991:
        !           992:        /*
        !           993:         * First check to see if this is tagged as an Apple UFS filesystem
        !           994:         * in the disklabel.
        !           995:         */
        !           996:        if (getdiskinfo(devvp, &dkw) == 0 &&
        !           997:            strcmp(dkw.dkw_ptype, DKW_PTYPE_APPLEUFS) == 0)
        !           998:                ret = 1;
        !           999: #ifdef APPLE_UFS
        !          1000:        else {
        !          1001:                struct appleufslabel *applefs;
        !          1002:                struct buf *bp;
        !          1003:                daddr_t blkno = APPLEUFS_LABEL_OFFSET / DEV_BSIZE;
        !          1004:                int error;
        !          1005:
        !          1006:                /*
        !          1007:                 * Manually look for an Apple UFS label, and if a valid one
        !          1008:                 * is found, then treat it like an Apple UFS filesystem anyway.
        !          1009:                 */
        !          1010:                error = bread(devvp, blkno, APPLEUFS_LABEL_SIZE, 0, &bp);
        !          1011:                if (error) {
        !          1012:                        DPRINTF("bread@0x%jx returned %d", (intmax_t)blkno, error);
        !          1013:                        return 0;
        !          1014:                }
        !          1015:                applefs = (struct appleufslabel *)bp->b_data;
        !          1016:                error = ffs_appleufs_validate(fs->fs_fsmnt, applefs, NULL);
        !          1017:                if (error == 0)
        !          1018:                        ret = 1;
        !          1019:                brelse(bp, 0);
        !          1020:        }
        !          1021: #endif
        !          1022:
        !          1023:        return ret;
        !          1024: }
        !          1025:
1.110     fvdl     1026: /*
1.1       mycroft  1027:  * Common code for mount and mountroot
                   1028:  */
                   1029: int
1.177     christos 1030: ffs_mountfs(struct vnode *devvp, struct mount *mp, struct lwp *l)
1.1       mycroft  1031: {
1.306     maxv     1032:        struct ufsmount *ump = NULL;
                   1033:        struct buf *bp = NULL;
                   1034:        struct fs *fs = NULL;
1.9       mycroft  1035:        dev_t dev;
1.84      lukem    1036:        void *space;
1.306     maxv     1037:        daddr_t sblockloc = 0;
                   1038:        int blks, fstype = 0;
1.255     mlelstv  1039:        int error, i, bsize, ronly, bset = 0;
1.52      drochner 1040: #ifdef FFS_EI
1.110     fvdl     1041:        int needswap = 0;               /* keep gcc happy */
1.52      drochner 1042: #endif
1.9       mycroft  1043:        int32_t *lp;
1.181     elad     1044:        kauth_cred_t cred;
1.319     maxv     1045:        u_int32_t allocsbsize, fs_sbsize = 0;
1.1       mycroft  1046:
1.9       mycroft  1047:        dev = devvp->v_rdev;
1.184     ad       1048:        cred = l ? l->l_cred : NOCRED;
1.159     mycroft  1049:
                   1050:        /* Flush out any old buffers remaining from a previous use. */
1.55      fvdl     1051:        vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY);
1.177     christos 1052:        error = vinvalbuf(devvp, V_SAVE, cred, l, 0, 0);
1.259     hannken  1053:        VOP_UNLOCK(devvp);
1.303     christos 1054:        if (error) {
1.319     maxv     1055:                DPRINTF("vinvalbuf returned %d", error);
1.303     christos 1056:                return error;
                   1057:        }
1.1       mycroft  1058:
                   1059:        ronly = (mp->mnt_flag & MNT_RDONLY) != 0;
                   1060:
1.214     ad       1061:        error = fstrans_mount(mp);
1.303     christos 1062:        if (error) {
1.319     maxv     1063:                DPRINTF("fstrans_mount returned %d", error);
1.214     ad       1064:                return error;
1.303     christos 1065:        }
1.214     ad       1066:
1.274     rmind    1067:        ump = kmem_zalloc(sizeof(*ump), KM_SLEEP);
1.231     simonb   1068:        mutex_init(&ump->um_lock, MUTEX_DEFAULT, IPL_NONE);
                   1069:        error = ffs_snapshot_init(ump);
1.303     christos 1070:        if (error) {
1.319     maxv     1071:                DPRINTF("ffs_snapshot_init returned %d", error);
1.231     simonb   1072:                goto out;
1.303     christos 1073:        }
1.231     simonb   1074:        ump->um_ops = &ffs_ufsops;
                   1075:
                   1076: #ifdef WAPBL
                   1077:  sbagain:
                   1078: #endif
1.110     fvdl     1079:        /*
1.192     isaki    1080:         * Try reading the superblock in each of its possible locations.
                   1081:         */
1.138     dsl      1082:        for (i = 0; ; i++) {
1.319     maxv     1083:                daddr_t fs_sblockloc;
1.306     maxv     1084:
1.138     dsl      1085:                if (bp != NULL) {
1.209     ad       1086:                        brelse(bp, BC_NOCACHE);
1.138     dsl      1087:                        bp = NULL;
                   1088:                }
                   1089:                if (sblock_try[i] == -1) {
1.319     maxv     1090:                        DPRINTF("no superblock found");
1.138     dsl      1091:                        error = EINVAL;
                   1092:                        fs = NULL;
                   1093:                        goto out;
                   1094:                }
1.306     maxv     1095:
1.303     christos 1096:                error = bread(devvp, sblock_try[i] / DEV_BSIZE, SBLOCKSIZE,
1.327     maxv     1097:                    0, &bp);
1.168     drochner 1098:                if (error) {
1.319     maxv     1099:                        DPRINTF("bread@0x%x returned %d",
                   1100:                            sblock_try[i] / DEV_BSIZE, error);
1.168     drochner 1101:                        fs = NULL;
1.110     fvdl     1102:                        goto out;
1.168     drochner 1103:                }
1.319     maxv     1104:                fs = (struct fs *)bp->b_data;
1.306     maxv     1105:
1.319     maxv     1106:                sblockloc = sblock_try[i];
                   1107:                DPRINTF("fs_magic 0x%x", fs->fs_magic);
1.314     maxv     1108:
                   1109:                /*
                   1110:                 * Swap: here, we swap fs->fs_sbsize in order to get the correct
                   1111:                 * size to read the superblock. Once read, we swap the whole
                   1112:                 * superblock structure.
                   1113:                 */
1.110     fvdl     1114:                if (fs->fs_magic == FS_UFS1_MAGIC) {
1.306     maxv     1115:                        fs_sbsize = fs->fs_sbsize;
1.110     fvdl     1116:                        fstype = UFS1;
1.34      bouyer   1117: #ifdef FFS_EI
1.110     fvdl     1118:                        needswap = 0;
1.275     nonaka   1119:                } else if (fs->fs_magic == FS_UFS1_MAGIC_SWAPPED) {
1.306     maxv     1120:                        fs_sbsize = bswap32(fs->fs_sbsize);
1.110     fvdl     1121:                        fstype = UFS1;
                   1122:                        needswap = 1;
1.34      bouyer   1123: #endif
1.110     fvdl     1124:                } else if (fs->fs_magic == FS_UFS2_MAGIC) {
1.306     maxv     1125:                        fs_sbsize = fs->fs_sbsize;
1.110     fvdl     1126:                        fstype = UFS2;
                   1127: #ifdef FFS_EI
                   1128:                        needswap = 0;
1.275     nonaka   1129:                } else if (fs->fs_magic == FS_UFS2_MAGIC_SWAPPED) {
1.306     maxv     1130:                        fs_sbsize = bswap32(fs->fs_sbsize);
1.110     fvdl     1131:                        fstype = UFS2;
                   1132:                        needswap = 1;
                   1133: #endif
1.112     fvdl     1134:                } else
1.138     dsl      1135:                        continue;
                   1136:
                   1137:                /* fs->fs_sblockloc isn't defined for old filesystems */
1.140     dsl      1138:                if (fstype == UFS1 && !(fs->fs_old_flags & FS_FLAGS_UPDATED)) {
                   1139:                        if (sblockloc == SBLOCK_UFS2)
1.138     dsl      1140:                                /*
                   1141:                                 * This is likely to be the first alternate
                   1142:                                 * in a filesystem with 64k blocks.
                   1143:                                 * Don't use it.
                   1144:                                 */
                   1145:                                continue;
1.319     maxv     1146:                        fs_sblockloc = sblockloc;
1.138     dsl      1147:                } else {
1.319     maxv     1148:                        fs_sblockloc = fs->fs_sblockloc;
1.138     dsl      1149: #ifdef FFS_EI
                   1150:                        if (needswap)
1.319     maxv     1151:                                fs_sblockloc = bswap64(fs_sblockloc);
1.138     dsl      1152: #endif
                   1153:                }
1.110     fvdl     1154:
1.138     dsl      1155:                /* Check we haven't found an alternate superblock */
1.319     maxv     1156:                if (fs_sblockloc != sblockloc)
1.138     dsl      1157:                        continue;
1.112     fvdl     1158:
1.314     maxv     1159:                /* Check the superblock size */
                   1160:                if (fs_sbsize > SBLOCKSIZE || fs_sbsize < sizeof(struct fs))
1.138     dsl      1161:                        continue;
1.314     maxv     1162:                fs = kmem_alloc((u_long)fs_sbsize, KM_SLEEP);
                   1163:                memcpy(fs, bp->b_data, fs_sbsize);
                   1164:
                   1165:                /* Swap the whole superblock structure, if necessary. */
                   1166: #ifdef FFS_EI
                   1167:                if (needswap) {
                   1168:                        ffs_sb_swap((struct fs*)bp->b_data, fs);
                   1169:                        fs->fs_flags |= FS_SWAPPED;
                   1170:                } else
                   1171: #endif
                   1172:                        fs->fs_flags &= ~FS_SWAPPED;
                   1173:
                   1174:                /*
                   1175:                 * Now that everything is swapped, the superblock is ready to
                   1176:                 * be sanitized.
                   1177:                 */
                   1178:                if (!ffs_superblock_validate(fs)) {
                   1179:                        kmem_free(fs, fs_sbsize);
                   1180:                        continue;
                   1181:                }
1.110     fvdl     1182:
1.138     dsl      1183:                /* Ok seems to be a good superblock */
                   1184:                break;
1.34      bouyer   1185:        }
                   1186:
1.111     fvdl     1187:        ump->um_fs = fs;
                   1188:
1.231     simonb   1189: #ifdef WAPBL
                   1190:        if ((mp->mnt_wapbl_replay == 0) && (fs->fs_flags & FS_DOWAPBL)) {
                   1191:                error = ffs_wapbl_replay_start(mp, fs, devvp);
1.303     christos 1192:                if (error && (mp->mnt_flag & MNT_FORCE) == 0) {
1.319     maxv     1193:                        DPRINTF("ffs_wapbl_replay_start returned %d", error);
1.231     simonb   1194:                        goto out;
1.303     christos 1195:                }
1.252     bouyer   1196:                if (!error) {
                   1197:                        if (!ronly) {
                   1198:                                /* XXX fsmnt may be stale. */
                   1199:                                printf("%s: replaying log to disk\n",
                   1200:                                    fs->fs_fsmnt);
                   1201:                                error = wapbl_replay_write(mp->mnt_wapbl_replay,
                   1202:                                    devvp);
1.303     christos 1203:                                if (error) {
1.319     maxv     1204:                                        DPRINTF("wapbl_replay_write returned %d",
                   1205:                                            error);
1.252     bouyer   1206:                                        goto out;
1.303     christos 1207:                                }
1.252     bouyer   1208:                                wapbl_replay_stop(mp->mnt_wapbl_replay);
                   1209:                                fs->fs_clean = FS_WASCLEAN;
                   1210:                        } else {
                   1211:                                /* XXX fsmnt may be stale */
                   1212:                                printf("%s: replaying log to memory\n",
                   1213:                                    fs->fs_fsmnt);
                   1214:                        }
1.231     simonb   1215:
1.252     bouyer   1216:                        /* Force a re-read of the superblock */
                   1217:                        brelse(bp, BC_INVAL);
                   1218:                        bp = NULL;
1.306     maxv     1219:                        kmem_free(fs, fs_sbsize);
1.252     bouyer   1220:                        fs = NULL;
                   1221:                        goto sbagain;
1.231     simonb   1222:                }
                   1223:        }
                   1224: #else /* !WAPBL */
                   1225:        if ((fs->fs_flags & FS_DOWAPBL) && (mp->mnt_flag & MNT_FORCE) == 0) {
                   1226:                error = EPERM;
1.319     maxv     1227:                DPRINTF("no force %d", error);
1.231     simonb   1228:                goto out;
                   1229:        }
                   1230: #endif /* !WAPBL */
                   1231:
1.154     yamt     1232:        ffs_oldfscompat_read(fs, ump, sblockloc);
1.153     mycroft  1233:        ump->um_maxfilesize = fs->fs_maxfilesize;
1.131     dbj      1234:
1.231     simonb   1235:        if (fs->fs_flags & ~(FS_KNOWN_FLAGS | FS_INTERNAL)) {
                   1236:                uprintf("%s: unknown ufs flags: 0x%08"PRIx32"%s\n",
                   1237:                    mp->mnt_stat.f_mntonname, fs->fs_flags,
                   1238:                    (mp->mnt_flag & MNT_FORCE) ? "" : ", not mounting");
                   1239:                if ((mp->mnt_flag & MNT_FORCE) == 0) {
                   1240:                        error = EINVAL;
1.319     maxv     1241:                        DPRINTF("no force %d", error);
1.231     simonb   1242:                        goto out;
                   1243:                }
                   1244:        }
                   1245:
1.89      fvdl     1246:        if (fs->fs_pendingblocks != 0 || fs->fs_pendinginodes != 0) {
                   1247:                fs->fs_pendingblocks = 0;
                   1248:                fs->fs_pendinginodes = 0;
                   1249:        }
1.56      drochner 1250:
1.110     fvdl     1251:        ump->um_fstype = fstype;
                   1252:        if (fs->fs_sbsize < SBLOCKSIZE)
1.209     ad       1253:                brelse(bp, BC_INVAL);
                   1254:        else
                   1255:                brelse(bp, 0);
1.1       mycroft  1256:        bp = NULL;
1.94      chs      1257:
1.329   ! maxv     1258:        if (ffs_is_appleufs(devvp, fs)) {
        !          1259: #ifdef APPLE_UFS
1.103     dbj      1260:                ump->um_flags |= UFS_ISAPPLEUFS;
                   1261: #else
1.319     maxv     1262:                DPRINTF("AppleUFS not supported");
1.103     dbj      1263:                error = EINVAL;
                   1264:                goto out;
1.329   ! maxv     1265: #endif
1.103     dbj      1266:        }
                   1267:
1.231     simonb   1268: #if 0
                   1269: /*
                   1270:  * XXX This code changes the behaviour of mounting dirty filesystems, to
                   1271:  * XXX require "mount -f ..." to mount them.  This doesn't match what
                   1272:  * XXX mount(8) describes and is disabled for now.
                   1273:  */
                   1274:        /*
                   1275:         * If the file system is not clean, don't allow it to be mounted
                   1276:         * unless MNT_FORCE is specified.  (Note: MNT_FORCE is always set
                   1277:         * for the root file system.)
                   1278:         */
                   1279:        if (fs->fs_flags & FS_DOWAPBL) {
                   1280:                /*
                   1281:                 * wapbl normally expects to be FS_WASCLEAN when the FS_DOWAPBL
                   1282:                 * bit is set, although there's a window in unmount where it
                   1283:                 * could be FS_ISCLEAN
                   1284:                 */
                   1285:                if ((mp->mnt_flag & MNT_FORCE) == 0 &&
                   1286:                    (fs->fs_clean & (FS_WASCLEAN | FS_ISCLEAN)) == 0) {
                   1287:                        error = EPERM;
                   1288:                        goto out;
                   1289:                }
                   1290:        } else
                   1291:                if ((fs->fs_clean & FS_ISCLEAN) == 0 &&
                   1292:                    (mp->mnt_flag & MNT_FORCE) == 0) {
                   1293:                        error = EPERM;
                   1294:                        goto out;
                   1295:                }
                   1296: #endif
                   1297:
1.94      chs      1298:        /*
1.306     maxv     1299:         * Verify that we can access the last block in the fs
1.99      chs      1300:         * if we're mounting read/write.
1.94      chs      1301:         */
1.99      chs      1302:        if (!ronly) {
1.296     christos 1303:                error = bread(devvp, FFS_FSBTODB(fs, fs->fs_size - 1),
1.327     maxv     1304:                    fs->fs_fsize, 0, &bp);
1.209     ad       1305:                if (error) {
1.319     maxv     1306:                        DPRINTF("bread@0x%jx returned %d",
1.303     christos 1307:                            (intmax_t)FFS_FSBTODB(fs, fs->fs_size - 1),
1.319     maxv     1308:                            error);
1.209     ad       1309:                        bset = BC_INVAL;
1.99      chs      1310:                        goto out;
1.209     ad       1311:                }
1.303     christos 1312:                if (bp->b_bcount != fs->fs_fsize) {
1.319     maxv     1313:                        DPRINTF("bcount %x != fsize %x", bp->b_bcount,
                   1314:                            fs->fs_fsize);
1.296     christos 1315:                        error = EINVAL;
1.303     christos 1316:                }
1.209     ad       1317:                brelse(bp, BC_INVAL);
1.99      chs      1318:                bp = NULL;
                   1319:        }
1.94      chs      1320:
1.1       mycroft  1321:        fs->fs_ronly = ronly;
1.231     simonb   1322:        /* Don't bump fs_clean if we're replaying journal */
1.306     maxv     1323:        if (!((fs->fs_flags & FS_DOWAPBL) && (fs->fs_clean & FS_WASCLEAN))) {
1.231     simonb   1324:                if (ronly == 0) {
                   1325:                        fs->fs_clean <<= 1;
                   1326:                        fs->fs_fmod = 1;
                   1327:                }
1.306     maxv     1328:        }
                   1329:
1.255     mlelstv  1330:        bsize = fs->fs_cssize;
                   1331:        blks = howmany(bsize, fs->fs_fsize);
1.9       mycroft  1332:        if (fs->fs_contigsumsize > 0)
1.255     mlelstv  1333:                bsize += fs->fs_ncg * sizeof(int32_t);
                   1334:        bsize += fs->fs_ncg * sizeof(*fs->fs_contigdirs);
1.273     para     1335:        allocsbsize = bsize;
                   1336:        space = kmem_alloc((u_long)allocsbsize, KM_SLEEP);
1.84      lukem    1337:        fs->fs_csp = space;
1.306     maxv     1338:
1.1       mycroft  1339:        for (i = 0; i < blks; i += fs->fs_frag) {
1.255     mlelstv  1340:                bsize = fs->fs_bsize;
1.1       mycroft  1341:                if (i + fs->fs_frag > blks)
1.255     mlelstv  1342:                        bsize = (blks - i) * fs->fs_fsize;
1.285     dholland 1343:                error = bread(devvp, FFS_FSBTODB(fs, fs->fs_csaddr + i), bsize,
1.327     maxv     1344:                              0, &bp);
1.19      christos 1345:                if (error) {
1.319     maxv     1346:                        DPRINTF("bread@0x%jx %d",
1.303     christos 1347:                            (intmax_t)FFS_FSBTODB(fs, fs->fs_csaddr + i),
1.319     maxv     1348:                            error);
1.303     christos 1349:                        goto out1;
1.1       mycroft  1350:                }
1.34      bouyer   1351: #ifdef FFS_EI
                   1352:                if (needswap)
1.84      lukem    1353:                        ffs_csum_swap((struct csum *)bp->b_data,
1.255     mlelstv  1354:                                (struct csum *)space, bsize);
1.34      bouyer   1355:                else
                   1356: #endif
1.255     mlelstv  1357:                        memcpy(space, bp->b_data, (u_int)bsize);
1.161     perry    1358:
1.255     mlelstv  1359:                space = (char *)space + bsize;
1.209     ad       1360:                brelse(bp, 0);
1.1       mycroft  1361:                bp = NULL;
                   1362:        }
1.9       mycroft  1363:        if (fs->fs_contigsumsize > 0) {
1.85      lukem    1364:                fs->fs_maxcluster = lp = space;
1.9       mycroft  1365:                for (i = 0; i < fs->fs_ncg; i++)
                   1366:                        *lp++ = fs->fs_contigsumsize;
1.85      lukem    1367:                space = lp;
1.9       mycroft  1368:        }
1.255     mlelstv  1369:        bsize = fs->fs_ncg * sizeof(*fs->fs_contigdirs);
1.85      lukem    1370:        fs->fs_contigdirs = space;
1.255     mlelstv  1371:        space = (char *)space + bsize;
                   1372:        memset(fs->fs_contigdirs, 0, bsize);
1.318     maxv     1373:
                   1374:        /* Compatibility for old filesystems - XXX */
1.85      lukem    1375:        if (fs->fs_avgfilesize <= 0)
                   1376:                fs->fs_avgfilesize = AVFILESIZ;
                   1377:        if (fs->fs_avgfpdir <= 0)
                   1378:                fs->fs_avgfpdir = AFPDIR;
1.150     hannken  1379:        fs->fs_active = NULL;
1.318     maxv     1380:
1.100     soren    1381:        mp->mnt_data = ump;
1.143     christos 1382:        mp->mnt_stat.f_fsidx.__fsid_val[0] = (long)dev;
                   1383:        mp->mnt_stat.f_fsidx.__fsid_val[1] = makefstype(MOUNT_FFS);
                   1384:        mp->mnt_stat.f_fsid = mp->mnt_stat.f_fsidx.__fsid_val[0];
1.169     christos 1385:        mp->mnt_stat.f_namemax = FFS_MAXNAMLEN;
1.153     mycroft  1386:        if (UFS_MPISAPPLEUFS(ump)) {
1.103     dbj      1387:                /* NeXT used to keep short symlinks in the inode even
                   1388:                 * when using FS_42INODEFMT.  In that case fs->fs_maxsymlinklen
                   1389:                 * is probably -1, but we still need to be able to identify
                   1390:                 * short symlinks.
                   1391:                 */
1.153     mycroft  1392:                ump->um_maxsymlinklen = APPLEUFS_MAXSYMLINKLEN;
                   1393:                ump->um_dirblksiz = APPLEUFS_DIRBLKSIZ;
                   1394:                mp->mnt_iflag |= IMNT_DTYPE;
                   1395:        } else {
                   1396:                ump->um_maxsymlinklen = fs->fs_maxsymlinklen;
1.283     dholland 1397:                ump->um_dirblksiz = UFS_DIRBLKSIZ;
1.153     mycroft  1398:                if (ump->um_maxsymlinklen > 0)
                   1399:                        mp->mnt_iflag |= IMNT_DTYPE;
                   1400:                else
                   1401:                        mp->mnt_iflag &= ~IMNT_DTYPE;
1.103     dbj      1402:        }
1.73      chs      1403:        mp->mnt_fs_bshift = fs->fs_bshift;
                   1404:        mp->mnt_dev_bshift = DEV_BSHIFT;        /* XXX */
1.1       mycroft  1405:        mp->mnt_flag |= MNT_LOCAL;
1.214     ad       1406:        mp->mnt_iflag |= IMNT_MPSAFE;
1.34      bouyer   1407: #ifdef FFS_EI
                   1408:        if (needswap)
                   1409:                ump->um_flags |= UFS_NEEDSWAP;
                   1410: #endif
1.1       mycroft  1411:        ump->um_mountp = mp;
                   1412:        ump->um_dev = dev;
                   1413:        ump->um_devvp = devvp;
                   1414:        ump->um_nindir = fs->fs_nindir;
1.73      chs      1415:        ump->um_lognindir = ffs(fs->fs_nindir) - 1;
1.256     mlelstv  1416:        ump->um_bptrtodb = fs->fs_fshift - DEV_BSHIFT;
1.1       mycroft  1417:        ump->um_seqinc = fs->fs_frag;
                   1418:        for (i = 0; i < MAXQUOTAS; i++)
                   1419:                ump->um_quotas[i] = NULLVP;
1.289     hannken  1420:        spec_node_setmountedfs(devvp, mp);
1.232     hannken  1421:        if (ronly == 0 && fs->fs_snapinum[0] != 0)
                   1422:                ffs_snapshot_mount(mp);
1.231     simonb   1423: #ifdef WAPBL
                   1424:        if (!ronly) {
                   1425:                KDASSERT(fs->fs_ronly == 0);
                   1426:                /*
                   1427:                 * ffs_wapbl_start() needs mp->mnt_stat initialised if it
                   1428:                 * needs to create a new log file in-filesystem.
                   1429:                 */
1.303     christos 1430:                error = ffs_statvfs(mp, &mp->mnt_stat);
                   1431:                if (error) {
1.319     maxv     1432:                        DPRINTF("ffs_statvfs returned %d", error);
1.303     christos 1433:                        goto out1;
                   1434:                }
1.231     simonb   1435:
                   1436:                error = ffs_wapbl_start(mp);
                   1437:                if (error) {
1.319     maxv     1438:                        DPRINTF("ffs_wapbl_start returned %d", error);
1.303     christos 1439:                        goto out1;
1.231     simonb   1440:                }
                   1441:        }
                   1442: #endif /* WAPBL */
1.264     bouyer   1443:        if (ronly == 0) {
                   1444: #ifdef QUOTA2
                   1445:                error = ffs_quota2_mount(mp);
                   1446:                if (error) {
1.319     maxv     1447:                        DPRINTF("ffs_quota2_mount returned %d", error);
1.303     christos 1448:                        goto out1;
1.264     bouyer   1449:                }
                   1450: #else
                   1451:                if (fs->fs_flags & FS_DOQUOTA2) {
                   1452:                        ump->um_flags |= UFS_QUOTA2;
                   1453:                        uprintf("%s: options QUOTA2 not enabled%s\n",
                   1454:                            mp->mnt_stat.f_mntonname,
                   1455:                            (mp->mnt_flag & MNT_FORCE) ? "" : ", not mounting");
                   1456:                        if ((mp->mnt_flag & MNT_FORCE) == 0) {
                   1457:                                error = EINVAL;
1.319     maxv     1458:                                DPRINTF("quota disabled %d", error);
1.303     christos 1459:                                goto out1;
1.264     bouyer   1460:                        }
                   1461:                }
                   1462: #endif
1.268     manu     1463:         }
                   1464:
1.279     drochner 1465:        if (mp->mnt_flag & MNT_DISCARD)
                   1466:                ump->um_discarddata = ffs_discard_init(devvp, fs);
                   1467:
1.1       mycroft  1468:        return (0);
1.303     christos 1469: out1:
                   1470:        kmem_free(fs->fs_csp, allocsbsize);
1.1       mycroft  1471: out:
1.231     simonb   1472: #ifdef WAPBL
                   1473:        if (mp->mnt_wapbl_replay) {
1.240     joerg    1474:                wapbl_replay_stop(mp->mnt_wapbl_replay);
1.231     simonb   1475:                wapbl_replay_free(mp->mnt_wapbl_replay);
                   1476:                mp->mnt_wapbl_replay = 0;
                   1477:        }
                   1478: #endif
                   1479:
1.214     ad       1480:        fstrans_unmount(mp);
1.128     dbj      1481:        if (fs)
1.273     para     1482:                kmem_free(fs, fs->fs_sbsize);
1.289     hannken  1483:        spec_node_setmountedfs(devvp, NULL);
1.1       mycroft  1484:        if (bp)
1.209     ad       1485:                brelse(bp, bset);
1.1       mycroft  1486:        if (ump) {
1.131     dbj      1487:                if (ump->um_oldfscompat)
1.273     para     1488:                        kmem_free(ump->um_oldfscompat, 512 + 3*sizeof(int32_t));
1.209     ad       1489:                mutex_destroy(&ump->um_lock);
1.273     para     1490:                kmem_free(ump, sizeof(*ump));
1.100     soren    1491:                mp->mnt_data = NULL;
1.1       mycroft  1492:        }
                   1493:        return (error);
                   1494: }
                   1495:
                   1496: /*
1.110     fvdl     1497:  * Sanity checks for loading old filesystem superblocks.
                   1498:  * See ffs_oldfscompat_write below for unwound actions.
1.1       mycroft  1499:  *
1.110     fvdl     1500:  * XXX - Parts get retired eventually.
                   1501:  * Unfortunately new bits get added.
1.1       mycroft  1502:  */
1.110     fvdl     1503: static void
1.166     thorpej  1504: ffs_oldfscompat_read(struct fs *fs, struct ufsmount *ump, daddr_t sblockloc)
1.110     fvdl     1505: {
                   1506:        off_t maxfilesize;
1.131     dbj      1507:        int32_t *extrasave;
1.110     fvdl     1508:
1.131     dbj      1509:        if ((fs->fs_magic != FS_UFS1_MAGIC) ||
                   1510:            (fs->fs_old_flags & FS_FLAGS_UPDATED))
1.111     fvdl     1511:                return;
                   1512:
1.131     dbj      1513:        if (!ump->um_oldfscompat)
1.273     para     1514:                ump->um_oldfscompat = kmem_alloc(512 + 3*sizeof(int32_t),
                   1515:                    KM_SLEEP);
1.131     dbj      1516:
                   1517:        memcpy(ump->um_oldfscompat, &fs->fs_old_postbl_start, 512);
                   1518:        extrasave = ump->um_oldfscompat;
                   1519:        extrasave += 512/sizeof(int32_t);
                   1520:        extrasave[0] = fs->fs_old_npsect;
                   1521:        extrasave[1] = fs->fs_old_interleave;
                   1522:        extrasave[2] = fs->fs_old_trackskew;
                   1523:
                   1524:        /* These fields will be overwritten by their
                   1525:         * original values in fs_oldfscompat_write, so it is harmless
                   1526:         * to modify them here.
                   1527:         */
                   1528:        fs->fs_cstotal.cs_ndir = fs->fs_old_cstotal.cs_ndir;
                   1529:        fs->fs_cstotal.cs_nbfree = fs->fs_old_cstotal.cs_nbfree;
                   1530:        fs->fs_cstotal.cs_nifree = fs->fs_old_cstotal.cs_nifree;
                   1531:        fs->fs_cstotal.cs_nffree = fs->fs_old_cstotal.cs_nffree;
                   1532:
                   1533:        fs->fs_maxbsize = fs->fs_bsize;
                   1534:        fs->fs_time = fs->fs_old_time;
                   1535:        fs->fs_size = fs->fs_old_size;
                   1536:        fs->fs_dsize = fs->fs_old_dsize;
                   1537:        fs->fs_csaddr = fs->fs_old_csaddr;
                   1538:        fs->fs_sblockloc = sblockloc;
                   1539:
1.231     simonb   1540:        fs->fs_flags = fs->fs_old_flags | (fs->fs_flags & FS_INTERNAL);
1.122     enami    1541:
1.131     dbj      1542:        if (fs->fs_old_postblformat == FS_42POSTBLFMT) {
                   1543:                fs->fs_old_nrpos = 8;
                   1544:                fs->fs_old_npsect = fs->fs_old_nsect;
                   1545:                fs->fs_old_interleave = 1;
                   1546:                fs->fs_old_trackskew = 0;
1.111     fvdl     1547:        }
                   1548:
                   1549:        if (fs->fs_old_inodefmt < FS_44INODEFMT) {
1.201     tsutsui  1550:                fs->fs_maxfilesize = (u_quad_t) 1LL << 39;
1.110     fvdl     1551:                fs->fs_qbmask = ~fs->fs_bmask;
                   1552:                fs->fs_qfmask = ~fs->fs_fmask;
                   1553:        }
1.111     fvdl     1554:
                   1555:        maxfilesize = (u_int64_t)0x80000000 * fs->fs_bsize - 1;
1.201     tsutsui  1556:        if (fs->fs_maxfilesize > maxfilesize)
                   1557:                fs->fs_maxfilesize = maxfilesize;
1.111     fvdl     1558:
1.110     fvdl     1559:        /* Compatibility for old filesystems */
                   1560:        if (fs->fs_avgfilesize <= 0)
                   1561:                fs->fs_avgfilesize = AVFILESIZ;
                   1562:        if (fs->fs_avgfpdir <= 0)
                   1563:                fs->fs_avgfpdir = AFPDIR;
1.131     dbj      1564:
1.110     fvdl     1565: #if 0
                   1566:        if (bigcgs) {
                   1567:                fs->fs_save_cgsize = fs->fs_cgsize;
                   1568:                fs->fs_cgsize = fs->fs_bsize;
                   1569:        }
                   1570: #endif
                   1571: }
                   1572:
                   1573: /*
                   1574:  * Unwinding superblock updates for old filesystems.
                   1575:  * See ffs_oldfscompat_read above for details.
                   1576:  *
                   1577:  * XXX - Parts get retired eventually.
                   1578:  * Unfortunately new bits get added.
                   1579:  */
                   1580: static void
1.166     thorpej  1581: ffs_oldfscompat_write(struct fs *fs, struct ufsmount *ump)
1.1       mycroft  1582: {
1.131     dbj      1583:        int32_t *extrasave;
                   1584:
                   1585:        if ((fs->fs_magic != FS_UFS1_MAGIC) ||
                   1586:            (fs->fs_old_flags & FS_FLAGS_UPDATED))
1.111     fvdl     1587:                return;
1.115     fvdl     1588:
1.111     fvdl     1589:        fs->fs_old_time = fs->fs_time;
                   1590:        fs->fs_old_cstotal.cs_ndir = fs->fs_cstotal.cs_ndir;
                   1591:        fs->fs_old_cstotal.cs_nbfree = fs->fs_cstotal.cs_nbfree;
                   1592:        fs->fs_old_cstotal.cs_nifree = fs->fs_cstotal.cs_nifree;
                   1593:        fs->fs_old_cstotal.cs_nffree = fs->fs_cstotal.cs_nffree;
1.131     dbj      1594:        fs->fs_old_flags = fs->fs_flags;
1.111     fvdl     1595:
1.110     fvdl     1596: #if 0
                   1597:        if (bigcgs) {
                   1598:                fs->fs_cgsize = fs->fs_save_cgsize;
                   1599:        }
                   1600: #endif
1.131     dbj      1601:
                   1602:        memcpy(&fs->fs_old_postbl_start, ump->um_oldfscompat, 512);
                   1603:        extrasave = ump->um_oldfscompat;
                   1604:        extrasave += 512/sizeof(int32_t);
                   1605:        fs->fs_old_npsect = extrasave[0];
                   1606:        fs->fs_old_interleave = extrasave[1];
                   1607:        fs->fs_old_trackskew = extrasave[2];
                   1608:
1.1       mycroft  1609: }
                   1610:
                   1611: /*
1.250     pooka    1612:  * unmount vfs operation
1.1       mycroft  1613:  */
                   1614: int
1.211     pooka    1615: ffs_unmount(struct mount *mp, int mntflags)
1.1       mycroft  1616: {
1.211     pooka    1617:        struct lwp *l = curlwp;
1.170     thorpej  1618:        struct ufsmount *ump = VFSTOUFS(mp);
                   1619:        struct fs *fs = ump->um_fs;
1.243     ad       1620:        int error, flags;
1.273     para     1621:        u_int32_t bsize;
1.231     simonb   1622: #ifdef WAPBL
                   1623:        extern int doforce;
                   1624: #endif
1.1       mycroft  1625:
1.279     drochner 1626:        if (ump->um_discarddata) {
                   1627:                ffs_discard_finish(ump->um_discarddata, mntflags);
                   1628:                ump->um_discarddata = NULL;
                   1629:        }
                   1630:
1.1       mycroft  1631:        flags = 0;
1.11      mycroft  1632:        if (mntflags & MNT_FORCE)
1.1       mycroft  1633:                flags |= FORCECLOSE;
1.243     ad       1634:        if ((error = ffs_flushfiles(mp, flags, l)) != 0)
                   1635:                return (error);
1.231     simonb   1636:        error = UFS_WAPBL_BEGIN(mp);
                   1637:        if (error == 0)
                   1638:                if (fs->fs_ronly == 0 &&
                   1639:                    ffs_cgupdate(ump, MNT_WAIT) == 0 &&
                   1640:                    fs->fs_clean & FS_WASCLEAN) {
1.243     ad       1641:                        fs->fs_clean = FS_ISCLEAN;
1.231     simonb   1642:                        fs->fs_fmod = 0;
                   1643:                        (void) ffs_sbupdate(ump, MNT_WAIT);
1.91      fvdl     1644:                }
1.231     simonb   1645:        if (error == 0)
                   1646:                UFS_WAPBL_END(mp);
                   1647: #ifdef WAPBL
                   1648:        KASSERT(!(mp->mnt_wapbl_replay && mp->mnt_wapbl));
                   1649:        if (mp->mnt_wapbl_replay) {
                   1650:                KDASSERT(fs->fs_ronly);
                   1651:                wapbl_replay_stop(mp->mnt_wapbl_replay);
                   1652:                wapbl_replay_free(mp->mnt_wapbl_replay);
                   1653:                mp->mnt_wapbl_replay = 0;
                   1654:        }
                   1655:        error = ffs_wapbl_stop(mp, doforce && (mntflags & MNT_FORCE));
                   1656:        if (error) {
                   1657:                return error;
1.15      mycroft  1658:        }
1.231     simonb   1659: #endif /* WAPBL */
1.250     pooka    1660:
1.54      enami    1661:        if (ump->um_devvp->v_type != VBAD)
1.289     hannken  1662:                spec_node_setmountedfs(ump->um_devvp, NULL);
1.53      wrstuden 1663:        vn_lock(ump->um_devvp, LK_EXCLUSIVE | LK_RETRY);
1.231     simonb   1664:        (void)VOP_CLOSE(ump->um_devvp, fs->fs_ronly ? FREAD : FREAD | FWRITE,
1.211     pooka    1665:                NOCRED);
1.53      wrstuden 1666:        vput(ump->um_devvp);
1.273     para     1667:
                   1668:        bsize = fs->fs_cssize;
                   1669:        if (fs->fs_contigsumsize > 0)
                   1670:                bsize += fs->fs_ncg * sizeof(int32_t);
                   1671:        bsize += fs->fs_ncg * sizeof(*fs->fs_contigdirs);
                   1672:        kmem_free(fs->fs_csp, bsize);
                   1673:
                   1674:        kmem_free(fs, fs->fs_sbsize);
1.131     dbj      1675:        if (ump->um_oldfscompat != NULL)
1.273     para     1676:                kmem_free(ump->um_oldfscompat, 512 + 3*sizeof(int32_t));
1.209     ad       1677:        mutex_destroy(&ump->um_lock);
1.223     hannken  1678:        ffs_snapshot_fini(ump);
1.273     para     1679:        kmem_free(ump, sizeof(*ump));
1.100     soren    1680:        mp->mnt_data = NULL;
1.1       mycroft  1681:        mp->mnt_flag &= ~MNT_LOCAL;
1.214     ad       1682:        fstrans_unmount(mp);
1.129     dbj      1683:        return (0);
1.1       mycroft  1684: }
                   1685:
                   1686: /*
                   1687:  * Flush out all the files in a filesystem.
                   1688:  */
1.19      christos 1689: int
1.177     christos 1690: ffs_flushfiles(struct mount *mp, int flags, struct lwp *l)
1.1       mycroft  1691: {
                   1692:        extern int doforce;
1.61      augustss 1693:        struct ufsmount *ump;
1.19      christos 1694:        int error;
1.1       mycroft  1695:
                   1696:        if (!doforce)
                   1697:                flags &= ~FORCECLOSE;
                   1698:        ump = VFSTOUFS(mp);
                   1699: #ifdef QUOTA
1.264     bouyer   1700:        if ((error = quota1_umount(mp, flags)) != 0)
                   1701:                return (error);
                   1702: #endif
                   1703: #ifdef QUOTA2
                   1704:        if ((error = quota2_umount(mp, flags)) != 0)
                   1705:                return (error);
1.1       mycroft  1706: #endif
1.278     manu     1707: #ifdef UFS_EXTATTR
                   1708:        if (ump->um_fstype == UFS1) {
                   1709:                if (ump->um_extattr.uepm_flags & UFS_EXTATTR_UEPM_STARTED)
                   1710:                        ufs_extattr_stop(mp, l);
                   1711:                if (ump->um_extattr.uepm_flags & UFS_EXTATTR_UEPM_INITIALIZED)
                   1712:                        ufs_extattr_uepm_destroy(&ump->um_extattr);
1.302     manu     1713:                mp->mnt_flag &= ~MNT_EXTATTR;
1.278     manu     1714:        }
                   1715: #endif
1.149     hannken  1716:        if ((error = vflush(mp, 0, SKIPSYSTEM | flags)) != 0)
                   1717:                return (error);
                   1718:        ffs_snapshot_unmount(mp);
1.55      fvdl     1719:        /*
                   1720:         * Flush all the files.
                   1721:         */
1.1       mycroft  1722:        error = vflush(mp, NULLVP, flags);
1.55      fvdl     1723:        if (error)
                   1724:                return (error);
                   1725:        /*
                   1726:         * Flush filesystem metadata.
                   1727:         */
                   1728:        vn_lock(ump->um_devvp, LK_EXCLUSIVE | LK_RETRY);
1.211     pooka    1729:        error = VOP_FSYNC(ump->um_devvp, l->l_cred, FSYNC_WAIT, 0, 0);
1.259     hannken  1730:        VOP_UNLOCK(ump->um_devvp);
1.231     simonb   1731:        if (flags & FORCECLOSE) /* XXXDBJ */
                   1732:                error = 0;
                   1733:
                   1734: #ifdef WAPBL
                   1735:        if (error)
                   1736:                return error;
                   1737:        if (mp->mnt_wapbl) {
                   1738:                error = wapbl_flush(mp->mnt_wapbl, 1);
                   1739:                if (flags & FORCECLOSE)
                   1740:                        error = 0;
                   1741:        }
                   1742: #endif
                   1743:
1.1       mycroft  1744:        return (error);
                   1745: }
                   1746:
                   1747: /*
                   1748:  * Get file system statistics.
                   1749:  */
                   1750: int
1.211     pooka    1751: ffs_statvfs(struct mount *mp, struct statvfs *sbp)
1.1       mycroft  1752: {
1.61      augustss 1753:        struct ufsmount *ump;
                   1754:        struct fs *fs;
1.1       mycroft  1755:
                   1756:        ump = VFSTOUFS(mp);
                   1757:        fs = ump->um_fs;
1.209     ad       1758:        mutex_enter(&ump->um_lock);
1.143     christos 1759:        sbp->f_bsize = fs->fs_bsize;
                   1760:        sbp->f_frsize = fs->fs_fsize;
1.1       mycroft  1761:        sbp->f_iosize = fs->fs_bsize;
                   1762:        sbp->f_blocks = fs->fs_dsize;
1.286     dholland 1763:        sbp->f_bfree = ffs_blkstofrags(fs, fs->fs_cstotal.cs_nbfree) +
1.285     dholland 1764:            fs->fs_cstotal.cs_nffree + FFS_DBTOFSB(fs, fs->fs_pendingblocks);
1.143     christos 1765:        sbp->f_bresvd = ((u_int64_t) fs->fs_dsize * (u_int64_t)
                   1766:            fs->fs_minfree) / (u_int64_t) 100;
                   1767:        if (sbp->f_bfree > sbp->f_bresvd)
                   1768:                sbp->f_bavail = sbp->f_bfree - sbp->f_bresvd;
                   1769:        else
                   1770:                sbp->f_bavail = 0;
1.282     dholland 1771:        sbp->f_files =  fs->fs_ncg * fs->fs_ipg - UFS_ROOTINO;
1.89      fvdl     1772:        sbp->f_ffree = fs->fs_cstotal.cs_nifree + fs->fs_pendinginodes;
1.143     christos 1773:        sbp->f_favail = sbp->f_ffree;
                   1774:        sbp->f_fresvd = 0;
1.209     ad       1775:        mutex_exit(&ump->um_lock);
1.143     christos 1776:        copy_statvfs_info(sbp, mp);
1.209     ad       1777:
1.1       mycroft  1778:        return (0);
                   1779: }
                   1780:
1.299     christos 1781: struct ffs_sync_ctx {
                   1782:        int waitfor;
                   1783:        bool is_suspending;
                   1784: };
                   1785:
                   1786: static bool
                   1787: ffs_sync_selector(void *cl, struct vnode *vp)
                   1788: {
                   1789:        struct ffs_sync_ctx *c = cl;
                   1790:        struct inode *ip;
                   1791:
                   1792:        ip = VTOI(vp);
                   1793:        /*
                   1794:         * Skip the vnode/inode if inaccessible.
                   1795:         */
                   1796:        if (ip == NULL || vp->v_type == VNON)
                   1797:                return false;
                   1798:
                   1799:        /*
                   1800:         * We deliberately update inode times here.  This will
                   1801:         * prevent a massive queue of updates accumulating, only
                   1802:         * to be handled by a call to unmount.
                   1803:         *
                   1804:         * XXX It would be better to have the syncer trickle these
                   1805:         * out.  Adjustment needed to allow registering vnodes for
                   1806:         * sync when the vnode is clean, but the inode dirty.  Or
                   1807:         * have ufs itself trickle out inode updates.
                   1808:         *
                   1809:         * If doing a lazy sync, we don't care about metadata or
                   1810:         * data updates, because they are handled by each vnode's
                   1811:         * synclist entry.  In this case we are only interested in
                   1812:         * writing back modified inodes.
                   1813:         */
                   1814:        if ((ip->i_flag & (IN_ACCESS | IN_CHANGE | IN_UPDATE |
                   1815:            IN_MODIFY | IN_MODIFIED | IN_ACCESSED)) == 0 &&
                   1816:            (c->waitfor == MNT_LAZY || (LIST_EMPTY(&vp->v_dirtyblkhd) &&
                   1817:            UVM_OBJ_IS_CLEAN(&vp->v_uobj))))
                   1818:                return false;
                   1819:
                   1820:        if (vp->v_type == VBLK && c->is_suspending)
                   1821:                return false;
                   1822:
                   1823:        return true;
                   1824: }
                   1825:
1.1       mycroft  1826: /*
                   1827:  * Go through the disk queues to initiate sandbagged IO;
                   1828:  * go through the inodes to write those that have been modified;
                   1829:  * initiate the writing of the super block if it has been modified.
                   1830:  *
                   1831:  * Note: we are always called with the filesystem marked `MPBUSY'.
                   1832:  */
                   1833: int
1.211     pooka    1834: ffs_sync(struct mount *mp, int waitfor, kauth_cred_t cred)
1.1       mycroft  1835: {
1.294     hannken  1836:        struct vnode *vp;
1.33      fvdl     1837:        struct ufsmount *ump = VFSTOUFS(mp);
                   1838:        struct fs *fs;
1.294     hannken  1839:        struct vnode_iterator *marker;
1.263     hannken  1840:        int error, allerror = 0;
1.253     hannken  1841:        bool is_suspending;
1.299     christos 1842:        struct ffs_sync_ctx ctx;
1.1       mycroft  1843:
                   1844:        fs = ump->um_fs;
1.33      fvdl     1845:        if (fs->fs_fmod != 0 && fs->fs_ronly != 0) {            /* XXX */
                   1846:                printf("fs = %s\n", fs->fs_fsmnt);
                   1847:                panic("update: rofs mod");
1.1       mycroft  1848:        }
1.214     ad       1849:
1.199     hannken  1850:        fstrans_start(mp, FSTRANS_SHARED);
1.253     hannken  1851:        is_suspending = (fstrans_getstate(mp) == FSTRANS_SUSPENDING);
                   1852:        /*
1.1       mycroft  1853:         * Write back each (modified) inode.
                   1854:         */
1.294     hannken  1855:        vfs_vnode_iterator_init(mp, &marker);
1.299     christos 1856:
                   1857:        ctx.waitfor = waitfor;
                   1858:        ctx.is_suspending = is_suspending;
                   1859:        while ((vp = vfs_vnode_iterator_next(marker, ffs_sync_selector, &ctx)))
                   1860:        {
1.294     hannken  1861:                error = vn_lock(vp, LK_EXCLUSIVE);
                   1862:                if (error) {
                   1863:                        vrele(vp);
1.214     ad       1864:                        continue;
1.294     hannken  1865:                }
1.245     ad       1866:                if (waitfor == MNT_LAZY) {
1.231     simonb   1867:                        error = UFS_WAPBL_BEGIN(vp->v_mount);
                   1868:                        if (!error) {
1.244     ad       1869:                                error = ffs_update(vp, NULL, NULL,
                   1870:                                    UPDATE_CLOSE);
1.231     simonb   1871:                                UFS_WAPBL_END(vp->v_mount);
                   1872:                        }
                   1873:                } else {
                   1874:                        error = VOP_FSYNC(vp, cred, FSYNC_NOLOG |
                   1875:                            (waitfor == MNT_WAIT ? FSYNC_WAIT : 0), 0, 0);
                   1876:                }
1.152     mycroft  1877:                if (error)
1.1       mycroft  1878:                        allerror = error;
1.263     hannken  1879:                vput(vp);
1.1       mycroft  1880:        }
1.294     hannken  1881:        vfs_vnode_iterator_destroy(marker);
                   1882:
1.1       mycroft  1883:        /*
                   1884:         * Force stale file system control information to be flushed.
                   1885:         */
1.132     hannken  1886:        if (waitfor != MNT_LAZY && (ump->um_devvp->v_numoutput > 0 ||
                   1887:            !LIST_EMPTY(&ump->um_devvp->v_dirtyblkhd))) {
1.55      fvdl     1888:                vn_lock(ump->um_devvp, LK_EXCLUSIVE | LK_RETRY);
                   1889:                if ((error = VOP_FSYNC(ump->um_devvp, cred,
1.231     simonb   1890:                    (waitfor == MNT_WAIT ? FSYNC_WAIT : 0) | FSYNC_NOLOG,
                   1891:                    0, 0)) != 0)
1.55      fvdl     1892:                        allerror = error;
1.259     hannken  1893:                VOP_UNLOCK(ump->um_devvp);
1.55      fvdl     1894:        }
1.264     bouyer   1895: #if defined(QUOTA) || defined(QUOTA2)
1.118     fvdl     1896:        qsync(mp);
1.1       mycroft  1897: #endif
1.33      fvdl     1898:        /*
                   1899:         * Write back modified superblock.
                   1900:         */
                   1901:        if (fs->fs_fmod != 0) {
                   1902:                fs->fs_fmod = 0;
1.182     kardel   1903:                fs->fs_time = time_second;
1.231     simonb   1904:                error = UFS_WAPBL_BEGIN(mp);
                   1905:                if (error)
1.64      mycroft  1906:                        allerror = error;
1.231     simonb   1907:                else {
                   1908:                        if ((error = ffs_cgupdate(ump, waitfor)))
                   1909:                                allerror = error;
1.239     joerg    1910:                        UFS_WAPBL_END(mp);
1.231     simonb   1911:                }
1.33      fvdl     1912:        }
1.231     simonb   1913:
                   1914: #ifdef WAPBL
                   1915:        if (mp->mnt_wapbl) {
                   1916:                error = wapbl_flush(mp->mnt_wapbl, 0);
                   1917:                if (error)
                   1918:                        allerror = error;
                   1919:        }
                   1920: #endif
                   1921:
1.193     hannken  1922:        fstrans_done(mp);
1.1       mycroft  1923:        return (allerror);
                   1924: }
                   1925:
                   1926: /*
1.325     hannken  1927:  * Load inode from disk and initialize vnode.
1.1       mycroft  1928:  */
1.325     hannken  1929: static int
                   1930: ffs_init_vnode(struct ufsmount *ump, struct vnode *vp, ino_t ino)
1.1       mycroft  1931: {
1.33      fvdl     1932:        struct fs *fs;
                   1933:        struct inode *ip;
1.1       mycroft  1934:        struct buf *bp;
1.43      thorpej  1935:        int error;
1.1       mycroft  1936:
1.298     hannken  1937:        fs = ump->um_fs;
1.68      fvdl     1938:
1.298     hannken  1939:        /* Read in the disk contents for the inode. */
                   1940:        error = bread(ump->um_devvp, FFS_FSBTODB(fs, ino_to_fsba(fs, ino)),
1.327     maxv     1941:                      (int)fs->fs_bsize, 0, &bp);
1.298     hannken  1942:        if (error)
                   1943:                return error;
1.1       mycroft  1944:
1.298     hannken  1945:        /* Allocate and initialize inode. */
1.216     ad       1946:        ip = pool_cache_get(ffs_inode_cache, PR_WAITOK);
1.298     hannken  1947:        memset(ip, 0, sizeof(struct inode));
1.110     fvdl     1948:        ip->i_ump = ump;
1.298     hannken  1949:        ip->i_fs = fs;
1.325     hannken  1950:        ip->i_dev = ump->um_dev;
1.1       mycroft  1951:        ip->i_number = ino;
1.325     hannken  1952:        if (ump->um_fstype == UFS1)
                   1953:                ip->i_din.ffs1_din = pool_cache_get(ffs_dinode1_cache,
                   1954:                    PR_WAITOK);
                   1955:        else
                   1956:                ip->i_din.ffs2_din = pool_cache_get(ffs_dinode2_cache,
                   1957:                    PR_WAITOK);
                   1958:        ffs_load_inode(bp, ip, fs, ino);
                   1959:        brelse(bp, 0);
                   1960:        ip->i_vnode = vp;
1.264     bouyer   1961: #if defined(QUOTA) || defined(QUOTA2)
1.203     hannken  1962:        ufsquota_init(ip);
1.1       mycroft  1963: #endif
1.86      chs      1964:
1.325     hannken  1965:        /* Initialise vnode with this inode. */
                   1966:        vp->v_tag = VT_UFS;
                   1967:        vp->v_op = ffs_vnodeop_p;
                   1968:        vp->v_vflag |= VV_LOCKSWORK;
                   1969:        vp->v_data = ip;
                   1970:
1.298     hannken  1971:        /* Initialize genfs node. */
1.213     dyoung   1972:        genfs_node_init(vp, &ffs_genfsops);
                   1973:
1.325     hannken  1974:        return 0;
                   1975: }
                   1976:
                   1977: /*
                   1978:  * Undo ffs_init_vnode().
                   1979:  */
                   1980: static void
                   1981: ffs_deinit_vnode(struct ufsmount *ump, struct vnode *vp)
                   1982: {
                   1983:        struct inode *ip = VTOI(vp);
                   1984:
                   1985:        if (ump->um_fstype == UFS1)
                   1986:                pool_cache_put(ffs_dinode1_cache, ip->i_din.ffs1_din);
1.110     fvdl     1987:        else
1.325     hannken  1988:                pool_cache_put(ffs_dinode2_cache, ip->i_din.ffs2_din);
                   1989:        pool_cache_put(ffs_inode_cache, ip);
                   1990:
                   1991:        genfs_node_destroy(vp);
                   1992:        vp->v_data = NULL;
                   1993: }
                   1994:
                   1995: /*
                   1996:  * Read an inode from disk and initialize this vnode / inode pair.
                   1997:  * Caller assures no other thread will try to load this inode.
                   1998:  */
                   1999: int
                   2000: ffs_loadvnode(struct mount *mp, struct vnode *vp,
                   2001:     const void *key, size_t key_len, const void **new_key)
                   2002: {
                   2003:        ino_t ino;
                   2004:        struct fs *fs;
                   2005:        struct inode *ip;
                   2006:        struct ufsmount *ump;
                   2007:        int error;
                   2008:
                   2009:        KASSERT(key_len == sizeof(ino));
                   2010:        memcpy(&ino, key, key_len);
                   2011:        ump = VFSTOUFS(mp);
                   2012:        fs = ump->um_fs;
                   2013:
                   2014:        error = ffs_init_vnode(ump, vp, ino);
                   2015:        if (error)
                   2016:                return error;
                   2017:
                   2018:        ip = VTOI(vp);
                   2019:        if (ip->i_mode == 0) {
                   2020:                ffs_deinit_vnode(ump, vp);
                   2021:
                   2022:                return ENOENT;
                   2023:        }
1.1       mycroft  2024:
1.298     hannken  2025:        /* Initialize the vnode from the inode. */
1.87      chs      2026:        ufs_vinit(mp, ffs_specop_p, ffs_fifoop_p, &vp);
                   2027:
1.298     hannken  2028:        /* Finish inode initialization.  */
1.1       mycroft  2029:        ip->i_devvp = ump->um_devvp;
1.254     pooka    2030:        vref(ip->i_devvp);
1.87      chs      2031:
1.1       mycroft  2032:        /*
                   2033:         * Ensure that uid and gid are correct. This is a temporary
                   2034:         * fix until fsck has been changed to do the update.
                   2035:         */
1.87      chs      2036:
1.110     fvdl     2037:        if (fs->fs_old_inodefmt < FS_44INODEFMT) {              /* XXX */
                   2038:                ip->i_uid = ip->i_ffs1_ouid;                    /* XXX */
                   2039:                ip->i_gid = ip->i_ffs1_ogid;                    /* XXX */
1.38      kleink   2040:        }                                                       /* XXX */
1.110     fvdl     2041:        uvm_vnp_setsize(vp, ip->i_size);
1.298     hannken  2042:        *new_key = &ip->i_number;
                   2043:        return 0;
1.1       mycroft  2044: }
                   2045:
                   2046: /*
1.325     hannken  2047:  * Create a new inode on disk and initialize this vnode / inode pair.
                   2048:  */
                   2049: int
                   2050: ffs_newvnode(struct mount *mp, struct vnode *dvp, struct vnode *vp,
                   2051:     struct vattr *vap, kauth_cred_t cred,
                   2052:     size_t *key_len, const void **new_key)
                   2053: {
                   2054:        ino_t ino;
                   2055:        struct fs *fs;
                   2056:        struct inode *ip;
                   2057:        struct timespec ts;
                   2058:        struct ufsmount *ump;
                   2059:        int error, mode;
                   2060:
                   2061:        KASSERT(dvp->v_mount == mp);
                   2062:        KASSERT(vap->va_type != VNON);
                   2063:
                   2064:        *key_len = sizeof(ino);
                   2065:        ump = VFSTOUFS(mp);
                   2066:        fs = ump->um_fs;
                   2067:        mode = MAKEIMODE(vap->va_type, vap->va_mode);
                   2068:
                   2069:        /* Allocate fresh inode. */
                   2070:        error = ffs_valloc(dvp, mode, cred, &ino);
                   2071:        if (error)
                   2072:                return error;
                   2073:
                   2074:        /* Attach inode to vnode. */
                   2075:        error = ffs_init_vnode(ump, vp, ino);
                   2076:        if (error) {
                   2077:                if (UFS_WAPBL_BEGIN(mp) == 0) {
                   2078:                        ffs_vfree(dvp, ino, mode);
                   2079:                        UFS_WAPBL_END(mp);
                   2080:                }
                   2081:                return error;
                   2082:        }
                   2083:
                   2084:        ip = VTOI(vp);
                   2085:        if (ip->i_mode || DIP(ip, size) || DIP(ip, blocks)) {
                   2086:                printf("free ino %" PRId64 " on %s:\n", ino, fs->fs_fsmnt);
                   2087:                printf("dmode %x mode %x dgen %x gen %x\n",
                   2088:                    DIP(ip, mode), ip->i_mode,
                   2089:                    DIP(ip, gen), ip->i_gen);
                   2090:                printf("size %" PRIx64 " blocks %" PRIx64 "\n",
                   2091:                    DIP(ip, size), DIP(ip, blocks));
                   2092:                panic("ffs_init_vnode: dup alloc");
                   2093:        }
                   2094:
                   2095:        /* Set uid / gid. */
                   2096:        if (cred == NOCRED || cred == FSCRED) {
                   2097:                ip->i_gid = 0;
                   2098:                ip->i_uid = 0;
                   2099:        } else {
                   2100:                ip->i_gid = VTOI(dvp)->i_gid;
                   2101:                ip->i_uid = kauth_cred_geteuid(cred);
                   2102:        }
                   2103:        DIP_ASSIGN(ip, gid, ip->i_gid);
                   2104:        DIP_ASSIGN(ip, uid, ip->i_uid);
                   2105:
                   2106: #if defined(QUOTA) || defined(QUOTA2)
                   2107:        error = UFS_WAPBL_BEGIN(mp);
                   2108:        if (error) {
                   2109:                ffs_deinit_vnode(ump, vp);
                   2110:
                   2111:                return error;
                   2112:        }
                   2113:        error = chkiq(ip, 1, cred, 0);
                   2114:        if (error) {
                   2115:                ffs_vfree(dvp, ino, mode);
                   2116:                UFS_WAPBL_END(mp);
                   2117:                ffs_deinit_vnode(ump, vp);
                   2118:
                   2119:                return error;
                   2120:        }
                   2121:        UFS_WAPBL_END(mp);
                   2122: #endif
                   2123:
                   2124:        /* Set type and finalize. */
                   2125:        ip->i_flags = 0;
                   2126:        DIP_ASSIGN(ip, flags, 0);
                   2127:        ip->i_mode = mode;
                   2128:        DIP_ASSIGN(ip, mode, mode);
                   2129:        if (vap->va_rdev != VNOVAL) {
                   2130:                /*
                   2131:                 * Want to be able to use this to make badblock
                   2132:                 * inodes, so don't truncate the dev number.
                   2133:                 */
                   2134:                if (ump->um_fstype == UFS1)
                   2135:                        ip->i_ffs1_rdev = ufs_rw32(vap->va_rdev,
                   2136:                            UFS_MPNEEDSWAP(ump));
                   2137:                else
                   2138:                        ip->i_ffs2_rdev = ufs_rw64(vap->va_rdev,
                   2139:                            UFS_MPNEEDSWAP(ump));
                   2140:        }
                   2141:        ufs_vinit(mp, ffs_specop_p, ffs_fifoop_p, &vp);
                   2142:        ip->i_devvp = ump->um_devvp;
                   2143:        vref(ip->i_devvp);
                   2144:
                   2145:        /* Set up a new generation number for this inode.  */
                   2146:        ip->i_gen++;
                   2147:        DIP_ASSIGN(ip, gen, ip->i_gen);
                   2148:        if (fs->fs_magic == FS_UFS2_MAGIC) {
                   2149:                vfs_timestamp(&ts);
                   2150:                ip->i_ffs2_birthtime = ts.tv_sec;
                   2151:                ip->i_ffs2_birthnsec = ts.tv_nsec;
                   2152:        }
                   2153:
                   2154:        uvm_vnp_setsize(vp, ip->i_size);
                   2155:        *new_key = &ip->i_number;
                   2156:        return 0;
                   2157: }
                   2158:
                   2159: /*
1.1       mycroft  2160:  * File handle to vnode
                   2161:  *
                   2162:  * Have to be really careful about stale file handles:
                   2163:  * - check that the inode number is valid
                   2164:  * - call ffs_vget() to get the locked inode
                   2165:  * - check for an unallocated inode (i_mode == 0)
                   2166:  * - check that the given client host has export rights and return
                   2167:  *   those rights via. exflagsp and credanonp
                   2168:  */
                   2169: int
1.166     thorpej  2170: ffs_fhtovp(struct mount *mp, struct fid *fhp, struct vnode **vpp)
1.1       mycroft  2171: {
1.183     martin   2172:        struct ufid ufh;
1.1       mycroft  2173:        struct fs *fs;
                   2174:
1.183     martin   2175:        if (fhp->fid_len != sizeof(struct ufid))
                   2176:                return EINVAL;
                   2177:
                   2178:        memcpy(&ufh, fhp, sizeof(ufh));
1.1       mycroft  2179:        fs = VFSTOUFS(mp)->um_fs;
1.282     dholland 2180:        if (ufh.ufid_ino < UFS_ROOTINO ||
1.183     martin   2181:            ufh.ufid_ino >= fs->fs_ncg * fs->fs_ipg)
1.1       mycroft  2182:                return (ESTALE);
1.183     martin   2183:        return (ufs_fhtovp(mp, &ufh, vpp));
1.1       mycroft  2184: }
                   2185:
                   2186: /*
                   2187:  * Vnode pointer to File handle
                   2188:  */
                   2189: /* ARGSUSED */
1.19      christos 2190: int
1.183     martin   2191: ffs_vptofh(struct vnode *vp, struct fid *fhp, size_t *fh_size)
1.1       mycroft  2192: {
1.61      augustss 2193:        struct inode *ip;
1.183     martin   2194:        struct ufid ufh;
1.1       mycroft  2195:
1.183     martin   2196:        if (*fh_size < sizeof(struct ufid)) {
                   2197:                *fh_size = sizeof(struct ufid);
                   2198:                return E2BIG;
                   2199:        }
1.1       mycroft  2200:        ip = VTOI(vp);
1.183     martin   2201:        *fh_size = sizeof(struct ufid);
                   2202:        memset(&ufh, 0, sizeof(ufh));
                   2203:        ufh.ufid_len = sizeof(struct ufid);
                   2204:        ufh.ufid_ino = ip->i_number;
                   2205:        ufh.ufid_gen = ip->i_gen;
                   2206:        memcpy(fhp, &ufh, sizeof(ufh));
1.1       mycroft  2207:        return (0);
1.33      fvdl     2208: }
                   2209:
                   2210: void
1.166     thorpej  2211: ffs_init(void)
1.33      fvdl     2212: {
1.59      jdolecek 2213:        if (ffs_initcount++ > 0)
                   2214:                return;
                   2215:
1.216     ad       2216:        ffs_inode_cache = pool_cache_init(sizeof(struct inode), 0, 0, 0,
                   2217:            "ffsino", NULL, IPL_NONE, NULL, NULL, NULL);
                   2218:        ffs_dinode1_cache = pool_cache_init(sizeof(struct ufs1_dinode), 0, 0, 0,
                   2219:            "ffsdino1", NULL, IPL_NONE, NULL, NULL, NULL);
                   2220:        ffs_dinode2_cache = pool_cache_init(sizeof(struct ufs2_dinode), 0, 0, 0,
                   2221:            "ffsdino2", NULL, IPL_NONE, NULL, NULL, NULL);
1.33      fvdl     2222:        ufs_init();
1.86      chs      2223: }
                   2224:
                   2225: void
1.166     thorpej  2226: ffs_reinit(void)
1.86      chs      2227: {
                   2228:        ufs_reinit();
1.59      jdolecek 2229: }
                   2230:
                   2231: void
1.166     thorpej  2232: ffs_done(void)
1.59      jdolecek 2233: {
                   2234:        if (--ffs_initcount > 0)
                   2235:                return;
                   2236:
                   2237:        ufs_done();
1.216     ad       2238:        pool_cache_destroy(ffs_dinode2_cache);
                   2239:        pool_cache_destroy(ffs_dinode1_cache);
                   2240:        pool_cache_destroy(ffs_inode_cache);
1.33      fvdl     2241: }
                   2242:
1.1       mycroft  2243: /*
                   2244:  * Write a superblock and associated information back to disk.
                   2245:  */
                   2246: int
1.166     thorpej  2247: ffs_sbupdate(struct ufsmount *mp, int waitfor)
1.1       mycroft  2248: {
1.61      augustss 2249:        struct fs *fs = mp->um_fs;
                   2250:        struct buf *bp;
1.110     fvdl     2251:        int error = 0;
                   2252:        u_int32_t saveflag;
1.34      bouyer   2253:
1.229     hannken  2254:        error = ffs_getblk(mp->um_devvp,
1.257     mlelstv  2255:            fs->fs_sblockloc / DEV_BSIZE, FFS_NOBLK,
1.229     hannken  2256:            fs->fs_sbsize, false, &bp);
                   2257:        if (error)
                   2258:                return error;
1.55      fvdl     2259:        saveflag = fs->fs_flags & FS_INTERNAL;
                   2260:        fs->fs_flags &= ~FS_INTERNAL;
1.161     perry    2261:
1.42      perry    2262:        memcpy(bp->b_data, fs, fs->fs_sbsize);
1.110     fvdl     2263:
                   2264:        ffs_oldfscompat_write((struct fs *)bp->b_data, mp);
1.34      bouyer   2265: #ifdef FFS_EI
                   2266:        if (mp->um_flags & UFS_NEEDSWAP)
1.123     enami    2267:                ffs_sb_swap((struct fs *)bp->b_data, (struct fs *)bp->b_data);
1.111     fvdl     2268: #endif
1.55      fvdl     2269:        fs->fs_flags |= saveflag;
1.34      bouyer   2270:
1.1       mycroft  2271:        if (waitfor == MNT_WAIT)
                   2272:                error = bwrite(bp);
                   2273:        else
                   2274:                bawrite(bp);
1.15      mycroft  2275:        return (error);
                   2276: }
                   2277:
                   2278: int
1.166     thorpej  2279: ffs_cgupdate(struct ufsmount *mp, int waitfor)
1.15      mycroft  2280: {
1.61      augustss 2281:        struct fs *fs = mp->um_fs;
                   2282:        struct buf *bp;
1.15      mycroft  2283:        int blks;
1.84      lukem    2284:        void *space;
1.15      mycroft  2285:        int i, size, error = 0, allerror = 0;
                   2286:
                   2287:        allerror = ffs_sbupdate(mp, waitfor);
1.1       mycroft  2288:        blks = howmany(fs->fs_cssize, fs->fs_fsize);
1.84      lukem    2289:        space = fs->fs_csp;
1.1       mycroft  2290:        for (i = 0; i < blks; i += fs->fs_frag) {
                   2291:                size = fs->fs_bsize;
                   2292:                if (i + fs->fs_frag > blks)
                   2293:                        size = (blks - i) * fs->fs_fsize;
1.285     dholland 2294:                error = ffs_getblk(mp->um_devvp, FFS_FSBTODB(fs, fs->fs_csaddr + i),
1.229     hannken  2295:                    FFS_NOBLK, size, false, &bp);
                   2296:                if (error)
                   2297:                        break;
1.34      bouyer   2298: #ifdef FFS_EI
                   2299:                if (mp->um_flags & UFS_NEEDSWAP)
                   2300:                        ffs_csum_swap((struct csum*)space,
1.38      kleink   2301:                            (struct csum*)bp->b_data, size);
1.34      bouyer   2302:                else
                   2303: #endif
1.42      perry    2304:                        memcpy(bp->b_data, space, (u_int)size);
1.84      lukem    2305:                space = (char *)space + size;
1.1       mycroft  2306:                if (waitfor == MNT_WAIT)
                   2307:                        error = bwrite(bp);
                   2308:                else
                   2309:                        bawrite(bp);
                   2310:        }
1.15      mycroft  2311:        if (!allerror && error)
                   2312:                allerror = error;
                   2313:        return (allerror);
1.1       mycroft  2314: }
1.170     thorpej  2315:
                   2316: int
                   2317: ffs_extattrctl(struct mount *mp, int cmd, struct vnode *vp,
1.211     pooka    2318:     int attrnamespace, const char *attrname)
1.170     thorpej  2319: {
                   2320: #ifdef UFS_EXTATTR
                   2321:        /*
                   2322:         * File-backed extended attributes are only supported on UFS1.
                   2323:         * UFS2 has native extended attributes.
                   2324:         */
                   2325:        if (VFSTOUFS(mp)->um_fstype == UFS1)
1.211     pooka    2326:                return (ufs_extattrctl(mp, cmd, vp, attrnamespace, attrname));
1.170     thorpej  2327: #endif
1.211     pooka    2328:        return (vfs_stdextattrctl(mp, cmd, vp, attrnamespace, attrname));
1.170     thorpej  2329: }
1.193     hannken  2330:
                   2331: int
                   2332: ffs_suspendctl(struct mount *mp, int cmd)
                   2333: {
                   2334:        int error;
                   2335:        struct lwp *l = curlwp;
                   2336:
                   2337:        switch (cmd) {
                   2338:        case SUSPEND_SUSPEND:
1.194     hannken  2339:                if ((error = fstrans_setstate(mp, FSTRANS_SUSPENDING)) != 0)
1.193     hannken  2340:                        return error;
1.211     pooka    2341:                error = ffs_sync(mp, MNT_WAIT, l->l_proc->p_cred);
1.193     hannken  2342:                if (error == 0)
1.194     hannken  2343:                        error = fstrans_setstate(mp, FSTRANS_SUSPENDED);
1.233     hannken  2344: #ifdef WAPBL
                   2345:                if (error == 0 && mp->mnt_wapbl)
                   2346:                        error = wapbl_flush(mp->mnt_wapbl, 1);
                   2347: #endif
1.193     hannken  2348:                if (error != 0) {
1.194     hannken  2349:                        (void) fstrans_setstate(mp, FSTRANS_NORMAL);
1.193     hannken  2350:                        return error;
                   2351:                }
                   2352:                return 0;
                   2353:
                   2354:        case SUSPEND_RESUME:
1.194     hannken  2355:                return fstrans_setstate(mp, FSTRANS_NORMAL);
1.193     hannken  2356:
                   2357:        default:
                   2358:                return EINVAL;
                   2359:        }
                   2360: }
1.242     ad       2361:
                   2362: /*
1.266     hannken  2363:  * Synch vnode for a mounted file system.
1.242     ad       2364:  */
                   2365: static int
                   2366: ffs_vfs_fsync(vnode_t *vp, int flags)
                   2367: {
1.266     hannken  2368:        int error, i, pflags;
1.243     ad       2369: #ifdef WAPBL
1.242     ad       2370:        struct mount *mp;
1.243     ad       2371: #endif
1.242     ad       2372:
                   2373:        KASSERT(vp->v_type == VBLK);
1.289     hannken  2374:        KASSERT(spec_node_getmountedfs(vp) != NULL);
1.242     ad       2375:
                   2376:        /*
                   2377:         * Flush all dirty data associated with the vnode.
                   2378:         */
                   2379:        pflags = PGO_ALLPAGES | PGO_CLEANIT;
                   2380:        if ((flags & FSYNC_WAIT) != 0)
                   2381:                pflags |= PGO_SYNCIO;
1.267     rmind    2382:        mutex_enter(vp->v_interlock);
1.242     ad       2383:        error = VOP_PUTPAGES(vp, 0, 0, pflags);
                   2384:        if (error)
                   2385:                return error;
                   2386:
                   2387: #ifdef WAPBL
1.289     hannken  2388:        mp = spec_node_getmountedfs(vp);
1.242     ad       2389:        if (mp && mp->mnt_wapbl) {
                   2390:                /*
                   2391:                 * Don't bother writing out metadata if the syncer is
                   2392:                 * making the request.  We will let the sync vnode
                   2393:                 * write it out in a single burst through a call to
                   2394:                 * VFS_SYNC().
                   2395:                 */
                   2396:                if ((flags & (FSYNC_DATAONLY | FSYNC_LAZY | FSYNC_NOLOG)) != 0)
                   2397:                        return 0;
                   2398:
                   2399:                /*
                   2400:                 * Don't flush the log if the vnode being flushed
                   2401:                 * contains no dirty buffers that could be in the log.
                   2402:                 */
                   2403:                if (!LIST_EMPTY(&vp->v_dirtyblkhd)) {
                   2404:                        error = wapbl_flush(mp->mnt_wapbl, 0);
                   2405:                        if (error)
                   2406:                                return error;
                   2407:                }
                   2408:
                   2409:                if ((flags & FSYNC_WAIT) != 0) {
1.267     rmind    2410:                        mutex_enter(vp->v_interlock);
1.242     ad       2411:                        while (vp->v_numoutput)
1.267     rmind    2412:                                cv_wait(&vp->v_cv, vp->v_interlock);
                   2413:                        mutex_exit(vp->v_interlock);
1.242     ad       2414:                }
                   2415:
                   2416:                return 0;
                   2417:        }
                   2418: #endif /* WAPBL */
                   2419:
1.277     chs      2420:        error = vflushbuf(vp, flags);
1.242     ad       2421:        if (error == 0 && (flags & FSYNC_CACHE) != 0) {
1.266     hannken  2422:                i = 1;
1.242     ad       2423:                (void)VOP_IOCTL(vp, DIOCCACHESYNC, &i, FWRITE,
                   2424:                    kauth_cred_get());
                   2425:        }
                   2426:
                   2427:        return error;
                   2428: }

CVSweb <webmaster@jp.NetBSD.org>