Annotation of XNU/bsd/ufs/ffs/ffs_vfsops.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
                      3:  *
                      4:  * @APPLE_LICENSE_HEADER_START@
                      5:  * 
                      6:  * The contents of this file constitute Original Code as defined in and
                      7:  * are subject to the Apple Public Source License Version 1.1 (the
                      8:  * "License").  You may not use this file except in compliance with the
                      9:  * License.  Please obtain a copy of the License at
                     10:  * http://www.apple.com/publicsource and read it before using this file.
                     11:  * 
                     12:  * This Original Code and all software distributed under the License are
                     13:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
                     14:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
                     15:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
                     16:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
                     17:  * License for the specific language governing rights and limitations
                     18:  * under the License.
                     19:  * 
                     20:  * @APPLE_LICENSE_HEADER_END@
                     21:  */
                     22: /* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */
                     23: /*
                     24:  * Copyright (c) 1989, 1991, 1993, 1994
                     25:  *     The Regents of the University of California.  All rights reserved.
                     26:  *
                     27:  * Redistribution and use in source and binary forms, with or without
                     28:  * modification, are permitted provided that the following conditions
                     29:  * are met:
                     30:  * 1. Redistributions of source code must retain the above copyright
                     31:  *    notice, this list of conditions and the following disclaimer.
                     32:  * 2. Redistributions in binary form must reproduce the above copyright
                     33:  *    notice, this list of conditions and the following disclaimer in the
                     34:  *    documentation and/or other materials provided with the distribution.
                     35:  * 3. All advertising materials mentioning features or use of this software
                     36:  *    must display the following acknowledgement:
                     37:  *     This product includes software developed by the University of
                     38:  *     California, Berkeley and its contributors.
                     39:  * 4. Neither the name of the University nor the names of its contributors
                     40:  *    may be used to endorse or promote products derived from this software
                     41:  *    without specific prior written permission.
                     42:  *
                     43:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     44:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     45:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     46:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     47:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     48:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     49:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     50:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     51:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     52:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     53:  * SUCH DAMAGE.
                     54:  *
                     55:  *     @(#)ffs_vfsops.c        8.31 (Berkeley) 5/20/95
                     56:  */
                     57: 
                     58: #include <rev_endian_fs.h>
                     59: #include <mach_nbc.h>
                     60: #include <sys/param.h>
                     61: #include <sys/systm.h>
                     62: #include <sys/namei.h>
                     63: #include <sys/proc.h>
                     64: #include <sys/kernel.h>
                     65: #include <sys/vnode.h>
                     66: #include <sys/socket.h>
                     67: #include <sys/mount.h>
                     68: #include <sys/buf.h>
                     69: #include <sys/mbuf.h>
                     70: #include <sys/file.h>
                     71: #ifdef NeXT
                     72: #include <bsd/dev/disk.h>
                     73: #else
                     74: #include <sys/disklabel.h>
                     75: #endif
                     76: #include <sys/ioctl.h>
                     77: #include <sys/errno.h>
                     78: #include <sys/malloc.h>
                     79: 
                     80: #include <miscfs/specfs/specdev.h>
                     81: 
                     82: #include <ufs/ufs/quota.h>
                     83: #include <ufs/ufs/ufsmount.h>
                     84: #include <ufs/ufs/inode.h>
                     85: #include <ufs/ufs/ufs_extern.h>
                     86: 
                     87: #include <ufs/ffs/fs.h>
                     88: #include <ufs/ffs/ffs_extern.h>
                     89: #if REV_ENDIAN_FS
                     90: #include <ufs/ufs/ufs_byte_order.h>
                     91: #include <architecture/byte_order.h>
                     92: #endif /* REV_ENDIAN_FS */
                     93: 
                     94: int ffs_sbupdate __P((struct ufsmount *, int));
                     95: 
                     96: struct vfsops ufs_vfsops = {
                     97:        ffs_mount,
                     98:        ufs_start,
                     99:        ffs_unmount,
                    100:        ufs_root,
                    101:        ufs_quotactl,
                    102:        ffs_statfs,
                    103:        ffs_sync,
                    104:        ffs_vget,
                    105:        ffs_fhtovp,
                    106:        ffs_vptofh,
                    107:        ffs_init,
                    108:        ffs_sysctl,
                    109: };
                    110: 
                    111: extern u_long nextgennumber;
                    112: 
                    113: /*
                    114:  * Called by main() when ufs is going to be mounted as root.
                    115:  */
                    116: ffs_mountroot()
                    117: {
                    118:        extern struct vnode *rootvp;
                    119:        struct fs *fs;
                    120:        struct mount *mp;
                    121:        struct proc *p = current_proc();        /* XXX */
                    122:        struct ufsmount *ump;
                    123:        u_int size;
                    124:        int error;
                    125:        
                    126:        /*
                    127:         * Get vnode for rootdev.
                    128:         */
                    129:        if (error = bdevvp(rootdev, &rootvp)) {
                    130:                printf("ffs_mountroot: can't setup bdevvp");
                    131:                return (error);
                    132:        }
                    133:        if (error = vfs_rootmountalloc("ufs", "root_device", &mp))
                    134:                return (error);
                    135:        if (error = ffs_mountfs(rootvp, mp, p)) {
                    136:                mp->mnt_vfc->vfc_refcount--;
                    137:                vfs_unbusy(mp, p);
                    138:                _FREE_ZONE(mp, sizeof (struct mount), M_MOUNT);
                    139:                return (error);
                    140:        }
                    141:        simple_lock(&mountlist_slock);
                    142:        CIRCLEQ_INSERT_TAIL(&mountlist, mp, mnt_list);
                    143:        simple_unlock(&mountlist_slock);
                    144:        ump = VFSTOUFS(mp);
                    145:        fs = ump->um_fs;
                    146:        (void) copystr(mp->mnt_stat.f_mntonname, fs->fs_fsmnt, MNAMELEN - 1, 0);
                    147:        (void)ffs_statfs(mp, &mp->mnt_stat, p);
                    148:        vfs_unbusy(mp, p);
                    149:        inittodr(fs->fs_time);
                    150:        return (0);
                    151: }
                    152: 
                    153: /*
                    154:  * VFS Operations.
                    155:  *
                    156:  * mount system call
                    157:  */
                    158: int
                    159: ffs_mount(mp, path, data, ndp, p)
                    160:        register struct mount *mp;
                    161:        char *path;
                    162:        caddr_t data;
                    163:        struct nameidata *ndp;
                    164:        struct proc *p;
                    165: {
                    166:        struct vnode *devvp;
                    167:        struct ufs_args args;
                    168:        struct ufsmount *ump;
                    169:        register struct fs *fs;
                    170:        u_int size;
                    171:        int error, flags;
                    172:        mode_t accessmode;
                    173: 
                    174:        if (error = copyin(data, (caddr_t)&args, sizeof (struct ufs_args)))
                    175:                return (error);
                    176:        /*
                    177:         * If updating, check whether changing from read-only to
                    178:         * read/write; if there is no device name, that's all we do.
                    179:         */
                    180:        if (mp->mnt_flag & MNT_UPDATE) {
                    181:                ump = VFSTOUFS(mp);
                    182:                fs = ump->um_fs;
                    183:                if (fs->fs_ronly == 0 && (mp->mnt_flag & MNT_RDONLY)) {
                    184:                        flags = WRITECLOSE;
                    185:                        if (mp->mnt_flag & MNT_FORCE)
                    186:                                flags |= FORCECLOSE;
                    187:                        if (error = ffs_flushfiles(mp, flags, p))
                    188:                                return (error);
                    189:                        fs->fs_clean = 1;
                    190:                        fs->fs_ronly = 1;
                    191:                        if (error = ffs_sbupdate(ump, MNT_WAIT)) {
                    192:                                fs->fs_clean = 0;
                    193:                                fs->fs_ronly = 0;
                    194:                                return (error);
                    195:                        }
                    196:                }
                    197:                if ((mp->mnt_flag & MNT_RELOAD) &&
                    198:                    (error = ffs_reload(mp, ndp->ni_cnd.cn_cred, p)))
                    199:                        return (error);
                    200:                if (fs->fs_ronly && (mp->mnt_flag & MNT_WANTRDWR)) {
                    201:                        /*
                    202:                         * If upgrade to read-write by non-root, then verify
                    203:                         * that user has necessary permissions on the device.
                    204:                         */
                    205:                        if (p->p_ucred->cr_uid != 0) {
                    206:                                devvp = ump->um_devvp;
                    207:                                vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, p);
                    208:                                if (error = VOP_ACCESS(devvp, VREAD | VWRITE,
                    209:                                    p->p_ucred, p)) {
                    210:                                        VOP_UNLOCK(devvp, 0, p);
                    211:                                        return (error);
                    212:                                }
                    213:                                VOP_UNLOCK(devvp, 0, p);
                    214:                        }
                    215:                        fs->fs_ronly = 0;
                    216:                        fs->fs_clean = 0;
                    217:                        (void) ffs_sbupdate(ump, MNT_WAIT);
                    218:                }
                    219:                if (args.fspec == 0) {
                    220:                        /*
                    221:                         * Process export requests.
                    222:                         */
                    223:                        return (vfs_export(mp, &ump->um_export, &args.export));
                    224:                }
                    225:        }
                    226:        /*
                    227:         * Not an update, or updating the name: look up the name
                    228:         * and verify that it refers to a sensible block device.
                    229:         */
                    230:        NDINIT(ndp, LOOKUP, FOLLOW, UIO_USERSPACE, args.fspec, p);
                    231:        if (error = namei(ndp))
                    232:                return (error);
                    233:        devvp = ndp->ni_vp;
                    234: 
                    235:        if (devvp->v_type != VBLK) {
                    236:                vrele(devvp);
                    237:                return (ENOTBLK);
                    238:        }
                    239:        if (major(devvp->v_rdev) >= nblkdev) {
                    240:                vrele(devvp);
                    241:                return (ENXIO);
                    242:        }
                    243:        /*
                    244:         * If mount by non-root, then verify that user has necessary
                    245:         * permissions on the device.
                    246:         */
                    247:        if (p->p_ucred->cr_uid != 0) {
                    248:                accessmode = VREAD;
                    249:                if ((mp->mnt_flag & MNT_RDONLY) == 0)
                    250:                        accessmode |= VWRITE;
                    251:                vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, p);
                    252:                if (error = VOP_ACCESS(devvp, accessmode, p->p_ucred, p)) {
                    253:                        vput(devvp);
                    254:                        return (error);
                    255:                }
                    256:                VOP_UNLOCK(devvp, 0, p);
                    257:        }
                    258:        if ((mp->mnt_flag & MNT_UPDATE) == 0)
                    259:                error = ffs_mountfs(devvp, mp, p);
                    260:        else {
                    261:                if (devvp != ump->um_devvp)
                    262:                        error = EINVAL; /* needs translation */
                    263:                else
                    264:                        vrele(devvp);
                    265:        }
                    266:        if (error) {
                    267:                vrele(devvp);
                    268:                return (error);
                    269:        }
                    270:        ump = VFSTOUFS(mp);
                    271:        fs = ump->um_fs;
                    272:        (void) copyinstr(path, fs->fs_fsmnt, sizeof(fs->fs_fsmnt) - 1, &size);
                    273:        bzero(fs->fs_fsmnt + size, sizeof(fs->fs_fsmnt) - size);
                    274:        bcopy((caddr_t)fs->fs_fsmnt, (caddr_t)mp->mnt_stat.f_mntonname,
                    275:            MNAMELEN);
                    276:        (void) copyinstr(args.fspec, mp->mnt_stat.f_mntfromname, MNAMELEN - 1, 
                    277:            &size);
                    278:        bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size);
                    279:        (void)ffs_statfs(mp, &mp->mnt_stat, p);
                    280:        return (0);
                    281: }
                    282: 
                    283: /*
                    284:  * Reload all incore data for a filesystem (used after running fsck on
                    285:  * the root filesystem and finding things to fix). The filesystem must
                    286:  * be mounted read-only.
                    287:  *
                    288:  * Things to do to update the mount:
                    289:  *     1) invalidate all cached meta-data.
                    290:  *     2) re-read superblock from disk.
                    291:  *     3) re-read summary information from disk.
                    292:  *     4) invalidate all inactive vnodes.
                    293:  *     5) invalidate all cached file data.
                    294:  *     6) re-read inode data for all active vnodes.
                    295:  */
                    296: ffs_reload(mountp, cred, p)
                    297:        register struct mount *mountp;
                    298:        struct ucred *cred;
                    299:        struct proc *p;
                    300: {
                    301:        register struct vnode *vp, *nvp, *devvp;
                    302:        struct inode *ip;
                    303:        struct csum *space;
                    304:        struct buf *bp;
                    305:        struct fs *fs, *newfs;
                    306: #ifndef NeXT
                    307:        struct partinfo dpart;
                    308: #endif /* NeXT */
                    309:        int i, blks, size, error;
                    310:        int32_t *lp;
                    311: #if REV_ENDIAN_FS
                    312:        int rev_endian = (mountp->mnt_flag & MNT_REVEND);
                    313: #endif /* REV_ENDIAN_FS */
                    314: 
                    315:        if ((mountp->mnt_flag & MNT_RDONLY) == 0)
                    316:                return (EINVAL);
                    317:        /*
                    318:         * Step 1: invalidate all cached meta-data.
                    319:         */
                    320:        devvp = VFSTOUFS(mountp)->um_devvp;
                    321:        if (vinvalbuf(devvp, 0, cred, p, 0, 0))
                    322:                panic("ffs_reload: dirty1");
                    323:        /*
                    324:         * Step 2: re-read superblock from disk.
                    325:         */
                    326: #ifdef NeXT
                    327:        VOP_DEVBLOCKSIZE(devvp,&size);
                    328: #else
                    329:        if (VOP_IOCTL(devvp, DIOCGPART, (caddr_t)&dpart, FREAD, NOCRED, p) != 0)
                    330:                size = DEV_BSIZE;
                    331:        else
                    332:                size = dpart.disklab->d_secsize;
                    333: #endif
                    334:        if (error = bread(devvp, (ufs_daddr_t)(SBOFF/size), SBSIZE, NOCRED,&bp))
                    335:                return (error);
                    336:        newfs = (struct fs *)bp->b_data;
                    337: #if REV_ENDIAN_FS
                    338:        if (rev_endian) {
                    339:                byte_swap_sbin(newfs);
                    340:        }
                    341: #endif /* REV_ENDIAN_FS */
                    342:        if (newfs->fs_magic != FS_MAGIC || newfs->fs_bsize > MAXBSIZE ||
                    343:            newfs->fs_bsize < sizeof(struct fs)) {
                    344: #if REV_ENDIAN_FS
                    345:                if (rev_endian)
                    346:                        byte_swap_sbout(newfs);
                    347: #endif /* REV_ENDIAN_FS */
                    348: 
                    349:                brelse(bp);
                    350:                return (EIO);           /* XXX needs translation */
                    351:        }
                    352:        fs = VFSTOUFS(mountp)->um_fs;
                    353:        /*
                    354:         * Copy pointer fields back into superblock before copying in   XXX
                    355:         * new superblock. These should really be in the ufsmount.      XXX
                    356:         * Note that important parameters (eg fs_ncg) are unchanged.
                    357:         */
                    358:        bcopy(&fs->fs_csp[0], &newfs->fs_csp[0], sizeof(fs->fs_csp));
                    359:        newfs->fs_maxcluster = fs->fs_maxcluster;
                    360:        bcopy(newfs, fs, (u_int)fs->fs_sbsize);
                    361:        if (fs->fs_sbsize < SBSIZE)
                    362:                bp->b_flags |= B_INVAL;
                    363: #if REV_ENDIAN_FS
                    364:        if (rev_endian)
                    365:                byte_swap_sbout(newfs);
                    366: #endif /* REV_ENDIAN_FS */
                    367:        brelse(bp);
                    368:        mountp->mnt_maxsymlinklen = fs->fs_maxsymlinklen;
                    369:        ffs_oldfscompat(fs);
                    370:        /*
                    371:         * Step 3: re-read summary information from disk.
                    372:         */
                    373:        blks = howmany(fs->fs_cssize, fs->fs_fsize);
                    374:        space = fs->fs_csp[0];
                    375:        for (i = 0; i < blks; i += fs->fs_frag) {
                    376:                size = fs->fs_bsize;
                    377:                if (i + fs->fs_frag > blks)
                    378:                        size = (blks - i) * fs->fs_fsize;
                    379:                if (error = bread(devvp, fsbtodb(fs, fs->fs_csaddr + i), size,
                    380:                    NOCRED, &bp))
                    381:                        return (error);
                    382: #if REV_ENDIAN_FS
                    383:                if (rev_endian) {
                    384:                        /* csum swaps */
                    385:                        byte_swap_ints((int *)bp->b_data, size / sizeof(int));
                    386:                }
                    387: #endif /* REV_ENDIAN_FS */
                    388:                bcopy(bp->b_data, fs->fs_csp[fragstoblks(fs, i)], (u_int)size);
                    389: #if REV_ENDIAN_FS
                    390:                if (rev_endian) {
                    391:                        /* csum swaps */
                    392:                        byte_swap_ints((int *)bp->b_data, size / sizeof(int));
                    393:                }
                    394: #endif /* REV_ENDIAN_FS */
                    395:                brelse(bp);
                    396:        }
                    397:        /*
                    398:         * We no longer know anything about clusters per cylinder group.
                    399:         */
                    400:        if (fs->fs_contigsumsize > 0) {
                    401:                lp = fs->fs_maxcluster;
                    402:                for (i = 0; i < fs->fs_ncg; i++)
                    403:                        *lp++ = fs->fs_contigsumsize;
                    404:        }
                    405: 
                    406: loop:
                    407:        simple_lock(&mntvnode_slock);
                    408:        for (vp = mountp->mnt_vnodelist.lh_first; vp != NULL; vp = nvp) {
                    409:                if (vp->v_mount != mountp) {
                    410:                        simple_unlock(&mntvnode_slock);
                    411:                        goto loop;
                    412:                }
                    413:                nvp = vp->v_mntvnodes.le_next;
                    414:                /*
                    415:                 * Step 4: invalidate all inactive vnodes.
                    416:                 */
                    417:                if (vrecycle(vp, &mntvnode_slock, p))
                    418:                        goto loop;
                    419:                /*
                    420:                 * Step 5: invalidate all cached file data.
                    421:                 */
                    422:                simple_lock(&vp->v_interlock);
                    423:                simple_unlock(&mntvnode_slock);
                    424:                if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK, p)) {
                    425:                        goto loop;
                    426:                }
                    427:                if (vinvalbuf(vp, 0, cred, p, 0, 0))
                    428:                        panic("ffs_reload: dirty2");
                    429:                /*
                    430:                 * Step 6: re-read inode data for all active vnodes.
                    431:                 */
                    432:                ip = VTOI(vp);
                    433:                if (error =
                    434:                    bread(devvp, fsbtodb(fs, ino_to_fsba(fs, ip->i_number)),
                    435:                    (int)fs->fs_bsize, NOCRED, &bp)) {
                    436:                        vput(vp);
                    437:                        return (error);
                    438:                }
                    439: #if REV_ENDIAN_FS
                    440:        if (rev_endian) {
                    441:                byte_swap_inode_in(((struct dinode *)bp->b_data +
                    442:                    ino_to_fsbo(fs, ip->i_number)), ip);
                    443:        } else {
                    444: #endif /* REV_ENDIAN_FS */
                    445:                ip->i_din = *((struct dinode *)bp->b_data +
                    446:                    ino_to_fsbo(fs, ip->i_number));
                    447: #if REV_ENDIAN_FS
                    448:        }
                    449: #endif /* REV_ENDIAN_FS */
                    450:                brelse(bp);
                    451:                vput(vp);
                    452:                simple_lock(&mntvnode_slock);
                    453:        }
                    454:        simple_unlock(&mntvnode_slock);
                    455:        return (0);
                    456: }
                    457: 
                    458: /*
                    459:  * Common code for mount and mountroot
                    460:  */
                    461: int
                    462: ffs_mountfs(devvp, mp, p)
                    463:        register struct vnode *devvp;
                    464:        struct mount *mp;
                    465:        struct proc *p;
                    466: {
                    467:        register struct ufsmount *ump;
                    468:        struct buf *bp;
                    469:        register struct fs *fs;
                    470:        dev_t dev;
                    471: #ifdef NeXT
                    472:        struct buf *cgbp;
                    473:        struct cg *cgp;
                    474:        int32_t clustersumoff;
                    475: #else
                    476:        struct partinfo dpart;
                    477: #endif /* NeXT */
                    478:        caddr_t base, space;
                    479:        int error, i, blks, size, ronly;
                    480:        int32_t *lp;
                    481:        struct ucred *cred;
                    482:        extern struct vnode *rootvp;
                    483:        u_int64_t maxfilesize;                                  /* XXX */
                    484:        u_int dbsize = DEV_BSIZE;
                    485: #if REV_ENDIAN_FS
                    486:        int rev_endian=0;
                    487: #endif /* REV_ENDIAN_FS */
                    488:        dev = devvp->v_rdev;
                    489:        cred = p ? p->p_ucred : NOCRED;
                    490:        /*
                    491:         * Disallow multiple mounts of the same device.
                    492:         * Disallow mounting of a device that is currently in use
                    493:         * (except for root, which might share swap device for miniroot).
                    494:         * Flush out any old buffers remaining from a previous use.
                    495:         */
                    496:        if (error = vfs_mountedon(devvp))
                    497:                return (error);
                    498:        if (vcount(devvp) > 1 && devvp != rootvp)
                    499:                return (EBUSY);
                    500:        if (error = vinvalbuf(devvp, V_SAVE, cred, p, 0, 0))
                    501:                return (error);
                    502: 
                    503:        ronly = (mp->mnt_flag & MNT_RDONLY) != 0;
                    504:        if (error = VOP_OPEN(devvp, ronly ? FREAD : FREAD|FWRITE, FSCRED, p))
                    505:                return (error);
                    506: #ifdef NeXT
                    507:        VOP_DEVBLOCKSIZE(devvp,&size);
                    508: #else
                    509:        if (VOP_IOCTL(devvp, DIOCGPART, (caddr_t)&dpart, FREAD, NOCRED, p) != 0)
                    510:                size = DEV_BSIZE;
                    511:        else
                    512:                size = dpart.disklab->d_secsize;
                    513: #endif
                    514: 
                    515:        bp = NULL;
                    516:        ump = NULL;
                    517:        if (error = bread(devvp, (ufs_daddr_t)(SBOFF/size), SBSIZE, cred, &bp))
                    518:                goto out;
                    519:        fs = (struct fs *)bp->b_data;
                    520: #if REV_ENDIAN_FS
                    521:        if (fs->fs_magic != FS_MAGIC || fs->fs_bsize > MAXBSIZE ||
                    522:            fs->fs_bsize < sizeof(struct fs)) {
                    523:                int magic = fs->fs_magic;
                    524:                
                    525:                byte_swap_ints(&magic, 1);
                    526:                if (magic != FS_MAGIC) {
                    527:                        error = EINVAL;
                    528:                        goto out;
                    529:                }
                    530:                byte_swap_sbin(fs);
                    531:                if (fs->fs_magic != FS_MAGIC || fs->fs_bsize > MAXBSIZE ||
                    532:                        fs->fs_bsize < sizeof(struct fs)) {
                    533:                        byte_swap_sbout(fs);
                    534:                        error = EINVAL;         /* XXX needs translation */
                    535:                        goto out;
                    536:                }
                    537:                rev_endian=1;
                    538:        }
                    539: #endif /* REV_ENDIAN_FS */
                    540:        if (fs->fs_magic != FS_MAGIC || fs->fs_bsize > MAXBSIZE ||
                    541:            fs->fs_bsize < sizeof(struct fs)) {
                    542: #if REV_ENDIAN_FS
                    543:                if (rev_endian)
                    544:                        byte_swap_sbout(fs);
                    545: #endif /* REV_ENDIAN_FS */
                    546:                error = EINVAL;         /* XXX needs translation */
                    547:                goto out;
                    548:        }
                    549: 
                    550: 
                    551:        /* Let's figure out the devblock size the file system is with */
                    552:        /* the device block size = fragment size / number of sectors per frag */
                    553: 
                    554:        dbsize = fs->fs_fsize / NSPF(fs);
                    555:        if(dbsize <= 0 ) {
                    556:                kprintf("device blocksize computaion failed\n");
                    557:         } else {
                    558:                 if (VOP_IOCTL(devvp, DKIOCSETBLOCKSIZE, &dbsize, FWRITE, NOCRED,
                    559:  p) != 0) {  
                    560:                        kprintf("failed to set device blocksize\n");
                    561:                 }  
                    562:                /* force the specfs to reread blocksize from size() */
                    563:                set_fsblocksize(devvp);
                    564:         } 
                    565: 
                    566: 
                    567:        /* XXX updating 4.2 FFS superblocks trashes rotational layout tables */
                    568:        if (fs->fs_postblformat == FS_42POSTBLFMT && !ronly) {
                    569: #if REV_ENDIAN_FS
                    570:                if (rev_endian)
                    571:                        byte_swap_sbout(fs);
                    572: #endif /* REV_ENDIAN_FS */
                    573:                error = EROFS;          /* needs translation */
                    574:                goto out;
                    575:        }
                    576: 
                    577: #ifdef NeXT
                    578:        /* If we are not mounting read only, then check for overlap 
                    579:         * condition in cylinder group's free block map.
                    580:         * If overlap exists, then force this into a read only mount
                    581:         * to avoid further corruption. PR#2216969
                    582:         */
                    583:        if (ronly == 0){
                    584:            if (error = bread (devvp, fsbtodb(fs, cgtod(fs, 0)),
                    585:                                                 (int)fs->fs_cgsize, NOCRED, &cgbp)) {
                    586:                    brelse(cgbp);
                    587:                    goto out;
                    588:            }
                    589:            cgp = (struct cg *)cgbp->b_data;
                    590: #if REV_ENDIAN_FS
                    591:        if (rev_endian)
                    592:                byte_swap_cgin(cgp,fs);
                    593: #endif /* REV_ENDIAN_FS */
                    594:            if (!cg_chkmagic(cgp)){
                    595: #if REV_ENDIAN_FS
                    596:                if (rev_endian)
                    597:                        byte_swap_cgout(cgp,fs);
                    598: #endif /* REV_ENDIAN_FS */
                    599:                    brelse(cgbp);
                    600:                    goto out;
                    601:            }
                    602:            if (cgp->cg_clustersumoff != 0) {
                    603:              /* Check for overlap */
                    604:              clustersumoff = cgp->cg_freeoff +
                    605:                      howmany(fs->fs_cpg * fs->fs_spc / NSPF(fs), NBBY);
                    606:              clustersumoff = roundup(clustersumoff, sizeof(long));
                    607:              if (cgp->cg_clustersumoff < clustersumoff) {
                    608:                    /* Overlap exists */
                    609:               mp->mnt_flag |= MNT_RDONLY;
                    610:                      ronly = 1;
                    611:              }
                    612:            }
                    613: #if REV_ENDIAN_FS
                    614:                if (rev_endian)
                    615:                        byte_swap_cgout(cgp,fs);
                    616: #endif /* REV_ENDIAN_FS */
                    617:                brelse(cgbp);
                    618:        }
                    619: #endif /* NeXT */
                    620: 
                    621:        ump = _MALLOC(sizeof *ump, M_UFSMNT, M_WAITOK);
                    622:        bzero((caddr_t)ump, sizeof *ump);
                    623:        ump->um_fs = _MALLOC((u_long)fs->fs_sbsize, M_UFSMNT,
                    624:            M_WAITOK);
                    625:        bcopy(bp->b_data, ump->um_fs, (u_int)fs->fs_sbsize);
                    626:        if (fs->fs_sbsize < SBSIZE)
                    627:                bp->b_flags |= B_INVAL;
                    628: #if REV_ENDIAN_FS
                    629:        if (rev_endian)
                    630:                byte_swap_sbout(fs);
                    631: #endif /* REV_ENDIAN_FS */
                    632:        brelse(bp);
                    633:        bp = NULL;
                    634:        fs = ump->um_fs;
                    635:        fs->fs_ronly = ronly;
                    636:        size = fs->fs_cssize;
                    637:        blks = howmany(size, fs->fs_fsize);
                    638:        if (fs->fs_contigsumsize > 0)
                    639:                size += fs->fs_ncg * sizeof(int32_t);
                    640:        base = space = _MALLOC((u_long)size, M_UFSMNT, M_WAITOK);
                    641:        base = space;
                    642:        for (i = 0; i < blks; i += fs->fs_frag) {
                    643:                size = fs->fs_bsize;
                    644:                if (i + fs->fs_frag > blks)
                    645:                        size = (blks - i) * fs->fs_fsize;
                    646:                if (error = bread(devvp, fsbtodb(fs, fs->fs_csaddr + i), size,
                    647:                    cred, &bp)) {
                    648:                        _FREE(base, M_UFSMNT);
                    649:                        goto out;
                    650:                }
                    651:                bcopy(bp->b_data, space, (u_int)size);
                    652: #if REV_ENDIAN_FS
                    653:                if (rev_endian)
                    654:                        byte_swap_ints((int *) space, size / sizeof(int));
                    655: #endif /* REV_ENDIAN_FS */
                    656:                fs->fs_csp[fragstoblks(fs, i)] = (struct csum *)space;
                    657:                space += size;
                    658:                brelse(bp);
                    659:                bp = NULL;
                    660:        }
                    661:        if (fs->fs_contigsumsize > 0) {
                    662:                fs->fs_maxcluster = lp = (int32_t *)space;
                    663:                for (i = 0; i < fs->fs_ncg; i++)
                    664:                        *lp++ = fs->fs_contigsumsize;
                    665:        }
                    666:        mp->mnt_data = (qaddr_t)ump;
                    667:        mp->mnt_stat.f_fsid.val[0] = (long)dev;
                    668:        mp->mnt_stat.f_fsid.val[1] = mp->mnt_vfc->vfc_typenum;
                    669: #ifdef NeXT
                    670: #warning hardcoded max symlen
                    671:        mp->mnt_maxsymlinklen = 60;
                    672: #else
                    673:        mp->mnt_maxsymlinklen = fs->fs_maxsymlinklen;
                    674: #endif
                    675: #if REV_ENDIAN_FS
                    676:        if (rev_endian)
                    677:                mp->mnt_flag |= MNT_REVEND;
                    678: #endif /* REV_ENDIAN_FS */
                    679:        ump->um_mountp = mp;
                    680:        ump->um_dev = dev;
                    681:        ump->um_devvp = devvp;
                    682:        ump->um_nindir = fs->fs_nindir;
                    683:        ump->um_bptrtodb = fs->fs_fsbtodb;
                    684:        ump->um_seqinc = fs->fs_frag;
                    685:        for (i = 0; i < MAXQUOTAS; i++)
                    686:                ump->um_quotas[i] = NULLVP;
                    687:        devvp->v_specflags |= SI_MOUNTEDON;
                    688:        ffs_oldfscompat(fs);
                    689:        ump->um_savedmaxfilesize = fs->fs_maxfilesize;          /* XXX */
                    690: #ifdef NeXT
                    691:        maxfilesize = (u_int64_t)0x100000000;                  /*4giga */
                    692: #else
                    693:        maxfilesize = (u_int64_t)0x40000000 * fs->fs_bsize - 1; /* XXX */
                    694: #endif /* NeXT */
                    695:        if (fs->fs_maxfilesize > maxfilesize)                   /* XXX */
                    696:                fs->fs_maxfilesize = maxfilesize;               /* XXX */
                    697:        if (ronly == 0) {
                    698:                fs->fs_clean = 0;
                    699:                (void) ffs_sbupdate(ump, MNT_WAIT);
                    700:        }
                    701:        return (0);
                    702: out:
                    703:        if (bp)
                    704:                brelse(bp);
                    705:        (void)VOP_CLOSE(devvp, ronly ? FREAD : FREAD|FWRITE, cred, p);
                    706:        if (ump) {
                    707:                _FREE(ump->um_fs, M_UFSMNT);
                    708:                _FREE(ump, M_UFSMNT);
                    709:                mp->mnt_data = (qaddr_t)0;
                    710:        }
                    711:        return (error);
                    712: }
                    713: 
                    714: /*
                    715:  * Sanity checks for old file systems.
                    716:  *
                    717:  * XXX - goes away some day.
                    718:  */
                    719: ffs_oldfscompat(fs)
                    720:        struct fs *fs;
                    721: {
                    722:        int i;
                    723: 
                    724:        fs->fs_npsect = max(fs->fs_npsect, fs->fs_nsect);       /* XXX */
                    725:        fs->fs_interleave = max(fs->fs_interleave, 1);          /* XXX */
                    726:        if (fs->fs_postblformat == FS_42POSTBLFMT)              /* XXX */
                    727:                fs->fs_nrpos = 8;                               /* XXX */
                    728:        if (fs->fs_inodefmt < FS_44INODEFMT) {                  /* XXX */
                    729:                u_int64_t sizepb = fs->fs_bsize;                /* XXX */
                    730:                                                                /* XXX */
                    731:                fs->fs_maxfilesize = fs->fs_bsize * NDADDR - 1; /* XXX */
                    732:                for (i = 0; i < NIADDR; i++) {                  /* XXX */
                    733:                        sizepb *= NINDIR(fs);                   /* XXX */
                    734:                        fs->fs_maxfilesize += sizepb;           /* XXX */
                    735:                }                                               /* XXX */
                    736:                fs->fs_qbmask = ~fs->fs_bmask;                  /* XXX */
                    737:                fs->fs_qfmask = ~fs->fs_fmask;                  /* XXX */
                    738:        }                                                       /* XXX */
                    739:        return (0);
                    740: }
                    741: 
                    742: /*
                    743:  * unmount system call
                    744:  */
                    745: int
                    746: ffs_unmount(mp, mntflags, p)
                    747:        struct mount *mp;
                    748:        int mntflags;
                    749:        struct proc *p;
                    750: {
                    751:        register struct ufsmount *ump;
                    752:        register struct fs *fs;
                    753:        int error, flags;
                    754:        flags = 0;
                    755:        if (mntflags & MNT_FORCE)
                    756:                flags |= FORCECLOSE;
                    757:        if (error = ffs_flushfiles(mp, flags, p))
                    758:                return (error);
                    759:        ump = VFSTOUFS(mp);
                    760:        fs = ump->um_fs;
                    761:        if (fs->fs_ronly == 0) {
                    762:                fs->fs_clean = 1;
                    763:                if (error = ffs_sbupdate(ump, MNT_WAIT)) {
                    764:                        fs->fs_clean = 0;
                    765: #ifndef NeXT
                    766:                /* we can atleast cleanup ; as the media could be WP */
                    767:                /* & during mount, we do not check for write failures  */
                    768:                /* FIXME LATER : the Correct fix would be to have */
                    769:                /* mount detect the WP media and downgrade to readonly mount */
                    770:                /* For now, here it is */
                    771:                        return (error);
                    772: #endif
                    773:                }
                    774:        }
                    775:        ump->um_devvp->v_specflags &= ~SI_MOUNTEDON;
                    776:        error = VOP_CLOSE(ump->um_devvp, fs->fs_ronly ? FREAD : FREAD|FWRITE,
                    777:                NOCRED, p);
                    778:        vrele(ump->um_devvp);
                    779: 
                    780:        _FREE(fs->fs_csp[0], M_UFSMNT);
                    781:        _FREE(fs, M_UFSMNT);
                    782:        _FREE(ump, M_UFSMNT);
                    783:        mp->mnt_data = (qaddr_t)0;
                    784: #if REV_ENDIAN_FS
                    785:        mp->mnt_flag &= ~MNT_REVEND;
                    786: #endif /* REV_ENDIAN_FS */
                    787:        return (error);
                    788: }
                    789: 
                    790: /*
                    791:  * Flush out all the files in a filesystem.
                    792:  */
                    793: ffs_flushfiles(mp, flags, p)
                    794:        register struct mount *mp;
                    795:        int flags;
                    796:        struct proc *p;
                    797: {
                    798:        register struct ufsmount *ump;
                    799:        int i, error;
                    800: 
                    801:        ump = VFSTOUFS(mp);
                    802: #if QUOTA
                    803:        if (mp->mnt_flag & MNT_QUOTA) {
                    804:                if (error = vflush(mp, NULLVP, SKIPSYSTEM|flags))
                    805:                        return (error);
                    806:                for (i = 0; i < MAXQUOTAS; i++) {
                    807:                        if (ump->um_quotas[i] == NULLVP)
                    808:                                continue;
                    809:                        quotaoff(p, mp, i);
                    810:                }
                    811:                /*
                    812:                 * Here we fall through to vflush again to ensure
                    813:                 * that we have gotten rid of all the system vnodes.
                    814:                 */
                    815:        }
                    816: #endif
                    817:        error = vflush(mp, NULLVP, flags);
                    818:        return (error);
                    819: }
                    820: 
                    821: /*
                    822:  * Get file system statistics.
                    823:  */
                    824: int
                    825: ffs_statfs(mp, sbp, p)
                    826:        struct mount *mp;
                    827:        register struct statfs *sbp;
                    828:        struct proc *p;
                    829: {
                    830:        register struct ufsmount *ump;
                    831:        register struct fs *fs;
                    832: 
                    833:        ump = VFSTOUFS(mp);
                    834:        fs = ump->um_fs;
                    835:        if (fs->fs_magic != FS_MAGIC)
                    836:                panic("ffs_statfs");
                    837:        sbp->f_bsize = fs->fs_fsize;
                    838:        sbp->f_iosize = fs->fs_bsize;
                    839:        sbp->f_blocks = fs->fs_dsize;
                    840:        sbp->f_bfree = fs->fs_cstotal.cs_nbfree * fs->fs_frag +
                    841:                fs->fs_cstotal.cs_nffree;
                    842:        sbp->f_bavail = freespace(fs, fs->fs_minfree);
                    843:        sbp->f_files =  fs->fs_ncg * fs->fs_ipg - ROOTINO;
                    844:        sbp->f_ffree = fs->fs_cstotal.cs_nifree;
                    845:        if (sbp != &mp->mnt_stat) {
                    846:                sbp->f_type = mp->mnt_vfc->vfc_typenum;
                    847:                bcopy((caddr_t)mp->mnt_stat.f_mntonname,
                    848:                        (caddr_t)&sbp->f_mntonname[0], MNAMELEN);
                    849:                bcopy((caddr_t)mp->mnt_stat.f_mntfromname,
                    850:                        (caddr_t)&sbp->f_mntfromname[0], MNAMELEN);
                    851:        }
                    852:        return (0);
                    853: }
                    854: 
                    855: /*
                    856:  * Go through the disk queues to initiate sandbagged IO;
                    857:  * go through the inodes to write those that have been modified;
                    858:  * initiate the writing of the super block if it has been modified.
                    859:  *
                    860:  * Note: we are always called with the filesystem marked `MPBUSY'.
                    861:  */
                    862: int
                    863: ffs_sync(mp, waitfor, cred, p)
                    864:        struct mount *mp;
                    865:        int waitfor;
                    866:        struct ucred *cred;
                    867:        struct proc *p;
                    868: {
                    869:        struct vnode *nvp, *vp;
                    870:        struct inode *ip;
                    871:        struct ufsmount *ump = VFSTOUFS(mp);
                    872:        struct fs *fs;
                    873:        int error, allerror = 0;
                    874: 
                    875:        fs = ump->um_fs;
                    876:        if (fs->fs_fmod != 0 && fs->fs_ronly != 0) {            /* XXX */
                    877:                printf("fs = %s\n", fs->fs_fsmnt);
                    878:                panic("update: rofs mod");
                    879:        }
                    880:        /*
                    881:         * Write back each (modified) inode.
                    882:         */
                    883:        simple_lock(&mntvnode_slock);
                    884: loop:
                    885:        for (vp = mp->mnt_vnodelist.lh_first;
                    886:             vp != NULL;
                    887:             vp = nvp) {
                    888:                /*
                    889:                 * If the vnode that we are about to sync is no longer
                    890:                 * associated with this mount point, start over.
                    891:                 */
                    892:                if (vp->v_mount != mp)
                    893:                        goto loop;
                    894:                simple_lock(&vp->v_interlock);
                    895:                nvp = vp->v_mntvnodes.le_next;
                    896:                ip = VTOI(vp);
                    897:                if ((vp->v_type == VNON) || (ip->i_flag &
                    898:                    (IN_ACCESS | IN_CHANGE | IN_MODIFIED | IN_UPDATE)) == 0 &&
                    899:                    vp->v_dirtyblkhd.lh_first == NULL) {
                    900:                        simple_unlock(&vp->v_interlock);
                    901:                        continue;
                    902:                }
                    903:                simple_unlock(&mntvnode_slock);
                    904:                error = vget(vp, LK_EXCLUSIVE | LK_NOWAIT | LK_INTERLOCK, p);
                    905:                if (error) {
                    906:                        simple_lock(&mntvnode_slock);
                    907:                        if (error == ENOENT)
                    908:                                goto loop;
                    909:                        continue;
                    910:                }
                    911:                if (error = VOP_FSYNC(vp, cred, waitfor, p))
                    912:                        allerror = error;
                    913:                VOP_UNLOCK(vp, 0, p);
                    914:                vrele(vp);
                    915:                simple_lock(&mntvnode_slock);
                    916:        }
                    917:        simple_unlock(&mntvnode_slock);
                    918:        /*
                    919:         * Force stale file system control information to be flushed.
                    920:         */
                    921:        if (error = VOP_FSYNC(ump->um_devvp, cred, waitfor, p))
                    922:                allerror = error;
                    923: #if QUOTA
                    924:        qsync(mp);
                    925: #endif
                    926:        /*
                    927:         * Write back modified superblock.
                    928:         */
                    929:        if (fs->fs_fmod != 0) {
                    930:                fs->fs_fmod = 0;
                    931:                fs->fs_time = time.tv_sec;
                    932:                if (error = ffs_sbupdate(ump, waitfor))
                    933:                        allerror = error;
                    934:        }
                    935:        return (allerror);
                    936: }
                    937: 
                    938: /*
                    939:  * Look up a FFS dinode number to find its incore vnode, otherwise read it
                    940:  * in from disk.  If it is in core, wait for the lock bit to clear, then
                    941:  * return the inode locked.  Detection and handling of mount points must be
                    942:  * done by the calling routine.
                    943:  */
                    944: int
                    945: ffs_vget(mp, ino, vpp)
                    946:        struct mount *mp;
                    947:        ino_t ino;
                    948:        struct vnode **vpp;
                    949: {
                    950:        struct proc *p = current_proc();                /* XXX */
                    951:        struct fs *fs;
                    952:        struct inode *ip;
                    953:        struct ufsmount *ump;
                    954:        struct buf *bp;
                    955:        struct vnode *vp;
                    956:        dev_t dev;
                    957:        int i, type, error;
                    958: 
                    959:        ump = VFSTOUFS(mp);
                    960:        dev = ump->um_dev;
                    961:        if ((*vpp = ufs_ihashget(dev, ino)) != NULL) {
                    962: #if MACH_NBC
                    963:                vp = *vpp;
                    964:                if ((vp->v_type == VREG)  && !(vp->v_vm_info)){
                    965:                        vm_info_init(vp);
                    966:                }
                    967: #endif /* MACH_NBC */
                    968:                return (0);
                    969:        }
                    970:        /* Allocate a new vnode/inode. */
                    971:         type = ump->um_devvp->v_tag == VT_MFS ? M_MFSNODE : M_FFSNODE; /* XXX */
                    972:        MALLOC_ZONE(ip, struct inode *, sizeof(struct inode), type, M_WAITOK);
                    973:        if (error = getnewvnode(VT_UFS, mp, ffs_vnodeop_p, &vp)) {
                    974:                FREE_ZONE(ip, sizeof(struct inode), type);
                    975:                *vpp = NULL;
                    976:                return (error);
                    977:        }
                    978:        bzero((caddr_t)ip, sizeof(struct inode));
                    979:        lockinit(&ip->i_lock, PINOD, "inode", 0, 0);
                    980:        vp->v_data = ip;
                    981:        ip->i_vnode = vp;
                    982:        ip->i_fs = fs = ump->um_fs;
                    983:        ip->i_dev = dev;
                    984:        ip->i_number = ino;
                    985: #if QUOTA
                    986:        for (i = 0; i < MAXQUOTAS; i++)
                    987:                ip->i_dquot[i] = NODQUOT;
                    988: #endif
                    989:        /*
                    990:         * Put it onto its hash chain and lock it so that other requests for
                    991:         * this inode will block if they arrive while we are sleeping waiting
                    992:         * for old data structures to be purged or for the contents of the
                    993:         * disk portion of this inode to be read.
                    994:         */
                    995:        ufs_ihashins(ip);
                    996: 
                    997:        /* Read in the disk contents for the inode, copy into the inode. */
                    998:        if (error = bread(ump->um_devvp, fsbtodb(fs, ino_to_fsba(fs, ino)),
                    999:            (int)fs->fs_bsize, NOCRED, &bp)) {
                   1000:                /*
                   1001:                 * The inode does not contain anything useful, so it would
                   1002:                 * be misleading to leave it on its hash chain. With mode
                   1003:                 * still zero, it will be unlinked and returned to the free
                   1004:                 * list by vput().
                   1005:                 */
                   1006:                vput(vp);
                   1007:                brelse(bp);
                   1008:                *vpp = NULL;
                   1009:                return (error);
                   1010:        }
                   1011: #if REV_ENDIAN_FS
                   1012:        if (mp->mnt_flag & MNT_REVEND) {
                   1013:                byte_swap_inode_in(((struct dinode *)bp->b_data + ino_to_fsbo(fs, ino)),ip);
                   1014:        } else {
                   1015: #endif /* REV_ENDIAN_FS */
                   1016:        ip->i_din = *((struct dinode *)bp->b_data + ino_to_fsbo(fs, ino));
                   1017: #if REV_ENDIAN_FS
                   1018:        }
                   1019: #endif /* REV_ENDIAN_FS */
                   1020:        brelse(bp);
                   1021: 
                   1022:        /*
                   1023:         * Initialize the vnode from the inode, check for aliases.
                   1024:         * Note that the underlying vnode may have changed.
                   1025:         */
                   1026:        if (error = ufs_vinit(mp, ffs_specop_p, FFS_FIFOOPS, &vp)) {
                   1027:                vput(vp);
                   1028:                *vpp = NULL;
                   1029:                return (error);
                   1030:        }
                   1031:        /*
                   1032:         * Finish inode initialization now that aliasing has been resolved.
                   1033:         */
                   1034:        ip->i_devvp = ump->um_devvp;
                   1035:        VREF(ip->i_devvp);
                   1036:        /*
                   1037:         * Set up a generation number for this inode if it does not
                   1038:         * already have one. This should only happen on old filesystems.
                   1039:         */
                   1040:        if (ip->i_gen == 0) {
                   1041:                if (++nextgennumber < (u_long)time.tv_sec)
                   1042:                        nextgennumber = time.tv_sec;
                   1043:                ip->i_gen = nextgennumber;
                   1044:                if ((vp->v_mount->mnt_flag & MNT_RDONLY) == 0)
                   1045:                        ip->i_flag |= IN_MODIFIED;
                   1046:        }
                   1047:        /*
                   1048:         * Ensure that uid and gid are correct. This is a temporary
                   1049:         * fix until fsck has been changed to do the update.
                   1050:         */
                   1051:        if (fs->fs_inodefmt < FS_44INODEFMT) {          /* XXX */
                   1052:                ip->i_uid = ip->i_din.di_ouid;          /* XXX */
                   1053:                ip->i_gid = ip->i_din.di_ogid;          /* XXX */
                   1054:        }                                               /* XXX */
                   1055: 
                   1056:        *vpp = vp;
                   1057: #if MACH_NBC
                   1058:        if ((vp->v_type == VREG)  && !(vp->v_vm_info)){
                   1059:                vm_info_init(vp);
                   1060:        }
                   1061: #endif /* MACH_NBC */
                   1062:        return (0);
                   1063: }
                   1064: 
                   1065: /*
                   1066:  * File handle to vnode
                   1067:  *
                   1068:  * Have to be really careful about stale file handles:
                   1069:  * - check that the inode number is valid
                   1070:  * - call ffs_vget() to get the locked inode
                   1071:  * - check for an unallocated inode (i_mode == 0)
                   1072:  * - check that the given client host has export rights and return
                   1073:  *   those rights via. exflagsp and credanonp
                   1074:  */
                   1075: int
                   1076: ffs_fhtovp(mp, fhp, nam, vpp, exflagsp, credanonp)
                   1077:        register struct mount *mp;
                   1078:        struct fid *fhp;
                   1079:        struct mbuf *nam;
                   1080:        struct vnode **vpp;
                   1081:        int *exflagsp;
                   1082:        struct ucred **credanonp;
                   1083: {
                   1084:        register struct ufid *ufhp;
                   1085:        struct fs *fs;
                   1086: 
                   1087:        ufhp = (struct ufid *)fhp;
                   1088:        fs = VFSTOUFS(mp)->um_fs;
                   1089:        if (ufhp->ufid_ino < ROOTINO ||
                   1090:            ufhp->ufid_ino >= fs->fs_ncg * fs->fs_ipg)
                   1091:                return (ESTALE);
                   1092:        return (ufs_check_export(mp, ufhp, nam, vpp, exflagsp, credanonp));
                   1093: }
                   1094: 
                   1095: /*
                   1096:  * Vnode pointer to File handle
                   1097:  */
                   1098: /* ARGSUSED */
                   1099: ffs_vptofh(vp, fhp)
                   1100:        struct vnode *vp;
                   1101:        struct fid *fhp;
                   1102: {
                   1103:        register struct inode *ip;
                   1104:        register struct ufid *ufhp;
                   1105: 
                   1106:        ip = VTOI(vp);
                   1107:        ufhp = (struct ufid *)fhp;
                   1108:        ufhp->ufid_len = sizeof(struct ufid);
                   1109:        ufhp->ufid_ino = ip->i_number;
                   1110:        ufhp->ufid_gen = ip->i_gen;
                   1111:        return (0);
                   1112: }
                   1113: 
                   1114: /*
                   1115:  * Initialize the filesystem; just use ufs_init.
                   1116:  */
                   1117: int
                   1118: ffs_init(vfsp)
                   1119:        struct vfsconf *vfsp;
                   1120: {
                   1121: 
                   1122:        return (ufs_init(vfsp));
                   1123: }
                   1124: 
                   1125: /*
                   1126:  * fast filesystem related variables.
                   1127:  */
                   1128: ffs_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
                   1129:        int *name;
                   1130:        u_int namelen;
                   1131:        void *oldp;
                   1132:        size_t *oldlenp;
                   1133:        void *newp;
                   1134:        size_t newlen;
                   1135:        struct proc *p;
                   1136: {
                   1137:        extern int doclusterread, doclusterwrite, doreallocblks, doasyncfree;
                   1138: 
                   1139:        /* all sysctl names at this level are terminal */
                   1140:        if (namelen != 1)
                   1141:                return (ENOTDIR);               /* overloaded */
                   1142: 
                   1143:        switch (name[0]) {
                   1144:        case FFS_CLUSTERREAD:
                   1145:                return (sysctl_int(oldp, oldlenp, newp, newlen,
                   1146:                    &doclusterread));
                   1147:        case FFS_CLUSTERWRITE:
                   1148:                return (sysctl_int(oldp, oldlenp, newp, newlen,
                   1149:                    &doclusterwrite));
                   1150:        case FFS_REALLOCBLKS:
                   1151:                return (sysctl_int(oldp, oldlenp, newp, newlen,
                   1152:                    &doreallocblks));
                   1153:        case FFS_ASYNCFREE:
                   1154:                return (sysctl_int(oldp, oldlenp, newp, newlen, &doasyncfree));
                   1155:        default:
                   1156:                return (EOPNOTSUPP);
                   1157:        }
                   1158:        /* NOTREACHED */
                   1159: }
                   1160: 
                   1161: /*
                   1162:  * Write a superblock and associated information back to disk.
                   1163:  */
                   1164: int
                   1165: ffs_sbupdate(mp, waitfor)
                   1166:        struct ufsmount *mp;
                   1167:        int waitfor;
                   1168: {
                   1169:        register struct fs *dfs, *fs = mp->um_fs;
                   1170:        register struct buf *bp;
                   1171:        int blks;
                   1172:        caddr_t space;
                   1173:        int i, size, error, allerror = 0;
                   1174: #ifdef NeXT
                   1175:        int devBlockSize=0;
                   1176: #endif /* NeXT */
                   1177: #if REV_ENDIAN_FS
                   1178:        int rev_endian=(mp->um_mountp->mnt_flag & MNT_REVEND);
                   1179: #endif /* REV_ENDIAN_FS */
                   1180: 
                   1181:        /*
                   1182:         * First write back the summary information.
                   1183:         */
                   1184:        blks = howmany(fs->fs_cssize, fs->fs_fsize);
                   1185:        space = (caddr_t)fs->fs_csp[0];
                   1186:        for (i = 0; i < blks; i += fs->fs_frag) {
                   1187:                size = fs->fs_bsize;
                   1188:                if (i + fs->fs_frag > blks)
                   1189:                        size = (blks - i) * fs->fs_fsize;
                   1190:                bp = getblk(mp->um_devvp, fsbtodb(fs, fs->fs_csaddr + i),
                   1191:                    size, 0, 0);
                   1192:                bcopy(space, bp->b_data, (u_int)size);
                   1193: #if REV_ENDIAN_FS
                   1194:                if (rev_endian) {
                   1195:                        byte_swap_ints((int *)bp->b_data, size / sizeof(int));
                   1196:                }
                   1197: #endif /* REV_ENDIAN_FS */
                   1198:                space += size;
                   1199:                if (waitfor != MNT_WAIT)
                   1200:                        bawrite(bp);
                   1201:                else if (error = bwrite(bp))
                   1202:                        allerror = error;
                   1203:        }
                   1204:        /*
                   1205:         * Now write back the superblock itself. If any errors occurred
                   1206:         * up to this point, then fail so that the superblock avoids
                   1207:         * being written out as clean.
                   1208:         */
                   1209:        if (allerror)
                   1210:                return (allerror);
                   1211: #ifdef NeXT
                   1212:        VOP_DEVBLOCKSIZE(mp->um_devvp,&devBlockSize);
                   1213:        bp = getblk(mp->um_devvp, (SBOFF/devBlockSize), (int)fs->fs_sbsize, 0, 0);
                   1214: #else
                   1215:        bp = getblk(mp->um_devvp, SBLOCK, (int)fs->fs_sbsize, 0, 0);
                   1216: #endif
                   1217:        bcopy((caddr_t)fs, bp->b_data, (u_int)fs->fs_sbsize);
                   1218:        /* Restore compatibility to old file systems.              XXX */
                   1219:        dfs = (struct fs *)bp->b_data;                          /* XXX */
                   1220:        if (fs->fs_postblformat == FS_42POSTBLFMT)              /* XXX */
                   1221:                dfs->fs_nrpos = -1;                             /* XXX */
                   1222: #if REV_ENDIAN_FS
                   1223:        /*  
                   1224:        *  Swapping bytes here ; so that in case
                   1225:        *   of inode format < FS_44INODEFMT appropriate
                   1226:        *   fields get moved 
                   1227:        */
                   1228:        if (rev_endian) {
                   1229:                byte_swap_sbout((struct fs *)bp->b_data);
                   1230:        }
                   1231: #endif /* REV_ENDIAN_FS */
                   1232:        if (fs->fs_inodefmt < FS_44INODEFMT) {                  /* XXX */
                   1233:                int32_t *lp, tmp;                               /* XXX */
                   1234:                                                                /* XXX */
                   1235:                lp = (int32_t *)&dfs->fs_qbmask;                /* XXX */
                   1236:                tmp = lp[4];                                    /* XXX */
                   1237:                for (i = 4; i > 0; i--)                         /* XXX */
                   1238:                        lp[i] = lp[i-1];                        /* XXX */
                   1239:                lp[0] = tmp;                                    /* XXX */
                   1240:        }                                                       /* XXX */
                   1241: #if REV_ENDIAN_FS
                   1242:        /* Note that dfs is already swapped so swap the filesize
                   1243:        *  before writing
                   1244:        */
                   1245:        if (rev_endian) {
                   1246:                dfs->fs_maxfilesize = NXSwapLongLong(mp->um_savedmaxfilesize);          /* XXX */
                   1247:        } else {
                   1248: #endif /* REV_ENDIAN_FS */
                   1249:                dfs->fs_maxfilesize = mp->um_savedmaxfilesize;  /* XXX */
                   1250: #if REV_ENDIAN_FS
                   1251:        }
                   1252: #endif /* REV_ENDIAN_FS */
                   1253:        if (waitfor != MNT_WAIT)
                   1254:                bawrite(bp);
                   1255:        else if (error = bwrite(bp))
                   1256:                allerror = error;
                   1257: 
                   1258:        return (allerror);
                   1259: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.