if (retval == E_NONE) {
block->blockHeader = bp;
block->buffer = (char *)buf_dataptr(bp);
+ block->blockNum = buf_lblkno(bp);
block->blockReadFromDisk = (buf_fromcache(bp) == 0); /* not found in cache ==> came from disk */
// XXXdbg
block->isModified = 0;
-#if BYTE_ORDER == LITTLE_ENDIAN
- /* Endian swap B-Tree node (only if it's a valid block) */
+ /* Check and endian swap B-Tree node (only if it's a valid block) */
if (!(options & kGetEmptyBlock)) {
/* This happens when we first open the b-tree, we might not have all the node data on hand */
if ((((BTNodeDescriptor *)block->buffer)->kind == kBTHeaderNode) &&
(((BTHeaderRec *)((char *)block->buffer + 14))->nodeSize != buf_count(bp)) &&
(SWAP_BE16 (((BTHeaderRec *)((char *)block->buffer + 14))->nodeSize) != buf_count(bp))) {
- /* Don't swap the descriptors at all, we don't care (this block will be invalidated) */
- SWAP_BT_NODE (block, ISHFSPLUS(VTOVCB(vp)), VTOC(vp)->c_fileid, 3);
-
- /* The node needs swapping */
+ /*
+ * Don't swap the node descriptor, record offsets, or other records.
+ * This record will be invalidated and re-read with the correct node
+ * size once the B-tree control block is set up with the node size
+ * from the header record.
+ */
+ retval = hfs_swap_BTNode (block, vp, kSwapBTNodeHeaderRecordOnly);
+
+ } else if (block->blockReadFromDisk) {
+ /*
+ * The node was just read from disk, so always swap/check it.
+ * This is necessary on big endian since the test below won't trigger.
+ */
+ retval = hfs_swap_BTNode (block, vp, kSwapBTNodeBigToHost);
} else if (*((UInt16 *)((char *)block->buffer + (block->blockSize - sizeof (UInt16)))) == 0x0e00) {
- SWAP_BT_NODE (block, ISHFSPLUS(VTOVCB(vp)), VTOC(vp)->c_fileid, 0);
-#if 0
- /* The node is not already in native byte order, hence corrupt */
- } else if (*((UInt16 *)((char *)block->buffer + (block->blockSize - sizeof (UInt16)))) != 0x000e) {
- panic ("%s Corrupt B-Tree node detected!\n", "GetBTreeBlock:");
-#endif
+ /*
+ * The node was left in the cache in non-native order, so swap it.
+ * This only happens on little endian, after the node is written
+ * back to disk.
+ */
+ retval = hfs_swap_BTNode (block, vp, kSwapBTNodeBigToHost);
}
+
+ /*
+ * If we got an error, then the node is only partially swapped.
+ * We mark the buffer invalid so that the next attempt to get the
+ * node will read it and attempt to swap again, and will notice
+ * the error again. If we didn't do this, the next attempt to get
+ * the node might use the partially swapped node as-is.
+ */
+ if (retval)
+ buf_markinvalid(bp);
}
-#endif
- } else {
+ }
+
+ if (retval) {
if (bp)
- buf_brelse(bp);
+ buf_brelse(bp);
block->blockHeader = NULL;
block->buffer = NULL;
}
static int
btree_journal_modify_block_end(struct hfsmount *hfsmp, struct buf *bp)
{
-#if BYTE_ORDER == LITTLE_ENDIAN
+ int retval;
struct vnode *vp = buf_vnode(bp);
BlockDescriptor block;
/* Prepare the block pointer */
block.blockHeader = bp;
block.buffer = (char *)buf_dataptr(bp);
+ block.blockNum = buf_lblkno(bp);
/* not found in cache ==> came from disk */
block.blockReadFromDisk = (buf_fromcache(bp) == 0);
block.blockSize = buf_count(bp);
// XXXdbg have to swap the data before it goes in the journal
- SWAP_BT_NODE (&block, ISHFSPLUS (VTOVCB(vp)), VTOC(vp)->c_fileid, 1);
-#endif
+ retval = hfs_swap_BTNode (&block, vp, kSwapBTNodeHostToBig);
+ if (retval)
+ panic("btree_journal_modify_block_end: about to write corrupt node!\n");
return journal_modify_block_end(hfsmp->jnl, bp);
}
}
+#define HFS_CLUMP_ADJ_LIMIT (200*1024*1024)
+
__private_extern__
OSStatus ExtendBTreeFile(FileReference vp, FSSize minEOF, FSSize maxEOF)
{
}
vcb = VTOVCB(vp);
-
+
+ /* Take past growth into account when extending the catalog file. */
+ if ((VTOC(vp)->c_fileid == kHFSCatalogFileID) &&
+ (bytesToAdd / vcb->blockSize) < filePtr->fcbExtents[0].blockCount) {
+ bytesToAdd = filePtr->fcbExtents[0].blockCount * (UInt64)vcb->blockSize;
+ bytesToAdd = MIN(bytesToAdd, HFS_CLUMP_ADJ_LIMIT);
+ }
/*
* The Extents B-tree can't have overflow extents. ExtendFileC will
* return an error if an attempt is made to extend the Extents B-tree