feat: add inodeLocation and inodeNumInRange to sfs
This commit is contained in:
1 parent
3dfdda8771
commit
8f2ecdb2d4
1 file changed
+151
@@ -156,3 +156,154 @@ static bool flushSuperblock(void)
|
|||||||
return blockWrite(0, buf);
|
return blockWrite(0, buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void inodeLocation(int32 inodeNum, uint32* blockAbs, uint32* index)
|
||||||
|
{
|
||||||
|
uint32 perBlock = sfsBlockSize / sizeof(SfsInode);
|
||||||
|
*blockAbs = sb.inodeTableStart + (uint32)inodeNum / perBlock;
|
||||||
|
*index = (uint32)inodeNum % perBlock;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Shared bound check for readInode/writeInodeRaw below: every REAL inode
|
||||||
|
number allocInodeNum ever hands out satisfies 1 <= n < sb.inodeCount (the
|
||||||
|
loop above never even considers slot 0, reserved as an eternal sentinel).
|
||||||
|
Every one of this file's own internal callers already passes a value it
|
||||||
|
got from allocInodeNum/sfsLookup/dirFind, so this never rejects a
|
||||||
|
legitimate call -- it exists to stop an out-of-range inodeNum (a caller
|
||||||
|
bug, or a deliberately-invalid probe like sfsModeOf(9999)) from silently
|
||||||
|
computing a block address past the real inode table and reading/writing
|
||||||
|
whatever data block happens to live there instead of failing cleanly. */
|
||||||
|
static bool inodeNumInRange(int32 inodeNum)
|
||||||
|
{
|
||||||
|
return inodeNum > 0 && (uint32)inodeNum < sb.inodeCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool readInode(int32 inodeNum, SfsInode* out)
|
||||||
|
{
|
||||||
|
if (!inodeNumInRange(inodeNum))
|
||||||
|
return false;
|
||||||
|
uint32 blk, idx;
|
||||||
|
inodeLocation(inodeNum, &blk, &idx);
|
||||||
|
uint8 buf[sfsBlockSize];
|
||||||
|
if (!blockRead(blk, buf))
|
||||||
|
return false;
|
||||||
|
memcpy(out, buf + (uint64)idx * sizeof(SfsInode), sizeof(SfsInode));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool writeInodeRaw(int32 inodeNum, const SfsInode* in)
|
||||||
|
{
|
||||||
|
if (!inodeNumInRange(inodeNum))
|
||||||
|
return false;
|
||||||
|
uint32 blk, idx;
|
||||||
|
inodeLocation(inodeNum, &blk, &idx);
|
||||||
|
uint8 buf[sfsBlockSize];
|
||||||
|
if (!blockRead(blk, buf))
|
||||||
|
return false;
|
||||||
|
memcpy(buf + (uint64)idx * sizeof(SfsInode), in, sizeof(SfsInode));
|
||||||
|
return blockWrite(blk, buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int32 allocInodeNum(void)
|
||||||
|
{
|
||||||
|
for (uint32 i = 1; i < sb.inodeCount; i++) {
|
||||||
|
if (!bitTest(inodeBitmap, i)) {
|
||||||
|
bitSet(inodeBitmap, i);
|
||||||
|
flushInodeBitmap();
|
||||||
|
return (int32)i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void freeInodeNum(int32 inodeNum)
|
||||||
|
{
|
||||||
|
bitClear(inodeBitmap, (uint32)inodeNum);
|
||||||
|
flushInodeBitmap();
|
||||||
|
}
|
||||||
|
|
||||||
|
static int32 allocDataBlockAbs(void)
|
||||||
|
{
|
||||||
|
uint32 dataBlockCount = sb.totalBlocks - sb.dataStart;
|
||||||
|
for (uint32 i = 0; i < dataBlockCount; i++) {
|
||||||
|
if (!bitTest(blockBitmap, i)) {
|
||||||
|
bitSet(blockBitmap, i);
|
||||||
|
flushBlockBitmap();
|
||||||
|
uint32 abs = sb.dataStart + i;
|
||||||
|
uint8 zero[sfsBlockSize];
|
||||||
|
memset(zero, 0, sizeof(zero));
|
||||||
|
blockWrite(abs, zero);
|
||||||
|
return (int32)abs;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void freeDataBlockAbs(uint32 blockAbs)
|
||||||
|
{
|
||||||
|
bitClear(blockBitmap, blockAbs - sb.dataStart);
|
||||||
|
flushBlockBitmap();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Allocates (if needed) blockAbs's holderAbs on first use and returns the
|
||||||
|
holder block's contents in buf, zeroed for a fresh allocation. Shared by
|
||||||
|
the single-indirect and each level of the double-indirect path below, so
|
||||||
|
the "allocate a pointer block, zero it, write it back" dance is written
|
||||||
|
once. *holderAbs is updated (and inode->blockCount bumped) when a new
|
||||||
|
block is allocated. */
|
||||||
|
static bool loadOrAllocPointerBlock(SfsInode* inode, uint32* holderAbs, uint8* buf)
|
||||||
|
{
|
||||||
|
if (*holderAbs == 0) {
|
||||||
|
int32 nb = allocDataBlockAbs();
|
||||||
|
if (nb < 0)
|
||||||
|
return false;
|
||||||
|
*holderAbs = (uint32)nb;
|
||||||
|
inode->blockCount++;
|
||||||
|
memset(buf, 0, sfsBlockSize);
|
||||||
|
return blockWrite(*holderAbs, buf);
|
||||||
|
}
|
||||||
|
return blockRead(*holderAbs, buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool getOrAllocBlockForWrite(SfsInode* inode, uint32 logicalIndex, uint32* outAbs)
|
||||||
|
{
|
||||||
|
if (logicalIndex < sfsDirectBlocks) {
|
||||||
|
if (inode->direct[logicalIndex] == 0) {
|
||||||
|
int32 nb = allocDataBlockAbs();
|
||||||
|
if (nb < 0)
|
||||||
|
return false;
|
||||||
|
inode->direct[logicalIndex] = (uint32)nb;
|
||||||
|
inode->blockCount++;
|
||||||
|
}
|
||||||
|
*outAbs = inode->direct[logicalIndex];
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32 indIndex = logicalIndex - sfsDirectBlocks;
|
||||||
|
if (indIndex < sfsPtrsPerBlock) {
|
||||||
|
uint8 indBuf[sfsBlockSize];
|
||||||
|
if (!loadOrAllocPointerBlock(inode, &inode->indirect, indBuf))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
uint32* ptrs = (uint32*)indBuf;
|
||||||
|
if (ptrs[indIndex] == 0) {
|
||||||
|
int32 nb = allocDataBlockAbs();
|
||||||
|
if (nb < 0)
|
||||||
|
return false;
|
||||||
|
ptrs[indIndex] = (uint32)nb;
|
||||||
|
inode->blockCount++;
|
||||||
|
if (!blockWrite(inode->indirect, indBuf))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
*outAbs = ptrs[indIndex];
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32 doubleIndex = indIndex - sfsPtrsPerBlock;
|
||||||
|
if (doubleIndex < sfsPtrsPerBlock * sfsPtrsPerBlock) {
|
||||||
|
uint32 outerIndex = doubleIndex / sfsPtrsPerBlock;
|
||||||
|
uint32 innerIndex = doubleIndex % sfsPtrsPerBlock;
|
||||||
|
|
||||||
|
uint8 outerBuf[sfsBlockSize];
|
||||||
|
if (!loadOrAllocPointerBlock(inode, &inode->doubleIndirect, outerBuf))
|
||||||
|
return false;
|
||||||
|
|
||||||
Reference in new issue
Block a user