added de/alloc inode datablock s

This commit is contained in:
Connor 2023-11-15 03:10:12 -08:00
parent 3ee1647e00
commit 6edece492c
25 changed files with 1338 additions and 1585 deletions

28
.gitignore vendored
View File

@ -1,15 +1,15 @@
build/* build/*
# vscode gitignore # vscode gitignore
.vscode/* .vscode/*
!.vscode/settings.json !.vscode/settings.json
!.vscode/tasks.json !.vscode/tasks.json
!.vscode/launch.json !.vscode/launch.json
!.vscode/extensions.json !.vscode/extensions.json
!.vscode/*.code-snippets !.vscode/*.code-snippets
# Local History for Visual Studio Code # Local History for Visual Studio Code
.history/ .history/
# Built Visual Studio Code Extensions # Built Visual Studio Code Extensions
*.vsix *.vsix

10
.vscode/settings.json vendored
View File

@ -1,6 +1,6 @@
{ {
"cmake.configureOnOpen": false, "cmake.configureOnOpen": false,
"cSpell.words": [ "cSpell.words": [
"unneccary" "unneccary"
] ]
} }

View File

@ -1,23 +1,25 @@
cmake_minimum_required (VERSION 3.1.0) cmake_minimum_required (VERSION 3.1.0)
project(fischl) project(fischl)
set(CMAKE_CXX_STANDARD 14) set(CMAKE_CXX_STANDARD 14)
include_directories( include_directories(
# fischl include files # fischl include files
${CMAKE_CURRENT_SOURCE_DIR}/include ${CMAKE_CURRENT_SOURCE_DIR}/include
) )
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/fs_data_types.cpp lib/fs/datablock_allocator.cpp
lib/fs/fs_resize.cpp lib/fs/fs_data_types.cpp
lib/fs/fs.cpp lib/fs/fs_resize.cpp
lib/fs/fs.cpp
) lib/fs/inode_allocator.cpp
enable_testing() )
add_subdirectory(test)
#enable_testing()
#add_subdirectory(test)

View File

@ -1,63 +1,63 @@
Problem - no header guards Problem - no header guards
Problem - code in header file Problem - code in header file
Problem - inconisitent use of SECTOR_SIZE IO_BLOCK_SIZE Problem - inconisitent use of SECTOR_SIZE IO_BLOCK_SIZE
?18: what is directory ?18: what is directory
22: read of less than sector-size unpermitted 22: read of less than sector-size unpermitted
?25: does the casting here work as expected, would a bitmask be better ?25: does the casting here work as expected, would a bitmask be better
Question: why are we passing a disk every time to superblock functions, shouldn't that be associated with the superblock (i.e. the file system object) Question: why are we passing a disk every time to superblock functions, shouldn't that be associated with the superblock (i.e. the file system object)
37: same issues with this function 37: same issues with this function
Superblock should be read and written to all at once to avoid unneccary io reads and should be stateful regarding the fs data (also it maybe good to rename superblock to fs and make it in charge of formatting the fs) Superblock should be read and written to all at once to avoid unneccary io reads and should be stateful regarding the fs data (also it maybe good to rename superblock to fs and make it in charge of formatting the fs)
57: magic num 57: magic num
?69: strange reference pattern with current_pos - usually handled by func returning num bytes read ?69: strange reference pattern with current_pos - usually handled by func returning num bytes read
?69: should these helper functions be in the inode at all ?69: should these helper functions be in the inode at all
?76: these two funcs could be combined together ?76: these two funcs could be combined together
?83: inode_construct may want to be named inode_load to fit pattern ?83: inode_construct may want to be named inode_load to fit pattern
inode objs (block_number) should likely be able to be made with out the use of inode_construct when they are first created inode objs (block_number) should likely be able to be made with out the use of inode_construct when they are first created
132: 132:
?142: odd use of block nums - byte addresses and io_block addresses ?142: odd use of block nums - byte addresses and io_block addresses
143: magic num 32? 143: magic num 32?
?144: possibly make this a continue also use 0b11111111 and 0b01111111 ?144: possibly make this a continue also use 0b11111111 and 0b01111111
?145: j = 0 twice ?145: j = 0 twice
?76: why is this function read_byte_at if it reads 8 bytes ?76: why is this function read_byte_at if it reads 8 bytes
?144: why is the last bit of the bitmask unused ?144: why is the last bit of the bitmask unused
?171: returned free must be zeroed before use ?171: returned free must be zeroed before use
177: no error handling for cannot allocate block (free list empty) 177: no error handling for cannot allocate block (free list empty)
?215: should this be made into a recursive func ?215: should this be made into a recursive func
241: no error checking 241: no error checking
278: the empty checking and adding to free list head seems busted 278: the empty checking and adding to free list head seems busted
303: -- 303: --
?315: && addr == 0 does nothing ?315: && addr == 0 does nothing
398: can try to deallocate the super block so // deal with empty needs implementation 398: can try to deallocate the super block so // deal with empty needs implementation
?433: why even mix sector size into free list ?433: why even mix sector size into free list
428: no limit checking 428: no limit checking

160
README.md
View File

@ -1,80 +1,80 @@
# iloveos # iloveos
Simply copying libfuse. Simply copying libfuse.
## Branching Rules ## Branching Rules
1. Fork the main branch and work on your own branch. 1. Fork the main branch and work on your own branch.
2. Test before initiating a Pull Request. 2. Test before initiating a Pull Request.
3. Get approved to get merged. 3. Get approved to get merged.
# Quick Start # Quick Start
## configure and build code ## configure and build code
make build directory make build directory
```bash ```bash
mkdir -p build && cd build mkdir -p build && cd build
cmake .. cmake ..
make # cmake --build . is same make # cmake --build . is same
``` ```
## run test ## run test
### add your own test file on test/CMakeList.txt ### add your own test file on test/CMakeList.txt
``` ```
set(TARGET_NAME run_tests) set(TARGET_NAME run_tests)
set(TEST_NAME test_test) set(TEST_NAME test_test)
# add test sources here ... # add test sources here ...
add_executable(${TARGET_NAME} add_executable(${TARGET_NAME}
../lib/fischl.cpp ../lib/fischl.cpp
testfischl.cpp testfischl.cpp
) )
add_executable(${TEST_NAME} add_executable(${TEST_NAME}
../lib/fischl.cpp ../lib/fischl.cpp
testtest.cpp testtest.cpp
) )
add_test(NAME ${TARGET_NAME} COMMAND ${TARGET_NAME}) add_test(NAME ${TARGET_NAME} COMMAND ${TARGET_NAME})
add_test(NAME ${TEST_NAME} COMMAND ${TEST_NAME}) add_test(NAME ${TEST_NAME} COMMAND ${TEST_NAME})
``` ```
### ctest ### ctest
```bash ```bash
ctest -VVV ctest -VVV
ctest -VV #Displays the output from the tests (e.g., stdout or stderr) in addition to the test information. ctest -VV #Displays the output from the tests (e.g., stdout or stderr) in addition to the test information.
``` ```
Test Result will be like this Test Result will be like this
```bash ```bash
[cloud-user@ip-172-31-22-147 build]$ ctest -VVV [cloud-user@ip-172-31-22-147 build]$ ctest -VVV
Test project /home/cloud-user/iloveos/build Test project /home/cloud-user/iloveos/build
Start 1: run_tests Start 1: run_tests
1/1 Test #1: run_tests ........................ Passed 0.00 sec 1/1 Test #1: run_tests ........................ Passed 0.00 sec
100% tests passed, 0 tests failed out of 1 100% tests passed, 0 tests failed out of 1
Total Test time (real) = 0.01 sec Total Test time (real) = 0.01 sec
``` ```
Failed demonstration Failed demonstration
```bash ```bash
[cloud-user@ip-172-31-22-147 build]$ ctest -VVV [cloud-user@ip-172-31-22-147 build]$ ctest -VVV
Test project /home/cloud-user/iloveos/build Test project /home/cloud-user/iloveos/build
Start 1: run_tests Start 1: run_tests
1/2 Test #1: run_tests ........................ Passed 0.00 sec 1/2 Test #1: run_tests ........................ Passed 0.00 sec
Start 2: test_test Start 2: test_test
2/2 Test #2: test_test ........................Subprocess aborted***Exception: 0.26 sec 2/2 Test #2: test_test ........................Subprocess aborted***Exception: 0.26 sec
50% tests passed, 1 tests failed out of 2 50% tests passed, 1 tests failed out of 2
Total Test time (real) = 0.27 sec Total Test time (real) = 0.27 sec
The following tests FAILED: The following tests FAILED:
2 - test_test (Subprocess aborted) 2 - test_test (Subprocess aborted)
Errors while running CTest Errors while running CTest
Output from these tests are in: /home/cloud-user/iloveos/build/Testing/Temporary/LastTest.log Output from these tests are in: /home/cloud-user/iloveos/build/Testing/Temporary/LastTest.log
Use "--rerun-failed --output-on-failure" to re-run the failed cases verbosely. Use "--rerun-failed --output-on-failure" to re-run the failed cases verbosely.
``` ```

View File

@ -1,7 +1,7 @@
class fischl{ class fischl{
// declare // declare
public: public:
int init(); int init();
}; };

View File

@ -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 &current_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 &current_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() {}
};

View File

@ -1,36 +1,39 @@
#ifndef FS_HPP #ifndef FS_HPP
#define FS_HPP #define FS_HPP
#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 "rawdisk.hpp" #include "fs_constants.hpp"
#include "rawdisk.hpp"
#define NUM_INODE_BLOCKS 1023
#define NUM_BLOCKS 2048 class Fs {
public:
class Fs { Fs(RawDisk *disk);
public: ~Fs();
Fs(RawDisk *disk);
int allocate_datablock(INode_Data *inode_data);
int resize(INode_Data *inode_data, u_int64_t size, bool absolute); 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();
int save_free_list_head(u_int64_t new_free_list_head); int save_free_list_head(u_int64_t new_free_list_head);
int save_inode_list_head(u_int64_t new_inode_list_head); int save_inode_list_head(u_int64_t new_inode_list_head);
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

View File

@ -1,32 +1,35 @@
#ifndef DATABLOCK_ALLOCATOR_HPP #ifndef DATABLOCK_ALLOCATOR_HPP
#define DATABLOCK_ALLOCATOR_HPP #define DATABLOCK_ALLOCATOR_HPP
class Fs; #include "fs_constants.hpp"
class DataBlock_Allocator { class Fs;
public:
DataBlock_Allocator(Fs *fs, u_int64_t block_segment_start, class DataBlock_Allocator {
u_int64_t block_segment_end); public:
DataBlock_Allocator(Fs *fs, u_int64_t block_segment_start,
virtual int new_datablock(u_int64_t *block_num) = 0; u_int64_t block_segment_end);
virtual int free_datablock(u_int64_t block_num) = 0;
virtual int new_datablock(u_int64_t *block_num) = 0;
virtual int format() = 0; virtual int free_datablock(u_int64_t block_num) = 0;
protected: virtual int format() = 0;
Fs *fs;
u_int64_t block_segment_start, block_segment_end; protected:
}; Fs *fs;
u_int64_t block_segment_start, block_segment_end;
class DataBlock_Allocator_Bitmap : DataBlock_Allocator { };
using DataBlock_Allocator::DataBlock_Allocator;
class DataBlock_Allocator_Bitmap : public DataBlock_Allocator {
const int DATABLOCKS_PER_BITMAP_BLOCK = 255; public:
DataBlock_Allocator_Bitmap(Fs *fs, u_int64_t block_segment_start,
int new_datablock(u_int64_t *block_num) override; u_int64_t block_segment_end)
int free_datablock(u_int64_t block_num) override; : DataBlock_Allocator(fs, block_segment_start, block_segment_end) {}
int format() override; int new_datablock(u_int64_t *block_num) override;
}; int free_datablock(u_int64_t block_num) override;
int format() override;
};
#endif #endif

View File

@ -1,51 +1,51 @@
#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[]); size_t read_u64(u_int64_t *num, char buf[]);
size_t read_u64(u_int64_t *num, char buf[]); size_t write_u32(u_int32_t num, char buf[]);
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 {
public:
class SuperBlock_Data { 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(); void serialize(char buf[]);
void serialize(char buf[]); void deserialize(char buf[]);
void deserialize(char buf[]); };
};
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 \
(4 * sizeof(u_int64_t) + (2 * sizeof(u_int32_t))) (4 * sizeof(u_int64_t) + (2 * sizeof(u_int32_t)))
struct INode_MetaData { struct INode_MetaData {
u_int64_t uid; u_int64_t uid;
u_int64_t gid; u_int64_t gid;
u_int64_t permissions; u_int64_t permissions;
u_int64_t size; // not yet implemented u_int64_t size; // not yet implemented
u_int32_t reference_count; u_int32_t reference_count;
u_int32_t flags; u_int32_t flags;
} metadata; } metadata;
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[]);
}; };
#endif #endif

View File

@ -1,41 +1,44 @@
#ifndef INODE_ALLOCATOR_HPP #ifndef INODE_ALLOCATOR_HPP
#define INODE_ALLOCATOR_HPP #define INODE_ALLOCATOR_HPP
#include "fs_data_types.hpp" #include "fs_constants.hpp"
#include "rawdisk.hpp" #include "fs_data_types.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);
virtual int new_inode(u_int64_t uid, u_int64_t gid, u_int64_t permissions, virtual int new_inode(u_int64_t uid, u_int64_t gid, u_int64_t permissions,
INode_Data *inode_data) = 0; INode_Data *inode_data) = 0;
virtual int free_inode(INode_Data *inode_data) = 0; virtual int free_inode(INode_Data *inode_data) = 0;
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;
u_int64_t block_segment_start, block_segment_end; u_int64_t block_segment_start, block_segment_end;
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,
int new_inode(u_int64_t uid, u_int64_t gid, u_int64_t permissions, u_int64_t block_segment_end)
INode_Data *inode_data) override; : INode_Allocator(fs, block_segment_start, block_segment_end) {}
int free_inode(INode_Data *inode_data) override;
int new_inode(u_int64_t uid, u_int64_t gid, u_int64_t permissions,
int format() override; INode_Data *inode_data) override;
}; int free_inode(INode_Data *inode_data) override;
int format() override;
};
#endif #endif

23
include/fs_constants.hpp Normal file
View 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

View File

@ -1,22 +1,40 @@
#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> class RawDisk {
#include <stdlib.h> public:
#include <string.h> u_int64_t diskSize;
#include <sys/ioctl.h>
#include <unistd.h> virtual int read_block(u_int64_t block_number, char *buffer) = 0;
virtual int write_block(u_int64_t block_number, char *buffer) = 0;
#define BLOCK_SIZE 4096
void print_block(u_int64_t block_number);
class RawDisk { };
public:
u_int64_t diskSize; class RealRawDisk : public RawDisk {
public:
virtual int read_block(u_int64_t block_number, char *buffer) = 0; int fd;
virtual int write_block(u_int64_t block_number, char *buffer) = 0; 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

View File

@ -1,8 +1,8 @@
#include "fischl.h" #include "fischl.h"
#include <cstdio> #include <cstdio>
int fischl::init(){ int fischl::init(){
printf("Hello Fischl!"); printf("Hello Fischl!");
return 3; return 3;
} }

View File

@ -1,136 +1,136 @@
#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 {
public:
class BitmapBlock_Data { char buf[IO_BLOCK_SIZE];
char buf[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_) : datablocks_per_bitmap(datablocks_per_bitmap_) {}
: datablocks_per_bitmap(datablocks_per_bitmap_) {}
u_int64_t get_next_node() {
u_int64_t get_next_node() { u_int64_t block_num;
u_int64_t block_num; read_u64(&block_num, buf);
read_u64(&block_num, buf); return block_num;
return block_num; }
} void set_next_node(u_int64_t block_num) { write_u64(block_num, buf); }
void set_next_node(u_int64_t block_num) { write_u64(block_num, buf); }
u_int64_t find_unfilled() {
u_int64_t find_unfilled() { const char *data = &buf[8];
const char *data = &buf[8]; 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; }
} u_int64_t claim_relative_block() {
u_int64_t claim_relative_block() { u_int64_t unfilled = find_unfilled();
u_int64_t unfilled = find_unfilled(); if (unfilled)
if (unfilled) buf[((unfilled - 1) / 8) + 8] |= (1 << ((unfilled - 1) % 8));
buf[((unfilled - 1) / 8) + 8] |= (1 << ((unfilled - 1) % 8)); return unfilled;
return unfilled; }
}
void release_relative_block(u_int64_t relative_block_num) {
void release_relative_block(u_int64_t relative_block_num) { relative_block_num -= 1;
relative_block_num -= 1; size_t index = (relative_block_num / 8) + 8;
size_t index = (relative_block_num / 8) + 8; 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; char zero_buf[IO_BLOCK_SIZE] = {0};
const char zero_buf[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 = fs->disk->read_block(bitmap_block_num, bitmap.buf)) < 0)
if ((err = 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();
if (relative_block_num == 0)
if (relative_block_num == 0) return -1;
return -1;
u_int64_t block_num_ = relative_block_num + bitmap_block_num;
u_int64_t block_num = relative_block_num + bitmap_block;
// NOTE: this could be removed for speed
// NOTE: this could be removed for speed if ((err = fs->disk->write_block(block_num_, zero_buf)) < 0)
if ((err = disk->write_block(block_num, zero_buf)) < 0) return err;
return err;
// Could be optimized
if (relative_block_num == DATABLOCKS_PER_BITMAP_BLOCK) { 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;
} }
int DataBlock_Allocator_Bitmap::free_datablock(u_int64_t block_num) { int DataBlock_Allocator_Bitmap::free_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);
const u_int64_t bitmap_region_size = DATABLOCKS_PER_BITMAP_BLOCK + 1; const u_int64_t bitmap_region_size = DATABLOCKS_PER_BITMAP_BLOCK + 1;
bool update_freelist = false; bool update_freelist = false;
u_int64_t bitmap_block_num = u_int64_t bitmap_block_num =
(((block_num - block_segment_start) / bitmap_region_size) * (((block_num - block_segment_start) / bitmap_region_size) *
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) {
update_freelist = true;
if (bitmap.find_unfilled() == 0) { bitmap.set_next_node(fs->superblock.free_list_head);
update_freelist = true; }
bitmap.set_next_node(fs->superblock.free_list_head);
} bitmap.release_relative_block(block_num - bitmap_block_num);
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;
if (update_freelist) if (update_freelist)
if ((err = fs->save_free_list_head(bitmap_block_num)) < 0) if ((err = fs->save_free_list_head(bitmap_block_num)) < 0)
return err; return err;
return 0; return 0;
// placing almost full bitmaps back at start of freelist is slow // placing almost full bitmaps back at start of freelist is slow
// potentially like 256 times slower throughput // potentially like 256 times slower throughput
} }
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;
return 0; return 0;
} }

View File

@ -1,102 +1,106 @@
#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 = new INode_Allocator_Freelist(this, 1, 1 + NUM_INODE_BLOCKS);
inode_allocator = INode_Allocator_Freelist(this, 1, 1 + NUM_INODE_BLOCKS); datablock_allocator =
datablock_allocator = new DataBlock_Allocator_Bitmap(this, 1 + NUM_INODE_BLOCKS, NUM_BLOCKS);
DataBlock_Allocator_Bitmap(this, 1 + NUM_INODE_BLOCKS, NUM_BLOCKS); };
};
Fs::~Fs() {
int Fs::format() { delete inode_allocator;
int err; delete datablock_allocator;
if ((err = store_superblock()) < 0) };
return err;
if ((err = inode_allocator.format()) < 0) int Fs::format() {
return err; int err;
if ((err = datablock_allocator.format()) < 0) if ((err = save_superblock()) < 0)
return err; return err;
return 0; if ((err = inode_allocator->format()) < 0)
} return err;
if ((err = datablock_allocator->format()) < 0)
int Fs::load_superblock() { return err;
char buf[BLOCK_SIZE]; return 0;
int err; }
if ((err = disk->read_block(0, buf)) < 0) int Fs::load_superblock() {
return err; char buf[IO_BLOCK_SIZE];
int err;
superblock.deserialize(buf);
if ((err = disk->read_block(0, buf)) < 0)
return 0; return err;
}
int Fs::store_superblock() { superblock.deserialize(buf);
char buf[BLOCK_SIZE] = {0};
int err; return 0;
}
superblock.serialize(buf); int Fs::save_superblock() {
char buf[IO_BLOCK_SIZE] = {0};
if ((err = disk->write_block(0, buf)) < 0) int err;
return err;
superblock.serialize(buf);
return 0;
} if ((err = disk->write_block(0, buf)) < 0)
return err;
int Fs::save_free_list_head(u_int64_t new_free_list_head) {
u_int64_t temp = superblock.free_list_head; return 0;
int err; }
superblock.free_list_head = new_free_list_head;
if ((err = fs->store_superblock()) < 0) { int Fs::save_free_list_head(u_int64_t new_free_list_head) {
superblock.free_list_head = temp; u_int64_t temp = superblock.free_list_head;
return err; int err;
} superblock.free_list_head = new_free_list_head;
return 0; if ((err = save_superblock()) < 0) {
} superblock.free_list_head = temp;
int Fs::save_inode_list_head(u_int64_t new_inode_list_head) { return err;
u_int64_t temp = superblock.inode_list_head; }
int err; return 0;
superblock.inode_list_head = new_inode_list_head; }
if ((err = fs->store_superblock()) < 0) { int Fs::save_inode_list_head(u_int64_t new_inode_list_head) {
superblock.inode_list_head = temp; u_int64_t temp = superblock.inode_list_head;
return err; int err;
} superblock.inode_list_head = new_inode_list_head;
return 0; if ((err = save_superblock()) < 0) {
} superblock.inode_list_head = temp;
return err;
int Fs::load_inode(INode_Data *inode_data) { }
char buf[BLOCK_SIZE]; return 0;
int err; }
u_int64_t block_num = inode_allocator.get_block_num(inode_data->inode_num); int Fs::load_inode(INode_Data *inode_data) {
if (block_num == 0) char buf[IO_BLOCK_SIZE];
return -1; int err;
u_int64_t block_offset =
inode_allocator.get_block_offset(inode_data->inode_num); u_int64_t block_num = inode_allocator->get_block_num(inode_data->inode_num);
if (block_num == 0)
if ((err = disk->read_block(block_num, buf)) < 0) return -1;
return err; u_int64_t block_offset =
inode_allocator->get_block_offset(inode_data->inode_num);
inode_data->deserialize(&buf[block_offset]);
if ((err = disk->read_block(block_num, buf)) < 0)
return 0; return err;
}
int Fs::save_inode(INode_Data *inode_data) { inode_data->deserialize(&buf[block_offset]);
char buf[BLOCK_SIZE];
int err; return 0;
}
u_int64_t block_num = inode_allocator.get_block_num(inode_data->inode_num); int Fs::save_inode(INode_Data *inode_data) {
if (block_num == 0) char buf[IO_BLOCK_SIZE];
return -1; int err;
u_int64_t block_offset =
inode_allocator.get_block_offset(inode_data->inode_num); u_int64_t block_num = inode_allocator->get_block_num(inode_data->inode_num);
if (block_num == 0)
if ((err = disk->read_block(block_num, buf)) < 0) return -1;
return err; u_int64_t block_offset =
inode_allocator->get_block_offset(inode_data->inode_num);
inode_data->serialize(&buf[block_offset]);
if ((err = disk->read_block(block_num, buf)) < 0)
if ((err = disk->write_block(block_num, buf)) < 0) return err;
return err;
inode_data->serialize(&buf[block_offset]);
return 0;
if ((err = disk->write_block(block_num, buf)) < 0)
return err;
return 0;
} }

View File

@ -1,108 +1,104 @@
#include "fs.hpp" #include "fs.hpp"
template <typename T> T write_int(T num, char buf[]) { template <typename T> T write_int(T num, char buf[]) {
size_t i = 0; size_t i = 0;
for (; i < sizeof(T); ++i) for (; i < sizeof(T); ++i)
buf[i] = (char)(num >> (i * 8)); buf[i] = (char)(num >> (i * 8));
return i; return i;
} }
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;
} return i;
(*num) = temp; }
return i;
} size_t write_u64(u_int64_t num, char buf[]) {
return write_int<u_int64_t>(num, buf);
size_t write_u64(u_int64_t num, char buf[]) { }
return write_int<u_int64_t>(num, buf);
} size_t read_u64(u_int64_t *num, char buf[]) {
return read_int<u_int64_t>(num, buf);
size_t read_u64(u_int64_t *num, char buf[]) { }
return read_int<u_int64_t>(num, buf);
} size_t write_u32(u_int32_t num, char buf[]) {
return write_int<u_int32_t>(num, buf);
size_t write_u32(u_int32_t num, char buf[]) { }
return write_int<u_int32_t>(num, buf);
} size_t read_u32(u_int32_t *num, char buf[]) {
return read_int<u_int32_t>(num, buf);
size_t read_u32(u_int32_t *num, char buf[]) { }
return read_int<u_int32_t>(num, buf);
} SuperBlock_Data::SuperBlock_Data() {
free_list_head = 0;
SuperBlock_Data::SuperBlock_Data() { inode_list_head = 0;
free_list_head = 0; }
inode_list_head = 0;
} void SuperBlock_Data::serialize(char buf[]) {
size_t i = 0;
SuperBlock_Data::serialize(char buf[]) { i += write_u64(free_list_head, &buf[i]);
size_t i = 0; i += write_u64(inode_list_head, &buf[i]);
i += write_u64(free_list_head, &buf[i]); }
i += write_u64(inode_list_head, &buf[i]);
} void SuperBlock_Data::deserialize(char buf[]) {
size_t i = 0;
SuperBlock_Data::deserialize(char buf[]) { i += read_u64(&free_list_head, &buf[i]);
size_t i = 0; i += read_u64(&inode_list_head, &buf[i]);
i += read_u64(&free_list_head, &buf[i]); }
i += read_u64(&inode_list_head, &buf[i]);
} INode_Data::INode_Data(u_int64_t inode_num) : inode_num(inode_num) {
metadata.uid = -1;
INode_Data::INode_Data(u_int64_t inode_num) { metadata.gid = -1;
inode_num = inode_num; metadata.permissions = -1;
metadata.size = 0;
metadata.uid = -1; metadata.reference_count = 0;
metadata.gid = -1;
metadata.permissions = -1; single_indirect_block = double_indirect_block = triple_indirect_block = 0;
metadata.size = 0;
metadata.reference_count = 0; for (size_t i = 0; i < NUMBER_OF_DIRECT_BLOCKS; ++i)
direct_blocks[i] = 0;
single_indirect_block = double_indirect_block = triple_indirect_block = 0; }
for (size_t i = 0; i < NUMBER_OF_DIRECT_BLOCKS; ++i) size_t INode_Data::serialize_metadata(char buf[]) {
direct_blocks[i] = 0; size_t i = 0;
} i += write_u64(metadata.uid, &buf[i]);
i += write_u64(metadata.gid, &buf[i]);
size_t INode_Data::serialize_metadata(char buf[]) { i += write_u64(metadata.permissions, &buf[i]);
size_t i = 0; i += write_u64(metadata.size, &buf[i]);
i += write_u64(metadata.uid, &buf[i]); i += write_u32(metadata.reference_count, &buf[i]);
i += write_u64(metadata.gid, &buf[i]); i += write_u32(metadata.flags, &buf[i]);
i += write_u64(metadata.permissions, &buf[i]); return i;
i += write_u64(metadata.size, &buf[i]); }
i += write_u32(metadata.reference_count, &buf[i]);
i += write_u32(metadata.flags, &buf[i]); size_t INode_Data::deserialize_metadata(char buf[]) {
return i; size_t i = 0;
} i += read_u64(&metadata.uid, &buf[i]);
i += read_u64(&metadata.gid, &buf[i]);
size_t INode_Data::deserialize_metadata(char buf[]) { i += read_u64(&metadata.permissions, &buf[i]);
size_t i = 0; i += read_u64(&metadata.size, &buf[i]);
i += read_u64(&metadata.uid, &buf[i]); i += read_u32(&metadata.reference_count, &buf[i]);
i += read_u64(&metadata.gid, &buf[i]); i += read_u32(&metadata.flags, &buf[i]);
i += read_u64(&metadata.permissions, &buf[i]); return i;
i += read_u64(&metadata.size, &buf[i]); }
i += read_u32(&metadata.reference_count, &buf[i]);
i += read_u32(&metadata.flags, &buf[i]); void INode_Data::serialize(char buf[]) {
return i; size_t i = 0;
} i += serialize_metadata(&buf[i]);
i += write_u64(triple_indirect_block, &buf[i]);
void INode_Data::serialize(char buf[]) { i += write_u64(double_indirect_block, &buf[i]);
size_t i = 0; i += write_u64(single_indirect_block, &buf[i]);
i += serialize_metadata(&buf[i]); for (size_t j = 0; j < NUMBER_OF_DIRECT_BLOCKS; ++j)
i += write_u64(triple_indirect_block, &buf[i]); i += write_u64(direct_blocks[j], &buf[i]);
i += write_u64(double_indirect_block, &buf[i]); }
i += write_u64(single_indirect_block, &buf[i]); void INode_Data::deserialize(char buf[]) {
for (size_t j = 0; j < NUMBER_OF_DIRECT_BLOCKS; ++j) size_t i = 0;
i += write_u64(direct_blocks[j], &buf[i]); i += deserialize_metadata(&buf[i]);
} i += read_u64(&triple_indirect_block, &buf[i]);
void INode_Data::deserialize(char buf[]) { i += read_u64(&double_indirect_block, &buf[i]);
size_t i = 0; i += read_u64(&single_indirect_block, &buf[i]);
i += deserialize_metadata(&buf[i]); for (size_t j = 0; j < NUMBER_OF_DIRECT_BLOCKS; ++j)
i += read_u64(&triple_indirect_block, &buf[i]); i += read_u64(&direct_blocks[j], &buf[i]);
i += read_u64(&double_indirect_block, &buf[i]);
i += read_u64(&single_indirect_block, &buf[i]);
for (size_t j = 0; j < NUMBER_OF_DIRECT_BLOCKS; ++j)
i += read_u64(&direct_blocks[j], &buf[i]);
} }

View File

@ -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;
}

View File

@ -1,94 +1,94 @@
#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; }
}
u_int64_t INode_Allocator::get_block_num(u_int64_t inode_num) {
u_int64_t INode_Allocator::get_block_num(u_int64_t inode_num) { u_int64_t block_num = block_segment_start + (inode_num / INODES_PER_BLOCK);
u_int64_t block_num = block_segment_start + (inode_num / INODES_PER_BLOCK); if (block_num >= block_segment_end)
if (block_num >= block_segment_end) return 0;
return 0; return block_num;
return block_num; }
} u_int64_t INode_Allocator::get_block_offset(u_int64_t inode_num) {
u_int64_t INode_Allocator::get_block_offset(u_int64_t inode_num) { return (inode_num % INODES_PER_BLOCK) * INODE_SIZE;
return (inode_num % INODES_PER_BLOCK) * INODE_SIZE; }
}
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[IO_BLOCK_SIZE];
char buf[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) {
inode_data->inode_num = 0xFFFFFFFFFFFFFFFF; inode_data->inode_num = 0xFFFFFFFFFFFFFFFF;
return err; return err;
} }
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);
u_int64_t block_offset = get_block_offset(inode_data->inode_num); u_int64_t block_offset = get_block_offset(inode_data->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;
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)
return err; return err;
return 0; return 0;
} }
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)
return err; return err;
return 0; return 0;
} }

View File

@ -1,10 +1,36 @@
#include "fischl.h" #include "fischl.h"
#include "rawdisk.h" #include "fs.hpp"
#include <stdio.h>
int main(){
fischl *F = new fischl; int main() {
F->init(); // printf("hello word!");
char *d = strdup("/dev/vdc"); // fischl *F = new fischl;
RawDisk *H = new RawDisk(d); // F->init();
return 0; // 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;
} }

View File

@ -1,124 +1,132 @@
#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;
if (read_block(block_number, buf) < 0) {
RealRawDisk(const char *directory) perror("Error printing datablock");
: fd(-1), dir(nullptr), numSectors(0), diskSize(0) { return;
dir = directory; }
/*dir = strdup("/dev/vdc");
numSectors = 62914560; printf("\nBlock %llu:\n", block_number);
diskSize = 32212254720;*/ for (int i = 0; i < IO_BLOCK_SIZE; i += sizeof(u_int64_t)) {
read_u64(&num, &buf[i]);
// Open the block device (replace /dev/sdX with the actual device) printf("%llu ", num);
fd = open(dir, O_RDWR); // Allow read and write if ((i / sizeof(u_int64_t)) % nums_per_line == nums_per_line - 1)
if (fd == -1) { printf("\n");
perror("Error opening device"); }
exit(1); }
}
RealRawDisk::RealRawDisk(const char *directory)
// Use ioctl with BLKGETSIZE to get the number of sectors : fd(-1), dir(nullptr), numSectors(0) {
if (ioctl(fd, BLKGETSIZE64, &diskSize) == -1) { dir = directory;
perror("Error getting disk size"); diskSize = 0;
close(fd); /*dir = strdup("/dev/vdc");
exit(1); numSectors = 62914560;
} diskSize = 32212254720;*/
// Calculate the size in bytes // Open the block device (replace /dev/sdX with the actual device)
numSectors = diskSize / 512; // Assuming a sector size of 512 bytes fd = open(dir, O_RDWR); // Allow read and write
if (fd == -1) {
printf("====Initializing RawDisk====\n"); perror("Error opening device");
printf("Number of sectors: %llu\n", numSectors); exit(1);
printf("Disk size (in bytes): %llu\n", diskSize); }
}
// Use ioctl with BLKGETSIZE to get the number of sectors
~RealRawDisk() { if (ioctl(fd, BLKGETSIZE64, &diskSize) == -1) {
if (fd != -1) { perror("Error getting disk size");
close(fd); close(fd);
} exit(1);
} }
int read_block(u_int64_t block_number, char *buffer) { // Calculate the size in bytes
u_int64_t offset = block_number * BLOCK_SIZE; numSectors = diskSize / 512; // Assuming a sector size of 512 bytes
if (lseek(fd, offset, SEEK_SET) == (u_int64_t)-1) { printf("====Initializing RawDisk====\n");
perror("Error seeking to offset"); printf("Number of sectors: %llu\n", numSectors);
return -1; printf("Disk size (in bytes): %llu\n", diskSize);
} }
// TODO: this is incorrect RealRawDisk::~RealRawDisk() {
ssize_t bytesRead = read(fd, buffer, BLOCK_SIZE); if (fd != -1) {
if (bytesRead < BLOCK_SIZE) { close(fd);
perror("Error reading from device"); }
return -1; }
}
int RealRawDisk::read_block(u_int64_t block_number, char *buffer) {
return 0; u_int64_t offset = block_number * IO_BLOCK_SIZE;
}
if (lseek(fd, offset, SEEK_SET) == (u_int64_t)-1) {
int write_block(u_int64_t block_number, char *buffer) { perror("Error seeking to offset");
u_int64_t offset = block_number * BLOCK_SIZE; return -1;
}
if (lseek(fd, offset, SEEK_SET) == (u_int64_t)-1) {
perror("Error seeking to offset"); // TODO: this is incorrect
return -1; ssize_t bytesRead = read(fd, buffer, IO_BLOCK_SIZE);
} if (bytesRead < IO_BLOCK_SIZE) {
perror("Error reading from device");
// TODO: this is incorrect return -1;
ssize_t bytesWritten = write(fd, buffer, BLOCK_SIZE); }
if (bytesWritten < BLOCK_SIZE) {
perror("Error writing to device"); return 0;
return -1; }
}
int RealRawDisk::write_block(u_int64_t block_number, char *buffer) {
return 0; u_int64_t offset = block_number * IO_BLOCK_SIZE;
}
}; if (lseek(fd, offset, SEEK_SET) == (u_int64_t)-1) {
perror("Error seeking to offset");
class FakeRawDisk : RawDisk { return -1;
public: }
char *disk;
// TODO: this is incorrect
FakeRawDisk(u_int64_t num_blocks) { ssize_t bytesWritten = write(fd, buffer, IO_BLOCK_SIZE);
disksize = num_blocks * BLOCK_SIZE; if (bytesWritten < IO_BLOCK_SIZE) {
disk = new char[disksize]; perror("Error writing to device");
if (disk == nullptr) { return -1;
perror("Error allocating fake disk"); }
exit(1);
} return 0;
printf("====Initializing FAKE RawDisk====\n"); }
printf("FAKE Disk size (in bytes): %llu\n", diskSize);
perror("!!! USING FAKE RawDisk - THIS IS FOR TESTING ONLY !!!"); FakeRawDisk::FakeRawDisk(u_int64_t num_blocks) {
} diskSize = num_blocks * IO_BLOCK_SIZE;
disk = new char[diskSize];
~FakeRawDisk() { delete[] disk; } if (disk == nullptr) {
perror("Error allocating fake disk");
int read_block(u_int64_t block_number, char *buffer) { exit(1);
u_int64_t offset = block_number * BLOCK_SIZE; }
printf("====Initializing FAKE RawDisk====\n");
if (offset + BLOCK_SIZE > diskSize) { printf("FAKE Disk size (in bytes): %llu\n", diskSize);
perror("Error reading past fake disk size"); perror("!!! USING FAKE RawDisk - THIS IS FOR TESTING ONLY !!!");
return -1; }
}
FakeRawDisk::~FakeRawDisk() { delete[] disk; }
memcpy(buffer, &disk[offset], BLOCK_SIZE);
int FakeRawDisk::read_block(u_int64_t block_number, char *buffer) {
return 0; u_int64_t offset = block_number * IO_BLOCK_SIZE;
}
if (offset + IO_BLOCK_SIZE > diskSize) {
int write_block(u_int64_t block_number, char *buffer) { perror("Error reading past fake disk size");
u_int64_t offset = block_number * BLOCK_SIZE; return -1;
}
if (offset + BLOCK_SIZE > diskSize) {
perror("Error writing past fake disk size"); memcpy(buffer, &disk[offset], IO_BLOCK_SIZE);
return -1;
} return 0;
}
memcpy(&disk[offset], buffer, BLOCK_SIZE);
int FakeRawDisk::write_block(u_int64_t block_number, char *buffer) {
return 0; u_int64_t offset = block_number * IO_BLOCK_SIZE;
}
}; if (offset + IO_BLOCK_SIZE > diskSize) {
perror("Error writing past fake disk size");
return -1;
}
memcpy(&disk[offset], buffer, IO_BLOCK_SIZE);
return 0;
}

