148 lines
3.7 KiB
C++
148 lines
3.7 KiB
C++
// Ext2BlockCache.cpp
|
|
// Author: Josh Holtrop
|
|
// Date: 12/29/05
|
|
// Modified: 12/29/05
|
|
|
|
#include "fs/vfs.h"
|
|
#include "Ext2BlockCache.h"
|
|
|
|
extern "C" {
|
|
#include "display/kout.h"
|
|
}
|
|
|
|
Ext2BlockCache::Ext2BlockCache(Ext2fs *fs, u32_t inum)
|
|
{
|
|
myFS = fs;
|
|
myInum = inum;
|
|
myInodeDirty = 0;
|
|
fs->readInode(inum, &myInode);
|
|
myBlockSize = 1024 << fs->getSuper()->s_log_block_size;
|
|
for (int i = 0; i < 3; i++)
|
|
{
|
|
myCache[i] = new u8_t[myBlockSize];
|
|
myCacheAddress[i] = 0;
|
|
myCacheDirty[i] = 0;
|
|
}
|
|
}
|
|
|
|
Ext2BlockCache::~Ext2BlockCache()
|
|
{
|
|
for (int i = 0; i < 3; i++)
|
|
{
|
|
if (myCacheDirty[i])
|
|
myFS->writeBlock(myCacheAddress[i], myCache[i]);
|
|
delete[] myCache[i];
|
|
}
|
|
if (myInodeDirty)
|
|
myFS->writeInode(myInum, &myInode);
|
|
}
|
|
|
|
int Ext2BlockCache::readBlock(u32_t blockNum, void *buf)
|
|
{
|
|
u32_t fsblock = getFSBlock(blockNum, 0);
|
|
if (fsblock == 0)
|
|
return -1;
|
|
return myFS->readBlock(fsblock, buf);
|
|
}
|
|
|
|
int Ext2BlockCache::writeBlock(u32_t blockNum, void *buf)
|
|
{
|
|
u32_t fsblock = getFSBlock(blockNum, 1);
|
|
if (fsblock == 0)
|
|
return -1;
|
|
return myFS->writeBlock(fsblock, buf);
|
|
}
|
|
|
|
void Ext2BlockCache::setCache(u32_t level, u32_t fsblock)
|
|
{
|
|
if (myCacheAddress[level] == fsblock)
|
|
return;
|
|
if (myCacheDirty[level])
|
|
myFS->writeBlock(myCacheAddress[level], myCache[level]);
|
|
myCacheAddress[level] = fsblock;
|
|
myCacheDirty[level] = 0;
|
|
myFS->readBlock(fsblock, myCache[level]);
|
|
}
|
|
|
|
u32_t Ext2BlockCache::getFSBlock(u32_t blockNum, int create)
|
|
{
|
|
if (blockNum < 12) /* direct pointer */
|
|
{
|
|
if (create && myInode.i_block[blockNum] == 0)
|
|
{
|
|
myInode.i_block[blockNum] = myFS->allocBlock();
|
|
myInodeDirty = 1;
|
|
}
|
|
return myInode.i_block[blockNum];
|
|
}
|
|
blockNum -= 12;
|
|
if (blockNum < myBlockSize) /* i_block[12] */
|
|
{
|
|
if (create && myInode.i_block[12] == 0)
|
|
{
|
|
myInode.i_block[12] = myFS->allocBlock();
|
|
myInodeDirty = 1;
|
|
}
|
|
setCache(0, myInode.i_block[12]);
|
|
/* blockNum indexes cache 0 */
|
|
if (create && myCache[0][blockNum] == 0)
|
|
{
|
|
myCache[0][blockNum] = myFS->allocBlock();
|
|
myCacheDirty[0] = 1;
|
|
}
|
|
return myCache[0][blockNum];
|
|
}
|
|
blockNum -= myBlockSize;
|
|
if (blockNum < (myBlockSize * myBlockSize)) /* i_block[13] */
|
|
{
|
|
if (create && myInode.i_block[13] == 0)
|
|
{
|
|
myInode.i_block[13] = myFS->allocBlock();
|
|
myInodeDirty = 1;
|
|
}
|
|
setCache(0, myInode.i_block[13]);
|
|
/* blockNum / myBlockSize indexes cache 0 */
|
|
if (create && myCache[0][blockNum / myBlockSize] == 0)
|
|
{
|
|
myCache[0][blockNum / myBlockSize] = myFS->allocBlock();
|
|
myCacheDirty[0] = 1;
|
|
}
|
|
setCache(1, myCache[0][blockNum / myBlockSize]);
|
|
/* blockNum % myBlockSize indexes cache 1 */
|
|
if (create && myCache[1][blockNum % myBlockSize] == 0)
|
|
{
|
|
myCache[1][blockNum % myBlockSize] = myFS->allocBlock();
|
|
myCacheDirty[1] = 1;
|
|
}
|
|
return myCache[1][blockNum % myBlockSize];
|
|
}
|
|
blockNum -= (myBlockSize * myBlockSize); /* i_block[14] */
|
|
if (create && myInode.i_block[14] == 0)
|
|
{
|
|
myInode.i_block[14] = myFS->allocBlock();
|
|
myInodeDirty = 1;
|
|
}
|
|
setCache(0, myInode.i_block[14]);
|
|
/* blockNum / (myBlockSize^2) indexes cache 0 */
|
|
if (create && myCache[0][blockNum / (myBlockSize * myBlockSize)] == 0)
|
|
{
|
|
myCache[0][blockNum / (myBlockSize * myBlockSize)] = myFS->allocBlock();
|
|
myCacheDirty[0] = 1;
|
|
}
|
|
setCache(1, myCache[0][blockNum / (myBlockSize * myBlockSize)]);
|
|
/* blockNum / myBlockSize indexes cache 1 */
|
|
if (create && myCache[1][blockNum / myBlockSize] == 0)
|
|
{
|
|
myCache[1][blockNum / myBlockSize] = myFS->allocBlock();
|
|
myCacheDirty[1] = 1;
|
|
}
|
|
setCache(2, myCache[1][blockNum / myBlockSize]);
|
|
/* blockNum % myBlockSize indexes cache 2 */
|
|
if (create && myCache[2][blockNum % myBlockSize] == 0)
|
|
{
|
|
myCache[2][blockNum % myBlockSize] = myFS->allocBlock();
|
|
myCacheDirty[2] = 1;
|
|
}
|
|
return myCache[2][blockNum % myBlockSize];
|
|
}
|