|
|
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.