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

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;
1.1.1.2 ! root      869:         if (hp && hp->h_meta && (hp->h_meta->h_nodeflags & (IN_ACCESS | IN_CHANGE | IN_MODIFIED | IN_UPDATE)) == 0 &&
1.1       root      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.