feat: add sfsWriteRaw and sfsTruncateInode to sfs
This commit is contained in:
1 parent
1203e0880e
commit
c13e57d322
1 file changed
+168
@@ -468,3 +468,171 @@ static bool getBlockForRead(const SfsInode* inode, uint32 logicalIndex, uint32*
|
||||
if (midPtrs[midIndex] == 0)
|
||||
return false;
|
||||
|
||||
uint8 leafBuf[sfsBlockSize];
|
||||
if (!blockRead(midPtrs[midIndex], leafBuf))
|
||||
return false;
|
||||
uint32* leafPtrs = (uint32*)leafBuf;
|
||||
*outAbs = leafPtrs[leafIndex];
|
||||
return *outAbs != 0;
|
||||
}
|
||||
|
||||
static bool sfsWriteRaw(SfsInode* inode, int32 inodeNum, uint64 position, const void* data, uint64 length)
|
||||
{
|
||||
if (length == 0)
|
||||
return true;
|
||||
|
||||
const uint8* src = (const uint8*)data;
|
||||
uint64 done = 0;
|
||||
while (done < length) {
|
||||
uint64 pos = position + done;
|
||||
uint32 logicalBlock = (uint32)(pos / sfsBlockSize);
|
||||
uint32 within = (uint32)(pos % sfsBlockSize);
|
||||
uint32 chunk = sfsBlockSize - within;
|
||||
if ((uint64)chunk > length - done)
|
||||
chunk = (uint32)(length - done);
|
||||
|
||||
uint32 blockAbs;
|
||||
if (!getOrAllocBlockForWrite(inode, logicalBlock, &blockAbs))
|
||||
return false;
|
||||
|
||||
uint8 blockBuf[sfsBlockSize];
|
||||
if (chunk == sfsBlockSize) {
|
||||
if (src)
|
||||
memcpy(blockBuf, src + done, sfsBlockSize);
|
||||
else
|
||||
memset(blockBuf, 0, sfsBlockSize);
|
||||
} else {
|
||||
if (!blockRead(blockAbs, blockBuf))
|
||||
return false;
|
||||
if (src)
|
||||
memcpy(blockBuf + within, src + done, chunk);
|
||||
else
|
||||
memset(blockBuf + within, 0, chunk);
|
||||
}
|
||||
if (!blockWrite(blockAbs, blockBuf))
|
||||
return false;
|
||||
|
||||
done += chunk;
|
||||
}
|
||||
|
||||
uint64 newSize = position + length;
|
||||
if (newSize > inode->size)
|
||||
inode->size = (uint32)newSize;
|
||||
inode->mtime = inode->ctime = (uint32)rtcNow();
|
||||
return writeInodeRaw(inodeNum, inode);
|
||||
}
|
||||
|
||||
static bool sfsTruncateInode(SfsInode* inode, int32 inodeNum, uint32 newSize)
|
||||
{
|
||||
uint32 oldBlocks = inode->size ? (inode->size + sfsBlockSize - 1) / sfsBlockSize : 0;
|
||||
uint32 neededBlocks = newSize ? (newSize + sfsBlockSize - 1) / sfsBlockSize : 0;
|
||||
|
||||
for (uint32 i = neededBlocks; i < oldBlocks; i++) {
|
||||
uint32 abs = 0;
|
||||
if (i < sfsDirectBlocks) {
|
||||
abs = inode->direct[i];
|
||||
inode->direct[i] = 0;
|
||||
} else {
|
||||
uint32 indIndex = i - sfsDirectBlocks;
|
||||
if (indIndex < sfsPtrsPerBlock) {
|
||||
if (inode->indirect == 0)
|
||||
continue;
|
||||
uint8 indBuf[sfsBlockSize];
|
||||
if (!blockRead(inode->indirect, indBuf))
|
||||
continue;
|
||||
uint32* ptrs = (uint32*)indBuf;
|
||||
abs = ptrs[indIndex];
|
||||
ptrs[indIndex] = 0;
|
||||
blockWrite(inode->indirect, indBuf);
|
||||
} else {
|
||||
uint32 doubleIndex = indIndex - sfsPtrsPerBlock;
|
||||
if (doubleIndex < sfsPtrsPerBlock * sfsPtrsPerBlock) {
|
||||
uint32 outerIndex = doubleIndex / sfsPtrsPerBlock;
|
||||
uint32 innerIndex = doubleIndex % sfsPtrsPerBlock;
|
||||
if (inode->doubleIndirect == 0)
|
||||
continue;
|
||||
uint8 outerBuf[sfsBlockSize];
|
||||
if (!blockRead(inode->doubleIndirect, outerBuf))
|
||||
continue;
|
||||
uint32* outerPtrs = (uint32*)outerBuf;
|
||||
if (outerPtrs[outerIndex] == 0)
|
||||
continue;
|
||||
uint8 innerBuf[sfsBlockSize];
|
||||
if (!blockRead(outerPtrs[outerIndex], innerBuf))
|
||||
continue;
|
||||
uint32* innerPtrs = (uint32*)innerBuf;
|
||||
abs = innerPtrs[innerIndex];
|
||||
innerPtrs[innerIndex] = 0;
|
||||
blockWrite(outerPtrs[outerIndex], innerBuf);
|
||||
} else {
|
||||
uint32 tripleIndex = doubleIndex - sfsPtrsPerBlock * sfsPtrsPerBlock;
|
||||
uint32 topIndex = tripleIndex / (sfsPtrsPerBlock * sfsPtrsPerBlock);
|
||||
uint32 midIndex = (tripleIndex / sfsPtrsPerBlock) % sfsPtrsPerBlock;
|
||||
uint32 leafIndex = tripleIndex % sfsPtrsPerBlock;
|
||||
if (inode->tripleIndirect == 0 || topIndex >= sfsPtrsPerBlock)
|
||||
continue;
|
||||
uint8 topBuf[sfsBlockSize];
|
||||
if (!blockRead(inode->tripleIndirect, topBuf))
|
||||
continue;
|
||||
uint32* topPtrs = (uint32*)topBuf;
|
||||
if (topPtrs[topIndex] == 0)
|
||||
continue;
|
||||
uint8 midBuf[sfsBlockSize];
|
||||
if (!blockRead(topPtrs[topIndex], midBuf))
|
||||
continue;
|
||||
uint32* midPtrs = (uint32*)midBuf;
|
||||
if (midPtrs[midIndex] == 0)
|
||||
continue;
|
||||
uint8 leafBuf[sfsBlockSize];
|
||||
if (!blockRead(midPtrs[midIndex], leafBuf))
|
||||
continue;
|
||||
uint32* leafPtrs = (uint32*)leafBuf;
|
||||
abs = leafPtrs[leafIndex];
|
||||
leafPtrs[leafIndex] = 0;
|
||||
blockWrite(midPtrs[midIndex], leafBuf);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (abs != 0) {
|
||||
freeDataBlockAbs(abs);
|
||||
inode->blockCount--;
|
||||
}
|
||||
}
|
||||
|
||||
/* Pointer-holder blocks themselves (the indirect block, every inner
|
||||
indirect block plus the outer double-indirect block, and every
|
||||
top/mid/leaf-pointer block of the triple-indirect chain) are
|
||||
reclaimed all-or-nothing once nothing addressed through them is
|
||||
needed anymore -- the loop above already frees every leaf data block
|
||||
that was in range, so by this point each holder either still guards
|
||||
live data (neededBlocks reaches into its range: leave it alone) or is
|
||||
entirely spent (free it, and everything it pointed at). Checked
|
||||
highest level first (triple, then double, then single) so a shrink
|
||||
that drops the whole file frees every level in one pass. */
|
||||
if (neededBlocks <= sfsDirectBlocks + sfsPtrsPerBlock + sfsPtrsPerBlock * sfsPtrsPerBlock
|
||||
&& inode->tripleIndirect != 0) {
|
||||
uint8 topBuf[sfsBlockSize];
|
||||
if (blockRead(inode->tripleIndirect, topBuf)) {
|
||||
uint32* topPtrs = (uint32*)topBuf;
|
||||
for (uint32 j = 0; j < sfsPtrsPerBlock; j++) {
|
||||
if (topPtrs[j] == 0)
|
||||
continue;
|
||||
uint8 midBuf[sfsBlockSize];
|
||||
if (blockRead(topPtrs[j], midBuf)) {
|
||||
uint32* midPtrs = (uint32*)midBuf;
|
||||
for (uint32 k = 0; k < sfsPtrsPerBlock; k++) {
|
||||
if (midPtrs[k] != 0) {
|
||||
freeDataBlockAbs(midPtrs[k]);
|
||||
inode->blockCount--;
|
||||
}
|
||||
}
|
||||
}
|
||||
freeDataBlockAbs(topPtrs[j]);
|
||||
inode->blockCount--;
|
||||
}
|
||||
}
|
||||
freeDataBlockAbs(inode->tripleIndirect);
|
||||
inode->tripleIndirect = 0;
|
||||
inode->blockCount--;
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user