added de/alloc inode datablock s
This commit is contained in:
parent
3ee1647e00
commit
6edece492c
@ -10,14 +10,16 @@ include_directories(
|
|||||||
|
|
||||||
add_executable(fischl
|
add_executable(fischl
|
||||||
|
|
||||||
# Header files
|
|
||||||
lib/fischl.cpp
|
lib/fischl.cpp
|
||||||
lib/main.cpp
|
lib/main.cpp
|
||||||
|
lib/rawdisk.cpp
|
||||||
|
lib/fs/datablock_allocator.cpp
|
||||||
lib/fs/fs_data_types.cpp
|
lib/fs/fs_data_types.cpp
|
||||||
lib/fs/fs_resize.cpp
|
lib/fs/fs_resize.cpp
|
||||||
lib/fs/fs.cpp
|
lib/fs/fs.cpp
|
||||||
|
lib/fs/inode_allocator.cpp
|
||||||
|
|
||||||
)
|
)
|
||||||
|
|
||||||
enable_testing()
|
#enable_testing()
|
||||||
add_subdirectory(test)
|
#add_subdirectory(test)
|
466
include/fs.h
466
include/fs.h
@ -1,466 +0,0 @@
|
|||||||
#include "rawdisk.h"
|
|
||||||
/*****************************************************
|
|
||||||
30GB Disk low-level operation and data structure: spuerblock, inode, and buffer
|
|
||||||
cache 512 bytes sector for 1 block, 62914560 block(sector) 4K bytes sector for 1
|
|
||||||
block, 7864320 block(sector)
|
|
||||||
|
|
||||||
one inode equipped with one 512 bytes block
|
|
||||||
|
|
||||||
*****************************************************/
|
|
||||||
#define SECTOR_SIZE 512
|
|
||||||
#define IO_BLOCK_SIZE 4096
|
|
||||||
#define MAX_INODE 524288
|
|
||||||
#define MAX_BLOCKNUM MAX_INODE * 2 // 62914560
|
|
||||||
|
|
||||||
class SuperBlock {
|
|
||||||
|
|
||||||
public:
|
|
||||||
SuperBlock(const char *directory) {}
|
|
||||||
~SuperBlock() {}
|
|
||||||
static u_int64_t getFreeListHead(RawDisk &disk) {
|
|
||||||
char buffer[8] = {0};
|
|
||||||
disk.rawdisk_read(0, buffer, sizeof(buffer));
|
|
||||||
u_int64_t t = 0;
|
|
||||||
for (int j = 0; j < 8; j++)
|
|
||||||
t = t | (((u_int64_t)(unsigned char)buffer[j]) << (8 * j));
|
|
||||||
return t;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void writeFreeListHead(RawDisk &disk, u_int64_t t) {
|
|
||||||
char buffer[8] = {0};
|
|
||||||
for (int j = 0; j < 8; j++) {
|
|
||||||
buffer[j] = (t >> (8 * j)) & 0xFF;
|
|
||||||
}
|
|
||||||
disk.rawdisk_write(0, buffer, sizeof(buffer));
|
|
||||||
}
|
|
||||||
|
|
||||||
static u_int64_t getFreeINodeHead(RawDisk &disk) {
|
|
||||||
char buffer[8] = {0};
|
|
||||||
disk.rawdisk_read(8, buffer, sizeof(buffer));
|
|
||||||
u_int64_t t = 0;
|
|
||||||
for (int j = 0; j < 8; j++)
|
|
||||||
t = t | (((u_int64_t)(unsigned char)buffer[j]) << (8 * j));
|
|
||||||
return t;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void writeFreeINodeHead(RawDisk &disk, u_int64_t t) {
|
|
||||||
char buffer[8] = {0};
|
|
||||||
for (int j = 0; j < 8; j++) {
|
|
||||||
buffer[j] = (t >> (8 * j)) & 0xFF;
|
|
||||||
}
|
|
||||||
disk.rawdisk_write(8, buffer, sizeof(buffer));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class INode {
|
|
||||||
// direct datablocks
|
|
||||||
u_int64_t blocks[48];
|
|
||||||
// indirect address
|
|
||||||
u_int64_t single_indirect, double_indirect, triple_indirect;
|
|
||||||
// other
|
|
||||||
|
|
||||||
u_int64_t uid;
|
|
||||||
u_int64_t gid;
|
|
||||||
u_int64_t permissions;
|
|
||||||
u_int64_t size;
|
|
||||||
u_int64_t block_number;
|
|
||||||
|
|
||||||
public:
|
|
||||||
void read_get_byte(u_int64_t &t, int ¤t_pos, char *buffer) {
|
|
||||||
t = 0;
|
|
||||||
for (int j = 0; j < 8; j++)
|
|
||||||
t = t | (((u_int64_t)(unsigned char)buffer[j + current_pos]) << (8 * j));
|
|
||||||
current_pos += 8;
|
|
||||||
}
|
|
||||||
|
|
||||||
static u_int64_t read_byte_at(int current_pos, char *buffer) {
|
|
||||||
u_int64_t t = 0;
|
|
||||||
for (int j = 0; j < 8; j++)
|
|
||||||
t = t | (((u_int64_t)(unsigned char)buffer[j + current_pos]) << (8 * j));
|
|
||||||
return t;
|
|
||||||
}
|
|
||||||
|
|
||||||
void inode_construct(u_int64_t blockNumber, RawDisk &disk) {
|
|
||||||
char buffer[SECTOR_SIZE] = {0};
|
|
||||||
disk.rawdisk_read(blockNumber * SECTOR_SIZE, buffer, sizeof(buffer));
|
|
||||||
block_number = blockNumber;
|
|
||||||
int current_pos = 0;
|
|
||||||
// initialize blocks
|
|
||||||
for (int i = 0; i < 48; i++) {
|
|
||||||
read_get_byte(blocks[i], current_pos, buffer);
|
|
||||||
}
|
|
||||||
read_get_byte(single_indirect, current_pos, buffer);
|
|
||||||
read_get_byte(double_indirect, current_pos, buffer);
|
|
||||||
read_get_byte(triple_indirect, current_pos, buffer);
|
|
||||||
read_get_byte(uid, current_pos, buffer);
|
|
||||||
read_get_byte(gid, current_pos, buffer);
|
|
||||||
read_get_byte(permissions, current_pos, buffer);
|
|
||||||
read_get_byte(size, current_pos, buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
void write_get_byte(u_int64_t t, int ¤t_pos, char *buffer) {
|
|
||||||
for (int j = 0; j < 8; j++) {
|
|
||||||
buffer[j + current_pos] = t & (((u_int64_t)1 << (8)) - 1);
|
|
||||||
t >>= 8;
|
|
||||||
}
|
|
||||||
current_pos += 8;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void write_byte_at(u_int64_t t, int current_pos, char *buffer) {
|
|
||||||
for (int j = 0; j < 8; j++) {
|
|
||||||
buffer[j + current_pos] = t & (((u_int64_t)1 << (8)) - 1);
|
|
||||||
t >>= 8;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void inode_save(RawDisk &disk) {
|
|
||||||
char buffer[SECTOR_SIZE] = {0};
|
|
||||||
int current_pos = 0;
|
|
||||||
for (int i = 0; i < 48; i++) {
|
|
||||||
write_get_byte(blocks[i], current_pos, buffer);
|
|
||||||
}
|
|
||||||
write_get_byte(single_indirect, current_pos, buffer);
|
|
||||||
write_get_byte(double_indirect, current_pos, buffer);
|
|
||||||
write_get_byte(triple_indirect, current_pos, buffer);
|
|
||||||
write_get_byte(uid, current_pos, buffer);
|
|
||||||
write_get_byte(gid, current_pos, buffer);
|
|
||||||
write_get_byte(permissions, current_pos, buffer);
|
|
||||||
write_get_byte(size, current_pos, buffer);
|
|
||||||
disk.rawdisk_write(block_number * SECTOR_SIZE, buffer, sizeof(buffer));
|
|
||||||
}
|
|
||||||
|
|
||||||
u_int64_t datablock_allocate_in_list(RawDisk &disk) {
|
|
||||||
// find a free data block
|
|
||||||
u_int64_t freeListHead = SuperBlock::getFreeListHead(disk);
|
|
||||||
/*
|
|
||||||
1. initialization
|
|
||||||
2. data block starting position
|
|
||||||
3. r/w between storage and rawdisk to maintain
|
|
||||||
*/
|
|
||||||
char buffer[IO_BLOCK_SIZE] = {0};
|
|
||||||
u_int64_t freeBlockNum = 0;
|
|
||||||
disk.rawdisk_read(freeListHead, buffer, sizeof(buffer));
|
|
||||||
for (int i = 8; i < 264; i++) {
|
|
||||||
if ((i < 263 && buffer[i] != -1) || (i == 263 && buffer[i] != 127)) {
|
|
||||||
int j = 0;
|
|
||||||
for (j = 0; j < 8; j++) {
|
|
||||||
if ((buffer[i] & (1 << j)) == 0) {
|
|
||||||
buffer[i] |= (1 << j);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (j < 8) {
|
|
||||||
freeBlockNum = freeListHead + ((i - 8) * 8 + j + 1) * IO_BLOCK_SIZE;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
disk.rawdisk_write(freeListHead, buffer, sizeof(buffer));
|
|
||||||
bool notFull = false;
|
|
||||||
for (int i = 8; i < 264; i++) {
|
|
||||||
if ((i < 263 && buffer[i] != -1) || (i == 263 && buffer[i] != 127)) {
|
|
||||||
notFull = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!notFull) {
|
|
||||||
printf("HEADER REMOVAL DETECTED %llu %llu\n", freeListHead, freeBlockNum);
|
|
||||||
u_int64_t next_header = read_byte_at(0, buffer);
|
|
||||||
SuperBlock::writeFreeListHead(disk, next_header);
|
|
||||||
}
|
|
||||||
return freeBlockNum;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool allo_single_indirect(RawDisk &disk, u_int64_t &single_i,
|
|
||||||
u_int64_t freeBlockNum) {
|
|
||||||
if (single_i == 0) {
|
|
||||||
|
|
||||||
single_i = datablock_allocate_in_list(disk);
|
|
||||||
}
|
|
||||||
bool inSingle = false;
|
|
||||||
char buffer[IO_BLOCK_SIZE] = {0};
|
|
||||||
disk.rawdisk_read(single_i, buffer, sizeof(buffer));
|
|
||||||
for (int i = 0; i < IO_BLOCK_SIZE; i += 8) {
|
|
||||||
u_int64_t addr = read_byte_at(i, buffer);
|
|
||||||
if (addr == 0) {
|
|
||||||
inSingle = true;
|
|
||||||
write_byte_at(freeBlockNum, i, buffer);
|
|
||||||
disk.rawdisk_write(single_i, buffer, sizeof(buffer));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return inSingle;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool allo_double_indirect(RawDisk &disk, u_int64_t &double_i,
|
|
||||||
u_int64_t freeBlockNum) {
|
|
||||||
if (double_i == 0) {
|
|
||||||
double_i = datablock_allocate_in_list(disk);
|
|
||||||
}
|
|
||||||
bool inDouble = false;
|
|
||||||
char buffer[IO_BLOCK_SIZE] = {0};
|
|
||||||
disk.rawdisk_read(double_i, buffer, sizeof(buffer));
|
|
||||||
for (int i = 0; i < IO_BLOCK_SIZE; i += 8) {
|
|
||||||
u_int64_t addr = read_byte_at(i, buffer);
|
|
||||||
bool flag = allo_single_indirect(disk, addr, freeBlockNum);
|
|
||||||
if (flag) {
|
|
||||||
write_byte_at(addr, i, buffer);
|
|
||||||
disk.rawdisk_write(double_i, buffer, sizeof(buffer));
|
|
||||||
inDouble = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return inDouble;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool allo_triple_indirect(RawDisk &disk, u_int64_t &triple_i,
|
|
||||||
u_int64_t freeBlockNum) {
|
|
||||||
if (triple_i == 0) {
|
|
||||||
triple_i = datablock_allocate_in_list(disk);
|
|
||||||
}
|
|
||||||
bool inTriple = false;
|
|
||||||
char buffer[IO_BLOCK_SIZE] = {0};
|
|
||||||
disk.rawdisk_read(triple_i, buffer, sizeof(buffer));
|
|
||||||
for (int i = 0; i < IO_BLOCK_SIZE; i += 8) {
|
|
||||||
u_int64_t addr = read_byte_at(i, buffer);
|
|
||||||
bool flag = allo_double_indirect(disk, addr, freeBlockNum);
|
|
||||||
if (flag) {
|
|
||||||
write_byte_at(addr, i, buffer);
|
|
||||||
disk.rawdisk_write(triple_i, buffer, sizeof(buffer));
|
|
||||||
inTriple = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return inTriple;
|
|
||||||
}
|
|
||||||
|
|
||||||
// allowcate 1 datablock and add to the end of the file
|
|
||||||
u_int64_t datablock_allocate(RawDisk &disk) {
|
|
||||||
// do we need to check dynamic?
|
|
||||||
|
|
||||||
// add the data block to blocks, single, double, triple
|
|
||||||
u_int64_t freeBlockNum = datablock_allocate_in_list(disk);
|
|
||||||
bool inBlocks = false;
|
|
||||||
for (int i = 0; i < 48; i++)
|
|
||||||
if (blocks[i] == 0) {
|
|
||||||
inBlocks = true;
|
|
||||||
blocks[i] = freeBlockNum;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (!inBlocks) {
|
|
||||||
bool inSingle = allo_single_indirect(disk, single_indirect, freeBlockNum);
|
|
||||||
if (!inSingle) {
|
|
||||||
bool inDouble =
|
|
||||||
allo_double_indirect(disk, double_indirect, freeBlockNum);
|
|
||||||
if (!inDouble) {
|
|
||||||
bool inTriple =
|
|
||||||
allo_triple_indirect(disk, triple_indirect, freeBlockNum);
|
|
||||||
// wait to deal with too big files
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// return the block number
|
|
||||||
inode_save(disk);
|
|
||||||
return freeBlockNum;
|
|
||||||
}
|
|
||||||
|
|
||||||
void datablock_deallocate_in_list(u_int64_t freeBlockNum, RawDisk &disk) {
|
|
||||||
// find the related 2048block head
|
|
||||||
u_int64_t freeBlockHead =
|
|
||||||
((freeBlockNum / SECTOR_SIZE - MAX_INODE) / (8 * 2048) * (8 * 2048) +
|
|
||||||
MAX_INODE) *
|
|
||||||
SECTOR_SIZE;
|
|
||||||
|
|
||||||
// mark it alive in its bitmap
|
|
||||||
char buffer[IO_BLOCK_SIZE] = {0};
|
|
||||||
bool notEmpty = false;
|
|
||||||
disk.rawdisk_read(freeBlockHead, buffer, sizeof(buffer));
|
|
||||||
for (int i = 8; i < 264; i++) {
|
|
||||||
if (buffer[i] != 0) {
|
|
||||||
notEmpty = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
u_int64_t inBlockPos = (freeBlockNum - freeBlockHead) / IO_BLOCK_SIZE - 1;
|
|
||||||
buffer[8 + inBlockPos / 8] &= (-1) ^ (1 << (inBlockPos % 8));
|
|
||||||
|
|
||||||
// if its bitmap was 0, add it back to the list head
|
|
||||||
if (!notEmpty) {
|
|
||||||
u_int64_t freeListHead = SuperBlock::getFreeListHead(disk);
|
|
||||||
write_byte_at(freeListHead, 0, buffer);
|
|
||||||
SuperBlock::writeFreeListHead(disk, freeBlockHead);
|
|
||||||
}
|
|
||||||
disk.rawdisk_write(freeBlockHead, buffer, sizeof(buffer));
|
|
||||||
}
|
|
||||||
|
|
||||||
u_int64_t deallo_single_indirect(RawDisk &disk, u_int64_t &single_i) {
|
|
||||||
if (single_i == 0) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
u_int64_t freeBlockNum = 0;
|
|
||||||
char buffer[IO_BLOCK_SIZE] = {0};
|
|
||||||
int delpoint = -1;
|
|
||||||
disk.rawdisk_read(single_i, buffer, sizeof(buffer));
|
|
||||||
for (int i = 4088; i >= 0; i--) {
|
|
||||||
u_int64_t addr = read_byte_at(i, buffer);
|
|
||||||
if (addr != 0) {
|
|
||||||
freeBlockNum = addr;
|
|
||||||
addr = 0;
|
|
||||||
write_byte_at(addr, i, buffer);
|
|
||||||
delpoint = i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
disk.rawdisk_write(single_i, buffer, sizeof(buffer));
|
|
||||||
u_int64_t addr = read_byte_at(0, buffer);
|
|
||||||
if (delpoint == 0 && addr == 0) {
|
|
||||||
datablock_deallocate_in_list(single_i, disk);
|
|
||||||
single_i = 0;
|
|
||||||
}
|
|
||||||
return freeBlockNum;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool deallo_double_indirect(RawDisk &disk, u_int64_t &double_i) {
|
|
||||||
if (double_i == 0) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
u_int64_t freeBlockNum = 0;
|
|
||||||
char buffer[IO_BLOCK_SIZE] = {0};
|
|
||||||
int delpoint = -1;
|
|
||||||
disk.rawdisk_read(double_i, buffer, sizeof(buffer));
|
|
||||||
for (int i = 4088; i >= 0; i -= 8) {
|
|
||||||
u_int64_t addr = read_byte_at(i, buffer);
|
|
||||||
u_int64_t inSingle = deallo_single_indirect(disk, addr);
|
|
||||||
if (inSingle) {
|
|
||||||
freeBlockNum = inSingle;
|
|
||||||
write_byte_at(addr, i, buffer);
|
|
||||||
delpoint = i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
disk.rawdisk_write(double_i, buffer, sizeof(buffer));
|
|
||||||
u_int64_t addr = read_byte_at(0, buffer);
|
|
||||||
if (delpoint == 0 && addr == 0) {
|
|
||||||
datablock_deallocate_in_list(double_i, disk);
|
|
||||||
double_i = 0;
|
|
||||||
}
|
|
||||||
return freeBlockNum;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool deallo_triple_indirect(RawDisk &disk, u_int64_t &triple_i) {
|
|
||||||
if (triple_i == 0) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
u_int64_t freeBlockNum = 0;
|
|
||||||
char buffer[IO_BLOCK_SIZE] = {0};
|
|
||||||
int delpoint = -1;
|
|
||||||
disk.rawdisk_read(triple_i, buffer, sizeof(buffer));
|
|
||||||
for (int i = 4088; i >= 0; i -= 8) {
|
|
||||||
u_int64_t addr = read_byte_at(i, buffer);
|
|
||||||
u_int64_t inDouble = deallo_double_indirect(disk, addr);
|
|
||||||
if (inDouble) {
|
|
||||||
freeBlockNum = inDouble;
|
|
||||||
write_byte_at(addr, i, buffer);
|
|
||||||
delpoint = i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
disk.rawdisk_write(triple_i, buffer, sizeof(buffer));
|
|
||||||
u_int64_t addr = read_byte_at(0, buffer);
|
|
||||||
if (delpoint == 0 && addr == 0) {
|
|
||||||
datablock_deallocate_in_list(triple_i, disk);
|
|
||||||
triple_i = 0;
|
|
||||||
}
|
|
||||||
return freeBlockNum;
|
|
||||||
}
|
|
||||||
|
|
||||||
// deallocate 1 datablock from the end of the file
|
|
||||||
u_int64_t datablock_deallocate(RawDisk &disk) {
|
|
||||||
// find the last datablock and remove it from inode (triple->direct)
|
|
||||||
u_int64_t freeBlockNum = 0;
|
|
||||||
freeBlockNum = deallo_triple_indirect(disk, triple_indirect);
|
|
||||||
if (!freeBlockNum) {
|
|
||||||
freeBlockNum = deallo_double_indirect(disk, double_indirect);
|
|
||||||
if (!freeBlockNum) {
|
|
||||||
freeBlockNum = deallo_single_indirect(disk, single_indirect);
|
|
||||||
if (!freeBlockNum) {
|
|
||||||
for (int i = 47; i >= 0; i--)
|
|
||||||
if (blocks[i] != 0) {
|
|
||||||
freeBlockNum = blocks[i];
|
|
||||||
blocks[i] = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
// deal with empty
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// add it back to freeBlocklist
|
|
||||||
datablock_deallocate_in_list(freeBlockNum, disk);
|
|
||||||
inode_save(disk);
|
|
||||||
return freeBlockNum;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class INodeOperation {
|
|
||||||
// free list head is at super block (0): first 8 bytes
|
|
||||||
|
|
||||||
public:
|
|
||||||
// initialization of the rawdisk
|
|
||||||
void initialize(RawDisk &disk) {
|
|
||||||
// initialize Inode list head
|
|
||||||
SuperBlock::writeFreeINodeHead(disk, 1);
|
|
||||||
for (u_int64_t i = 1; i < MAX_INODE; i++) {
|
|
||||||
char buffer[SECTOR_SIZE] = {0};
|
|
||||||
u_int64_t t = i + 1;
|
|
||||||
if (t < MAX_INODE) {
|
|
||||||
for (int j = 0; j < 8; j++) {
|
|
||||||
buffer[j] = (t >> (8 * j)) & 0xFF;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
disk.rawdisk_write(i * SECTOR_SIZE, buffer, sizeof(buffer));
|
|
||||||
}
|
|
||||||
SuperBlock::writeFreeListHead(
|
|
||||||
disk, MAX_INODE * SECTOR_SIZE); // maximum inode number 2^19 0x80000
|
|
||||||
// Have tested this initialize function but MAX_BLOCK too much, MAX_INODE*2
|
|
||||||
// works
|
|
||||||
for (u_int64_t i = MAX_INODE; i < MAX_BLOCKNUM - 4096; i += 2048 * 8) {
|
|
||||||
char buffer[IO_BLOCK_SIZE] = {0};
|
|
||||||
u_int64_t t = (i + 2048 * 8) * SECTOR_SIZE;
|
|
||||||
// t is address, storing in to buffer
|
|
||||||
for (int j = 0; j < 8; j++) {
|
|
||||||
buffer[j] = (t >> (8 * j)) & 0xFF;
|
|
||||||
}
|
|
||||||
disk.rawdisk_write(i * SECTOR_SIZE, buffer, sizeof(buffer));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// allocate an inode from free inode list head and return the number of the
|
|
||||||
// inode the i-th inode is in the i-th block
|
|
||||||
u_int64_t inode_allocate(RawDisk &disk) {
|
|
||||||
u_int64_t freeINodeHead = SuperBlock::getFreeINodeHead(disk);
|
|
||||||
char buffer[SECTOR_SIZE] = {0};
|
|
||||||
disk.rawdisk_read(freeINodeHead * SECTOR_SIZE, buffer, sizeof(buffer));
|
|
||||||
u_int64_t newINodeHead = INode::read_byte_at(0, buffer);
|
|
||||||
// deal with no more INode
|
|
||||||
SuperBlock::writeFreeINodeHead(disk, newINodeHead);
|
|
||||||
// to do: initialize the INode on disk at freeINodeHead
|
|
||||||
|
|
||||||
// return inode number
|
|
||||||
return freeINodeHead;
|
|
||||||
}
|
|
||||||
|
|
||||||
// free the inode and add it to the free inode list head
|
|
||||||
void inode_free(RawDisk &disk, u_int64_t INodeNumber) {
|
|
||||||
u_int64_t freeINodeHead = SuperBlock::getFreeINodeHead(disk);
|
|
||||||
char buffer[SECTOR_SIZE] = {0};
|
|
||||||
INode::write_byte_at(freeINodeHead, 0, buffer);
|
|
||||||
disk.rawdisk_write(INodeNumber * SECTOR_SIZE, buffer, sizeof(buffer));
|
|
||||||
SuperBlock::writeFreeINodeHead(disk, INodeNumber);
|
|
||||||
}
|
|
||||||
|
|
||||||
// ignore for now
|
|
||||||
void inode_read() {}
|
|
||||||
|
|
||||||
void inode_write() {}
|
|
||||||
};
|
|
@ -4,24 +4,24 @@
|
|||||||
#include "fs/datablock_allocator.hpp"
|
#include "fs/datablock_allocator.hpp"
|
||||||
#include "fs/fs_data_types.hpp"
|
#include "fs/fs_data_types.hpp"
|
||||||
#include "fs/inode_allocator.hpp"
|
#include "fs/inode_allocator.hpp"
|
||||||
|
#include "fs_constants.hpp"
|
||||||
#include "rawdisk.hpp"
|
#include "rawdisk.hpp"
|
||||||
|
|
||||||
#define NUM_INODE_BLOCKS 1023
|
|
||||||
#define NUM_BLOCKS 2048
|
|
||||||
|
|
||||||
class Fs {
|
class Fs {
|
||||||
public:
|
public:
|
||||||
Fs(RawDisk *disk);
|
Fs(RawDisk *disk);
|
||||||
|
~Fs();
|
||||||
|
|
||||||
int resize(INode_Data *inode_data, u_int64_t size, bool absolute);
|
int allocate_datablock(INode_Data *inode_data);
|
||||||
|
int deallocate_datablock(INode_Data *inode_data);
|
||||||
|
|
||||||
int format();
|
int format();
|
||||||
|
|
||||||
// should probably be private but is not for testing
|
// should probably be private but is not for testing
|
||||||
RawDisk *disk;
|
RawDisk *disk;
|
||||||
SuperBlock_Data superblock;
|
SuperBlock_Data superblock;
|
||||||
INode_Allocator inode_allocator;
|
INode_Allocator *inode_allocator;
|
||||||
DataBlock_Allocator datablock_allocator;
|
DataBlock_Allocator *datablock_allocator;
|
||||||
|
|
||||||
int load_superblock();
|
int load_superblock();
|
||||||
int save_superblock();
|
int save_superblock();
|
||||||
@ -31,6 +31,9 @@ public:
|
|||||||
|
|
||||||
int load_inode(INode_Data *inode_data);
|
int load_inode(INode_Data *inode_data);
|
||||||
int save_inode(INode_Data *inode_data);
|
int save_inode(INode_Data *inode_data);
|
||||||
|
|
||||||
|
int allocate_indirect(u_int64_t *storage, int n);
|
||||||
|
int deallocate_indirect(u_int64_t *storage, int n);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
@ -1,6 +1,8 @@
|
|||||||
#ifndef DATABLOCK_ALLOCATOR_HPP
|
#ifndef DATABLOCK_ALLOCATOR_HPP
|
||||||
#define DATABLOCK_ALLOCATOR_HPP
|
#define DATABLOCK_ALLOCATOR_HPP
|
||||||
|
|
||||||
|
#include "fs_constants.hpp"
|
||||||
|
|
||||||
class Fs;
|
class Fs;
|
||||||
|
|
||||||
class DataBlock_Allocator {
|
class DataBlock_Allocator {
|
||||||
@ -18,10 +20,11 @@ protected:
|
|||||||
u_int64_t block_segment_start, block_segment_end;
|
u_int64_t block_segment_start, block_segment_end;
|
||||||
};
|
};
|
||||||
|
|
||||||
class DataBlock_Allocator_Bitmap : DataBlock_Allocator {
|
class DataBlock_Allocator_Bitmap : public DataBlock_Allocator {
|
||||||
using DataBlock_Allocator::DataBlock_Allocator;
|
public:
|
||||||
|
DataBlock_Allocator_Bitmap(Fs *fs, u_int64_t block_segment_start,
|
||||||
const int DATABLOCKS_PER_BITMAP_BLOCK = 255;
|
u_int64_t block_segment_end)
|
||||||
|
: DataBlock_Allocator(fs, block_segment_start, block_segment_end) {}
|
||||||
|
|
||||||
int new_datablock(u_int64_t *block_num) override;
|
int new_datablock(u_int64_t *block_num) override;
|
||||||
int free_datablock(u_int64_t block_num) override;
|
int free_datablock(u_int64_t block_num) override;
|
||||||
|
@ -1,9 +1,7 @@
|
|||||||
#ifndef FS_DATA_TYPES_HPP
|
#ifndef FS_DATA_TYPES_HPP
|
||||||
#define FS_DATA_TYPES_HPP
|
#define FS_DATA_TYPES_HPP
|
||||||
|
|
||||||
#include "rawdisk.hpp"
|
#include "fs_constants.hpp"
|
||||||
|
|
||||||
#define INODE_SIZE 512
|
|
||||||
|
|
||||||
size_t write_u64(u_int64_t num, char buf[]);
|
size_t write_u64(u_int64_t num, char buf[]);
|
||||||
|
|
||||||
@ -14,6 +12,7 @@ size_t write_u32(u_int32_t num, char buf[]);
|
|||||||
size_t read_u32(u_int32_t *num, char buf[]);
|
size_t read_u32(u_int32_t *num, char buf[]);
|
||||||
|
|
||||||
class SuperBlock_Data {
|
class SuperBlock_Data {
|
||||||
|
public:
|
||||||
u_int64_t free_list_head;
|
u_int64_t free_list_head;
|
||||||
u_int64_t inode_list_head;
|
u_int64_t inode_list_head;
|
||||||
SuperBlock_Data();
|
SuperBlock_Data();
|
||||||
@ -22,6 +21,7 @@ class SuperBlock_Data {
|
|||||||
};
|
};
|
||||||
|
|
||||||
class INode_Data {
|
class INode_Data {
|
||||||
|
public:
|
||||||
u_int64_t inode_num;
|
u_int64_t inode_num;
|
||||||
|
|
||||||
#define NUMBER_OF_METADATA_BYTES \
|
#define NUMBER_OF_METADATA_BYTES \
|
||||||
@ -37,13 +37,13 @@ class INode_Data {
|
|||||||
size_t serialize_metadata(char buf[]);
|
size_t serialize_metadata(char buf[]);
|
||||||
size_t deserialize_metadata(char buf[]);
|
size_t deserialize_metadata(char buf[]);
|
||||||
|
|
||||||
const size_t NUMBER_OF_DIRECT_BLOCKS =
|
#define NUMBER_OF_DIRECT_BLOCKS \
|
||||||
((INODE_SIZE - NUMBER_OF_METADATA_BYTES) / sizeof(u_int64_t)) - 3;
|
(((INODE_SIZE - NUMBER_OF_METADATA_BYTES) / sizeof(u_int64_t)) - 3)
|
||||||
|
|
||||||
u_int64_t single_indirect_block, double_indirect_block, triple_indirect_block;
|
u_int64_t single_indirect_block, double_indirect_block, triple_indirect_block;
|
||||||
u_int64_t direct_blocks[NUMBER_OF_DIRECT_BLOCKS];
|
u_int64_t direct_blocks[NUMBER_OF_DIRECT_BLOCKS];
|
||||||
|
|
||||||
INode_Data(u_int64_t inode_num);
|
INode_Data(u_int64_t inode_num = 0xFFFFFFFFFFFFFFFF);
|
||||||
void serialize(char buf[]);
|
void serialize(char buf[]);
|
||||||
void deserialize(char buf[]);
|
void deserialize(char buf[]);
|
||||||
};
|
};
|
||||||
|
@ -1,14 +1,14 @@
|
|||||||
#ifndef INODE_ALLOCATOR_HPP
|
#ifndef INODE_ALLOCATOR_HPP
|
||||||
#define INODE_ALLOCATOR_HPP
|
#define INODE_ALLOCATOR_HPP
|
||||||
|
|
||||||
|
#include "fs_constants.hpp"
|
||||||
#include "fs_data_types.hpp"
|
#include "fs_data_types.hpp"
|
||||||
#include "rawdisk.hpp"
|
|
||||||
|
|
||||||
class Fs;
|
class Fs;
|
||||||
|
|
||||||
class INode_Allocator {
|
class INode_Allocator {
|
||||||
public:
|
public:
|
||||||
const int INODES_PER_BLOCK = BLOCK_SIZE / INODE_SIZE;
|
const int INODES_PER_BLOCK = IO_BLOCK_SIZE / INODE_SIZE;
|
||||||
|
|
||||||
INode_Allocator(Fs *fs, u_int64_t block_segment_start,
|
INode_Allocator(Fs *fs, u_int64_t block_segment_start,
|
||||||
u_int64_t block_segment_end);
|
u_int64_t block_segment_end);
|
||||||
@ -19,8 +19,8 @@ public:
|
|||||||
|
|
||||||
virtual int format() = 0;
|
virtual int format() = 0;
|
||||||
|
|
||||||
u_int64_t get_block_num(INode_Data *inode_data);
|
u_int64_t get_block_num(u_int64_t inode_data);
|
||||||
u_int64_t get_block_offset(INode_Data *inode_data);
|
u_int64_t get_block_offset(u_int64_t inode_data);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Fs *fs;
|
Fs *fs;
|
||||||
@ -28,8 +28,11 @@ protected:
|
|||||||
u_int64_t max_num_inodes;
|
u_int64_t max_num_inodes;
|
||||||
};
|
};
|
||||||
|
|
||||||
class INode_Allocator_Freelist : INode_Allocator {
|
class INode_Allocator_Freelist : public INode_Allocator {
|
||||||
using INode_Allocator::INode_Allocator;
|
public:
|
||||||
|
INode_Allocator_Freelist(Fs *fs, u_int64_t block_segment_start,
|
||||||
|
u_int64_t block_segment_end)
|
||||||
|
: INode_Allocator(fs, block_segment_start, block_segment_end) {}
|
||||||
|
|
||||||
int new_inode(u_int64_t uid, u_int64_t gid, u_int64_t permissions,
|
int new_inode(u_int64_t uid, u_int64_t gid, u_int64_t permissions,
|
||||||
INode_Data *inode_data) override;
|
INode_Data *inode_data) override;
|
||||||
|
23
include/fs_constants.hpp
Normal file
23
include/fs_constants.hpp
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
#ifndef FS_CONSTANTS_HPP
|
||||||
|
#define FS_CONSTANTS_HPP
|
||||||
|
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <inttypes.h>
|
||||||
|
#include <linux/fs.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
|
||||||
|
#define IO_BLOCK_SIZE 4096
|
||||||
|
|
||||||
|
#define NUM_INODE_BLOCKS 1023
|
||||||
|
#define NUM_BLOCKS 2048
|
||||||
|
|
||||||
|
#define INODE_SIZE 512
|
||||||
|
|
||||||
|
#define DATABLOCKS_PER_BITMAP_BLOCK 255
|
||||||
|
|
||||||
|
#endif
|
@ -1,15 +1,7 @@
|
|||||||
#ifndef RAWDISK_HPP
|
#ifndef RAWDISK_HPP
|
||||||
#define RAWDISK_HPP
|
#define RAWDISK_HPP
|
||||||
|
|
||||||
#include <fcntl.h>
|
#include "fs_constants.hpp"
|
||||||
#include <linux/fs.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <sys/ioctl.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
#define BLOCK_SIZE 4096
|
|
||||||
|
|
||||||
class RawDisk {
|
class RawDisk {
|
||||||
public:
|
public:
|
||||||
@ -17,6 +9,32 @@ public:
|
|||||||
|
|
||||||
virtual int read_block(u_int64_t block_number, char *buffer) = 0;
|
virtual int read_block(u_int64_t block_number, char *buffer) = 0;
|
||||||
virtual int write_block(u_int64_t block_number, char *buffer) = 0;
|
virtual int write_block(u_int64_t block_number, char *buffer) = 0;
|
||||||
|
|
||||||
|
void print_block(u_int64_t block_number);
|
||||||
|
};
|
||||||
|
|
||||||
|
class RealRawDisk : public RawDisk {
|
||||||
|
public:
|
||||||
|
int fd;
|
||||||
|
const char *dir;
|
||||||
|
u_int64_t numSectors;
|
||||||
|
|
||||||
|
RealRawDisk(const char *directory);
|
||||||
|
~RealRawDisk();
|
||||||
|
|
||||||
|
int read_block(u_int64_t block_number, char *buffer) override;
|
||||||
|
int write_block(u_int64_t block_number, char *buffer) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
class FakeRawDisk : public RawDisk {
|
||||||
|
public:
|
||||||
|
char *disk;
|
||||||
|
|
||||||
|
FakeRawDisk(u_int64_t num_blocks);
|
||||||
|
~FakeRawDisk();
|
||||||
|
|
||||||
|
int read_block(u_int64_t block_number, char *buffer) override;
|
||||||
|
int write_block(u_int64_t block_number, char *buffer) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
@ -1,14 +1,13 @@
|
|||||||
#include "fs.hpp"
|
#include "fs.hpp"
|
||||||
|
|
||||||
DataBlock_Allocator::DataBlock_Allocator(Fs *fs, u_int64_t block_segment_start,
|
DataBlock_Allocator::DataBlock_Allocator(Fs *fs, u_int64_t block_segment_start,
|
||||||
u_int64_t block_segment_end) {
|
u_int64_t block_segment_end)
|
||||||
fs = fs;
|
: fs(fs), block_segment_start(block_segment_start),
|
||||||
block_segment_start = block_segment_start;
|
block_segment_end(block_segment_end) {}
|
||||||
block_segment_end = block_segment_end;
|
|
||||||
}
|
|
||||||
|
|
||||||
class BitmapBlock_Data {
|
class BitmapBlock_Data {
|
||||||
char buf[BLOCK_SIZE];
|
public:
|
||||||
|
char buf[IO_BLOCK_SIZE];
|
||||||
u_int64_t datablocks_per_bitmap;
|
u_int64_t datablocks_per_bitmap;
|
||||||
|
|
||||||
BitmapBlock_Data(u_int64_t datablocks_per_bitmap_)
|
BitmapBlock_Data(u_int64_t datablocks_per_bitmap_)
|
||||||
@ -26,7 +25,7 @@ class BitmapBlock_Data {
|
|||||||
u_int64_t i = 0;
|
u_int64_t i = 0;
|
||||||
|
|
||||||
for (; i < datablocks_per_bitmap; ++i)
|
for (; i < datablocks_per_bitmap; ++i)
|
||||||
if (data[i / 8] & (1 << (i % 8)) == 0)
|
if ((data[i / 8] & (1 << (i % 8))) == 0)
|
||||||
return i + 1;
|
return i + 1;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -44,19 +43,19 @@ class BitmapBlock_Data {
|
|||||||
int offset = relative_block_num % 8;
|
int offset = relative_block_num % 8;
|
||||||
buf[index] &= ~(1 << offset);
|
buf[index] &= ~(1 << offset);
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
int DataBlock_Allocator_Bitmap::new_datablock(u_int64_t *block_num) {
|
int DataBlock_Allocator_Bitmap::new_datablock(u_int64_t *block_num) {
|
||||||
int err;
|
int err;
|
||||||
BitmapBlock_Data bitmap = BitmapBlock_Data(DATABLOCKS_PER_BITMAP_BLOCK);
|
BitmapBlock_Data bitmap = BitmapBlock_Data(DATABLOCKS_PER_BITMAP_BLOCK);
|
||||||
u_int64_t bitmap_block_num = fs->superblock.free_list_head;
|
u_int64_t bitmap_block_num = fs->superblock.free_list_head;
|
||||||
const char zero_buf[BLOCK_SIZE] = {0};
|
char zero_buf[IO_BLOCK_SIZE] = {0};
|
||||||
|
|
||||||
if (bitmap_block_num < block_segment_start ||
|
if (bitmap_block_num < block_segment_start ||
|
||||||
bitmap_block_num >= block_segment_end)
|
bitmap_block_num >= block_segment_end)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if ((err = disk->read_block(bitmap_block_num, bitmap.buf)) < 0)
|
if ((err = fs->disk->read_block(bitmap_block_num, bitmap.buf)) < 0)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
u_int64_t relative_block_num = bitmap.claim_relative_block();
|
u_int64_t relative_block_num = bitmap.claim_relative_block();
|
||||||
@ -64,22 +63,23 @@ int DataBlock_Allocator_Bitmap::new_datablock(u_int64_t *block_num) {
|
|||||||
if (relative_block_num == 0)
|
if (relative_block_num == 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
u_int64_t block_num = relative_block_num + bitmap_block;
|
u_int64_t block_num_ = relative_block_num + bitmap_block_num;
|
||||||
|
|
||||||
// NOTE: this could be removed for speed
|
// NOTE: this could be removed for speed
|
||||||
if ((err = disk->write_block(block_num, zero_buf)) < 0)
|
if ((err = fs->disk->write_block(block_num_, zero_buf)) < 0)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
if (relative_block_num == DATABLOCKS_PER_BITMAP_BLOCK) {
|
// Could be optimized
|
||||||
|
if (bitmap.find_unfilled() == 0) {
|
||||||
if ((err = fs->save_free_list_head(bitmap.get_next_node())) < 0)
|
if ((err = fs->save_free_list_head(bitmap.get_next_node())) < 0)
|
||||||
return err;
|
return err;
|
||||||
bitmap.set_next_node(0);
|
bitmap.set_next_node(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((err = disk->write_block(bitmap_block_num, bitmap.buf)) < 0)
|
if ((err = fs->disk->write_block(bitmap_block_num, bitmap.buf)) < 0)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
(*block_num) = block_num;
|
(*block_num) = block_num_;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -94,17 +94,17 @@ int DataBlock_Allocator_Bitmap::free_datablock(u_int64_t block_num) {
|
|||||||
bitmap_region_size) +
|
bitmap_region_size) +
|
||||||
block_segment_start;
|
block_segment_start;
|
||||||
|
|
||||||
if ((err = disk->read_block(bitmap_block_num, bitmap.buf)) < 0)
|
if ((err = fs->disk->read_block(bitmap_block_num, bitmap.buf)) < 0)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
bitmap.release_relative_block(block_num - bitmap_block_num);
|
|
||||||
|
|
||||||
if (bitmap.find_unfilled() == 0) {
|
if (bitmap.find_unfilled() == 0) {
|
||||||
update_freelist = true;
|
update_freelist = true;
|
||||||
bitmap.set_next_node(fs->superblock.free_list_head);
|
bitmap.set_next_node(fs->superblock.free_list_head);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((err = disk->write_block(bitmap_block_num, bitmap.buf)) < 0)
|
bitmap.release_relative_block(block_num - bitmap_block_num);
|
||||||
|
|
||||||
|
if ((err = fs->disk->write_block(bitmap_block_num, bitmap.buf)) < 0)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
if (update_freelist)
|
if (update_freelist)
|
||||||
@ -119,16 +119,16 @@ int DataBlock_Allocator_Bitmap::free_datablock(u_int64_t block_num) {
|
|||||||
|
|
||||||
int DataBlock_Allocator_Bitmap::format() {
|
int DataBlock_Allocator_Bitmap::format() {
|
||||||
const u_int64_t bitmap_region_size = DATABLOCKS_PER_BITMAP_BLOCK + 1;
|
const u_int64_t bitmap_region_size = DATABLOCKS_PER_BITMAP_BLOCK + 1;
|
||||||
char buf[BLOCK_SIZE] = {0};
|
char buf[IO_BLOCK_SIZE] = {0};
|
||||||
int err;
|
int err;
|
||||||
u_int64_t i = block_segment_start;
|
u_int64_t i = block_segment_start;
|
||||||
for (; i <= block_segment_end - (2 * bitmap_region_size);
|
for (; i <= block_segment_end - (2 * bitmap_region_size);
|
||||||
i += bitmap_region_size) {
|
i += bitmap_region_size) {
|
||||||
write_u64(i + bitmap_region_size, buf);
|
write_u64(i + bitmap_region_size, buf);
|
||||||
if ((err = disk->write_block(i, buf)) < 0)
|
if ((err = fs->disk->write_block(i, buf)) < 0)
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
if ((err = disk->write_block(i, buf)) < 0)
|
if ((err = fs->disk->write_block(i, buf)) < 0)
|
||||||
return err;
|
return err;
|
||||||
if ((err = fs->save_free_list_head(block_segment_start)) < 0)
|
if ((err = fs->save_free_list_head(block_segment_start)) < 0)
|
||||||
return err;
|
return err;
|
||||||
|
@ -1,26 +1,30 @@
|
|||||||
#include "fs.hpp"
|
#include "fs.hpp"
|
||||||
|
|
||||||
Fs::Fs(RawDisk *disk) {
|
Fs::Fs(RawDisk *disk) : disk(disk) {
|
||||||
disk = disk;
|
|
||||||
superblock = SuperBlock_Data();
|
superblock = SuperBlock_Data();
|
||||||
inode_allocator = INode_Allocator_Freelist(this, 1, 1 + NUM_INODE_BLOCKS);
|
inode_allocator = new INode_Allocator_Freelist(this, 1, 1 + NUM_INODE_BLOCKS);
|
||||||
datablock_allocator =
|
datablock_allocator =
|
||||||
DataBlock_Allocator_Bitmap(this, 1 + NUM_INODE_BLOCKS, NUM_BLOCKS);
|
new DataBlock_Allocator_Bitmap(this, 1 + NUM_INODE_BLOCKS, NUM_BLOCKS);
|
||||||
|
};
|
||||||
|
|
||||||
|
Fs::~Fs() {
|
||||||
|
delete inode_allocator;
|
||||||
|
delete datablock_allocator;
|
||||||
};
|
};
|
||||||
|
|
||||||
int Fs::format() {
|
int Fs::format() {
|
||||||
int err;
|
int err;
|
||||||
if ((err = store_superblock()) < 0)
|
if ((err = save_superblock()) < 0)
|
||||||
return err;
|
return err;
|
||||||
if ((err = inode_allocator.format()) < 0)
|
if ((err = inode_allocator->format()) < 0)
|
||||||
return err;
|
return err;
|
||||||
if ((err = datablock_allocator.format()) < 0)
|
if ((err = datablock_allocator->format()) < 0)
|
||||||
return err;
|
return err;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Fs::load_superblock() {
|
int Fs::load_superblock() {
|
||||||
char buf[BLOCK_SIZE];
|
char buf[IO_BLOCK_SIZE];
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
if ((err = disk->read_block(0, buf)) < 0)
|
if ((err = disk->read_block(0, buf)) < 0)
|
||||||
@ -30,8 +34,8 @@ int Fs::load_superblock() {
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
int Fs::store_superblock() {
|
int Fs::save_superblock() {
|
||||||
char buf[BLOCK_SIZE] = {0};
|
char buf[IO_BLOCK_SIZE] = {0};
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
superblock.serialize(buf);
|
superblock.serialize(buf);
|
||||||
@ -46,7 +50,7 @@ int Fs::save_free_list_head(u_int64_t new_free_list_head) {
|
|||||||
u_int64_t temp = superblock.free_list_head;
|
u_int64_t temp = superblock.free_list_head;
|
||||||
int err;
|
int err;
|
||||||
superblock.free_list_head = new_free_list_head;
|
superblock.free_list_head = new_free_list_head;
|
||||||
if ((err = fs->store_superblock()) < 0) {
|
if ((err = save_superblock()) < 0) {
|
||||||
superblock.free_list_head = temp;
|
superblock.free_list_head = temp;
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
@ -56,7 +60,7 @@ int Fs::save_inode_list_head(u_int64_t new_inode_list_head) {
|
|||||||
u_int64_t temp = superblock.inode_list_head;
|
u_int64_t temp = superblock.inode_list_head;
|
||||||
int err;
|
int err;
|
||||||
superblock.inode_list_head = new_inode_list_head;
|
superblock.inode_list_head = new_inode_list_head;
|
||||||
if ((err = fs->store_superblock()) < 0) {
|
if ((err = save_superblock()) < 0) {
|
||||||
superblock.inode_list_head = temp;
|
superblock.inode_list_head = temp;
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
@ -64,14 +68,14 @@ int Fs::save_inode_list_head(u_int64_t new_inode_list_head) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int Fs::load_inode(INode_Data *inode_data) {
|
int Fs::load_inode(INode_Data *inode_data) {
|
||||||
char buf[BLOCK_SIZE];
|
char buf[IO_BLOCK_SIZE];
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
u_int64_t block_num = inode_allocator.get_block_num(inode_data->inode_num);
|
u_int64_t block_num = inode_allocator->get_block_num(inode_data->inode_num);
|
||||||
if (block_num == 0)
|
if (block_num == 0)
|
||||||
return -1;
|
return -1;
|
||||||
u_int64_t block_offset =
|
u_int64_t block_offset =
|
||||||
inode_allocator.get_block_offset(inode_data->inode_num);
|
inode_allocator->get_block_offset(inode_data->inode_num);
|
||||||
|
|
||||||
if ((err = disk->read_block(block_num, buf)) < 0)
|
if ((err = disk->read_block(block_num, buf)) < 0)
|
||||||
return err;
|
return err;
|
||||||
@ -81,14 +85,14 @@ int Fs::load_inode(INode_Data *inode_data) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
int Fs::save_inode(INode_Data *inode_data) {
|
int Fs::save_inode(INode_Data *inode_data) {
|
||||||
char buf[BLOCK_SIZE];
|
char buf[IO_BLOCK_SIZE];
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
u_int64_t block_num = inode_allocator.get_block_num(inode_data->inode_num);
|
u_int64_t block_num = inode_allocator->get_block_num(inode_data->inode_num);
|
||||||
if (block_num == 0)
|
if (block_num == 0)
|
||||||
return -1;
|
return -1;
|
||||||
u_int64_t block_offset =
|
u_int64_t block_offset =
|
||||||
inode_allocator.get_block_offset(inode_data->inode_num);
|
inode_allocator->get_block_offset(inode_data->inode_num);
|
||||||
|
|
||||||
if ((err = disk->read_block(block_num, buf)) < 0)
|
if ((err = disk->read_block(block_num, buf)) < 0)
|
||||||
return err;
|
return err;
|
||||||
|
@ -10,10 +10,8 @@ template <typename T> T write_int(T num, char buf[]) {
|
|||||||
template <typename T> T read_int(T *num, char buf[]) {
|
template <typename T> T read_int(T *num, char buf[]) {
|
||||||
size_t i = 0;
|
size_t i = 0;
|
||||||
T temp = 0;
|
T temp = 0;
|
||||||
for (; i < sizeof(T); ++i) {
|
for (; i < sizeof(T); ++i)
|
||||||
temp <<= 8;
|
temp |= (((T)buf[i]) & 0xFF) << (8 * i);
|
||||||
temp |= ((T)buf[i]) & 0xFF;
|
|
||||||
}
|
|
||||||
(*num) = temp;
|
(*num) = temp;
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
@ -39,21 +37,19 @@ SuperBlock_Data::SuperBlock_Data() {
|
|||||||
inode_list_head = 0;
|
inode_list_head = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
SuperBlock_Data::serialize(char buf[]) {
|
void SuperBlock_Data::serialize(char buf[]) {
|
||||||
size_t i = 0;
|
size_t i = 0;
|
||||||
i += write_u64(free_list_head, &buf[i]);
|
i += write_u64(free_list_head, &buf[i]);
|
||||||
i += write_u64(inode_list_head, &buf[i]);
|
i += write_u64(inode_list_head, &buf[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
SuperBlock_Data::deserialize(char buf[]) {
|
void SuperBlock_Data::deserialize(char buf[]) {
|
||||||
size_t i = 0;
|
size_t i = 0;
|
||||||
i += read_u64(&free_list_head, &buf[i]);
|
i += read_u64(&free_list_head, &buf[i]);
|
||||||
i += read_u64(&inode_list_head, &buf[i]);
|
i += read_u64(&inode_list_head, &buf[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
INode_Data::INode_Data(u_int64_t inode_num) {
|
INode_Data::INode_Data(u_int64_t inode_num) : inode_num(inode_num) {
|
||||||
inode_num = inode_num;
|
|
||||||
|
|
||||||
metadata.uid = -1;
|
metadata.uid = -1;
|
||||||
metadata.gid = -1;
|
metadata.gid = -1;
|
||||||
metadata.permissions = -1;
|
metadata.permissions = -1;
|
||||||
|
@ -0,0 +1,133 @@
|
|||||||
|
#include "fs.hpp"
|
||||||
|
|
||||||
|
int Fs::allocate_datablock(INode_Data *inode_data) {
|
||||||
|
int result;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < NUMBER_OF_DIRECT_BLOCKS; ++i)
|
||||||
|
if (inode_data->direct_blocks[i] == 0) {
|
||||||
|
if ((result = datablock_allocator->new_datablock(
|
||||||
|
&(inode_data->direct_blocks[i]))) < 0)
|
||||||
|
return result;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
result = allocate_indirect(&(inode_data->single_indirect_block), 1);
|
||||||
|
if (result <= 0)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
result = allocate_indirect(&(inode_data->double_indirect_block), 2);
|
||||||
|
if (result <= 0)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
result = allocate_indirect(&(inode_data->triple_indirect_block), 3);
|
||||||
|
if (result <= 0)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This can simply be made non recursive by copy pasting - it is just written
|
||||||
|
// this way as a proof of concept
|
||||||
|
int Fs::allocate_indirect(u_int64_t *storage, int n) {
|
||||||
|
char buf[IO_BLOCK_SIZE];
|
||||||
|
int result;
|
||||||
|
|
||||||
|
if ((*storage) == 0) {
|
||||||
|
if ((result = datablock_allocator->new_datablock(storage)) < 0)
|
||||||
|
return result;
|
||||||
|
if (n == 0)
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (n == 0)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
u_int64_t temp;
|
||||||
|
|
||||||
|
if ((result = disk->read_block(*storage, buf)) < 0)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < IO_BLOCK_SIZE; i += sizeof(u_int64_t)) {
|
||||||
|
read_u64(&temp, &buf[i]);
|
||||||
|
result = allocate_indirect(&temp, n - 1);
|
||||||
|
if (result < 0)
|
||||||
|
return result;
|
||||||
|
if (result == 0) {
|
||||||
|
write_u64(temp, &buf[i]);
|
||||||
|
if ((result = disk->write_block(*storage, buf)) < 0)
|
||||||
|
return result;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Fs::deallocate_datablock(INode_Data *inode_data) {
|
||||||
|
int result;
|
||||||
|
|
||||||
|
result = deallocate_indirect(&(inode_data->triple_indirect_block), 3);
|
||||||
|
if (result <= 0)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
result = deallocate_indirect(&(inode_data->double_indirect_block), 2);
|
||||||
|
if (result <= 0)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
result = deallocate_indirect(&(inode_data->single_indirect_block), 1);
|
||||||
|
if (result <= 0)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
for (size_t i = NUMBER_OF_DIRECT_BLOCKS - 1; i >= 0; --i)
|
||||||
|
if (inode_data->direct_blocks[i] != 0) {
|
||||||
|
if ((result = datablock_allocator->free_datablock(
|
||||||
|
inode_data->direct_blocks[i])) < 0)
|
||||||
|
return result;
|
||||||
|
inode_data->direct_blocks[i] = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Fs::deallocate_indirect(u_int64_t *storage, int n) {
|
||||||
|
char buf[IO_BLOCK_SIZE];
|
||||||
|
int result;
|
||||||
|
|
||||||
|
if (*storage == 0)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
if (n == 0) {
|
||||||
|
if ((result = datablock_allocator->free_datablock(*storage)) < 0)
|
||||||
|
return result;
|
||||||
|
(*storage) = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
u_int64_t temp;
|
||||||
|
|
||||||
|
if ((result = disk->read_block(*storage, buf)) < 0)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
for (size_t i = IO_BLOCK_SIZE - sizeof(u_int64_t); i >= 0;
|
||||||
|
i -= sizeof(u_int64_t)) {
|
||||||
|
read_u64(&temp, &buf[i]);
|
||||||
|
result = deallocate_indirect(&temp, n - 1);
|
||||||
|
if (result < 0)
|
||||||
|
return result;
|
||||||
|
if (result == 0) {
|
||||||
|
if (i == 0 && temp == 0) {
|
||||||
|
if ((result = datablock_allocator->free_datablock(*storage)) < 0)
|
||||||
|
return result;
|
||||||
|
(*storage) = 0;
|
||||||
|
} else {
|
||||||
|
write_u64(temp, &buf[i]);
|
||||||
|
if ((result = disk->write_block(*storage, buf)) < 0)
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
@ -1,10 +1,9 @@
|
|||||||
#include "fs.hpp"
|
#include "fs.hpp"
|
||||||
|
|
||||||
INode_Allocator::INode_Allocator(Fs *fs, u_int64_t block_segment_start,
|
INode_Allocator::INode_Allocator(Fs *fs, u_int64_t block_segment_start,
|
||||||
u_int64_t block_segment_end) {
|
u_int64_t block_segment_end)
|
||||||
fs = fs;
|
: fs(fs), block_segment_start(block_segment_start),
|
||||||
block_segment_start = block_segment_start;
|
block_segment_end(block_segment_end) {
|
||||||
block_segment_end = block_segment_end;
|
|
||||||
max_num_inodes = (block_segment_end - block_segment_start) * INODES_PER_BLOCK;
|
max_num_inodes = (block_segment_end - block_segment_start) * INODES_PER_BLOCK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -21,30 +20,31 @@ u_int64_t INode_Allocator::get_block_offset(u_int64_t inode_num) {
|
|||||||
int INode_Allocator_Freelist::new_inode(u_int64_t uid, u_int64_t gid,
|
int INode_Allocator_Freelist::new_inode(u_int64_t uid, u_int64_t gid,
|
||||||
u_int64_t permissions,
|
u_int64_t permissions,
|
||||||
INode_Data *inode_data) {
|
INode_Data *inode_data) {
|
||||||
char buf[BLOCK_SIZE];
|
char buf[IO_BLOCK_SIZE];
|
||||||
int err;
|
int err;
|
||||||
u_int64_t inode_num = fs->superblock.inode_list_head;
|
u_int64_t inode_num = fs->superblock.inode_list_head;
|
||||||
if (inode_num > max_num_inodes)
|
if (inode_num > max_num_inodes)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
u_int64_t block_num = get_block_num(inode_num);
|
u_int64_t block_num = get_block_num(inode_num);
|
||||||
|
u_int64_t block_offset = get_block_offset(inode_num);
|
||||||
|
|
||||||
if (block_num == 0)
|
if (block_num == 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if ((err = disk->read_block(block_num, buf)) < 0)
|
if ((err = fs->disk->read_block(block_num, buf)) < 0)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
u_int64_t new_inode_list_head = 0;
|
u_int64_t new_inode_list_head = 0;
|
||||||
read_u64(&new_inode_list_head, buf);
|
read_u64(&new_inode_list_head, &buf[block_offset]);
|
||||||
if ((err = fs->save_inode_list_head(new_inode_list_head)) < 0)
|
if ((err = fs->save_inode_list_head(new_inode_list_head)) < 0)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
(*inode_data) = INode_Data(inode_num);
|
(*inode_data) = INode_Data(inode_num);
|
||||||
|
|
||||||
metadata.uid = uid;
|
inode_data->metadata.uid = uid;
|
||||||
metadata.gid = gid;
|
inode_data->metadata.gid = gid;
|
||||||
metadata.permissions = permissions;
|
inode_data->metadata.permissions = permissions;
|
||||||
|
|
||||||
// It is debatable if this function should do this:
|
// It is debatable if this function should do this:
|
||||||
if ((err = fs->save_inode(inode_data)) < 0) {
|
if ((err = fs->save_inode(inode_data)) < 0) {
|
||||||
@ -55,7 +55,7 @@ int INode_Allocator_Freelist::new_inode(u_int64_t uid, u_int64_t gid,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
int INode_Allocator_Freelist::free_inode(INode_Data *inode_data) {
|
int INode_Allocator_Freelist::free_inode(INode_Data *inode_data) {
|
||||||
char buf[BLOCK_SIZE];
|
char buf[IO_BLOCK_SIZE];
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
u_int64_t block_num = get_block_num(inode_data->inode_num);
|
u_int64_t block_num = get_block_num(inode_data->inode_num);
|
||||||
@ -64,12 +64,12 @@ int INode_Allocator_Freelist::free_inode(INode_Data *inode_data) {
|
|||||||
if (block_num == 0)
|
if (block_num == 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if ((err = disk->read_block(block_num, buf)) < 0)
|
if ((err = fs->disk->read_block(block_num, buf)) < 0)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
write_u64(fs->superblock.inode_list_head, &buf[block_offset]);
|
write_u64(fs->superblock.inode_list_head, &buf[block_offset]);
|
||||||
|
|
||||||
if ((err = disk->write_block(block_num, buf)) < 0)
|
if ((err = fs->disk->write_block(block_num, buf)) < 0)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
if ((err = fs->save_inode_list_head(inode_data->inode_num)) < 0)
|
if ((err = fs->save_inode_list_head(inode_data->inode_num)) < 0)
|
||||||
@ -79,13 +79,13 @@ int INode_Allocator_Freelist::free_inode(INode_Data *inode_data) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int INode_Allocator_Freelist::format() {
|
int INode_Allocator_Freelist::format() {
|
||||||
char buf[BLOCK_SIZE];
|
char buf[IO_BLOCK_SIZE];
|
||||||
int err;
|
int err;
|
||||||
u_int64_t next_inode_num = 1;
|
u_int64_t next_inode_num = 1;
|
||||||
for (u_int64_t i = block_segment_start; i < block_segment_end; ++i) {
|
for (u_int64_t i = block_segment_start; i < block_segment_end; ++i) {
|
||||||
for (int j = 0; j < INODES_PER_BLOCK; ++next_inode_num, ++j)
|
for (int j = 0; j < INODES_PER_BLOCK; ++next_inode_num, ++j)
|
||||||
write_u64(next_inode_num, &buf[j * INODE_SIZE]);
|
write_u64(next_inode_num, &buf[j * INODE_SIZE]);
|
||||||
if ((err = disk->write_block(i, buf)) < 0)
|
if ((err = fs->disk->write_block(i, buf)) < 0)
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
if ((err = fs->save_inode_list_head(0)) < 0)
|
if ((err = fs->save_inode_list_head(0)) < 0)
|
||||||
|
36
lib/main.cpp
36
lib/main.cpp
@ -1,10 +1,36 @@
|
|||||||
#include "fischl.h"
|
#include "fischl.h"
|
||||||
#include "rawdisk.h"
|
#include "fs.hpp"
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
fischl *F = new fischl;
|
// printf("hello word!");
|
||||||
F->init();
|
// fischl *F = new fischl;
|
||||||
char *d = strdup("/dev/vdc");
|
// F->init();
|
||||||
RawDisk *H = new RawDisk(d);
|
// char *d = strdup("/dev/vdc");
|
||||||
|
RawDisk *disk = new FakeRawDisk(2048);
|
||||||
|
Fs *fs = new Fs(disk);
|
||||||
|
fs->format();
|
||||||
|
disk->print_block(0);
|
||||||
|
disk->print_block(1);
|
||||||
|
INode_Data inode_data = INode_Data();
|
||||||
|
fs->inode_allocator->new_inode(1, 2, 3, &inode_data);
|
||||||
|
int err;
|
||||||
|
for (int i = 0; i < 56 + 512 + 4; ++i)
|
||||||
|
err = fs->allocate_datablock(&inode_data);
|
||||||
|
|
||||||
|
for (int i = 0; i < 3; ++i)
|
||||||
|
printf("%d\n", err = fs->deallocate_datablock(&inode_data));
|
||||||
|
|
||||||
|
fs->save_inode(&inode_data);
|
||||||
|
|
||||||
|
disk->print_block(0);
|
||||||
|
disk->print_block(1);
|
||||||
|
|
||||||
|
disk->print_block(1081);
|
||||||
|
|
||||||
|
disk->print_block(1596);
|
||||||
|
|
||||||
|
disk->print_block(1597);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
@ -1,14 +1,28 @@
|
|||||||
#include "rawdisk.hpp"
|
#include "fs.hpp"
|
||||||
|
|
||||||
class RealRawDisk : RawDisk {
|
void RawDisk::print_block(u_int64_t block_number) {
|
||||||
public:
|
const int nums_per_line = 64;
|
||||||
int fd;
|
char buf[IO_BLOCK_SIZE];
|
||||||
const char *dir;
|
u_int64_t num;
|
||||||
u_int64_t numSectors;
|
|
||||||
|
|
||||||
RealRawDisk(const char *directory)
|
if (read_block(block_number, buf) < 0) {
|
||||||
: fd(-1), dir(nullptr), numSectors(0), diskSize(0) {
|
perror("Error printing datablock");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("\nBlock %llu:\n", block_number);
|
||||||
|
for (int i = 0; i < IO_BLOCK_SIZE; i += sizeof(u_int64_t)) {
|
||||||
|
read_u64(&num, &buf[i]);
|
||||||
|
printf("%llu ", num);
|
||||||
|
if ((i / sizeof(u_int64_t)) % nums_per_line == nums_per_line - 1)
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RealRawDisk::RealRawDisk(const char *directory)
|
||||||
|
: fd(-1), dir(nullptr), numSectors(0) {
|
||||||
dir = directory;
|
dir = directory;
|
||||||
|
diskSize = 0;
|
||||||
/*dir = strdup("/dev/vdc");
|
/*dir = strdup("/dev/vdc");
|
||||||
numSectors = 62914560;
|
numSectors = 62914560;
|
||||||
diskSize = 32212254720;*/
|
diskSize = 32212254720;*/
|
||||||
@ -35,14 +49,14 @@ public:
|
|||||||
printf("Disk size (in bytes): %llu\n", diskSize);
|
printf("Disk size (in bytes): %llu\n", diskSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
~RealRawDisk() {
|
RealRawDisk::~RealRawDisk() {
|
||||||
if (fd != -1) {
|
if (fd != -1) {
|
||||||
close(fd);
|
close(fd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int read_block(u_int64_t block_number, char *buffer) {
|
int RealRawDisk::read_block(u_int64_t block_number, char *buffer) {
|
||||||
u_int64_t offset = block_number * BLOCK_SIZE;
|
u_int64_t offset = block_number * IO_BLOCK_SIZE;
|
||||||
|
|
||||||
if (lseek(fd, offset, SEEK_SET) == (u_int64_t)-1) {
|
if (lseek(fd, offset, SEEK_SET) == (u_int64_t)-1) {
|
||||||
perror("Error seeking to offset");
|
perror("Error seeking to offset");
|
||||||
@ -50,8 +64,8 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO: this is incorrect
|
// TODO: this is incorrect
|
||||||
ssize_t bytesRead = read(fd, buffer, BLOCK_SIZE);
|
ssize_t bytesRead = read(fd, buffer, IO_BLOCK_SIZE);
|
||||||
if (bytesRead < BLOCK_SIZE) {
|
if (bytesRead < IO_BLOCK_SIZE) {
|
||||||
perror("Error reading from device");
|
perror("Error reading from device");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -59,8 +73,8 @@ public:
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int write_block(u_int64_t block_number, char *buffer) {
|
int RealRawDisk::write_block(u_int64_t block_number, char *buffer) {
|
||||||
u_int64_t offset = block_number * BLOCK_SIZE;
|
u_int64_t offset = block_number * IO_BLOCK_SIZE;
|
||||||
|
|
||||||
if (lseek(fd, offset, SEEK_SET) == (u_int64_t)-1) {
|
if (lseek(fd, offset, SEEK_SET) == (u_int64_t)-1) {
|
||||||
perror("Error seeking to offset");
|
perror("Error seeking to offset");
|
||||||
@ -68,23 +82,18 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO: this is incorrect
|
// TODO: this is incorrect
|
||||||
ssize_t bytesWritten = write(fd, buffer, BLOCK_SIZE);
|
ssize_t bytesWritten = write(fd, buffer, IO_BLOCK_SIZE);
|
||||||
if (bytesWritten < BLOCK_SIZE) {
|
if (bytesWritten < IO_BLOCK_SIZE) {
|
||||||
perror("Error writing to device");
|
perror("Error writing to device");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
class FakeRawDisk : RawDisk {
|
FakeRawDisk::FakeRawDisk(u_int64_t num_blocks) {
|
||||||
public:
|
diskSize = num_blocks * IO_BLOCK_SIZE;
|
||||||
char *disk;
|
disk = new char[diskSize];
|
||||||
|
|
||||||
FakeRawDisk(u_int64_t num_blocks) {
|
|
||||||
disksize = num_blocks * BLOCK_SIZE;
|
|
||||||
disk = new char[disksize];
|
|
||||||
if (disk == nullptr) {
|
if (disk == nullptr) {
|
||||||
perror("Error allocating fake disk");
|
perror("Error allocating fake disk");
|
||||||
exit(1);
|
exit(1);
|
||||||
@ -94,31 +103,30 @@ public:
|
|||||||
perror("!!! USING FAKE RawDisk - THIS IS FOR TESTING ONLY !!!");
|
perror("!!! USING FAKE RawDisk - THIS IS FOR TESTING ONLY !!!");
|
||||||
}
|
}
|
||||||
|
|
||||||
~FakeRawDisk() { delete[] disk; }
|
FakeRawDisk::~FakeRawDisk() { delete[] disk; }
|
||||||
|
|
||||||
int read_block(u_int64_t block_number, char *buffer) {
|
int FakeRawDisk::read_block(u_int64_t block_number, char *buffer) {
|
||||||
u_int64_t offset = block_number * BLOCK_SIZE;
|
u_int64_t offset = block_number * IO_BLOCK_SIZE;
|
||||||
|
|
||||||
if (offset + BLOCK_SIZE > diskSize) {
|
if (offset + IO_BLOCK_SIZE > diskSize) {
|
||||||
perror("Error reading past fake disk size");
|
perror("Error reading past fake disk size");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(buffer, &disk[offset], BLOCK_SIZE);
|
memcpy(buffer, &disk[offset], IO_BLOCK_SIZE);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int write_block(u_int64_t block_number, char *buffer) {
|
int FakeRawDisk::write_block(u_int64_t block_number, char *buffer) {
|
||||||
u_int64_t offset = block_number * BLOCK_SIZE;
|
u_int64_t offset = block_number * IO_BLOCK_SIZE;
|
||||||
|
|
||||||
if (offset + BLOCK_SIZE > diskSize) {
|
if (offset + IO_BLOCK_SIZE > diskSize) {
|
||||||
perror("Error writing past fake disk size");
|
perror("Error writing past fake disk size");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(&disk[offset], buffer, BLOCK_SIZE);
|
memcpy(&disk[offset], buffer, IO_BLOCK_SIZE);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
};
|
|
Loading…
x
Reference in New Issue
Block a user