View File

@ -1,17 +1,17 @@
set(TARGET_LAYER0 test_layer0) set(TARGET_LAYER0 test_layer0)
set(TARGET_LAYER1_API test_layer1_API) set(TARGET_LAYER1_API test_layer1_API)
set(DIR_PLACE /dev/vdb) set(DIR_PLACE /dev/vdb)
# add test sources here ... # add test sources here ...
add_executable(${TARGET_LAYER0} add_executable(${TARGET_LAYER0}
# add need lib and source code here # add need lib and source code here
layer0.cpp layer0.cpp
) )
add_executable(${TARGET_LAYER1_API} add_executable(${TARGET_LAYER1_API}
# add need lib and source code here # add need lib and source code here
layer1_API.cpp layer1_API.cpp
) )
# add test to activate ctest -VV # add test to activate ctest -VV
add_test(NAME ${TARGET_LAYER0} COMMAND sudo ./${TARGET_LAYER0} ${DIR_PLACE}) add_test(NAME ${TARGET_LAYER0} COMMAND sudo ./${TARGET_LAYER0} ${DIR_PLACE})
add_test(NAME ${TARGET_LAYER1_API} COMMAND sudo ./${TARGET_LAYER1_API} ${DIR_PLACE}) add_test(NAME ${TARGET_LAYER1_API} COMMAND sudo ./${TARGET_LAYER1_API} ${DIR_PLACE})

