#include <stddef.h>
#include "ubixfs.h"
#include "inode.h"
#include "superblock.h"
UbixFS::UbixFS(void) {
freeBlockList = NULL;
} // UbixFS::UbixFS
int32
UbixFS::getFreeBlock(uInt32 AG) {
// AG == AllocationGroup
signed char * ptr;
signed char * endPtr;
int32 count;
int32 subCount = 128;
// Check to make sure neither of these are null
if (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);
/*
* endPtr is the very last address we can look at before we wrap around
* This calculation is probably not correct if the number of blocks isn't
* divisible by 8
*/
endPtr = freeBlockList + ((superBlock->numAGs << superBlock->AGShift) >> 3);
// Scan through the freeBlockList
while (*ptr == -1) {
if (++ptr == endPtr) {
ptr = freeBlockList;
count = 0;
} else {
count +=8;
} // else
} // while *ptr == -1
do {
if ((*ptr & subCount) == 0) break;
subCount >>= 1;
++count;
} 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
int
UbixFS::format(dev_t * dev) {
return 0;
} // UbixFS::format
UbixFS::~UbixFS(void) {
delete [] freeBlockList;
return;
}