Annotation of XNU/bsd/hfs/hfs_btreeio.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
                      3:  *
                      4:  * @APPLE_LICENSE_HEADER_START@
                      5:  * 
                      6:  * The contents of this file constitute Original Code as defined in and
                      7:  * are subject to the Apple Public Source License Version 1.1 (the
                      8:  * "License").  You may not use this file except in compliance with the
                      9:  * License.  Please obtain a copy of the License at
                     10:  * http://www.apple.com/publicsource and read it before using this file.
                     11:  * 
                     12:  * This Original Code and all software distributed under the License are
                     13:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
                     14:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
                     15:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
                     16:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
                     17:  * License for the specific language governing rights and limitations
                     18:  * under the License.
                     19:  * 
                     20:  * @APPLE_LICENSE_HEADER_END@
                     21:  */
                     22: /*     @(#)hfs_btreeio.c
                     23: *
                     24: *      (c) 1998, 2000 Apple Computer, Inc.  All Rights Reserved
                     25: *
                     26: *      hfs_btreeio.c -- I/O Routines for the HFS B-tree files.
                     27: *
                     28: *      HISTORY
                     29: *      15-Feb-2000     Don Brady       Added ClearBTNodes.
                     30: *      16-Jul-1998     Don Brady               In ExtendBtreeFile force all b-tree nodes to be contiguous on disk.
                     31: *       4-Jun-1998     Pat Dirks               Changed to do all B*-Tree writes synchronously (FORCESYNCBTREEWRITES = 1)
                     32: *      18-apr-1998     Don Brady               Call brelse on bread failure.
                     33: *      17-Apr-1998     Pat Dirks               Fixed ReleaseBTreeBlock to not call brelse when bwrite or bdwrite is called.
                     34: *      13-apr-1998     Don Brady               Add ExtendBTreeFile routine (from BTreeWrapper.c).
                     35: *      26-mar-1998     Don Brady               SetBTreeBlockSize was incorrectly excluding 512 byte blockSize.
                     36: *      18-feb-1998     Don Brady               Initially created file.
                     37: *
                     38: */
                     39: 
                     40: #include <sys/param.h>
                     41: #include <sys/systm.h>
                     42: #include <sys/buf.h>
                     43: #include <sys/mount.h>
                     44: #include <sys/vnode.h>
                     45: 
                     46: 
                     47: #include "hfs.h"
                     48: #include "hfs_dbg.h"
                     49:        
                     50: #include "hfscommon/headers/FileMgrInternal.h"
                     51: #include "hfscommon/headers/BTreesPrivate.h"
                     52: 
                     53: #define FORCESYNCBTREEWRITES 0
                     54: 
                     55: static OSStatus FlushAlternate( ExtendedVCB *vcb );
                     56: 
                     57: static int ClearBTNodes(struct vnode *vp, long blksize, off_t offset, off_t amount);
                     58: 
                     59: 
                     60: OSStatus SetBTreeBlockSize(FileReference vp, ByteCount blockSize, ItemCount minBlockCount)
                     61: {
                     62:        BTreeControlBlockPtr    bTreePtr;
                     63:        
                     64:        DBG_ASSERT(vp != NULL);
                     65:        DBG_ASSERT(VTOFCB(vp) != NULL);
                     66:        DBG_ASSERT(VTOFCB(vp)->fcbBTCBPtr != NULL);
                     67:        DBG_ASSERT(blockSize >= kMinNodeSize);
                     68:     if (blockSize > MAXBSIZE )
                     69:         return (fsBTBadNodeSize);
                     70: 
                     71:     DBG_TREE(("SetBlockSizeProc: blockSize=%ld for file %ld\n", blockSize, H_FILEID(VTOH(vp))));
                     72: 
                     73:        bTreePtr = (BTreeControlBlockPtr)(VTOH(vp)->fcbBTCBPtr);
                     74:        bTreePtr->nodeSize = blockSize;
                     75:        
                     76:     return (E_NONE);
                     77: }
                     78: 
                     79: 
                     80: OSStatus GetBTreeBlock(FileReference vp, UInt32 blockNum, GetBlockOptions options, BlockDescriptor *block)
                     81: {
                     82:     OSStatus    retval = E_NONE;
                     83:     struct buf   *bp = NULL;
                     84: 
                     85:     if (options & kGetEmptyBlock)
                     86:         bp = getblk (vp,
                     87:                     IOBLKNOFORBLK(blockNum, VTOHFS(vp)->hfs_phys_block_size),
                     88:                     IOBYTECCNTFORBLK(blockNum, block->blockSize, VTOHFS(vp)->hfs_phys_block_size),
                     89:                     0,
                     90:                     0);
                     91:     else
                     92:         retval = bread (vp,
                     93:                         IOBLKNOFORBLK(blockNum, VTOHFS(vp)->hfs_phys_block_size),
                     94:                         IOBYTECCNTFORBLK(blockNum, block->blockSize, VTOHFS(vp)->hfs_phys_block_size),
                     95:                         NOCRED,
                     96:                         &bp);
                     97: 
                     98:     DBG_ASSERT(bp != NULL);
                     99:     DBG_ASSERT(bp->b_data != NULL);
                    100:     DBG_ASSERT(bp->b_bcount == block->blockSize);
                    101:     DBG_ASSERT(bp->b_lblkno == blockNum);
                    102: 
                    103:     if (bp == NULL)
                    104:         retval = -1;   //XXX need better error
                    105: 
                    106:     if (retval == E_NONE) {
                    107:         block->blockHeader = bp;
                    108:         block->buffer = bp->b_data + IOBYTEOFFSETFORBLK(bp->b_blkno, VTOHFS(vp)->hfs_phys_block_size);
                    109:         block->blockReadFromDisk = (bp->b_flags & B_CACHE) == 0;       /* not found in cache ==> came from disk */
                    110:     } else {
                    111:        if (bp)
                    112:                        brelse(bp);
                    113:         block->blockHeader = NULL;
                    114:         block->buffer = NULL;
                    115:     }
                    116: 
                    117:     return (retval);
                    118: }
                    119: 
                    120: 
                    121: OSStatus ReleaseBTreeBlock(FileReference vp, BlockDescPtr blockPtr, ReleaseBlockOptions options)
                    122: {
                    123:     OSStatus   retval = E_NONE;
                    124:     struct buf *bp = NULL;
                    125: 
                    126:     bp = (struct buf *) blockPtr->blockHeader;
                    127: 
                    128:     if (bp == NULL) {
                    129:         DBG_TREE(("ReleaseBlockProc: blockHeader is zero!\n"));
                    130:         retval = -1;
                    131:         goto exit;
                    132:     }
                    133: 
                    134:     if (options & kTrashBlock) {
                    135:         bp->b_flags |= B_INVAL;
                    136:        brelse(bp);     /* note: B-tree code will clear blockPtr->blockHeader and blockPtr->buffer */
                    137:     } else {
                    138:         if (options & kForceWriteBlock) {
                    139:             bp->b_flags |= B_DIRTY;
                    140:             retval = bwrite(bp);
                    141:         } else if (options & kMarkBlockDirty) {
                    142:             bp->b_flags |= B_DIRTY;
                    143: #if FORCESYNCBTREEWRITES
                    144:             bwrite(bp);
                    145: #else
                    146:                        if (options & kLockTransaction) {
                    147: 
                    148:                    /*
                    149:                     *
                    150:                     * Set the B_LOCKED flag and unlock the buffer, causing brelse to move
                    151:                     * the buffer onto the LOCKED free list.  This is necessary, otherwise
                    152:                     * getnewbuf() would try to reclaim the buffers using bawrite, which
                    153:                     * isn't going to work.
                    154:                     *
                    155:                     */
                    156:                    bp->b_flags |= B_LOCKED;
                    157:                };
                    158:             bdwrite(bp);
                    159: 
                    160: #endif
                    161:         } else {
                    162:                brelse(bp);     /* note: B-tree code will clear blockPtr->blockHeader and blockPtr->buffer */
                    163:         };
                    164:     };
                    165: 
                    166: exit:
                    167:     return (retval);
                    168: }
                    169: 
                    170: 
                    171: OSStatus ExtendBTreeFile(FileReference vp, FSSize minEOF, FSSize maxEOF)
                    172: {
                    173: #pragma unused (maxEOF)
                    174: 
                    175:        OSStatus        retval;
                    176:        UInt64          actualBytesAdded;
                    177:        UInt64          bytesToAdd;
                    178:     UInt32             extendFlags;
                    179:        BTreeInfoRec btInfo;
                    180:        ExtendedVCB     *vcb;
                    181:        FCB                     *filePtr;
                    182:     struct proc *p = NULL;
                    183: 
                    184: 
                    185:        filePtr = GetFileControlBlock(vp);
                    186: 
                    187:        if ( minEOF > filePtr->fcbEOF )
                    188:        {
                    189:                bytesToAdd = minEOF - filePtr->fcbEOF;
                    190: 
                    191:                if (bytesToAdd < filePtr->fcbClmpSize)
                    192:                        bytesToAdd = filePtr->fcbClmpSize;              //XXX why not always be a mutiple of clump size?
                    193:        }
                    194:        else
                    195:        {
                    196:                DBG_TREE((" ExtendBTreeFile: minEOF is smaller than current size!"));
                    197:                return -1;
                    198:        }
                    199: 
                    200:        vcb = FCBTOVCB(filePtr);
                    201:        
                    202:        /*
                    203:         * The Extents B-tree can't have overflow extents. ExtendFileC will
                    204:         * return an error if an attempt is made to extend the Extents B-tree
                    205:         * when the resident extents are exhausted.
                    206:         */
                    207:     /* XXX warning - this can leave the volume bitmap unprotected during ExtendFileC call */
                    208:        if(H_FILEID(filePtr) != kHFSExtentsFileID)
                    209:        {
                    210:                p = current_proc();
                    211:                /* lock extents b-tree (also protects volume bitmap) */
                    212:                retval = hfs_metafilelocking(VTOHFS(vp), kHFSExtentsFileID, LK_EXCLUSIVE, p);
                    213:                if (retval)
                    214:                        return (retval);
                    215:        }
                    216: 
                    217:     (void) BTGetInformation(filePtr, 0, &btInfo);
                    218: 
                    219:        /*
                    220:      * The b-tree code expects nodes to be contiguous. So when
                    221:         * the allocation block size is less than the b-tree node
                    222:      * size, we need to force disk allocations to be contiguous.
                    223:      */
                    224:        if (vcb->blockSize >= btInfo.nodeSize) {
                    225:                extendFlags = 0;
                    226:        } else {
                    227:                /* Ensure that all b-tree nodes are contiguous on disk */
                    228:                extendFlags = kEFAllMask | kEFContigMask;
                    229:        }
                    230: 
                    231:     retval = ExtendFileC(vcb, filePtr, bytesToAdd, extendFlags, &actualBytesAdded );
                    232: 
                    233:        if(H_FILEID(filePtr) != kHFSExtentsFileID)
                    234:                (void) hfs_metafilelocking(VTOHFS(vp), kHFSExtentsFileID, LK_RELEASE, p);
                    235: 
                    236:        if (retval)
                    237:                return (retval);
                    238: 
                    239:        if (actualBytesAdded < bytesToAdd)
                    240:                DBG_TREE((" ExtendBTreeFile: actualBytesAdded < bytesToAdd!"));
                    241:        
                    242:        filePtr->fcbEOF = filePtr->fcbPLen;
                    243: 
                    244:        retval = ClearBTNodes(vp, btInfo.nodeSize, filePtr->fcbEOF - actualBytesAdded, actualBytesAdded);       
                    245:        if (retval)
                    246:                return (retval);
                    247:        
                    248:        /*
                    249:         * Update the Alternate MDB or Alternate VolumeHeader
                    250:         */
                    251:        if ((H_FILEID(filePtr) == kHFSExtentsFileID)    ||
                    252:            (H_FILEID(filePtr) == kHFSCatalogFileID)    ||
                    253:            (H_FILEID(filePtr) == kHFSAttributesFileID)
                    254:           ) {
                    255:                MarkVCBDirty( vcb );
                    256:                if (vcb->vcbSigWord == kHFSPlusSigWord) {
                    257:                        retval = hfs_flushvolumeheader(VCBTOHFS(vcb), 0);
                    258:                } else {
                    259:                        retval = hfs_flushMDB(VCBTOHFS(vcb), 0);
                    260:                }
                    261:                if (retval == 0) {
                    262:                        retval = FlushAlternate(vcb);
                    263:                }
                    264:        }
                    265:        
                    266:        return retval;
                    267: }
                    268: 
                    269: 
                    270: static OSStatus
                    271: FlushAlternate( ExtendedVCB *vcb )
                    272: {
                    273:        void *maindata;
                    274:        void *altdata;
                    275:        int result;
                    276: 
                    277:        /* Get the main MDB/VolumeHeader block */
                    278:        result = GetBlock_glue(gbDefault,
                    279:                        (vcb->hfsPlusIOPosOffset / kHFSBlockSize) + kMasterDirectoryBlock,
                    280:                        (Ptr *)&maindata, kNoFileReference, vcb);
                    281:        if (result) return (result);
                    282:        
                    283:        /* Get the alternate MDB/VolumeHeader block */
                    284:        result = GetBlock_glue( gbDefault, vcb->altIDSector,
                    285:                        (Ptr *)&altdata, kNoFileReference, vcb );
                    286: 
                    287:        if (result == 0) {
                    288:                bcopy(maindata, altdata, kMDBSize);
                    289: 
                    290:                result = RelBlock_glue( (Ptr)altdata, rbWriteMask );
                    291:        }
                    292: 
                    293:        (void) RelBlock_glue( (Ptr)maindata, rbFreeMask );
                    294:        
                    295:        return (result);
                    296: }
                    297: 
                    298: 
                    299: /*
                    300:  * Clear out (zero) new b-tree nodes on disk.
                    301:  */
                    302: static int
                    303: ClearBTNodes(struct vnode *vp, long blksize, off_t offset, off_t amount)
                    304: {
                    305:        struct buf *bp = NULL;
                    306:        daddr_t blk;
                    307:        daddr_t blkcnt;
                    308:     
                    309:        blk = offset / blksize;
                    310:        blkcnt = amount / blksize;
                    311:        
                    312:        while (blkcnt > 0) {
                    313:                bp = getblk(vp, blk, blksize, 0, 0);    /* ubc: BLK_META */
                    314:                if (bp == NULL)
                    315:                        continue;
                    316:                bzero((char *)bp->b_data, blksize);
                    317:                bp->b_flags |= (B_DIRTY | B_AGE);
                    318: 
                    319:                 /* wait/yield every 32 blocks so we don't hog all the buffers */
                    320:                if ((blk % 32) == 0)
                    321:                        bwrite(bp);
                    322:                else
                    323:                        bawrite(bp);
                    324:                --blkcnt;
                    325:                ++blk;
                    326:        }
                    327: 
                    328:        return (0);
                    329: }

unix.superglobalmegacorp.com

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