2 * COPYRIGHT: GNU GENERAL PUBLIC LICENSE VERSION 2
3 * PROJECT: ReiserFs file system driver for Windows NT/2000/XP/Vista.
5 * PURPOSE: Disk block operations that are specific to ReiserFS.
6 * PROGRAMMER: Mark Piper, Matt Wu, Bo Brantén.
11 /* INCLUDES *****************************************************************/
15 /* GLOBALS ***************************************************************/
17 extern PRFSD_GLOBAL RfsdGlobal
;
19 /* DEFINITIONS *************************************************************/
22 #pragma alloc_text(PAGE, RfsdAllocateAndLoadBlock)
23 #pragma alloc_text(PAGE, RfsdFindItemHeaderInBlock)
24 #pragma alloc_text(PAGE, RfsdLoadItem)
27 /* FUNCTIONS *************************************************************/
30 Returns the address of an allocated buffer (WHICH THE CALLER WILL BE RESPONSIBLE FOR FREEING!), filled with the contents of the given block number on disk.
31 (This is really just an alternative interface to LoadBlock)
34 RfsdAllocateAndLoadBlock(
36 IN ULONG BlockIndex
) // The ordinal block number to read
38 // Allocate the return buffer (the caller will be responsible for freeing this!)
39 PUCHAR pReturnBuffer
= ExAllocatePoolWithTag(NonPagedPool
, Vcb
->BlockSize
, RFSD_POOL_TAG
); // NOTE: for now, I'm switching this to non-paged, because i was getting crashes
44 { DbgBreak(); return NULL
; }
46 // Read the block in from disk, or from cache.
47 if (!RfsdLoadBlock(Vcb
, BlockIndex
, pReturnBuffer
))
48 { DbgBreak(); ExFreePool(pReturnBuffer
); return NULL
; }
50 // Return the result to the caller.
55 Finds the item header inside a given leaf node block that matches a given key.
57 STATUS_INVALID_HANDLE if the block given to search is invalid
58 STATUS_NO_SUCH_MEMBER if the key is not found in the block given
61 RfsdFindItemHeaderInBlock(
63 IN PRFSD_KEY_IN_MEMORY pTargetKey
, // The key to match against
64 IN PUCHAR pBlockBuffer
, // A filled disk block, provided by the caller
65 OUT PRFSD_ITEM_HEAD
* ppMatchingItemHeader
, // A pointer to a PRFSD_ITEM_HEAD. The PRFSD_ITEM_HEAD will point to the item head matching Key, or NULL if there was no such item head in the given block.
66 IN
RFSD_KEY_COMPARISON (*fpComparisonFunction
)(PRFSD_KEY_IN_MEMORY
, PRFSD_KEY_IN_MEMORY
)
69 // Read the block header
70 PRFSD_BLOCK_HEAD pBlockHeader
= (PRFSD_BLOCK_HEAD
) pBlockBuffer
;
71 PUCHAR pItemHeaderListBuffer
= (PUCHAR
) pBlockBuffer
+ sizeof(RFSD_BLOCK_HEAD
);
75 *ppMatchingItemHeader
= NULL
;
77 // Sanity check that the block (and therefore its header) is there
78 if (!pBlockHeader
) { return STATUS_INVALID_HANDLE
; }
79 ASSERT(pBlockHeader
->blk_level
== 1);
81 // Search through the item headers to find one with a key matching pTargetKey
83 ULONG idxCurrentItemHeader
= 0;
84 PRFSD_ITEM_HEAD pCurrentItemHeader
= NULL
;
85 RFSD_KEY_IN_MEMORY CurrentItemKey
;
87 for(idxCurrentItemHeader
= 0; idxCurrentItemHeader
< pBlockHeader
->blk_nr_item
; idxCurrentItemHeader
++)
89 // Grab the item header, and its key
90 pCurrentItemHeader
= (PRFSD_ITEM_HEAD
) (pItemHeaderListBuffer
+ idxCurrentItemHeader
* sizeof(RFSD_ITEM_HEAD
));
93 &( pCurrentItemHeader
->ih_key
), pCurrentItemHeader
->ih_version
,
94 &( CurrentItemKey
) ); // <
96 // Check if this item is the one being searched for
97 if ( RFSD_KEYS_MATCH
== (*fpComparisonFunction
)( pTargetKey
, &CurrentItemKey
) )
99 *ppMatchingItemHeader
= pCurrentItemHeader
;
100 return STATUS_SUCCESS
;
104 // If a matching key was never found, simply return
105 return STATUS_NO_SUCH_MEMBER
;
110 Given an item's key, load the block, the item header, and the item buffer associated with the key.
112 STATUS_INTERNAL_ERROR if leaf node could not be reached
113 STATUS_NO_SUCH_MEMBER if the item header could not be located
114 STATUS_INSUFFICIENT_RESOURCES if the leaf node buffer could not be allocated
120 IN PRFSD_KEY_IN_MEMORY pItemKey
, // The key of the item to find
121 OUT PRFSD_ITEM_HEAD
* ppMatchingItemHeader
,
122 OUT PUCHAR
* ppItemBuffer
,
123 OUT PUCHAR
* ppBlockBuffer
, // Block buffer, which backs the other output data structures. The caller must free this (even in the case of an error)!
124 OPTIONAL OUT PULONG pBlockNumber
, // The ordinal disk block number at which the item was found
125 IN
RFSD_KEY_COMPARISON (*fpComparisonFunction
)(PRFSD_KEY_IN_MEMORY
, PRFSD_KEY_IN_MEMORY
)
129 ULONG LeafNodeBlockNumber
;
133 // Clear the output pointers
134 *ppItemBuffer
= *ppBlockBuffer
= NULL
;
135 *ppMatchingItemHeader
= NULL
;
136 if (pBlockNumber
) *pBlockNumber
= 0;
139 // Find the block number of the leaf node bock (on disk), that should contain the item w/ pItemKey
140 Status
= NavigateToLeafNode(
141 Vcb
, pItemKey
, Vcb
->SuperBlock
->s_root_block
,
142 &(LeafNodeBlockNumber
)
144 if (!NT_SUCCESS(Status
)){ DbgBreak(); return STATUS_INTERNAL_ERROR
; }
145 if (pBlockNumber
) *pBlockNumber
= LeafNodeBlockNumber
;
148 // Load the block (which the caller must later free)
149 *ppBlockBuffer
= RfsdAllocateAndLoadBlock(Vcb
, LeafNodeBlockNumber
);
150 if (!*ppBlockBuffer
) { return STATUS_INSUFFICIENT_RESOURCES
; }
153 // Get the item header and its information
154 Status
= RfsdFindItemHeaderInBlock(
155 Vcb
, pItemKey
, *ppBlockBuffer
,
156 ( ppMatchingItemHeader
), //<
159 if (Status
== STATUS_NO_SUCH_MEMBER
) { return STATUS_NO_SUCH_MEMBER
; }
160 if (!*ppMatchingItemHeader
) { return STATUS_INTERNAL_ERROR
; }
162 // Setup the item buffer
163 *ppItemBuffer
= (PUCHAR
) *ppBlockBuffer
+ (*ppMatchingItemHeader
)->ih_item_location
;
165 return STATUS_SUCCESS
;