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

1.1     ! root        1: /*
        !             2:  * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
        !             3:  *
        !             4:  * @APPLE_LICENSE_HEADER_START@
        !             5:  * 
        !             6:  * Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
        !             7:  * Reserved.  This file contains Original Code and/or Modifications of
        !             8:  * Original Code as defined in and that are subject to the Apple Public
        !             9:  * Source License Version 1.1 (the "License").  You may not use this file
        !            10:  * except in compliance with the License.  Please obtain a copy of the
        !            11:  * License at http://www.apple.com/publicsource and read it before using
        !            12:  * this file.
        !            13:  * 
        !            14:  * The Original Code and all software distributed under the License are
        !            15:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
        !            16:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
        !            17:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
        !            18:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
        !            19:  * License for the specific language governing rights and limitations
        !            20:  * under the License.
        !            21:  * 
        !            22:  * @APPLE_LICENSE_HEADER_END@
        !            23:  */
        !            24: 
        !            25: /*     @(#)hfs_btreeio.c
        !            26: *
        !            27: *      (c) 1998 Apple Computer, Inc.  All Rights Reserved
        !            28: *
        !            29: *      hfs_btreeio.c -- I/O Routines for the HFS B-tree files.
        !            30: *
        !            31: *      HISTORY
        !            32: *      16-Jul-1998     Don Brady               In ExtendBtreeFile force all b-tree nodes to be contiguous on disk.
        !            33: *       4-Jun-1998     Pat Dirks               Changed to do all B*-Tree writes synchronously (FORCESYNCBTREEWRITES = 1)
        !            34: *      18-apr-1998     Don Brady               Call brelse on bread failure.
        !            35: *      17-Apr-1998     Pat Dirks               Fixed ReleaseBTreeBlock to not call brelse when bwrite or bdwrite is called.
        !            36: *      13-apr-1998     Don Brady               Add ExtendBTreeFile routine (from BTreeWrapper.c).
        !            37: *      26-mar-1998     Don Brady               SetBTreeBlockSize was incorrectly excluding 512 byte blockSize.
        !            38: *      18-feb-1998     Don Brady               Initially created file.
        !            39: *
        !            40: */
        !            41: 
        !            42: #include <sys/types.h>
        !            43: #include <sys/buf.h>
        !            44: #include <sys/systm.h>
        !            45: #include <machine/spl.h>
        !            46: 
        !            47: #include "hfs.h"
        !            48: #include "hfs_dbg.h"
        !            49: #include "hfscommon/headers/system/MacOSTypes.h"
        !            50: #include "hfscommon/headers/FileMgrInternal.h"
        !            51: #include "hfscommon/headers/BTreesInternal.h"
        !            52: 
        !            53: #define FORCESYNCBTREEWRITES 0
        !            54: 
        !            55: OSStatus SetBTreeBlockSize(FileReference vp, ByteCount blockSize, ItemCount minBlockCount)
        !            56: {
        !            57:     if (blockSize > MAXBSIZE )
        !            58:         return (fsBTBadNodeSize);
        !            59: 
        !            60:     DBG_TREE(("SetBlockSizeProc: blockSize=%ld for file %ld\n", blockSize, VTOFCB(vp)->fcbFlNm));
        !            61: 
        !            62:     VTOH(vp)->h_meta->h_logBlockSize = blockSize;
        !            63:     VTOH(vp)->h_meta->h_physBlkPerLogBlk = blockSize / kHFSBlockSize;
        !            64: 
        !            65:     return (E_NONE);
        !            66: }
        !            67: 
        !            68: 
        !            69: OSStatus GetBTreeBlock(FileReference vp, UInt32 blockNum, GetBlockOptions options, BlockDescriptor *block)
        !            70: {
        !            71:     OSStatus    retval = E_NONE;
        !            72:     struct buf   *bp = NULL;
        !            73: 
        !            74:     //XXX DJB - what about kForceReadBlock option?
        !            75: 
        !            76: //     DBG_TREE(("GetBlockProc: block=%ld, blockSize=%ld\n", blockNum, block->blockSize));
        !            77: 
        !            78:     if (options & kGetEmptyBlock)
        !            79:         bp = getblk (vp,
        !            80:                     IOBLKNOFORBLK(blockNum, VTOHFS(vp)->hfs_phys_block_size),
        !            81:                     IOBYTECCNTFORBLK(blockNum, block->blockSize, VTOHFS(vp)->hfs_phys_block_size),
        !            82:                     0,
        !            83:                     0);
        !            84:     else
        !            85:         retval = bread (vp,
        !            86:                         IOBLKNOFORBLK(blockNum, VTOHFS(vp)->hfs_phys_block_size),
        !            87:                         IOBYTECCNTFORBLK(blockNum, block->blockSize, VTOHFS(vp)->hfs_phys_block_size),
        !            88:                         NOCRED,
        !            89:                         &bp);
        !            90: 
        !            91: //     DBG_TREE(("GetBlockProc: bp->b_bufsize=%ld, bp->b_bcount=%ld, bp->b_lblkno=%ld\n", bp->b_bufsize, bp->b_bcount, bp->b_lblkno));
        !            92: 
        !            93:     DBG_ASSERT(bp != NULL);
        !            94:     DBG_ASSERT(bp->b_data != NULL);
        !            95:     DBG_ASSERT(bp->b_bcount == block->blockSize);
        !            96:     DBG_ASSERT(bp->b_lblkno == blockNum);
        !            97: 
        !            98:     if (bp == NULL)
        !            99:         retval = -1;   //XXX need better error
        !           100: 
        !           101:     if (retval == E_NONE) {
        !           102:         block->blockHeader = bp;
        !           103:         block->buffer = bp->b_data + IOBYTEOFFSETFORBLK(bp->b_blkno, VTOHFS(vp)->hfs_phys_block_size);
        !           104:         block->blockReadFromDisk = (bp->b_flags & B_CACHE) == 0;       /* not found in cache ==> came from disk */
        !           105:     } else {
        !           106:        if (bp)
        !           107:                        brelse(bp);
        !           108:         block->blockHeader = NULL;
        !           109:         block->buffer = NULL;
        !           110:     }
        !           111: 
        !           112:     return (retval);
        !           113: }
        !           114: 
        !           115: 
        !           116: OSStatus ReleaseBTreeBlock(FileReference vp, BlockDescPtr blockPtr, ReleaseBlockOptions options)
        !           117: {
        !           118:     OSStatus   retval = E_NONE;
        !           119:     struct buf *bp = NULL;
        !           120:     int s;
        !           121: 
        !           122:     bp = (struct buf *) blockPtr->blockHeader;
        !           123: 
        !           124:     if (bp == NULL) {
        !           125:         DBG_TREE(("ReleaseBlockProc: blockHeader is zero!\n"));
        !           126:         retval = -1;
        !           127:         goto exit;
        !           128:     }
        !           129: 
        !           130: //     DBG_TREE(("ReleaseBlockProc: bp->b_lblkno=%ld, bp->b_bcount=%ld\n\n", bp->b_lblkno, bp->b_bcount));
        !           131: 
        !           132:     if (options & kTrashBlock) {
        !           133:         bp->b_flags |= B_INVAL;
        !           134:        brelse(bp);     /* note: B-tree code will clear blockPtr->blockHeader and blockPtr->buffer */
        !           135:     } else {
        !           136:         if (options & kForceWriteBlock) {
        !           137:             bp->b_flags |= B_DIRTY;
        !           138:             retval = bwrite(bp);
        !           139:         } else if (options & kMarkBlockDirty) {
        !           140:             bp->b_flags |= B_DIRTY;
        !           141: #if FORCESYNCBTREEWRITES
        !           142:             bwrite(bp);
        !           143: #else
        !           144: 
        !           145:             /*
        !           146:              *
        !           147:              * Set the B_LOCKED flag and unlock the buffer, causing brelse to move
        !           148:              * the buffer onto the LOCKED free list.  This is necessary, otherwise
        !           149:              * getnewbuf() would try to reclaim the buffers using bawrite, which
        !           150:              * isn't going to work.
        !           151:              *
        !           152:              */
        !           153:             bp->b_flags |= B_LOCKED;
        !           154:             bdwrite(bp);
        !           155: 
        !           156: #endif
        !           157:         } else {
        !           158:                brelse(bp);     /* note: B-tree code will clear blockPtr->blockHeader and blockPtr->buffer */
        !           159:         };
        !           160:     };
        !           161: 
        !           162: exit:
        !           163:     return (retval);
        !           164: }
        !           165: 
        !           166: 
        !           167: OSStatus ExtendBTreeFile(FileReference vp, FSSize minEOF, FSSize maxEOF)
        !           168: {
        !           169: #pragma unused (maxEOF)
        !           170: 
        !           171:        OSStatus        retval;
        !           172:        UInt32          actualBytesAdded;
        !           173:        UInt32          bytesToAdd;
        !           174:     UInt32             extendFlags;
        !           175:        BTreeInfoRec btInfo;
        !           176:        ExtendedVCB     *vcb;
        !           177:        FCB                     *filePtr;
        !           178:     struct proc *p = NULL;
        !           179: 
        !           180: 
        !           181:        filePtr = GetFileControlBlock(vp);
        !           182: 
        !           183:        if ( minEOF > filePtr->fcbEOF )
        !           184:        {
        !           185:                bytesToAdd = minEOF - filePtr->fcbEOF;
        !           186: 
        !           187:                if (bytesToAdd < filePtr->fcbClmpSize)
        !           188:                        bytesToAdd = filePtr->fcbClmpSize;              //XXX why not always be a mutiple of clump size?
        !           189:        }
        !           190:        else
        !           191:        {
        !           192:                DBG_TREE((" ExtendBTreeFile: minEOF is smaller than current size!"));
        !           193:                return -1;
        !           194:        }
        !           195: 
        !           196:        vcb = filePtr->fcbVPtr;
        !           197:        
        !           198:        /*
        !           199:         * The Extents B-tree can't have overflow extents. ExtendFileC will
        !           200:         * return an error if an attempt is made to extend the Extents B-tree
        !           201:         * when the resident extents are exhausted.
        !           202:         */
        !           203:     /* XXX warning - this can leave the volume bitmap unprotected during ExtendFileC call */
        !           204:        if(filePtr->fcbFlNm != kHFSExtentsFileID)
        !           205:        {
        !           206:                p = CURRENT_PROC;
        !           207:                /* lock extents b-tree (also protects volume bitmap) */
        !           208:                retval = hfs_metafilelocking(VTOHFS(vp), kHFSExtentsFileID, LK_EXCLUSIVE, p);
        !           209:                if (retval)
        !           210:                        return (retval);
        !           211:        }
        !           212: 
        !           213:     (void) BTGetInformation(filePtr, 0, &btInfo);
        !           214: 
        !           215:        /*
        !           216:      * The b-tree code expects nodes to be contiguous. So when
        !           217:         * the allocation block size is less than the b-tree node
        !           218:      * size, we need to force disk allocations to be contiguous.
        !           219:      */
        !           220:        if (vcb->blockSize >= btInfo.nodeSize) {
        !           221:                extendFlags = 0;
        !           222:        } else {
        !           223:                /* Ensure that all b-tree nodes are contiguous on disk */
        !           224:                extendFlags = kEFAllMask | kEFContigMask;
        !           225:        }
        !           226: 
        !           227:     retval = ExtendFileC(vcb, filePtr, bytesToAdd, extendFlags, &actualBytesAdded );
        !           228: 
        !           229:        if(filePtr->fcbFlNm != kHFSExtentsFileID)
        !           230:                (void) hfs_metafilelocking(VTOHFS(vp), kHFSExtentsFileID, LK_RELEASE, p);
        !           231: 
        !           232:        if (retval)
        !           233:                return (retval);
        !           234: 
        !           235:        if (actualBytesAdded < bytesToAdd)
        !           236:                DBG_TREE((" ExtendBTreeFile: actualBytesAdded < bytesToAdd!"));
        !           237:                
        !           238:        filePtr->fcbEOF = filePtr->fcbPLen;             // new B-tree looks at fcbEOF
        !           239:        
        !           240:        /*
        !           241:         * Update the Alternate MDB or Alternate VolumeHeader
        !           242:         */
        !           243:        if ( vcb->vcbSigWord == kHFSPlusSigWord )
        !           244:        {
        !           245:                //      If any of the HFS+ private files change size, flush them back to the Alternate volume header
        !           246:                if (    (filePtr->fcbFlNm == kHFSExtentsFileID) 
        !           247:                         ||     (filePtr->fcbFlNm == kHFSCatalogFileID)
        !           248:                         ||     (filePtr->fcbFlNm == kHFSStartupFileID)
        !           249:                         ||     (filePtr->fcbFlNm == kHFSAttributesFileID) )
        !           250:                {
        !           251:                        MarkVCBDirty( vcb );
        !           252:                        retval = FlushAlternateVolumeControlBlock( vcb, true );
        !           253:                }
        !           254:        }
        !           255:        else if ( vcb->vcbSigWord == kHFSSigWord )
        !           256:        {
        !           257:                if ( filePtr->fcbFlNm == kHFSExtentsFileID )
        !           258:                {
        !           259:                        vcb->vcbXTAlBlks = filePtr->fcbPLen / vcb->blockSize;
        !           260:                        MarkVCBDirty( vcb );
        !           261:                        retval = FlushAlternateVolumeControlBlock( vcb, false );
        !           262:                }
        !           263:                else if ( filePtr->fcbFlNm == kHFSCatalogFileID )
        !           264:                {
        !           265:                        vcb->vcbCTAlBlks = filePtr->fcbPLen / vcb->blockSize;
        !           266:                        MarkVCBDirty( vcb );
        !           267:                        retval = FlushAlternateVolumeControlBlock( vcb, false );
        !           268:                }
        !           269:        }
        !           270:        
        !           271:        return retval;
        !           272: 
        !           273: }
        !           274: 

unix.superglobalmegacorp.com

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