Annotation of XNU/bsd/ufs/ffs/ffs_vfsops.c, revision 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.