|
|
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:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.