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)
|
if (midPtrs[midIndex] == 0)
|
||||||
return false;
|
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