From 1203e0880e2b169e6efa5d88c1c12d357714f611 Mon Sep 17 00:00:00 2001 From: DualFroz Date: Mon, 7 Sep 2026 17:11:41 +0200 Subject: [PATCH] feat: add getBlockForRead to sfs --- src/sfs.c | 161 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 161 insertions(+) diff --git a/src/sfs.c b/src/sfs.c index 266c772..00d1770 100644 --- a/src/sfs.c +++ b/src/sfs.c @@ -307,3 +307,164 @@ static bool getOrAllocBlockForWrite(SfsInode* inode, uint32 logicalIndex, uint32 if (!loadOrAllocPointerBlock(inode, &inode->doubleIndirect, outerBuf)) return false; + uint32* outerPtrs = (uint32*)outerBuf; + uint8 innerBuf[sfsBlockSize]; + bool outerNeedsFlush = false; + if (outerPtrs[outerIndex] == 0) { + int32 nb = allocDataBlockAbs(); + if (nb < 0) + return false; + outerPtrs[outerIndex] = (uint32)nb; + inode->blockCount++; + outerNeedsFlush = true; + memset(innerBuf, 0, sizeof(innerBuf)); + if (!blockWrite(outerPtrs[outerIndex], innerBuf)) + return false; + } else if (!blockRead(outerPtrs[outerIndex], innerBuf)) { + return false; + } + if (outerNeedsFlush && !blockWrite(inode->doubleIndirect, outerBuf)) + return false; + + uint32* innerPtrs = (uint32*)innerBuf; + if (innerPtrs[innerIndex] == 0) { + int32 nb = allocDataBlockAbs(); + if (nb < 0) + return false; + innerPtrs[innerIndex] = (uint32)nb; + inode->blockCount++; + if (!blockWrite(outerPtrs[outerIndex], innerBuf)) + return false; + } + *outAbs = innerPtrs[innerIndex]; + return true; + } + + /* Same three-level shape as the double-indirect block above, one level + deeper: tripleIndirect -> top (128 mid-block pointers) -> mid (128 + leaf-block pointers) -> leaf (128 data-block pointers) -> data. */ + uint32 tripleIndex = doubleIndex - sfsPtrsPerBlock * sfsPtrsPerBlock; + uint32 topIndex = tripleIndex / (sfsPtrsPerBlock * sfsPtrsPerBlock); + uint32 midIndex = (tripleIndex / sfsPtrsPerBlock) % sfsPtrsPerBlock; + uint32 leafIndex = tripleIndex % sfsPtrsPerBlock; + if (topIndex >= sfsPtrsPerBlock) + return false; /* past the addressing limit (~1 GiB) */ + + uint8 topBuf[sfsBlockSize]; + if (!loadOrAllocPointerBlock(inode, &inode->tripleIndirect, topBuf)) + return false; + + uint32* topPtrs = (uint32*)topBuf; + uint8 midBuf[sfsBlockSize]; + bool topNeedsFlush = false; + if (topPtrs[topIndex] == 0) { + int32 nb = allocDataBlockAbs(); + if (nb < 0) + return false; + topPtrs[topIndex] = (uint32)nb; + inode->blockCount++; + topNeedsFlush = true; + memset(midBuf, 0, sizeof(midBuf)); + if (!blockWrite(topPtrs[topIndex], midBuf)) + return false; + } else if (!blockRead(topPtrs[topIndex], midBuf)) { + return false; + } + if (topNeedsFlush && !blockWrite(inode->tripleIndirect, topBuf)) + return false; + + uint32* midPtrs = (uint32*)midBuf; + uint8 leafBuf[sfsBlockSize]; + bool midNeedsFlush = false; + if (midPtrs[midIndex] == 0) { + int32 nb = allocDataBlockAbs(); + if (nb < 0) + return false; + midPtrs[midIndex] = (uint32)nb; + inode->blockCount++; + midNeedsFlush = true; + memset(leafBuf, 0, sizeof(leafBuf)); + if (!blockWrite(midPtrs[midIndex], leafBuf)) + return false; + } else if (!blockRead(midPtrs[midIndex], leafBuf)) { + return false; + } + if (midNeedsFlush && !blockWrite(topPtrs[topIndex], midBuf)) + return false; + + uint32* leafPtrs = (uint32*)leafBuf; + if (leafPtrs[leafIndex] == 0) { + int32 nb = allocDataBlockAbs(); + if (nb < 0) + return false; + leafPtrs[leafIndex] = (uint32)nb; + inode->blockCount++; + if (!blockWrite(midPtrs[midIndex], leafBuf)) + return false; + } + *outAbs = leafPtrs[leafIndex]; + return true; +} + +static bool getBlockForRead(const SfsInode* inode, uint32 logicalIndex, uint32* outAbs) +{ + if (logicalIndex < sfsDirectBlocks) { + *outAbs = inode->direct[logicalIndex]; + return *outAbs != 0; + } + + uint32 indIndex = logicalIndex - sfsDirectBlocks; + if (indIndex < sfsPtrsPerBlock) { + if (inode->indirect == 0) + return false; + uint8 indBuf[sfsBlockSize]; + if (!blockRead(inode->indirect, indBuf)) + return false; + uint32* ptrs = (uint32*)indBuf; + *outAbs = ptrs[indIndex]; + return *outAbs != 0; + } + + uint32 doubleIndex = indIndex - sfsPtrsPerBlock; + if (doubleIndex < sfsPtrsPerBlock * sfsPtrsPerBlock) { + uint32 outerIndex = doubleIndex / sfsPtrsPerBlock; + uint32 innerIndex = doubleIndex % sfsPtrsPerBlock; + if (inode->doubleIndirect == 0) + return false; + + uint8 outerBuf[sfsBlockSize]; + if (!blockRead(inode->doubleIndirect, outerBuf)) + return false; + uint32* outerPtrs = (uint32*)outerBuf; + if (outerPtrs[outerIndex] == 0) + return false; + + uint8 innerBuf[sfsBlockSize]; + if (!blockRead(outerPtrs[outerIndex], innerBuf)) + return false; + uint32* innerPtrs = (uint32*)innerBuf; + *outAbs = innerPtrs[innerIndex]; + return *outAbs != 0; + } + + uint32 tripleIndex = doubleIndex - sfsPtrsPerBlock * sfsPtrsPerBlock; + uint32 topIndex = tripleIndex / (sfsPtrsPerBlock * sfsPtrsPerBlock); + uint32 midIndex = (tripleIndex / sfsPtrsPerBlock) % sfsPtrsPerBlock; + uint32 leafIndex = tripleIndex % sfsPtrsPerBlock; + if (topIndex >= sfsPtrsPerBlock || inode->tripleIndirect == 0) + return false; + + uint8 topBuf[sfsBlockSize]; + if (!blockRead(inode->tripleIndirect, topBuf)) + return false; + uint32* topPtrs = (uint32*)topBuf; + if (topPtrs[topIndex] == 0) + return false; + + uint8 midBuf[sfsBlockSize]; + if (!blockRead(topPtrs[topIndex], midBuf)) + return false; + uint32* midPtrs = (uint32*)midBuf; + if (midPtrs[midIndex] == 0) + return false; +