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

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

CVSweb <webmaster@jp.NetBSD.org>