View File

@ -1,29 +1,29 @@
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <assert.h> #include <assert.h>
#include "rawdisk.h" #include "rawdisk.h"
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
const char* d = (argc < 2) ? "/dev/vdc" : argv[1]; const char* d = (argc < 2) ? "/dev/vdc" : argv[1];
RawDisk *H = new RawDisk(d); RawDisk *H = new RawDisk(d);
char *buf = "iloveosdfjlseirfnerig"; char *buf = "iloveosdfjlseirfnerig";
char readBuffer[512] = {0}; // Initialize to zeros char readBuffer[512] = {0}; // Initialize to zeros
//printf("dir %s, numSectors %lld, diskSize %lld \n", H->dir, H->numSectors, H->diskSize); //printf("dir %s, numSectors %lld, diskSize %lld \n", H->dir, H->numSectors, H->diskSize);
//use number to substitute H->getnumSector(), getnumSectors() are not yest implemented //use number to substitute H->getnumSector(), getnumSectors() are not yest implemented
for(u_int64_t i = 0; i < 10; i++) { for(u_int64_t i = 0; i < 10; i++) {
H->rawdisk_write(i*512, buf, strlen(buf));//Change write_API H->rawdisk_write(i*512, buf, strlen(buf));//Change write_API
} }
//use number to substitute H->getnumSector(), getnumSectors() are not yest implemented //use number to substitute H->getnumSector(), getnumSectors() are not yest implemented
for(u_int64_t i = 0; i < 10; i++) { for(u_int64_t i = 0; i < 10; i++) {
H->rawdisk_read(i*512, readBuffer, sizeof(readBuffer));//Change read_API H->rawdisk_read(i*512, readBuffer, sizeof(readBuffer));//Change read_API
assert(strncmp(readBuffer, buf, strlen(buf)) == 0); assert(strncmp(readBuffer, buf, strlen(buf)) == 0);
} }
delete H; // Delete the RawDisk object delete H; // Delete the RawDisk object
return 0; return 0;
} }

