Annotation of kernel/bsd/hfs/hfs_vfsops.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
        !             3:  *
        !             4:  * @APPLE_LICENSE_HEADER_START@
        !             5:  * 
        !             6:  * Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
        !             7:  * Reserved.  This file contains Original Code and/or Modifications of
        !             8:  * Original Code as defined in and that are subject to the Apple Public
        !             9:  * Source License Version 1.1 (the "License").  You may not use this file
        !            10:  * except in compliance with the License.  Please obtain a copy of the
        !            11:  * License at http://www.apple.com/publicsource and read it before using
        !            12:  * this file.
        !            13:  * 
        !            14:  * The Original Code and all software distributed under the License are
        !            15:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
        !            16:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
        !            17:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
        !            18:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
        !            19:  * License for the specific language governing rights and limitations
        !            20:  * under the License.
        !            21:  * 
        !            22:  * @APPLE_LICENSE_HEADER_END@
        !            23:  */
        !            24: /*
        !            25:  * Copyright (c) 1991, 1993, 1994
        !            26:  *     The Regents of the University of California.  All rights reserved.
        !            27:  * (c) UNIX System Laboratories, Inc.
        !            28:  * All or some portions of this file are derived from material licensed
        !            29:  * to the University of California by American Telephone and Telegraph
        !            30:  * Co. or Unix System Laboratories, Inc. and are reproduced herein with
        !            31:  * the permission of UNIX System Laboratories, Inc.
        !            32:  *
        !            33:  * Redistribution and use in source and binary forms, with or without
        !            34:  * modification, are permitted provided that the following conditions
        !            35:  * are met:
        !            36:  * 1. Redistributions of source code must retain the above copyright
        !            37:  *    notice, this list of conditions and the following disclaimer.
        !            38:  * 2. Redistributions in binary form must reproduce the above copyright
        !            39:  *    notice, this list of conditions and the following disclaimer in the
        !            40:  *    documentation and/or other materials provided with the distribution.
        !            41:  * 3. All advertising materials mentioning features or use of this software
        !            42:  *    must display the following acknowledgement:
        !            43:  *     This product includes software developed by the University of
        !            44:  *     California, Berkeley and its contributors.
        !            45:  * 4. Neither the name of the University nor the names of its contributors
        !            46:  *    may be used to endorse or promote products derived from this software
        !            47:  *    without specific prior written permission.
        !            48:  *
        !            49:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
        !            50:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        !            51:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
        !            52:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
        !            53:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
        !            54:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
        !            55:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            56:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
        !            57:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
        !            58:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
        !            59:  * SUCH DAMAGE.
        !            60:  *
        !            61:  *      hfs_vfsops.c
        !            62:  *  derived from       @(#)ufs_vfsops.c        8.8 (Berkeley) 5/20/95
        !            63:  *
        !            64:  *      (c) Copyright 1997-1998 Apple Computer, Inc. All rights reserved.
        !            65:  *
        !            66:  *      hfs_vfsops.c -- VFS layer for loadable HFS file system.
        !            67:  *
        !            68:  *      HISTORY
        !            69:  *              12-Nov-1998     Pat Dirks       Changed hfs_statfs to return volume's actual log. block size (#2286198).
        !            70:  *             22-Aug-1998     Scott Roberts   Assign uid,gid, and mask for default on objects.
        !            71:  *             29-Jul-1998     Pat Dirks               Fixed changed hfs_vget() to release complex node when retrying for data fork node.
        !            72:  *             27-Jul-1998     Scott Roberts   Changes hfs_vget() to return data forks instead of complex.
        !            73:  *         14-Jul-1998  CHW                    Added check for use count of device node in hfs_mountfs
        !            74:  *         1-Jul-1998  Don Brady               Always set kHFSVolumeUnmountedMask bit of vcb->vcbAtrb in hfs_unmount.
        !            75:  *        30-Jun-1998  Don Brady               Removed hard-coded EINVAL error in hfs_mountfs (for radar #2249539).
        !            76:  *        24-Jun-1998  Don Brady               Added setting of timezone to hfs_mount (radar #2226387).
        !            77:  *             4-Jun-1998      Don Brady               Use VPUT/VRELE macros instead of vput/vrele.
        !            78:  *             6-May-1998      Scott Roberts   Updated hfs_vget with kernel changes.
        !            79:  *             29-Apr-1998     Don Brady               Update hfs_statfs to actually fill in statfs fields (radar #2227092).
        !            80:  *             23-Apr-1998     Pat Dirks               Cleaned up code to call brelse() on errors from bread().
        !            81:  *              4/20/1998      Don Brady               Remove course-grained hfs metadata locking.
        !            82:  *              4/18/1998      Don Brady               Add VCB locking.
        !            83:  *              4/16/1998      Don Brady       hfs_unmount now flushes the volume bitmap. Add b-tree locking to hfs_vget.
        !            84:  *               4/8/1998      Don Brady       Replace hfs_mdbupdate with hfs_flushvolumeheader and hfs_flushMDB.
        !            85:  *               4/8/1998      Don Brady       In hfs_unmount call hfs_mdbupdate before trashing metafiles!
        !            86:  *               4/3/1998      Don Brady       Call InitCatalogCache instead of PostInitFS.
        !            87:  *               4/1/1998      Don Brady       Get rid of gHFSFlags, gReqstVol and gFlushOnlyFlag globals (not used).
        !            88:  *              3/30/1998      Don Brady       In hfs_unmount use SKIPSYSTEM option on first vflush.
        !            89:  *              3/26/1998      Don Brady       Changed hfs_unmount to call vflush before calling hfsUnmount.
        !            90:  *                                                             In hfs_mountfs don't mount hfs-wrapper.
        !            91:  *              3/19/1998      Pat Dirks       Fixed bug in hfs_mount where device vnode was being
        !            92:  *                                                             released on way out.
        !            93:  *      11/14/1997     Pat Dirks       Derived from hfs_vfsops.c
        !            94:  */
        !            95: 
        !            96: #include <sys/types.h>
        !            97: #include <sys/namei.h>
        !            98: #include <sys/param.h>
        !            99: #include <sys/proc.h>
        !           100: #include <mach/machine/vm_types.h>
        !           101: #include <sys/vnode.h>
        !           102: #include <sys/mount.h>
        !           103: #include <sys/malloc.h>
        !           104: #include <sys/fcntl.h>
        !           105: #include <sys/stat.h>
        !           106: #include <libkern/libkern.h>
        !           107: #include <bsd/dev/disk.h>
        !           108: #include <mach/machine/simple_lock.h>
        !           109: #include <miscfs/specfs/specdev.h>
        !           110: #include <sys/systm.h>
        !           111: #include <mach/features.h>
        !           112: #include <kern/mapfs.h>
        !           113: 
        !           114: #include "hfs.h"
        !           115: #include "hfs_dbg.h"
        !           116: #include "mount_hfs.h"
        !           117: 
        !           118: #include "hfscommon/headers/FileMgrInternal.h"
        !           119: 
        !           120: typedef (*PFI)();
        !           121: 
        !           122: extern char *strncpy __P((char *, const char *, size_t));       /* Kernel already includes a copy of strncpy somewhere... */
        !           123: extern int strcmp __P((const char *, const char *));            /* Kernel already includes a copy of strcmp somewhere... */
        !           124: 
        !           125: extern struct proc * current_proc_EXTERNAL();
        !           126: 
        !           127: /* The following refer to kernel global variables used in the loading/initialization: */
        !           128: extern int maxvfsslots;                                        /* Total number of slots in the system's vfsconf table */
        !           129: extern int maxvfsconf;                                 /* The highest fs type number [old-style ID] in use [dispite its name] */
        !           130: extern int vfs_opv_numops;                                     /* The total number of defined vnode operations */
        !           131: extern int kdp_flag;
        !           132: 
        !           133: #if    DIAGNOSTIC
        !           134: int hfs_dbg_all = 0;
        !           135: int hfs_dbg_vfs = 0;
        !           136: int hfs_dbg_vop = 1;
        !           137: int hfs_dbg_load = 0;
        !           138: int hfs_dbg_io = 1;
        !           139: int hfs_dbg_utils = 1;
        !           140: int hfs_dbg_rw = 1;
        !           141: int hfs_dbg_DIT = 0;
        !           142: int hfs_dbg_tree = 0;
        !           143: int hfs_dbg_err = 0;
        !           144: int hfs_dbg_test = 0;
        !           145: #endif
        !           146: 
        !           147: /*
        !           148:  * HFS File System globals:
        !           149:  */
        !           150: Ptr                                    gBufferAddress[BUFFERPTRLISTSIZE];
        !           151: struct buf                     *gBufferHeaderPtr[BUFFERPTRLISTSIZE];
        !           152: int                                    gBufferListIndex;
        !           153: simple_lock_data_t     gBufferPtrListLock;
        !           154: 
        !           155: static char hfs_fs_name[MFSNAMELEN] = "hfs";
        !           156: 
        !           157: /* The following represent information held in low-memory on the MacOS: */
        !           158: 
        !           159: struct FSVarsRec       *gFSMVars;
        !           160: 
        !           161: /*
        !           162:  * Global variables defined in other modules:
        !           163:  */
        !           164: extern struct vnodeopv_desc hfs_vnodeop_opv_desc;
        !           165: 
        !           166: 
        !           167: int hfs_reload(struct mount *mp, struct ucred *cred, struct proc *p);
        !           168: int hfs_mountfs(struct vnode *devvp, struct mount *mp, struct proc *p);
        !           169: int hfs_vget(struct mount *mp, void *objID, struct vnode **vpp);
        !           170: void hfs_vhashinit();
        !           171: 
        !           172: static int hfs_statfs();
        !           173: 
        !           174: 
        !           175: /*
        !           176:  * VFS Operations.
        !           177:  *
        !           178:  * mount system call
        !           179:  */
        !           180: 
        !           181: static int hfs_mount (mp, path, data, ndp, p)
        !           182: register struct mount   *mp;
        !           183: char                    *path;
        !           184: caddr_t                 data;
        !           185: struct nameidata        *ndp;
        !           186: struct proc             *p;
        !           187: {
        !           188:     struct hfsmount                    *hfsmp;
        !           189:     struct vnode                       *devvp;
        !           190:     struct hfs_mount_args      args;
        !           191:     size_t                                     size;
        !           192:     int                                                retval = E_NONE;
        !           193:     mode_t                                     accessmode;
        !           194: 
        !           195:     DBG_FUNC_NAME("hfs_mount");
        !           196:     DBG_PRINT_FUNC_NAME();
        !           197: 
        !           198: #if DIAGNOSTIC
        !           199: //  call_kdp();
        !           200: #endif
        !           201: 
        !           202: #if FORCE_READONLY
        !           203: //    DBG_ASSERT((mp->mnt_flag & MNT_RDONLY) == MNT_RDONLY);      /* Should already be set */
        !           204:     mp->mnt_flag |= MNT_RDONLY;         /* ALWAYS act as if it's mounted read-only */
        !           205: #endif  /* FORCE_READONLY */
        !           206: 
        !           207:     if ((retval = copyin(data, (caddr_t)&args, sizeof(args))))
        !           208:         goto error_exit;
        !           209: 
        !           210:     /*
        !           211:      * If updating, check whether changing from read-only to
        !           212:      * read/write; if there is no device name, that's all we do.
        !           213:      */
        !           214:     if (mp->mnt_flag & MNT_UPDATE) {
        !           215:         unsigned short flags;
        !           216: 
        !           217:         DBG_VFS(("hfs_mount: handling update...\n"));
        !           218: 
        !           219:         hfsmp = VFSTOHFS(mp);
        !           220:         if (hfsmp->hfs_fs_ronly == 0 && (mp->mnt_flag & MNT_RDONLY)) {
        !           221:             flags = WRITECLOSE;
        !           222:             if (mp->mnt_flag & MNT_FORCE)
        !           223:                 flags |= FORCECLOSE;
        !           224:             if ((retval = hfs_flushfiles(mp, flags)))
        !           225:                 goto error_exit;
        !           226:             hfsmp->hfs_fs_clean = 1;
        !           227:             hfsmp->hfs_fs_ronly = 1;
        !           228:             if (HFSTOVCB(hfsmp)->vcbSigWord == kHFSPlusSigWord)
        !           229:                retval = hfs_flushvolumeheader(hfsmp, MNT_WAIT);
        !           230:             else
        !           231:                retval = hfs_flushMDB(hfsmp, MNT_WAIT);
        !           232:             
        !           233:             if (retval) {
        !           234:                 hfsmp->hfs_fs_clean = 0;
        !           235:                 hfsmp->hfs_fs_ronly = 0;
        !           236:                 goto error_exit;
        !           237:             }
        !           238:         }
        !           239: 
        !           240:         if ((mp->mnt_flag & MNT_RELOAD) &&
        !           241:             (retval = hfs_reload(mp, ndp->ni_cnd.cn_cred, p)))
        !           242:             goto error_exit;
        !           243: 
        !           244:         if (hfsmp->hfs_fs_ronly && (mp->mnt_flag & MNT_WANTRDWR)) {
        !           245:             /*
        !           246:              * If upgrade to read-write by non-root, then verify
        !           247:              * that user has necessary permissions on the device.
        !           248:              */
        !           249:             if (p->p_ucred->cr_uid != 0) {
        !           250:                 devvp = hfsmp->hfs_devvp;
        !           251:                 vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, p);
        !           252:                 if ((retval = VOP_ACCESS(devvp, VREAD | VWRITE, p->p_ucred, p))) {
        !           253:                     VOP_UNLOCK(devvp, 0, p);
        !           254:                     goto error_exit;
        !           255:                 }
        !           256:                 VOP_UNLOCK(devvp, 0, p);
        !           257:             }
        !           258:             hfsmp->hfs_fs_ronly = 0;
        !           259:             hfsmp->hfs_fs_clean = 0;
        !           260:                if (HFSTOVCB(hfsmp)->vcbSigWord == kHFSPlusSigWord)
        !           261:                                retval = hfs_flushvolumeheader(hfsmp, MNT_WAIT);
        !           262:                        else
        !           263:                                retval = hfs_flushMDB(hfsmp, MNT_WAIT);
        !           264: 
        !           265:             if (retval != E_NONE)
        !           266:                 goto error_exit;
        !           267:         }
        !           268: 
        !           269: #if 0   /* XXX PPD */
        !           270:         if (args.ma_fspec == 0) {
        !           271:             /*
        !           272:              * Process export requests.
        !           273:              */
        !           274:             retval = (vfs_export(mp, &hfsmp->hfs_export, &args.ma_export));
        !           275:         }
        !           276: #endif
        !           277: 
        !           278:         goto std_exit;
        !           279:     }
        !           280: 
        !           281:     /*
        !           282:      * Not an update, or updating the name: look up the name
        !           283:      * and verify that it refers to a sensible block device.
        !           284:      */
        !           285:     DBG_VFS(("hfs_mount: looking up device name (%s)...\n", args.ma_fspec));
        !           286: 
        !           287:     NDINIT(ndp, LOOKUP, FOLLOW, UIO_USERSPACE, args.ma_fspec, p);
        !           288:     retval = namei(ndp);
        !           289:     if (retval != E_NONE) {
        !           290:         DBG_ERR(("hfs_mount: CAN'T GET DEVICE: %s, %x\n", args.ma_fspec, ndp->ni_vp->v_rdev));
        !           291:         goto error_exit;
        !           292:     }
        !           293: 
        !           294:     devvp = ndp->ni_vp;
        !           295:     DBG_VFS(("hfs_mount: Device is %x\n",(uint)devvp));
        !           296: 
        !           297:     if (devvp->v_type != VBLK) {
        !           298:         VRELE(devvp);
        !           299:         retval = ENOTBLK;
        !           300:         goto error_exit;
        !           301:     };
        !           302:     if (major(devvp->v_rdev) >= nblkdev) {
        !           303:         VRELE(devvp);
        !           304:         retval = ENXIO;
        !           305:         goto error_exit;
        !           306:     };
        !           307: 
        !           308:     /*
        !           309:      * If mount by non-root, then verify that user has necessary
        !           310:      * permissions on the device.
        !           311:      */
        !           312:     if (p->p_ucred->cr_uid != 0) {
        !           313:         DBG_VFS(("hfs_mount: Checking mounting access\n"));
        !           314:         accessmode = VREAD;
        !           315:         if ((mp->mnt_flag & MNT_RDONLY) == 0)
        !           316:             accessmode |= VWRITE;
        !           317:         vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, p);
        !           318:         if ((retval = VOP_ACCESS(devvp, accessmode, p->p_ucred, p))) {
        !           319:             VPUT(devvp);
        !           320:             goto error_exit;
        !           321:         }
        !           322:         VOP_UNLOCK(devvp, 0, p);
        !           323:     }
        !           324: 
        !           325:        /* establish the zimezone (not used by HFS Plus) */
        !           326:        gTimeZone = args.ma_timezone;
        !           327: 
        !           328:     DBG_VFS(("hfs_mount: Attempting to mount on %s\n", path));
        !           329:     retval = hfs_mountfs(devvp, mp, p);
        !           330: 
        !           331:     if (retval != E_NONE) {
        !           332:         VRELE(devvp);
        !           333:         goto error_exit;
        !           334:     };
        !           335: 
        !           336:     hfsmp = VFSTOHFS(mp);
        !           337: 
        !           338:     hfsmp->hfs_uid = args.ma_uid;
        !           339:     hfsmp->hfs_gid = args.ma_gid;
        !           340:     hfsmp->hfs_dir_mask = args.ma_mask & ALLPERMS;
        !           341:     if (args.ma_flags & HFSFSMNT_NOXONFILES)
        !           342:         hfsmp->hfs_file_mask = (args.ma_mask & DEFFILEMODE);
        !           343:     else
        !           344:         hfsmp->hfs_file_mask = args.ma_mask & ALLPERMS;
        !           345: 
        !           346:     hfsmp->hfs_encoding = args.ma_encoding;
        !           347:        
        !           348:        /* Set the mount flag to indicate that we support volfs  */
        !           349:     mp->mnt_flag |= MNT_DOVOLFS;
        !           350:     
        !           351: 
        !           352:     (void) copyinstr(path, hfsmp->hfs_mountpoint, sizeof(hfsmp->hfs_mountpoint) - 1, &size);
        !           353:     bzero(hfsmp->hfs_mountpoint + size, sizeof(hfsmp->hfs_mountpoint) - size);
        !           354:     bcopy((caddr_t)hfsmp->hfs_mountpoint, (caddr_t)mp->mnt_stat.f_mntonname, MNAMELEN);
        !           355:     (void) copyinstr(args.ma_fspec, mp->mnt_stat.f_mntfromname, MNAMELEN - 1, &size);
        !           356:     bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size);
        !           357:     (void)hfs_statfs(mp, &mp->mnt_stat, p);
        !           358:     retval = E_NONE;
        !           359:     DBG_VFS(("hfs_mount: SUCCESSFULL MOUNT of %s on %s\n", mp->mnt_stat.f_mntfromname, mp->mnt_stat.f_mntonname));
        !           360: 
        !           361:     goto std_exit;
        !           362: 
        !           363: error_exit:
        !           364:     /* No special exit-path processing to do */
        !           365:         DBG_VFS(("hfs_mount: BAD MOUNT of %s on %s with an error of %d\n", mp->mnt_stat.f_mntfromname, mp->mnt_stat.f_mntonname, retval));
        !           366: 
        !           367: std_exit:
        !           368:         return (retval);
        !           369: 
        !           370: }
        !           371: 
        !           372: 
        !           373: /*
        !           374:  * Reload all incore data for a filesystem (used after running fsck on
        !           375:                                             * the root filesystem and finding things to fix). The filesystem must
        !           376:  * be mounted read-only.
        !           377:  *
        !           378:  * Things to do to update the mount:
        !           379:  *      1) invalidate all cached meta-data.
        !           380:  *      2) re-read superblock from disk.
        !           381:  *      3) re-read summary information from disk.
        !           382:  *      4) invalidate all inactive vnodes.
        !           383:  *      5) invalidate all cached file data.
        !           384:  *      6) re-read hfsnode data for all active vnodes.
        !           385:  */
        !           386: int hfs_reload(mountp, cred, p)
        !           387: register struct mount *mountp;
        !           388: struct ucred *cred;
        !           389: struct proc *p;
        !           390: {
        !           391: #if 0 /* XXX PPD */
        !           392:     register struct vnode *vp, *nvp, *devvp;
        !           393:     struct hfsnode *hp;
        !           394:     struct csum *space;
        !           395:     struct buf *bp;
        !           396:     struct hfsmount *hfsmp, *newfs;
        !           397:     struct disk_label *lab;
        !           398:     int i, blks, size, retval;
        !           399:     int32_t *lp;
        !           400: 
        !           401:     if ((mountp->mnt_flag & MNT_RDONLY) == 0)
        !           402:         return (EINVAL);
        !           403:     /*
        !           404:      * Step 1: invalidate all cached meta-data.
        !           405:      */
        !           406:     devvp = VFSTOUFS(mountp)->um_devvp;
        !           407:     if (vinvalbuf(devvp, 0, cred, p, 0, 0))
        !           408:         panic("ffs_reload: dirty1");
        !           409:     /*
        !           410:      * Step 2: re-read superblock from disk.
        !           411:      */
        !           412: 
        !           413: 
        !           414:     if (retval = bread(devvp, (ufs_daddr_t)(SBOFF/size), SBSIZE, NOCRED,&bp)) {
        !           415:        if (bp) brelse(bp);
        !           416:         return (retval);
        !           417:     };
        !           418: 
        !           419:     /*
        !           420:      * Copy pointer fields back into superblock before copying in               XXX
        !           421:      * new superblock. These should really be in the HFS mount point.   XXX
        !           422:      * Note that important parameters (eg fs_ncg) are unchanged.
        !           423:      */
        !           424:     bcopy(&hfsmp->hfs_fs_csp[0], &newfs->fs_csp[0], sizeof(hfsmp->hfs_fs_csp));
        !           425:     newfs->fs_maxcluster = hfsmp->hfs_fs_maxcluster;
        !           426:     bcopy(newfs, hfsmp, (u_int)hfsmp->hfs_fs_sbsize);
        !           427:     if (hfsmp->hfs_fs_sbsize < SBSIZE)
        !           428:         bp->b_flags |= B_INVAL;
        !           429:     brelse(bp);
        !           430:     mountp->mnt_maxsymlinklen = 0;
        !           431:     ffs_oldfscompat(hfsmp);
        !           432:     /*
        !           433:      * Step 3: re-read summary information from disk.
        !           434:      */
        !           435:     blks = howmany(hfsmp->hfs_fs_cssize, hfsmp->hfs_fs_fsize);
        !           436:     space = hfsmp->hfs_fs_csp[0];
        !           437:     for (i = 0; i < blks; i += hfsmp->hfs_fs_frag) {
        !           438:         size = hfsmp->hfs_fs_bsize;
        !           439:         if (i + hfsmp->hfs_fs_frag > blks)
        !           440:             size = (blks - i) * hfsmp->hfs_fs_fsize;
        !           441:         if (retval = bread(devvp, fsbtodb(hfsmp, hfsmp->hfs_fs_csaddr + i), size, NOCRED, &bp)) {
        !           442:             if (bp) brelse(bp);
        !           443:             return (retval);
        !           444:         };
        !           445:         bcopy(bp->b_data, hfsmp->hfs_fs_csp[fragstoblks(hfsmp, i)], (u_int)size);
        !           446:         brelse(bp);
        !           447:     }
        !           448:     /*
        !           449:      * We no longer know anything about clusters per cylinder group.
        !           450:      */
        !           451:     if (hfsmp->hfs_fs_contigsumsize > 0) {
        !           452:         lp = hfsmp->hfs_fs_maxcluster;
        !           453:         for (i = 0; i < hfsmp->hfs_fs_ncg; i++)
        !           454:             *lp++ = hfsmp->hfs_fs_contigsumsize;
        !           455:     }
        !           456: 
        !           457: loop:
        !           458:     simple_lock(&mntvnode_slock);
        !           459:     for (vp = mountp->mnt_vnodelist.lh_first; vp != NULL; vp = nvp) {
        !           460:         if (vp->v_mount != mountp) {
        !           461:             simple_unlock(&mntvnode_slock);
        !           462:             goto loop;
        !           463:         }
        !           464:         nvp = vp->v_mntvnodes.le_next;
        !           465:         /*
        !           466:          * Step 4: invalidate all inactive vnodes.
        !           467:          */
        !           468:         if (vrecycle(vp, &mntvnode_slock, p))
        !           469:             goto loop;
        !           470:         /*
        !           471:          * Step 5: invalidate all cached file data.
        !           472:          */
        !           473:         simple_lock(&vp->v_interlock);
        !           474:         simple_unlock(&mntvnode_slock);
        !           475:         if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK, p)) {
        !           476:             goto loop;
        !           477:         }
        !           478:         if (vinvalbuf(vp, 0, cred, p, 0, 0))
        !           479:             panic("hfs_reload: dirty2");
        !           480:         /*
        !           481:          * Step 6: re-read hfsnode data for all active vnodes.
        !           482:          */
        !           483:         hp = VTOI(vp);
        !           484:         if ((retval = bread(devvp, fsbtodb(hfsmp, ino_to_fsba(hfsmp, hp->h_i_number)),
        !           485:                                                        (int)hfsmp->hfs_fs_bsize, NOCRED, &bp))) {
        !           486:             VPUT(vp);
        !           487:             if (bp) brelse(bp);
        !           488:             return (retval);
        !           489:         }
        !           490:         hp->h_i_din = *((struct dinode *)bp->b_data +
        !           491:                       ino_to_fsbo(hfsmp, hp->h_i_number));
        !           492:         brelse(bp);
        !           493:         VPUT(vp);
        !           494:         simple_lock(&mntvnode_slock);
        !           495:     }
        !           496:     simple_unlock(&mntvnode_slock);
        !           497: #endif
        !           498:     return (0);
        !           499: }
        !           500: 
        !           501: /*
        !           502:  * Common code for mount and mountroot
        !           503:  */
        !           504: int
        !           505: hfs_mountfs(struct vnode *devvp, struct mount *mp, struct proc *p)
        !           506: {
        !           507:     int                         retval = E_NONE;
        !           508:     register struct hfsmount   *hfsmp;
        !           509:     struct buf                                 *bp;
        !           510:     dev_t                       dev;
        !           511:     HFSMasterDirectoryBlock            *mdbp;
        !           512:     int                         size, ronly;
        !           513:     struct ucred                               *cred;
        !           514: 
        !           515:     DBG_VFS(("hfs_mountfs: mp = 0x%lX\n", (u_long)mp));
        !           516: 
        !           517:     dev = devvp->v_rdev;
        !           518:     cred = p ? p->p_ucred : NOCRED;
        !           519:     /*
        !           520:      * Disallow multiple mounts of the same device.
        !           521:      * Disallow mounting of a device that is currently in use
        !           522:      * (except for root, which might share swap device for miniroot).
        !           523:      * Flush out any old buffers remaining from a previous use.
        !           524:      */
        !           525:     if ((retval = vfs_mountedon(devvp)))
        !           526:         return (retval);
        !           527:     if (vcount(devvp) > 1 && devvp != rootvp)
        !           528:                 return (EBUSY);
        !           529:     if ((retval = vinvalbuf(devvp, V_SAVE, cred, p, 0, 0)))
        !           530:         return (retval);
        !           531: 
        !           532:     ronly = (mp->mnt_flag & MNT_RDONLY) != 0;
        !           533:     DBG_VFS(("hfs_mountfs: opening device...\n"));
        !           534:     if ((retval = VOP_OPEN(devvp, ronly ? FREAD : FREAD|FWRITE, FSCRED, p)))
        !           535:         return (retval);
        !           536: 
        !           537:     size = 512;
        !           538:     DBG_VFS(("hfs_mountfs: size = %d (DEV_BSIZE = %d).\n", size, DEV_BSIZE));
        !           539: 
        !           540:     bp = NULL;
        !           541:     hfsmp = NULL;
        !           542:     DBG_VFS(("hfs_mountfs: reading MDB [block no. %d + %d bytes, size %d bytes]...\n",
        !           543:              IOBLKNOFORBLK(kMasterDirectoryBlock, size),
        !           544:              IOBYTEOFFSETFORBLK(kMasterDirectoryBlock, size),
        !           545:              IOBYTECCNTFORBLK(kMasterDirectoryBlock, kMDBSize, size)));
        !           546: 
        !           547:     if ((retval = bread(devvp, IOBLKNOFORBLK(kMasterDirectoryBlock, size),
        !           548:                                                   IOBYTECCNTFORBLK(kMasterDirectoryBlock, kMDBSize, size), cred, &bp))) {
        !           549:         if (bp) brelse(bp);
        !           550:         goto error_exit;
        !           551:        };
        !           552:     mdbp = (HFSMasterDirectoryBlock*) ((char *)bp->b_data + IOBYTEOFFSETFORBLK(kMasterDirectoryBlock, size));
        !           553: 
        !           554:     DBG_VFS(("hfs_mountfs: allocating hfsmount structure...\n"));
        !           555:     MALLOC(hfsmp, struct hfsmount *, sizeof(struct hfsmount), M_HFSMNT, M_WAITOK);
        !           556:     bzero(hfsmp, sizeof(struct hfsmount));
        !           557: 
        !           558:     DBG_VFS(("hfs_mountfs: Initializing hfsmount structure at 0x%lX...\n", (u_long)hfsmp));
        !           559:     /*
        !           560:      *  Init the volume information structure
        !           561:      */
        !           562:     mp->mnt_data = (qaddr_t)hfsmp;
        !           563:     hfsmp->hfs_mp = mp;                                                /* Make VFSTOHFS work */
        !           564:     hfsmp->hfs_vcb.vcb_hfsmp = hfsmp;          /* Make VCBTOHFS work */
        !           565:     hfsmp->hfs_raw_dev = devvp->v_rdev;
        !           566:     hfsmp->hfs_devvp = devvp;
        !           567:     hfsmp->hfs_phys_block_size = size;
        !           568:     /* The hfs_log_block_size field is updated in the respective hfs_MountHFS[Plus]Volume routine */
        !           569:     hfsmp->hfs_log_block_size = BestBlockSizeFit(mdbp->drAlBlkSiz, MAXBSIZE, hfsmp->hfs_phys_block_size);
        !           570:     hfsmp->hfs_fs_ronly = ronly;
        !           571: 
        !           572:        if (mdbp->drSigWord == kHFSPlusSigWord) {
        !           573:                DBG_VFS(("hfs_mountfs: mounting wrapper-less HFS-Plus volume...\n"));
        !           574:         retval = hfs_MountHFSPlusVolume(hfsmp, (HFSPlusVolumeHeader*) bp->b_data, 0, p);
        !           575:        }
        !           576:        else if (mdbp->drEmbedSigWord == kHFSPlusSigWord) {
        !           577:                u_long                          embBlkOffset;
        !           578:                HFSPlusVolumeHeader     *vhp;
        !           579: 
        !           580:                embBlkOffset = (mdbp->drEmbedExtent.startBlock * (mdbp->drAlBlkSiz)/kHFSBlockSize) + mdbp->drAlBlSt;
        !           581:         DBG_VFS(("hfs_mountfs: mounting embedded HFS-Plus volume at sector %ld...\n", embBlkOffset));
        !           582:                brelse(bp);
        !           583:                bp = NULL;              /* done with MDB, go grab Volume Header */
        !           584:                mdbp = NULL;
        !           585: 
        !           586:                retval = bread( devvp,
        !           587:                                                IOBLKNOFORBLK(kMasterDirectoryBlock+embBlkOffset, size),
        !           588:                                                IOBYTECCNTFORBLK(kMasterDirectoryBlock+embBlkOffset, kMDBSize, size),
        !           589:                                                cred,
        !           590:                                                &bp);
        !           591:                if (retval) {
        !           592:                        if (bp) brelse(bp);
        !           593:                        goto error_exit;
        !           594:                };
        !           595:                vhp = (HFSPlusVolumeHeader*) ((char *)bp->b_data + IOBYTEOFFSETFORBLK(kMasterDirectoryBlock, size));
        !           596: 
        !           597:                retval = hfs_MountHFSPlusVolume(hfsmp, vhp, embBlkOffset, p);
        !           598:     }
        !           599:     else { // pass all other volume formats to MountHFSVolume  
        !           600:                DBG_VFS(("hfs_mountfs: mounting regular HFS volume...\n"));
        !           601:                retval = hfs_MountHFSVolume( hfsmp, mdbp, p);
        !           602:        }
        !           603: 
        !           604:     if ( retval ) {
        !           605:                goto error_exit;
        !           606:        }
        !           607: 
        !           608:     brelse(bp);
        !           609:     bp = NULL;
        !           610:        
        !           611:     if (HFSTOVCB(hfsmp)->vcbSigWord == kHFSPlusSigWord)
        !           612:         mp->mnt_stat.f_fsid.val[0] = (long)dev;
        !           613:     else
        !           614:         mp->mnt_stat.f_fsid.val[0] = (long)dev | HFSFSMNT_HFSSTDMASK;
        !           615:     mp->mnt_stat.f_fsid.val[1] = mp->mnt_vfc->vfc_typenum;
        !           616:     mp->mnt_maxsymlinklen = 0;
        !           617:     devvp->v_specflags |= SI_MOUNTEDON;
        !           618: 
        !           619:     if (ronly == 0) {
        !           620:         hfsmp->hfs_fs_clean = 0;
        !           621:         if (HFSTOVCB(hfsmp)->vcbSigWord == kHFSPlusSigWord)
        !           622:                (void) hfs_flushvolumeheader(hfsmp, MNT_WAIT);
        !           623:         else
        !           624:                (void) hfs_flushMDB(hfsmp, MNT_WAIT);
        !           625:     }
        !           626:     goto std_exit;
        !           627: 
        !           628: error_exit:
        !           629:         DBG_VFS(("hfs_mountfs: exiting with error %d...\n", retval));
        !           630: 
        !           631:     if (bp)
        !           632:         brelse(bp);
        !           633:     (void)VOP_CLOSE(devvp, ronly ? FREAD : FREAD|FWRITE, cred, p);
        !           634:     if (hfsmp) {
        !           635:         FREE(hfsmp, M_HFSMNT);
        !           636:         mp->mnt_data = (qaddr_t)0;
        !           637:     }
        !           638: 
        !           639: std_exit:
        !           640:         return (retval);
        !           641: }
        !           642: 
        !           643: 
        !           644: /*
        !           645:  * Make a filesystem operational.
        !           646:  * Nothing to do at the moment.
        !           647:  */
        !           648: /* ARGSUSED */
        !           649: int hfs_start(mp, flags, p)
        !           650: struct mount *mp;
        !           651: int flags;
        !           652: struct proc *p;
        !           653: {
        !           654:     DBG_FUNC_NAME("hfs_start");
        !           655:     DBG_PRINT_FUNC_NAME();
        !           656: 
        !           657:     return (0);
        !           658: }
        !           659: 
        !           660: 
        !           661: /*
        !           662:  * unmount system call
        !           663:  */
        !           664: int hfs_unmount(mp, mntflags, p)
        !           665: struct mount *mp;
        !           666: int mntflags;
        !           667: struct proc *p;
        !           668: {
        !           669:     struct hfsmount            *hfsmp = VFSTOHFS(mp);
        !           670:     int                                        retval = E_NONE;
        !           671:     int                                        uflags; /* vflush flag for user vnodes pass */
        !           672: 
        !           673:     DBG_VFS(("hfs_unmount: volume: 0x%x\n", (uint)hfsmp));
        !           674:     uflags = SKIPSYSTEM;
        !           675:     if (mntflags & MNT_FORCE)
        !           676:         uflags |= FORCECLOSE;
        !           677:         
        !           678:        /*
        !           679:         *      Remove any user vnodes (non-system)
        !           680:         */
        !           681:     retval = vflush(mp, NULL, uflags);
        !           682:        
        !           683:        /* Run it again, if we were busy...there might be complex nodes left */
        !           684:        if (retval == EBUSY)
        !           685:         retval = vflush(mp, NULL, uflags);
        !           686: 
        !           687:     if (retval != E_NONE)
        !           688:         return (retval);
        !           689: 
        !           690:        /*
        !           691:         *      Flush out the volume bitmap and MDB/Volume Header
        !           692:         */
        !           693:    if (hfsmp->hfs_fs_ronly == 0) {
        !           694:         hfsmp->hfs_fs_clean = 1;
        !           695:                HFSTOVCB(hfsmp)->vcbAtrb |=     kHFSVolumeUnmountedMask;
        !           696:         if (HFSTOVCB(hfsmp)->vcbSigWord == kHFSPlusSigWord)
        !           697:                retval = hfs_flushvolumeheader(hfsmp, MNT_WAIT);
        !           698:         else
        !           699:                retval = hfs_flushMDB(hfsmp, MNT_WAIT);
        !           700:        
        !           701:         if (retval == 0)
        !           702:                        retval = VOP_FSYNC(hfsmp->hfs_devvp, NOCRED, MNT_WAIT, p);
        !           703: 
        !           704:         if (retval) {
        !           705:             hfsmp->hfs_fs_clean = 0;
        !           706:             if ((mntflags & MNT_FORCE) == 0)
        !           707:                                return (retval);        /* could not flush everything */
        !           708:                }
        !           709:     }
        !           710: 
        !           711:        /*
        !           712:         *      Invalidate our caches and release metadata vnodes
        !           713:         */
        !           714:     retval = hfsUnmount(hfsmp, p);
        !           715:     if(retval != E_NONE) {
        !           716:         DBG_ERR(("hfs_unmount: hfsUnmount FAILED: %d\n", retval));
        !           717:     }
        !           718: 
        !           719:        /*
        !           720:         *      Remove the metadata vnodes (they should not be busy)
        !           721:         */
        !           722:     retval = vflush(mp, NULL, 0);
        !           723:     ASSERT(retval != EBUSY);
        !           724:     if (retval != E_NONE)
        !           725:         return (retval);       /* XXX leaving now would be bad - we're in an inconsistent state! */
        !           726: 
        !           727:     hfsmp->hfs_devvp->v_specflags &= ~SI_MOUNTEDON;
        !           728: 
        !           729:     retval = VOP_CLOSE(hfsmp->hfs_devvp, hfsmp->hfs_fs_ronly ? FREAD : FREAD|FWRITE,
        !           730:                        NOCRED, p);
        !           731:     VRELE(hfsmp->hfs_devvp);
        !           732: 
        !           733:     FREE(hfsmp, M_HFSMNT);
        !           734:     mp->mnt_data = (qaddr_t)0;
        !           735: 
        !           736:     DBG_VFS(("hfs_unmount: Finished, returning %d\n", retval));
        !           737: 
        !           738:     return(retval);
        !           739: }
        !           740: 
        !           741: 
        !           742: /*
        !           743:  * Return the root of a filesystem.
        !           744:  *
        !           745:  *              OUT - vpp, should be locked and vget()'d (to increment usecount and lock)
        !           746:  */
        !           747: int hfs_root(mp, vpp)
        !           748: struct mount *mp;
        !           749: struct vnode **vpp;
        !           750: {
        !           751:     struct vnode *nvp;
        !           752:     int retval;
        !           753:     UInt32 rootObjID = kRootDirID;
        !           754: 
        !           755:     DBG_FUNC_NAME("hfs_root");
        !           756:     DBG_PRINT_FUNC_NAME();
        !           757: 
        !           758:     if ((retval = VFS_VGET(mp, &rootObjID, &nvp)))
        !           759:         return (retval);
        !           760: 
        !           761:     *vpp = nvp;
        !           762:     return (0);
        !           763: }
        !           764: 
        !           765: /*
        !           766:  * Do operations associated with quotas
        !           767:  */
        !           768: int hfs_quotactl(mp, cmds, uid, arg, p)
        !           769: struct mount *mp;
        !           770: int cmds;
        !           771: uid_t uid;
        !           772: caddr_t arg;
        !           773: struct proc *p;
        !           774: {
        !           775:     DBG_FUNC_NAME("hfs_quotactl");
        !           776:     DBG_PRINT_FUNC_NAME();
        !           777: 
        !           778:     return (EOPNOTSUPP);
        !           779: }
        !           780: 
        !           781: 
        !           782: 
        !           783: /*
        !           784:  * Get file system statistics.
        !           785:  */
        !           786: static int hfs_statfs(mp, sbp, p)
        !           787: struct mount *mp;
        !           788: register struct statfs *sbp;
        !           789: struct proc *p;
        !           790: {
        !           791:     ExtendedVCB *vcb = VFSTOVCB(mp);
        !           792:     struct hfsmount *hfsmp = VFSTOHFS(mp);
        !           793:     u_long freeCNIDs;
        !           794: 
        !           795:     DBG_FUNC_NAME("hfs_statfs");
        !           796:     DBG_PRINT_FUNC_NAME();
        !           797: 
        !           798:        freeCNIDs = (u_long)0xFFFFFFFF - (u_long)vcb->vcbNxtCNID;
        !           799: 
        !           800:        sbp->f_bsize = vcb->blockSize;
        !           801:     sbp->f_iosize = hfsmp->hfs_log_block_size;
        !           802:        sbp->f_blocks = vcb->totalBlocks;
        !           803:        sbp->f_bfree = vcb->freeBlocks;
        !           804:        sbp->f_bavail = vcb->freeBlocks;
        !           805:        sbp->f_files = (u_long)vcb->vcbFilCnt + (u_long)vcb->vcbDirCnt;
        !           806:        sbp->f_ffree = MIN(freeCNIDs, vcb->freeBlocks);
        !           807:        
        !           808:     sbp->f_type = 0;
        !           809:     if (sbp != &mp->mnt_stat) {
        !           810:         sbp->f_type = mp->mnt_vfc->vfc_typenum;
        !           811:         bcopy((caddr_t)mp->mnt_stat.f_mntonname,
        !           812:               (caddr_t)&sbp->f_mntonname[0], MNAMELEN);
        !           813:         bcopy((caddr_t)mp->mnt_stat.f_mntfromname,
        !           814:               (caddr_t)&sbp->f_mntfromname[0], MNAMELEN);
        !           815:     }
        !           816:     return (0);
        !           817: }
        !           818: 
        !           819: 
        !           820: /*
        !           821:  * Go through the disk queues to initiate sandbagged IO;
        !           822:  * go through the inodes to write those that have been modified;
        !           823:  * initiate the writing of the super block if it has been modified.
        !           824:  *
        !           825:  * Note: we are always called with the filesystem marked `MPBUSY'.
        !           826:  */
        !           827: static int hfs_sync(mp, waitfor, cred, p)
        !           828: struct mount *mp;
        !           829: int waitfor;
        !           830: struct ucred *cred;
        !           831: struct proc *p;
        !           832: {
        !           833:     struct vnode               *nvp, *vp, *btvp;
        !           834:     struct hfsnode             *hp;
        !           835:     struct hfsmount            *hfsmp = VFSTOHFS(mp);
        !           836:     ExtendedVCB                        *vcb;
        !           837:     int error, allerror = 0;
        !           838: 
        !           839:     DBG_FUNC_NAME("hfs_sync");
        !           840:     DBG_PRINT_FUNC_NAME();
        !           841: 
        !           842:     hfsmp = VFSTOHFS(mp);
        !           843:     if (hfsmp->hfs_fs_ronly != 0) {
        !           844:         panic("update: rofs mod");
        !           845:     };
        !           846: 
        !           847:     /*
        !           848:      * Write back each 'modified' vnode
        !           849:      */
        !           850:     btvp = 0;
        !           851:     simple_lock(&mntvnode_slock);
        !           852: 
        !           853: loop:;
        !           854: 
        !           855:     for (vp = mp->mnt_vnodelist.lh_first;
        !           856:          vp != NULL;
        !           857:          vp = nvp) {
        !           858:         /*
        !           859:          * If the vnode that we are about to sync is no longer
        !           860:          * associated with this mount point, start over.
        !           861:          */
        !           862:         if (vp->v_mount != mp)
        !           863:             goto loop;
        !           864:         simple_lock(&vp->v_interlock);
        !           865:         nvp = vp->v_mntvnodes.le_next;
        !           866:         hp = VTOH(vp);
        !           867:         if (H_FILEID(hp) == 3)
        !           868:             btvp = vp;
        !           869:         if ((hp->h_meta->h_nodeflags & (IN_ACCESS | IN_CHANGE | IN_MODIFIED | IN_UPDATE)) == 0 &&
        !           870:             vp->v_dirtyblkhd.lh_first == NULL) {
        !           871:             simple_unlock(&vp->v_interlock);
        !           872:             continue;
        !           873:         }
        !           874: 
        !           875:         simple_unlock(&mntvnode_slock);
        !           876:         error = vget(vp, LK_EXCLUSIVE | LK_NOWAIT | LK_INTERLOCK, p);
        !           877:         DBG_ASSERT(*((int*)&vp->v_interlock) == 0);
        !           878:         if (error) {
        !           879:             DBG_ERR(("hfs_sync: error %d on vget for vnode 0x%lX.\n", error, (u_long)vp));
        !           880:             simple_lock(&mntvnode_slock);
        !           881:             if (error == ENOENT)
        !           882:                 goto loop;
        !           883:             continue;
        !           884:         }
        !           885: 
        !           886:         if ((error = VOP_FSYNC(vp, cred, waitfor, p))) {
        !           887:             DBG_ERR(("hfs_sync: error %d calling fsync on vnode 0x%X.\n", error, (u_int)vp));
        !           888:             allerror = error;
        !           889:         };
        !           890:         DBG_ASSERT(*((volatile int *)(&(vp)->v_interlock))==0);
        !           891:         VPUT(vp);
        !           892:         simple_lock(&mntvnode_slock);
        !           893:     };
        !           894: 
        !           895:     /* Now reprocess the BTree node, stored above */
        !           896:     {
        !           897:         /*
        !           898:          * If the vnode that we are about to sync is no longer
        !           899:          * associated with this mount point, start over.
        !           900:          */
        !           901:         if ((btvp==0) || (btvp->v_mount != mp))
        !           902:             goto skipBtree;
        !           903:         simple_lock(&btvp->v_interlock);
        !           904:         hp = VTOH(btvp);
        !           905:         if ((hp->h_meta->h_nodeflags & (IN_ACCESS | IN_CHANGE | IN_MODIFIED | IN_UPDATE)) == 0 &&
        !           906:             btvp->v_dirtyblkhd.lh_first == NULL) {
        !           907:             simple_unlock(&btvp->v_interlock);
        !           908:             goto skipBtree;
        !           909:         }
        !           910:         simple_unlock(&mntvnode_slock);
        !           911:         error = vget(btvp, LK_EXCLUSIVE | LK_NOWAIT | LK_INTERLOCK, p);
        !           912:         if (error) {
        !           913:             simple_lock(&mntvnode_slock);
        !           914:             goto skipBtree;
        !           915:         }
        !           916:         if ((error = VOP_FSYNC(btvp, cred, waitfor, p)))
        !           917:             allerror = error;
        !           918:         VOP_UNLOCK(btvp, 0, p);
        !           919:         VRELE(btvp);
        !           920:         simple_lock(&mntvnode_slock);
        !           921:     };
        !           922: 
        !           923: skipBtree:;
        !           924: 
        !           925:     simple_unlock(&mntvnode_slock);
        !           926: 
        !           927:     /*
        !           928:      * Force stale file system control information to be flushed.
        !           929:      */
        !           930:     if ((error = VOP_FSYNC(hfsmp->hfs_devvp, cred, waitfor, p)))
        !           931:         allerror = error;
        !           932:     /*
        !           933:      * Write back modified superblock.
        !           934:      */
        !           935:        vcb = HFSTOVCB(hfsmp);
        !           936: 
        !           937:     if (IsVCBDirty(vcb)) {
        !           938:        if (vcb->vcbSigWord == kHFSPlusSigWord)
        !           939:                error = hfs_flushvolumeheader(hfsmp, waitfor);
        !           940:        else
        !           941:                error = hfs_flushMDB(hfsmp, waitfor);
        !           942:        
        !           943:         if (error)
        !           944:             allerror = error;
        !           945:     };
        !           946: 
        !           947:     return (allerror);
        !           948: }
        !           949: 
        !           950: 
        !           951: /*
        !           952:  * File handle to vnode
        !           953:  *
        !           954:  * Have to be really careful about stale file handles:
        !           955:  * - check that the hfsnode number is valid
        !           956:  * - call hfs_vget() to get the locked hfsnode
        !           957:  * - check for an unallocated hfsnode (i_mode == 0)
        !           958:  * - check that the given client host has export rights and return
        !           959:  *   those rights via. exflagsp and credanonp
        !           960:  */
        !           961: int
        !           962: hfs_fhtovp(mp, fhp, nam, vpp, exflagsp, credanonp)
        !           963: register struct mount *mp;
        !           964: struct fid *fhp;
        !           965: struct mbuf *nam;
        !           966: struct vnode **vpp;
        !           967: int *exflagsp;
        !           968: struct ucred **credanonp;
        !           969: {
        !           970:     DBG_FUNC_NAME("hfs_fhtovp");
        !           971:     DBG_PRINT_FUNC_NAME();
        !           972: 
        !           973:     return (EOPNOTSUPP);
        !           974: }
        !           975: 
        !           976: /*
        !           977:  * Vnode pointer to File handle
        !           978:  */
        !           979: /* ARGSUSED */
        !           980: static int hfs_vptofh(vp, fhp)
        !           981: struct vnode *vp;
        !           982: struct fid *fhp;
        !           983: {
        !           984:     DBG_FUNC_NAME("hfs_vptofh");
        !           985:     DBG_PRINT_FUNC_NAME();
        !           986: 
        !           987:     return (EOPNOTSUPP);
        !           988: }
        !           989: 
        !           990: 
        !           991: 
        !           992: /*
        !           993:  * Initial HFS filesystems, done only once.
        !           994:  */
        !           995: int
        !           996: hfs_init(vfsp)
        !           997: struct vfsconf *vfsp;
        !           998: {
        !           999:     int i;
        !          1000:     static int done = 0;
        !          1001:     OSErr err;
        !          1002: 
        !          1003:     DBG_FUNC_NAME("hfs_init");
        !          1004:     DBG_PRINT_FUNC_NAME();
        !          1005: 
        !          1006:     if (done)
        !          1007:         return (0);
        !          1008:     done = 1;
        !          1009:     hfs_vhashinit();
        !          1010: 
        !          1011:     simple_lock_init (&gBufferPtrListLock);
        !          1012: 
        !          1013:     for (i = BUFFERPTRLISTSIZE - 1; i >= 0; --i) {
        !          1014:         gBufferAddress[i] = NULL;
        !          1015:         gBufferHeaderPtr[i] = NULL;
        !          1016:     };
        !          1017:     gBufferListIndex = 0;
        !          1018: 
        !          1019:     /*
        !          1020:      * Do any initialization that the MacOS/Rhapsody shared code relies on
        !          1021:      * (normally done as part of MacOS's startup):
        !          1022:      */
        !          1023:     MALLOC(gFSMVars, FSVarsRec *, sizeof(FSVarsRec), M_HFSMNT, M_WAITOK);
        !          1024:     bzero(gFSMVars, sizeof(FSVarsRec));
        !          1025: 
        !          1026:        /*
        !          1027:         * Allocate Catalog Iterator cache...
        !          1028:         */
        !          1029:        err = InitCatalogCache();
        !          1030: #if DIAGNOSTIC
        !          1031:     if (err) PANIC("hfs_init: Error returned from InitCatalogCache() call.");
        !          1032: #endif
        !          1033:        /*
        !          1034:         * XXX do we need to setup the following?
        !          1035:         *
        !          1036:         * GMT offset, Unicode globals, CatSearch Buffers, BTSscanner
        !          1037:         */
        !          1038: 
        !          1039:     return E_NONE;
        !          1040: }
        !          1041: 
        !          1042: /*
        !          1043:  * fast filesystem related variables.
        !          1044:  */
        !          1045: static int hfs_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
        !          1046: int *name;
        !          1047: u_int namelen;
        !          1048: void *oldp;
        !          1049: size_t *oldlenp;
        !          1050: void *newp;
        !          1051: size_t newlen;
        !          1052: struct proc *p;
        !          1053: {
        !          1054:     DBG_FUNC_NAME("hfs_sysctl");
        !          1055:     DBG_PRINT_FUNC_NAME();
        !          1056: 
        !          1057:     return (EOPNOTSUPP);
        !          1058: }
        !          1059: 
        !          1060: /*     This will return a vnode or either a directory or a data vnode based on an object id. If
        !          1061:  *  it is a file id, its data fork will be returned.
        !          1062:  */
        !          1063: 
        !          1064: int hfs_vget(struct mount *mp,
        !          1065:              void *ino,
        !          1066:              struct vnode **vpp)
        !          1067: {
        !          1068:     struct hfsmount    *hfsmp;
        !          1069:     struct proc                        *p;
        !          1070:     dev_t                              dev;
        !          1071:     hfsCatalogInfo             catInfo;
        !          1072:     UInt8                              forkType;
        !          1073:     int                                retval = E_NONE;
        !          1074: 
        !          1075:     DBG_VFS(("hfs_vget: ino = %ld\n", *(UInt32 *)ino));
        !          1076: 
        !          1077:     hfsmp = VFSTOHFS(mp);
        !          1078:     p = CURRENT_PROC;
        !          1079:     dev = hfsmp->hfs_raw_dev;
        !          1080:        
        !          1081:        /* First check to see if it is in the cache */
        !          1082:        /* If it is, and it is complex, check again if its data fork is there */
        !          1083:     *vpp = hfs_vhashget(dev, *(UInt32 *)ino, kDirCmplx);
        !          1084:     if (*vpp && (*vpp)->v_type == VCPLX) {
        !          1085:         vput(*vpp);
        !          1086:         *vpp = hfs_vhashget(dev, *(UInt32 *)ino, kDataFork);
        !          1087:        }
        !          1088: 
        !          1089:        /* The vnode is not in the cache, so lets make it */
        !          1090:     if (*vpp == NULL)
        !          1091:       {
        !          1092:        /* lock catalog b-tree */
        !          1093:         retval = hfs_metafilelocking(hfsmp, kHFSCatalogFileID, LK_SHARED, p);
        !          1094:         if (retval != E_NONE) goto Err_Exit;
        !          1095: 
        !          1096:         retval = hfsLookup(VFSTOVCB(mp), *(UInt32 *)ino, NULL, -1, 0, &catInfo);
        !          1097: 
        !          1098:         /* unlock catalog b-tree */
        !          1099:         (void) hfs_metafilelocking(hfsmp, kHFSCatalogFileID, LK_RELEASE, p);
        !          1100: 
        !          1101:         if (retval != E_NONE) goto Err_Exit;
        !          1102: 
        !          1103:         forkType = (catInfo.nodeData.nodeType == kCatalogFolderNode) ? kDirCmplx : kDataFork;
        !          1104:         retval = hfsGet(VFSTOVCB(mp), &catInfo, forkType, NULL, vpp);
        !          1105:       }
        !          1106: 
        !          1107: #if MACH_NBC
        !          1108:     if (*vpp && ((*vpp)->v_type == VREG)  && !((*vpp)->v_vm_info)){
        !          1109:         vm_info_init(*vpp);
        !          1110:     }
        !          1111: #endif /* MACH_NBC */
        !          1112: 
        !          1113: Err_Exit:
        !          1114: 
        !          1115:        if (retval != E_NONE) {
        !          1116:         DBG_VFS(("hfs_vget: Error returned of %d\n", retval));
        !          1117:                }
        !          1118:        else {
        !          1119:         DBG_VFS(("hfs_vget: vp = 0x%x\n", (u_int)*vpp));
        !          1120:                }
        !          1121: 
        !          1122:     return (retval);
        !          1123: 
        !          1124: }
        !          1125: 
        !          1126: short hfs_flushfiles(struct mount *mp, unsigned short flags)
        !          1127: {
        !          1128:     int  retval;
        !          1129: 
        !          1130:     DBG_FUNC_NAME("hfs_flushfiles");
        !          1131:     DBG_PRINT_FUNC_NAME();
        !          1132: 
        !          1133:     retval = vflush(mp, VFSTOVCB(mp)->catalogRefNum, flags);
        !          1134:        if (retval) return retval;
        !          1135:        DBG_VFS(("\tAll files except Catalog is flushed\n"));
        !          1136: 
        !          1137:        /* Now 'close' the catalog Btree, and then flush it */
        !          1138:     VRELE(VFSTOVCB(mp)->catalogRefNum);
        !          1139:     retval = vflush(mp, NULL, flags);
        !          1140:     DBG_VFS(("\tCatalog is now flushed\n"));
        !          1141:    return (retval);
        !          1142: }
        !          1143: 
        !          1144: 
        !          1145: short hfs_flushMDB(struct hfsmount *hfsmp, int waitfor)
        !          1146: {
        !          1147:        ExtendedVCB                     *vcb = HFSTOVCB(hfsmp);
        !          1148:        FCB                                             *fcb;
        !          1149:        HFSMasterDirectoryBlock *mdb;
        !          1150:        struct buf                              *bp;
        !          1151:        int                                             retval;
        !          1152:        int                     size = kMDBSize;        /* 512 */
        !          1153:        size_t                                  namelen;
        !          1154: 
        !          1155:        if (vcb->vcbSigWord != kHFSSigWord)
        !          1156:                return EINVAL;
        !          1157: 
        !          1158:     ASSERT(hfsmp->hfs_devvp != NULL);
        !          1159: 
        !          1160:        retval = bread(hfsmp->hfs_devvp, IOBLKNOFORBLK(kMasterDirectoryBlock, size),
        !          1161:                                        IOBYTECCNTFORBLK(kMasterDirectoryBlock, kMDBSize, size), NOCRED, &bp);
        !          1162:        if (retval) {
        !          1163:            DBG_VFS((" hfs_flushMDB bread return error! (%d)\n", retval));
        !          1164:                if (bp) brelse(bp);
        !          1165:                return retval;
        !          1166:        }
        !          1167: 
        !          1168:     ASSERT(bp != NULL);
        !          1169:     ASSERT(bp->b_data != NULL);
        !          1170:     ASSERT(bp->b_bcount == size);
        !          1171: 
        !          1172:        mdb = (HFSMasterDirectoryBlock *)((char *)bp->b_data + IOBYTEOFFSETFORBLK(kMasterDirectoryBlock, size));
        !          1173: 
        !          1174:        VCB_LOCK(vcb);
        !          1175:        mdb->drCrDate   = vcb->vcbCrDate;
        !          1176:        mdb->drLsMod    = vcb->vcbLsMod;
        !          1177:        mdb->drAtrb             = vcb->vcbAtrb;
        !          1178:        mdb->drNmFls    = vcb->vcbNmFls;
        !          1179:        mdb->drAllocPtr = vcb->nextAllocation;
        !          1180:        mdb->drClpSiz   = vcb->vcbClpSiz;
        !          1181:        mdb->drNxtCNID  = vcb->vcbNxtCNID;
        !          1182:        mdb->drFreeBks  = vcb->freeBlocks;
        !          1183: 
        !          1184:     copystr(vcb->vcbVN, &mdb->drVN[1], sizeof(mdb->drVN)-1, &namelen);
        !          1185:     mdb->drVN[0] = namelen-1;
        !          1186:     mdb->drVN[namelen] = '\0';
        !          1187:        
        !          1188:        mdb->drVolBkUp  = vcb->vcbVolBkUp;
        !          1189:        mdb->drVSeqNum  = vcb->vcbVSeqNum;
        !          1190:        mdb->drWrCnt    = vcb->vcbWrCnt;
        !          1191:        mdb->drNmRtDirs = vcb->vcbNmRtDirs;
        !          1192:        mdb->drFilCnt   = vcb->vcbFilCnt;
        !          1193:        mdb->drDirCnt   = vcb->vcbDirCnt;
        !          1194:        
        !          1195:        bcopy(vcb->vcbFndrInfo, mdb->drFndrInfo, sizeof(mdb->drFndrInfo));
        !          1196: 
        !          1197:        fcb = VTOFCB(vcb->extentsRefNum);
        !          1198:        bcopy(fcb->fcbExtRec, mdb->drXTExtRec, sizeof(HFSExtentRecord));
        !          1199:        mdb->drXTFlSize = fcb->fcbPLen;
        !          1200:        mdb->drXTClpSiz = fcb->fcbClmpSize;
        !          1201:        
        !          1202:        fcb = VTOFCB(vcb->catalogRefNum);
        !          1203:        bcopy(fcb->fcbExtRec, mdb->drCTExtRec, sizeof(HFSExtentRecord));
        !          1204:        mdb->drCTFlSize = fcb->fcbPLen;
        !          1205:        mdb->drCTClpSiz = fcb->fcbClmpSize;
        !          1206:        VCB_UNLOCK(vcb);
        !          1207: 
        !          1208: 
        !          1209:     if (waitfor != MNT_WAIT)
        !          1210:                bawrite(bp);
        !          1211:     else 
        !          1212:                retval = bwrite(bp);
        !          1213:  
        !          1214:        MarkVCBClean( vcb );
        !          1215: 
        !          1216:        return (retval);
        !          1217: }
        !          1218: 
        !          1219: 
        !          1220: short hfs_flushvolumeheader(struct hfsmount *hfsmp, int waitfor)
        !          1221: {
        !          1222:     ExtendedVCB                        *vcb = HFSTOVCB(hfsmp);
        !          1223:     ExtendedFCB                                *extendedFCB;
        !          1224:     FCB                                                *fcb;
        !          1225:     HFSPlusVolumeHeader                *volumeHeader;
        !          1226:        struct vnode                    *vp;
        !          1227:     int                                                retval;
        !          1228:     int                     size = sizeof(HFSPlusVolumeHeader);
        !          1229:     struct buf                                 *bp;
        !          1230: 
        !          1231:        if (vcb->vcbSigWord != kHFSPlusSigWord)
        !          1232:                return EINVAL;
        !          1233: 
        !          1234:        retval = bread(hfsmp->hfs_devvp, IOBLKNOFORBLK((vcb->hfsPlusIOPosOffset / 512) + kMasterDirectoryBlock, size),
        !          1235:                                        IOBYTECCNTFORBLK(kMasterDirectoryBlock, kMDBSize, size), NOCRED, &bp);
        !          1236:        if (retval) {
        !          1237:            DBG_VFS((" hfs_flushvolumeheader bread return error! (%d)\n", retval));
        !          1238:                if (bp) brelse(bp);
        !          1239:                return retval;
        !          1240:        }
        !          1241: 
        !          1242:     ASSERT(bp != NULL);
        !          1243:     ASSERT(bp->b_data != NULL);
        !          1244:     ASSERT(bp->b_bcount == size);
        !          1245: 
        !          1246:        volumeHeader = (HFSPlusVolumeHeader *)((char *)bp->b_data +
        !          1247:                                        IOBYTEOFFSETFORBLK((vcb->hfsPlusIOPosOffset / 512) + kMasterDirectoryBlock, size));
        !          1248: 
        !          1249:        /*
        !          1250:         * For embedded HFS+ volumes, update create date if neccessary
        !          1251:         */
        !          1252:        if (vcb->hfsPlusIOPosOffset != 0 && volumeHeader->createDate != vcb->vcbCrDate)
        !          1253:          {
        !          1254:                struct buf                              *bp2;
        !          1255:                HFSMasterDirectoryBlock *mdb;
        !          1256: 
        !          1257:                retval = bread(hfsmp->hfs_devvp, IOBLKNOFORBLK(kMasterDirectoryBlock, kMDBSize),
        !          1258:                                                IOBYTECCNTFORBLK(kMasterDirectoryBlock, kMDBSize, kMDBSize), NOCRED, &bp2);
        !          1259:                if (retval != E_NONE) {
        !          1260:                        if (bp2) brelse(bp2);
        !          1261:                } else {
        !          1262:                        mdb = (HFSMasterDirectoryBlock *)((char *)bp2->b_data + IOBYTEOFFSETFORBLK(kMasterDirectoryBlock, kMDBSize));
        !          1263:                        if ( mdb->drCrDate != vcb->vcbCrDate )
        !          1264:                          {
        !          1265:                                mdb->drCrDate = vcb->vcbCrDate;         /* ppick up the new create date */
        !          1266:                                (void) bwrite(bp2);                                     /* write out the changes */
        !          1267:                          }
        !          1268:                        else
        !          1269:                          {
        !          1270:                                brelse(bp2);                                            /* just release it */
        !          1271:                          }
        !          1272:                  }     
        !          1273:          }
        !          1274: 
        !          1275:        VCB_LOCK(vcb);
        !          1276:        /* Note: only update the lower 16 bits worth of attributes */
        !          1277:        volumeHeader->attributes                 =      (volumeHeader->attributes & 0xFFFF0000) + (UInt16) vcb->vcbAtrb;
        !          1278:        volumeHeader->lastMountedVersion = kHFSPlusMountVersion;
        !          1279:        volumeHeader->createDate                 =      vcb->vcbCrDate;
        !          1280:        volumeHeader->modifyDate                 =      LocalToUTC(vcb->vcbLsMod);
        !          1281:        volumeHeader->backupDate                 =      LocalToUTC(vcb->vcbVolBkUp);
        !          1282:        volumeHeader->checkedDate                =      vcb->checkedDate;
        !          1283:        volumeHeader->fileCount                  =      vcb->vcbFilCnt;
        !          1284:        volumeHeader->folderCount                =      vcb->vcbDirCnt;
        !          1285: //     volumeHeader->blockSize                  =      vcb->blockSize;
        !          1286: //     volumeHeader->totalBlocks                =      vcb->totalBlocks;
        !          1287:        volumeHeader->freeBlocks                 =      vcb->freeBlocks;
        !          1288:        volumeHeader->nextAllocation     =      vcb->nextAllocation;
        !          1289:        volumeHeader->rsrcClumpSize              =      vcb->vcbClpSiz;
        !          1290:        volumeHeader->dataClumpSize              =      vcb->vcbClpSiz;
        !          1291:        volumeHeader->nextCatalogID              =      vcb->vcbNxtCNID;
        !          1292:        volumeHeader->writeCount                 =      vcb->vcbWrCnt;
        !          1293:        volumeHeader->encodingsBitmap    =      vcb->encodingsBitmap;
        !          1294: 
        !          1295:        //XXX djb should we use the vcb or fcb clumpSize values?
        !          1296:        volumeHeader->allocationFile.clumpSize  = vcb->allocationsClumpSize;
        !          1297:        volumeHeader->extentsFile.clumpSize             = vcb->vcbXTClpSiz;
        !          1298:        volumeHeader->catalogFile.clumpSize             = vcb->vcbCTClpSiz;
        !          1299: 
        !          1300:        bcopy( vcb->vcbFndrInfo, volumeHeader->finderInfo, sizeof(volumeHeader->finderInfo) );
        !          1301: 
        !          1302:        VCB_UNLOCK(vcb);
        !          1303: 
        !          1304:        vp = vcb->extentsRefNum;
        !          1305:        extendedFCB = GetParallelFCB(vp);
        !          1306:        bcopy( extendedFCB->extents, volumeHeader->extentsFile.extents, sizeof(HFSPlusExtentRecord) );
        !          1307:        fcb = VTOFCB(vp);
        !          1308:        volumeHeader->extentsFile.logicalSize.lo = fcb->fcbEOF;
        !          1309:        volumeHeader->extentsFile.logicalSize.hi = 0;
        !          1310:        volumeHeader->extentsFile.totalBlocks = fcb->fcbPLen / vcb->blockSize;
        !          1311: 
        !          1312:        vp = vcb->catalogRefNum;
        !          1313:        extendedFCB = GetParallelFCB(vp);
        !          1314:        bcopy( extendedFCB->extents, volumeHeader->catalogFile.extents, sizeof(HFSPlusExtentRecord) );
        !          1315:        fcb = VTOFCB(vp);
        !          1316:        volumeHeader->catalogFile.logicalSize.lo = fcb->fcbPLen;
        !          1317:        volumeHeader->catalogFile.logicalSize.hi = 0;
        !          1318:        volumeHeader->catalogFile.totalBlocks = fcb->fcbPLen / vcb->blockSize;
        !          1319: 
        !          1320:        vp = vcb->allocationsRefNum;
        !          1321:        extendedFCB = GetParallelFCB(vp);
        !          1322:        bcopy( extendedFCB->extents, volumeHeader->allocationFile.extents, sizeof(HFSPlusExtentRecord) );
        !          1323:        fcb = VTOFCB(vp);
        !          1324:        volumeHeader->allocationFile.logicalSize.lo = fcb->fcbPLen;
        !          1325:        volumeHeader->allocationFile.logicalSize.hi = 0;
        !          1326:        volumeHeader->allocationFile.totalBlocks = fcb->fcbPLen / vcb->blockSize;
        !          1327: 
        !          1328:        vp = vcb->attributesRefNum;
        !          1329:        if (vp != 0)            //      Only update fields if an attributes file existed and was open
        !          1330:          {
        !          1331:                extendedFCB = GetParallelFCB(vp);
        !          1332:                bcopy( extendedFCB->extents, volumeHeader->attributesFile.extents, sizeof(HFSPlusExtentRecord) );
        !          1333:                fcb = VTOFCB(vp);
        !          1334:                volumeHeader->attributesFile.logicalSize.lo = fcb->fcbPLen;
        !          1335:                volumeHeader->attributesFile.logicalSize.hi = 0;
        !          1336:                volumeHeader->attributesFile.clumpSize = fcb->fcbClmpSize;
        !          1337:                volumeHeader->attributesFile.totalBlocks = fcb->fcbPLen / vcb->blockSize;
        !          1338:          }
        !          1339: 
        !          1340:     if (waitfor != MNT_WAIT)
        !          1341:         bawrite(bp);
        !          1342:     else 
        !          1343:                retval = bwrite(bp);
        !          1344:  
        !          1345:        MarkVCBClean( vcb );
        !          1346: 
        !          1347:        return (retval);
        !          1348: }
        !          1349: 
        !          1350: 
        !          1351: /*
        !          1352:  *      Moved here to avoid having to define prototypes
        !          1353:  */
        !          1354: 
        !          1355: /*
        !          1356:  * hfs vfs operations.
        !          1357:  */
        !          1358: struct vfsops hfs_vfsops = {
        !          1359:     hfs_mount,
        !          1360:     hfs_start,
        !          1361:     hfs_unmount,
        !          1362:     hfs_root,
        !          1363:     hfs_quotactl,
        !          1364:     hfs_statfs,
        !          1365:     hfs_sync,
        !          1366:     hfs_vget,
        !          1367:     hfs_fhtovp,
        !          1368:     hfs_vptofh,
        !          1369:     hfs_init,
        !          1370:     hfs_sysctl
        !          1371: };
        !          1372: 
        !          1373: void
        !          1374: load_hfs(int loadArgument) {
        !          1375:     struct vfsconf *vfsconflistentry;
        !          1376:     int entriesRemaining;
        !          1377:     struct vfsconf *newvfsconf = NULL;
        !          1378:     struct vfsconf *lastentry = NULL;
        !          1379:     int j;
        !          1380:     int (***opv_desc_vector_p)();
        !          1381:     int (**opv_desc_vector)();
        !          1382:     struct vnodeopv_entry_desc *opve_descp;
        !          1383: 
        !          1384: #pragma unused(loadArgument)
        !          1385: 
        !          1386:     /*
        !          1387:      * This routine is responsible for all the initialization that would
        !          1388:      * ordinarily be done as part of the system startup; it calls hfs_init
        !          1389:      * to do the initialization that is strictly HFS-specific.
        !          1390:      */
        !          1391: 
        !          1392: #if DIAGNOSTIC
        !          1393: //      call_kdp();
        !          1394: #endif
        !          1395:     DBG_LOAD(("load_hfs: Starting...\n"));
        !          1396: 
        !          1397:     /*
        !          1398:      prevvfsconf is supposed to be the entry preceding the new entry.
        !          1399:      To make sure we can always get hooked in SOMEWHERE in the list,
        !          1400:      start it out at the first entry of the list.  This assumes the
        !          1401:      first entry in the list will be non-empty and not HFS.
        !          1402: 
        !          1403:      This becomes irrelevant when HFS is compiled into the list.
        !          1404:      */
        !          1405:     DBG_LOAD(("load_hfs: Scanning vfsconf list...\n"));
        !          1406:     vfsconflistentry = vfsconf;
        !          1407:     for (entriesRemaining = maxvfsslots; entriesRemaining > 0; --entriesRemaining) {
        !          1408:         if (vfsconflistentry->vfc_vfsops != NULL) {
        !          1409:             /*
        !          1410:              * Check to see if we're reloading a new version of hfs during debugging
        !          1411:              * and overwrite the previously assigned entry if we find one:
        !          1412:              */
        !          1413:             if (strcmp(vfsconflistentry->vfc_name, hfs_fs_name) == 0) {
        !          1414:                 newvfsconf = vfsconflistentry;
        !          1415:                 break;
        !          1416:             } else {
        !          1417:                 lastentry = vfsconflistentry;
        !          1418:             };
        !          1419:         } else {
        !          1420:             /*
        !          1421:              * This is at least a POSSIBLE place to insert the new entry...
        !          1422:              */
        !          1423:             newvfsconf = vfsconflistentry;
        !          1424:         };
        !          1425:         ++vfsconflistentry;
        !          1426:     };
        !          1427: 
        !          1428:     if (newvfsconf) {
        !          1429:         DBG_LOAD(("load_hfs: filling in vfsconf entry at 0x%X; lastentry = 0x%X.\n", (u_int)newvfsconf, (u_int)lastentry));
        !          1430:         newvfsconf->vfc_vfsops = &hfs_vfsops;
        !          1431:         strncpy(&newvfsconf->vfc_name[0], hfs_fs_name, MFSNAMELEN);
        !          1432:         newvfsconf->vfc_typenum = maxvfsconf++;
        !          1433:         newvfsconf->vfc_refcount = 0;
        !          1434:         newvfsconf->vfc_flags = 0;
        !          1435:         newvfsconf->vfc_mountroot = NULL;       /* Can't mount root of file system [yet] */
        !          1436: 
        !          1437:         /* Hook into the list: */
        !          1438:         newvfsconf->vfc_next = NULL;
        !          1439:         if (lastentry) {
        !          1440:             newvfsconf->vfc_next = lastentry->vfc_next;
        !          1441:             lastentry->vfc_next = newvfsconf;
        !          1442:         };
        !          1443: 
        !          1444:         /* Based on vfs_op_init and ... */
        !          1445:         opv_desc_vector_p = hfs_vnodeop_opv_desc.opv_desc_vector_p;
        !          1446: 
        !          1447:         DBG_LOAD(("load_hfs: Allocating and initializing VNode ops vector...\n"));
        !          1448: 
        !          1449:         /*
        !          1450:          * Allocate and init the vector.
        !          1451:          * Also handle backwards compatibility.
        !          1452:          */
        !          1453:         MALLOC(*opv_desc_vector_p, PFI *, vfs_opv_numops*sizeof(PFI), M_TEMP, M_WAITOK);
        !          1454:         bzero (*opv_desc_vector_p, vfs_opv_numops*sizeof(PFI));
        !          1455: 
        !          1456:         opv_desc_vector = *opv_desc_vector_p;
        !          1457:         for (j=0; hfs_vnodeop_opv_desc.opv_desc_ops[j].opve_op; j++) {
        !          1458:             opve_descp = &(hfs_vnodeop_opv_desc.opv_desc_ops[j]);
        !          1459: 
        !          1460:             /*
        !          1461:              * Sanity check:  is this operation listed
        !          1462:              * in the list of operations?  We check this
        !          1463:              * by seeing if its offest is zero.  Since
        !          1464:              * the default routine should always be listed
        !          1465:              * first, it should be the only one with a zero
        !          1466:              * offset.  Any other operation with a zero
        !          1467:              * offset is probably not listed in
        !          1468:              * vfs_op_descs, and so is probably an error.
        !          1469:              *
        !          1470:              * A panic here means the layer programmer
        !          1471:              * has committed the all-too common bug
        !          1472:              * of adding a new operation to the layer's
        !          1473:              * list of vnode operations but
        !          1474:              * not adding the operation to the system-wide
        !          1475:              * list of supported operations.
        !          1476:              */
        !          1477:             if (opve_descp->opve_op->vdesc_offset == 0 &&
        !          1478:                 opve_descp->opve_op->vdesc_offset != VOFFSET(vop_default)) {
        !          1479:                 printf("load_hfs: operation %s not listed in %s.\n",
        !          1480:                        opve_descp->opve_op->vdesc_name,
        !          1481:                        "vfs_op_descs");
        !          1482:                 panic ("load_hfs: bad operation");
        !          1483:             }
        !          1484:             /*
        !          1485:              * Fill in this entry.
        !          1486:              */
        !          1487:             opv_desc_vector[opve_descp->opve_op->vdesc_offset] =
        !          1488:                 opve_descp->opve_impl;
        !          1489:         }
        !          1490: 
        !          1491:         /*
        !          1492:          * Finally, go back and replace unfilled routines
        !          1493:          * with their default.  (Sigh, an O(n^3) algorithm.  I
        !          1494:                                  * could make it better, but that'd be work, and n is small.)
        !          1495:          */
        !          1496:         opv_desc_vector_p = hfs_vnodeop_opv_desc.opv_desc_vector_p;
        !          1497: 
        !          1498:         /*
        !          1499:          * Force every operations vector to have a default routine.
        !          1500:          */
        !          1501:         opv_desc_vector = *opv_desc_vector_p;
        !          1502:         if (opv_desc_vector[VOFFSET(vop_default)]==NULL) {
        !          1503:             panic("load_hfs: operation vector without default routine.");
        !          1504:         }
        !          1505:         for (j = 0;j<vfs_opv_numops; j++)
        !          1506:             if (opv_desc_vector[j] == NULL)
        !          1507:                 opv_desc_vector[j] =
        !          1508:                     opv_desc_vector[VOFFSET(vop_default)];
        !          1509: 
        !          1510:         DBG_LOAD(("load_hfs: calling hfs_init()...\n"));
        !          1511:         hfs_init(newvfsconf);
        !          1512:     };
        !          1513: }
        !          1514: 
        !          1515: void
        !          1516: unload_hfs(int unloadArgument) {
        !          1517:     int entriesRemaining;
        !          1518:     struct vfsconf *vfsconflistentry;
        !          1519:     struct vfsconf *prevconf = NULL;
        !          1520:     struct vfsconf *hfsconf = NULL;
        !          1521: 
        !          1522:     DBG_LOAD(("unload_hfs: removing HFS from vfs conf. list...\n"));
        !          1523: 
        !          1524:     prevconf = vfsconflistentry = vfsconf;
        !          1525:     for (entriesRemaining = maxvfsslots;
        !          1526:          (entriesRemaining > 0) && (vfsconflistentry != NULL);
        !          1527:          --entriesRemaining) {
        !          1528:         if ((vfsconflistentry->vfc_vfsops != NULL) && (strcmp(vfsconflistentry->vfc_name, hfs_fs_name) == 0)) {
        !          1529:             hfsconf = vfsconflistentry;
        !          1530:             break;
        !          1531:         };
        !          1532:         prevconf = vfsconflistentry;
        !          1533:         vfsconflistentry = vfsconflistentry->vfc_next;
        !          1534:     };
        !          1535: 
        !          1536:     if (hfsconf != NULL) {
        !          1537:         if (prevconf != NULL) {
        !          1538:             /* Unlink the HFS entry from the list: */
        !          1539:             prevconf->vfc_next = hfsconf->vfc_next;
        !          1540:         } else {
        !          1541:             DBG_LOAD(("unload_hfs: no previous entry in list.\n"));
        !          1542:         }
        !          1543:     } else {
        !          1544:         DBG_LOAD(("unload_hfs: couldn't find hfs conf. list entry.\n"));
        !          1545:     };
        !          1546: 
        !          1547:     FREE(*hfs_vnodeop_opv_desc.opv_desc_vector_p, M_TEMP);
        !          1548: }

unix.superglobalmegacorp.com

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