-/*************************************************************************************/
-
-/*************************************************************************************/
-/*
- * The following two routines work in tandem: StoreBufferMapping stores
- * successive buffer address -> buffer pointer mappings in a circular
- * match list, advancing the list index forward each time, while LookupBufferMapping
- * looks backwards through the list to look up a particular mapping (which is
- * typically the entry currently pointed to by gBufferAddress).
- *
- */
-static void StoreBufferMapping(caddr_t bufferAddress, struct buf *bp)
-{
- int i;
-
- DBG_ASSERT(gBufferListIndex >= 0);
- DBG_ASSERT(gBufferListIndex < BUFFERPTRLISTSIZE);
-
- simple_lock(&gBufferPtrListLock);
-
- /* We've got at most BUFFERPTRLISTSIZE tries at this... */
- for (i = BUFFERPTRLISTSIZE; i > 0; --i) {
- if (gBufferAddress[gBufferListIndex] == NULL) {
- gBufferAddress[gBufferListIndex] = bufferAddress;
- gBufferHeaderPtr[gBufferListIndex] = bp;
- break;
- }
- gBufferListIndex = (gBufferListIndex + 1) % BUFFERPTRLISTSIZE;
- };
-
- if (i == 0) {
- panic("StoreBufferMapping: couldn't find an empty slot in buffer list.");
- };
-
- DBG_ASSERT(gBufferListIndex >= 0);
- DBG_ASSERT(gBufferListIndex < BUFFERPTRLISTSIZE);
-
- simple_unlock(&gBufferPtrListLock);
-}
-
-
-/*static*/ OSErr LookupBufferMapping(caddr_t bufferAddress, struct buf **bpp, int *mappingIndexPtr)
-{
- OSErr err = E_NONE;
- int i;
- int listIndex = gBufferListIndex;
- struct buf *bp = NULL;
-
- DBG_ASSERT(gBufferListIndex >= 0);
- DBG_ASSERT(gBufferListIndex < BUFFERPTRLISTSIZE);
-
- simple_lock(&gBufferPtrListLock);
-
- /* We've got at most BUFFERPTRLISTSIZE tries at this... */
- for (i = BUFFERPTRLISTSIZE; i > 0; --i) {
- if (gBufferAddress[listIndex] == bufferAddress) {
- *mappingIndexPtr = listIndex;
- bp = gBufferHeaderPtr[listIndex];
- break;
- };
-
- listIndex = (listIndex - 1);
- if (listIndex < 0) {
- listIndex = BUFFERPTRLISTSIZE - 1;
- };
- };
-
- if (bp == NULL) {
- DEBUG_BREAK_MSG(("LookupBufferMapping: couldn't find buffer header for buffer in list.\n"));
- err = -1;
- };
-
- DBG_ASSERT(gBufferListIndex >= 0);
- DBG_ASSERT(gBufferListIndex < BUFFERPTRLISTSIZE);
-
- simple_unlock(&gBufferPtrListLock);
-
- *bpp = bp;
- return err;
-}
-
-
-static void ReleaseMappingEntry(int entryIndex) {
-
- DBG_ASSERT(gBufferListIndex >= 0);
- DBG_ASSERT(gBufferListIndex < BUFFERPTRLISTSIZE);
-
- simple_lock(&gBufferPtrListLock);
- gBufferAddress[entryIndex] = NULL;
- simple_unlock(&gBufferPtrListLock);
-};
-#if HFS_DIAGNOSTIC
-#define DBG_GETBLOCK 0
-#else
-#define DBG_GETBLOCK 0
-#endif
-
-OSErr GetBlock_glue (UInt16 options, UInt32 blockNum, Ptr *baddress, FileReference fileRefNum, ExtendedVCB * vcb)
-{
- int status;
- struct buf *bp = NULL;
- int readcount = 0;
-
-#if DBG_GETBLOCK
- DBG_IO(("Getting block %ld with options %d and a refnum of %x\n", blockNum, options, fileRefNum ));
-#endif
-
- if ((options & ~(gbReadMask | gbNoReadMask)) != 0) {
- DEBUG_BREAK_MSG(("GetBlock_glue: options = 0x%04X.\n", options));
- };
-
- *baddress = NULL;
-
- if (options & gbNoReadMask) {
- if (fileRefNum == NULL) {
- bp = getblk (VCBTOHFS(vcb)->hfs_devvp,
- IOBLKNOFORBLK(blockNum, VCBTOHFS(vcb)->hfs_phys_block_size),
- IOBYTECCNTFORBLK(blockNum, kHFSBlockSize, VCBTOHFS(vcb)->hfs_phys_block_size),
- 0,
- 0,
- BLK_META);
- } else {
- bp = getblk (fileRefNum,
- IOBLKNOFORBLK(blockNum, VCBTOHFS(vcb)->hfs_phys_block_size),
- IOBYTECCNTFORBLK(blockNum, kHFSBlockSize, VCBTOHFS(vcb)->hfs_phys_block_size),
- 0,
- 0,
- BLK_META);
- };
- status = E_NONE;
- } else {
- do {
- if (fileRefNum == NULL) {
- status = meta_bread (VCBTOHFS(vcb)->hfs_devvp,
- IOBLKNOFORBLK(blockNum, VCBTOHFS(vcb)->hfs_phys_block_size),
- IOBYTECCNTFORBLK(blockNum, kHFSBlockSize, VCBTOHFS(vcb)->hfs_phys_block_size),
- NOCRED,
- &bp);
- } else {
- status = meta_bread (fileRefNum,
- IOBLKNOFORBLK(blockNum, VCBTOHFS(vcb)->hfs_phys_block_size),
- IOBYTECCNTFORBLK(blockNum, kHFSBlockSize, VCBTOHFS(vcb)->hfs_phys_block_size),
- NOCRED,
- &bp);
- };
- if (status != E_NONE) {
- if (bp) brelse(bp);
- goto Error_Exit;
- };
-
- if (bp == NULL) {
- status = -1;
- goto Error_Exit;
- };
-
- ++readcount;
-
- if ((options & gbReadMask) && (bp->b_flags & B_CACHE)) {
- /* Rats! The block was found in the cache just when we really wanted a
- fresh copy off disk...
- */
- if (bp->b_flags & B_DIRTY) {
- DEBUG_BREAK_MSG(("GetBlock_glue: forced read for dirty block!\n"))
- };
- bp->b_flags |= B_INVAL;
- brelse(bp);
-
- /* Fall through and try again until we get a fresh copy from the disk... */
- };
- } while (((options & gbReadMask) != 0) && (readcount <= 1));
- };
-
- *baddress = bp->b_data + IOBYTEOFFSETFORBLK(bp->b_blkno, VCBTOHFS(vcb)->hfs_phys_block_size);
- StoreBufferMapping(*baddress, bp);
-
-Error_Exit: ;
- return status;
-}
-
-
-OSErr RelBlock_glue (Ptr address, UInt16 options )
-{
- int err;
- struct buf *bp;
- int mappingEntry;
-
- if (options & ~(rbTrashMask | rbDirtyMask | rbWriteMask) == 0) {
- DEBUG_BREAK_MSG(("RelBlock_glue: options = 0x%04X.\n", options));
- };
-
- if ((err = LookupBufferMapping(address, &bp, &mappingEntry))) {
- DEBUG_BREAK_MSG(("Failed to find buffer pointer for buffer in RelBlock_glue.\n"));
- } else {
- if (bp->b_flags & B_DIRTY) {
- /* The buffer was previously marked dirty (using MarkBlock_glue):
- now's the time to write it. */
- options |= rbDirtyMask;
- };
- ReleaseMappingEntry(mappingEntry);
- if (options & rbTrashMask) {
- bp->b_flags |= B_INVAL;
- brelse(bp);
- } else {
- if (options & (rbDirtyMask | rbWriteMask)) {
- bp->b_flags |= B_DIRTY;
- if (options & rbWriteMask) {
- bwrite(bp);
- } else {
- bdwrite(bp);
- }
- } else {
- brelse(bp);
- };
- };
- err = E_NONE;
- };
- return err;
-}
-