Annotation of kernel/bsd/hfs/hfs_btreeio.c, revision 1.1.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.