1313using namespace orbisFSTool ;
1414
1515#pragma mark OrbisFSBlockAllocator
16- OrbisFSBlockAllocator::OrbisFSBlockAllocator (OrbisFSImage *parent, uint32_t allocatorInfoBlock)
17- : _parent(parent)
16+ OrbisFSBlockAllocator::OrbisFSBlockAllocator (OrbisFSImage *parent, uint32_t allocatorInfoBlock, bool virtualMode )
17+ : _parent(parent), _blockSize(_parent-> getBlocksize ())
1818, _info(NULL )
1919{
20- _info = (OrbisFSAllocatorInfoElem_t*)_parent->getBlock (allocatorInfoBlock);
20+ if (virtualMode) {
21+ _virtualMem[allocatorInfoBlock] = {(const void *)_parent->getBlock (allocatorInfoBlock),_blockSize};
22+ }
23+
24+ _info = (OrbisFSAllocatorInfoElem_t*)getBlock (allocatorInfoBlock);
2125}
2226
2327OrbisFSBlockAllocator::~OrbisFSBlockAllocator (){
2428 //
2529}
2630
2731#pragma mark OrbisFSBlockAllocator private
32+ uint8_t *OrbisFSBlockAllocator::getBlock (uint32_t blkNum){
33+ if (_virtualMem.size () == 0 ){
34+ return _parent->getBlock (blkNum);
35+ }else {
36+ /*
37+ We're in virtual mode!
38+ Cache unseed blocks and return everything only from cache
39+ */
40+ auto c = _virtualMem.find (blkNum);
41+ if (c != _virtualMem.end ()) return c->second .data ();
42+
43+ _virtualMem[blkNum] = {(const void *)_parent->getBlock (blkNum),_blockSize};
44+
45+ try {
46+ return _virtualMem.at (blkNum).data ();
47+ } catch (...) {
48+ reterror (" OrbisFSBlockAllocator virtual mode error!" );
49+ }
50+ }
51+ }
52+
2853#pragma mark OrbisFSBlockAllocator public
2954uint64_t OrbisFSBlockAllocator::getTotalBlockNum (){
3055 uint64_t ret = 1 ;
31- uint32_t maxEntries = _parent-> getBlocksize () / sizeof (*_info);
56+ uint32_t maxEntries = _blockSize / sizeof (*_info);
3257 for (uint32_t i=0 ; i<maxEntries; i++) {
3358 if (_info[i].bitmapBlk .type != ORBIS_FS_CHAINLINK_TYPE_LINK) break ;
3459 ret += _info[i].totalBlocks ;
@@ -38,7 +63,7 @@ uint64_t OrbisFSBlockAllocator::getTotalBlockNum(){
3863
3964uint64_t OrbisFSBlockAllocator::getFreeBlocksNum (){
4065 uint64_t ret = 0 ;
41- uint32_t maxEntries = _parent-> getBlocksize () / sizeof (*_info);
66+ uint32_t maxEntries = _blockSize / sizeof (*_info);
4267 for (uint32_t i=0 ; i<maxEntries; i++) {
4368 if (_info[i].bitmapBlk .type != ORBIS_FS_CHAINLINK_TYPE_LINK) break ;
4469 ret += _info[i].freeBlocks ;
@@ -47,16 +72,39 @@ uint64_t OrbisFSBlockAllocator::getFreeBlocksNum(){
4772}
4873
4974bool OrbisFSBlockAllocator::isBlockFree (uint32_t blkNum){
50- uint32_t maxEntries = _parent-> getBlocksize () / sizeof (*_info);
75+ uint32_t maxEntries = _blockSize / sizeof (*_info);
5176 for (uint32_t i=0 ; i<maxEntries; i++) {
5277 OrbisFSAllocatorInfoElem_t ci = _info[i];
5378 if (ci.bitmapBlk .type != ORBIS_FS_CHAINLINK_TYPE_LINK) break ;
5479 if (blkNum >= ci.totalBlocks ) {
5580 blkNum -= ci.totalBlocks ;
5681 continue ;
5782 }
58- uint8_t *bitmap = _parent->getBlock (ci.bitmapBlk .blk );
59- return (bitmap[blkNum/8 ] >> (blkNum & 3 )) & 1 ;
83+ uint8_t *bitmap = getBlock (ci.bitmapBlk .blk );
84+ uint32_t blkIdx = blkNum >> 3 ;
85+ uint32_t blkOff = blkNum & 7 ;
86+ return (bitmap[blkIdx] >> blkOff) & 1 ;
87+ }
88+ reterror (" failed to find block in bitmap" );
89+ }
90+
91+ void OrbisFSBlockAllocator::freeBlock (uint32_t blkNum){
92+ uint32_t maxEntries = _blockSize / sizeof (*_info);
93+ for (uint32_t i=0 ; i<maxEntries; i++) {
94+ OrbisFSAllocatorInfoElem_t *ci = &_info[i];
95+ if (ci->bitmapBlk .type != ORBIS_FS_CHAINLINK_TYPE_LINK) break ;
96+ if (blkNum >= ci->totalBlocks ) {
97+ blkNum -= ci->totalBlocks ;
98+ continue ;
99+ }
100+ uint8_t *bitmap = getBlock (ci->bitmapBlk .blk );
101+ uint32_t blkIdx = blkNum >> 3 ;
102+ uint32_t blkOff = blkNum & 7 ;
103+ retassure (((bitmap[blkIdx] >> blkOff) & 1 ) == 0 , " double free detected!" );
104+ bitmap[blkIdx] |= (1 <<blkOff);
105+ ci->freeBlocks ++;
106+ retassure (ci->freeBlocks <= ci->totalBlocks , " Error: freeBlocks > totalBlocks" );
107+ return ;
60108 }
61109 reterror (" failed to find block in bitmap" );
62110}
0 commit comments