View File

@ -1,118 +1,118 @@
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <assert.h> #include <assert.h>
#include "fs.h" #include "fs.h"
#include <inttypes.h> #include <inttypes.h>
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
const char* d = (argc < 2) ? "/dev/vdc" : argv[1]; const char* d = (argc < 2) ? "/dev/vdc" : argv[1];
RawDisk *H = new RawDisk(d); RawDisk *H = new RawDisk(d);
printf("test inode\n"); printf("test inode\n");
INodeOperation inop; INodeOperation inop;
inop.initialize(*H);//for inode initialization and datablock initialization inop.initialize(*H);//for inode initialization and datablock initialization
char buffer[8] = {0}; char buffer[8] = {0};
/**************************test inode Initialization***************************/ /**************************test inode Initialization***************************/
//test the begining of inode 1th //test the begining of inode 1th
H->rawdisk_read((1) * SECTOR_SIZE, buffer, sizeof(buffer)); H->rawdisk_read((1) * SECTOR_SIZE, buffer, sizeof(buffer));
u_int64_t t = 0; u_int64_t t = 0;
for (int j = 0; j < 8; j++) for (int j = 0; j < 8; j++)
t |= ((u_int64_t)(unsigned char)buffer[j]) << (8 * j); t |= ((u_int64_t)(unsigned char)buffer[j]) << (8 * j);
assert(t == 2);//the first 1th unused inode will store the next unused inode 2th assert(t == 2);//the first 1th unused inode will store the next unused inode 2th
//test the number before end of inode 524286th //test the number before end of inode 524286th
H->rawdisk_read((MAX_INODE - 2) * SECTOR_SIZE, buffer, sizeof(buffer)); H->rawdisk_read((MAX_INODE - 2) * SECTOR_SIZE, buffer, sizeof(buffer));
t = 0; t = 0;
for (int j = 0; j < 8; j++) for (int j = 0; j < 8; j++)
t |= ((u_int64_t)(unsigned char)buffer[j]) << (8 * j); t |= ((u_int64_t)(unsigned char)buffer[j]) << (8 * j);
assert(t == MAX_INODE - 1);//store the maximun th inode assert(t == MAX_INODE - 1);//store the maximun th inode
//test the end of inode 524287th //test the end of inode 524287th
H->rawdisk_read((MAX_INODE - 1) * SECTOR_SIZE, buffer, sizeof(buffer)); H->rawdisk_read((MAX_INODE - 1) * SECTOR_SIZE, buffer, sizeof(buffer));
t = 0; t = 0;
for (int j = 0; j < 8; j++) for (int j = 0; j < 8; j++)
t |= ((u_int64_t)(unsigned char)buffer[j]) << (8 * j); t |= ((u_int64_t)(unsigned char)buffer[j]) << (8 * j);
assert(t == 0);//the end of inode(524287th inode) do not have the next inode address assert(t == 0);//the end of inode(524287th inode) do not have the next inode address
/**************************test datablock Initialization***************************/ /**************************test datablock Initialization***************************/
//we separate 2048 4kB I/O block(1+2047) as a group and the first I/O block will manage the following 2047 I/O block usage. //we separate 2048 4kB I/O block(1+2047) as a group and the first I/O block will manage the following 2047 I/O block usage.
//the first 8 bytes(0~7) in first I/O block store the address of next first I/O block, the following 256(8~263) bytes record 2047 I/O block usage. //the first 8 bytes(0~7) in first I/O block store the address of next first I/O block, the following 256(8~263) bytes record 2047 I/O block usage.
//test the begining of free datablock //test the begining of free datablock
H->rawdisk_read((MAX_INODE) * SECTOR_SIZE, buffer, sizeof(buffer));//the begining of free datablock will store from address (MAX_INODE) * SECTOR_SIZE H->rawdisk_read((MAX_INODE) * SECTOR_SIZE, buffer, sizeof(buffer));//the begining of free datablock will store from address (MAX_INODE) * SECTOR_SIZE
t = 0; t = 0;
for (int j = 0; j < 8; j++) for (int j = 0; j < 8; j++)
t |= ((u_int64_t)(unsigned char)buffer[j]) << (8 * j); t |= ((u_int64_t)(unsigned char)buffer[j]) << (8 * j);
assert(t == (MAX_INODE+2048*8)*SECTOR_SIZE);//the first 8 bytes of 4k I/O block will store the next address(after 2048*4k I/O block) assert(t == (MAX_INODE+2048*8)*SECTOR_SIZE);//the first 8 bytes of 4k I/O block will store the next address(after 2048*4k I/O block)
//test the end of the datablock //test the end of the datablock
H->rawdisk_read((MAX_BLOCKNUM - 2048*8) * SECTOR_SIZE, buffer, sizeof(buffer)); H->rawdisk_read((MAX_BLOCKNUM - 2048*8) * SECTOR_SIZE, buffer, sizeof(buffer));
t = 0; t = 0;
for (int j = 0; j < 8; j++) for (int j = 0; j < 8; j++)
t |= ((u_int64_t)(unsigned char)buffer[j]) << (8 * j); t |= ((u_int64_t)(unsigned char)buffer[j]) << (8 * j);
assert(t == (MAX_BLOCKNUM)*SECTOR_SIZE); assert(t == (MAX_BLOCKNUM)*SECTOR_SIZE);
/***************************test inode de/allocation**********************************/ /***************************test inode de/allocation**********************************/
//when requesting an inode, the inode_allocation will give you the inode number, we use inode_list to store the sequence allocate inode //when requesting an inode, the inode_allocation will give you the inode number, we use inode_list to store the sequence allocate inode
//arrary version //arrary version
int inode_list[20] = {0}; int inode_list[20] = {0};
int record_free[10] = {0};//should do a pop up structure to record the free inode int record_free[10] = {0};//should do a pop up structure to record the free inode
int rec = 9; int rec = 9;
//printf("Allocate 20 inode num:{"); //printf("Allocate 20 inode num:{");
for(int i=0;i<20;i++){ for(int i=0;i<20;i++){
inode_list[i] = inop.inode_allocate(*H); inode_list[i] = inop.inode_allocate(*H);
assert(inode_list[i] == i+1); assert(inode_list[i] == i+1);
//printf(" %d", inode_list[i]); //printf(" %d", inode_list[i]);
} }
//printf("}\n"); //printf("}\n");
for(int i=10;i<20;i++){ for(int i=10;i<20;i++){
inop.inode_free(*H,inode_list[i]);//free the 10 element from inode_list[10] inop.inode_free(*H,inode_list[i]);//free the 10 element from inode_list[10]
record_free[i-10] = inode_list[i]; record_free[i-10] = inode_list[i];
} }
//allocate again the last 10 //allocate again the last 10
printf("Allocate again: inode num:{"); printf("Allocate again: inode num:{");
for(int i=10;i<20;i++){ for(int i=10;i<20;i++){
inode_list[i] = inop.inode_allocate(*H); inode_list[i] = inop.inode_allocate(*H);
//printf("inode %d, rec_f %d\n,", inode_list[i],record_free[rec]); //printf("inode %d, rec_f %d\n,", inode_list[i],record_free[rec]);
assert(inode_list[i] == record_free[rec]); assert(inode_list[i] == record_free[rec]);
rec--; rec--;
} }
printf("}\n"); printf("}\n");
/***************************test direct blocks[48] de/allocation**********************************/ /***************************test direct blocks[48] de/allocation**********************************/
//after free the datablock, the program will find the first smallest address of datablock to give to the inode //after free the datablock, the program will find the first smallest address of datablock to give to the inode
//should test random resize each node, but should use datablock_free data structure to record //should test random resize each node, but should use datablock_free data structure to record
INode inode_inside[10]; INode inode_inside[10];
u_int64_t rec_datablock_free[10][3] = {0};//array version u_int64_t rec_datablock_free[10][3] = {0};//array version
for(int i=0;i<10;i++){ for(int i=0;i<10;i++){
inode_inside[i].inode_construct(inode_list[i],*H); inode_inside[i].inode_construct(inode_list[i],*H);
//printf("%dth data block starting addres: ", i); //printf("%dth data block starting addres: ", i);
for(int j=0;j<6;j++){ for(int j=0;j<6;j++){
inode_inside[i].datablock_allocate(*H); inode_inside[i].datablock_allocate(*H);
//printf("%d," ,inode_inside[i].datablock_allocate(*H)); //printf("%d," ,inode_inside[i].datablock_allocate(*H));
} }
//printf("\n"); //printf("\n");
} }
for(int i=0;i<10;i++){ for(int i=0;i<10;i++){
//printf("%dth data block free addres: ", i); //printf("%dth data block free addres: ", i);
for(int j = 2;j >=0;j--){ for(int j = 2;j >=0;j--){
rec_datablock_free[i][j] = inode_inside[i].datablock_deallocate(*H); rec_datablock_free[i][j] = inode_inside[i].datablock_deallocate(*H);
//printf("", rec_datablock_free[i][j]); //printf("", rec_datablock_free[i][j]);
} }
//printf("\n"); //printf("\n");
} }
for(int i=0;i<10;i++){ for(int i=0;i<10;i++){
//printf("%dth data block allocate again addres: ", i); //printf("%dth data block allocate again addres: ", i);
for(int j=0;j<3;j++){ for(int j=0;j<3;j++){
assert(inode_inside[i].datablock_allocate(*H) == rec_datablock_free[i][j]); assert(inode_inside[i].datablock_allocate(*H) == rec_datablock_free[i][j]);
//printf("%d," ,inode_inside[i].datablock_allocate(*H)); //printf("%d," ,inode_inside[i].datablock_allocate(*H));
} }
//printf("\n"); //printf("\n");
} }
//printf("}\n"); //printf("}\n");
delete H; // Delete the RawDisk object delete H; // Delete the RawDisk object
return 0; return 0;
} }

View File

@ -1,13 +1,13 @@
#include "fischl.h" #include "fischl.h"
#include <assert.h> #include <assert.h>
void testFischlInit(){ void testFischlInit(){
fischl *F = new fischl; fischl *F = new fischl;
assert(F->init()==3); assert(F->init()==3);
delete F; delete F;
} }
int main(){ int main(){
testFischlInit(); testFischlInit();
return 0; return 0;
} }