#include <stddef.h>
#include "ubixfs.h"
#include "inode.h"
#include "superblock.h"
UbixFS::UbixFS(dev_t * dev) {
device = dev;
freeBlockList = NULL;
} // UbixFS::UbixFS
int
UbixFS::init(void) {
return 0;
} // UbixFS::init
int32
UbixFS::getFreeBlock(uInt32 AG) {
// AG == AllocationGroup
signed char * ptr;
int32 count;
int32 subCount = 128;
// Check to make sure neither of these are null
if (device == NULL || freeBlockList == NULL || superBlock == NULL) return -1;
// Are there any blocks available?
if (superBlock->numBlocks == superBlock->usedBlocks) return -1;
/*
* count is the block from the base of the list.
* Since we're given a specific AG to look through, we start the count at
* AG << AGShift, where AGShift is the shift value of the number of blocks
* in an AG
*/
count = (AG << superBlock->AGShift);
/*
* The freeBlockList is a bit map of the free/used blocks.
* Used = on bit
* Unused = off bit
* There are 8 bits per byte (hopefully) and so we have to divide the count
* by 8 to get our starting byte offset to look from
*/
ptr = freeBlockList + (count >> 3);
// Scan through the freeBlockList
rescan:
while (*ptr == -1) {
++ptr;
count += 8;
if (count+8 > superBlock->numBlocks) break;
} // while *ptr == -1
subCount = 128;
do {
if ((*ptr & subCount) == 0) break;
subCount >>= 1;
++count;
if (count == superBlock->numBlocks) {
count = 0;
ptr = freeBlockList;
goto rescan;
} // if
} while(subCount > 1);
*ptr |= subCount; // mark this block as used
++superBlock->usedBlocks; // increment the number of used blocks
return count; // return the allocated block number
} // Ubixfs::getFreeBlock
/*
* UbixFS::getFreeBlock(void)
* upon success returns a free block based on the next AG after the lastUsedAG
* failure returns -1
*/
int32
UbixFS::getFreeBlock(void) {
if (superBlock == NULL) return -1;
if (superBlock->lastUsedAG == superBlock->numAGs)
superBlock->lastUsedAG = 0;
else
superBlock->lastUsedAG++;
return getFreeBlock(superBlock->lastUsedAG);
} // UbixFS::getFreeBlock
int32
UbixFS::get8FreeBlocks(uInt32 AG) {
// AG == AllocationGroup
signed char * ptr;
signed char * endPtr;
int32 count;
if (device == NULL || freeBlockList == NULL || superBlock == NULL) return -1;
// Are there any blocks available?
if (superBlock->usedBlocks+8 > superBlock->numBlocks) return -1;
/*
* count is the block from the base of the list.
* Since we're given a specific AG to look through, we start the count at
* AG << AGShift, where AGShift is the shift value of the number of blocks
* in an AG
*/
count = (AG << superBlock->AGShift);
endPtr = freeBlockList + (superBlock->numBlocks >> 3);
bool secondTime = false;
while (*ptr != 0) {
++ptr;
count += 8;
if (ptr == endPtr) {
if (secondTime)
return -1;
else
secondTime = true;
count = 0;
ptr = freeBlockList;
} // if
} // while
*ptr = -1;
return count;
} // UbixFS::get8FreeBlocks
int
UbixFS::format(dev_t * dev) {
return 0;
} // UbixFS::format
UbixFS::~UbixFS(void) {
delete [] freeBlockList;
return;
}