Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 37 additions & 32 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,48 +101,53 @@ on the type of file:
```
inode
+-----------------------+
| i_mode = IFDIR | 0755 | block 123
| ei_block = 123 ----|--------> +----------------+
| i_size = 4 KiB | 0 | ee_block = 0 |
| i_blocks = 1 | | ee_len = 8 | block 84
+-----------------------+ | ee_start = 84 |---> +-----------+
|----------------| 0 | 24 (foo) |
1 | ee_block = 8 | |-----------|
| ee_len = 8 | 1 | 45 (bar) |
| ee_start = 16 | |-----------|
|----------------| | ... |
| ... | |-----------|
|----------------| 14 | 0 |
341 | ee_block = 0 | +-----------+
| ee_len = 0 |
| ee_start = 0 |
+----------------+
| i_mode = IFDIR | 0755 | block 123 (simplefs_file_ei_block)
| ei_block = 123 ----|---> +----------------+
| i_size = 4 KiB | | nr_files = 7 |
| i_blocks = 1 | |----------------|
+-----------------------+ 0 | ee_block = 0 |
| ee_len = 8 | block 84(simplefs_dir_block)
| ee_start = 84 |---> +-------------+
| nr_file = 2 | |nr_files = 2 |
|----------------| |-------------|
1 | ee_block = 8 | 0 | inode = 24 |
| ee_len = 8 | | nr_blk = 1 |
| ee_start = 16 | | (foo) |
| nr_file = 5 | |-------------|
|----------------| 1 | inode = 45 |
| ... | | nr_blk = 14 |
|----------------| | (bar) |
341 | ee_block = 0 | |-------------|
| ee_len = 0 | | ... |
| ee_start = 0 | |-------------|
| nr_file = 12 | 14 | 0 |
+----------------+ +-------------+

```
- For a file, it lists the extents that hold the actual data of the file.
Given that block IDs are stored as values of `sizeof(struct simplefs_extent)`
bytes, a single block can accommodate up to 341 links. This limitation
restricts the maximum size of a file to approximately 10.65 MiB (10,912 KiB).
```
inode
+-----------------------+
| i_mode = IFDIR | 0644 | block 93
| ei_block = 93 ----|------> +----------------+
| i_size = 10 KiB | 0 | ee_block = 0 |
| i_blocks = 25 | | ee_len = 8 | extent 94
inode
+-----------------------+
| i_mode = IFDIR | 0644 | block 93
| ei_block = 93 ----|------> +----------------+
| i_size = 10 KiB | 0 | ee_block = 0 |
| i_blocks = 25 | | ee_len = 8 | extent 94
+-----------------------+ | ee_start = 94 |---> +--------+
|----------------| | |
|----------------| | |
1 | ee_block = 8 | +--------+
| ee_len = 8 | extent 99
| ee_start = 99 |---> +--------+
| ee_start = 99 |---> +--------+
|----------------| | |
2 | ee_block = 16 | +--------+
| ee_len = 8 | extent 66
| ee_len = 8 | extent 66
| ee_start = 66 |---> +--------+
|----------------| | |
| ... | +--------+
|----------------|
341 | ee_block = 0 |
|----------------|
341 | ee_block = 0 |
| ee_len = 0 |
| ee_start = 0 |
+----------------+
Expand All @@ -158,8 +163,8 @@ comprises three members:

```
struct simplefs_extent
+----------------+
| ee_block = 0 |
+----------------+
| ee_block = 0 |
| ee_len = 200| extent
| ee_start = 12 |-----------> +---------+
+----------------+ block 12 | |
Expand All @@ -181,7 +186,7 @@ The journaling support in simplefs is implemented using the jbd2 subsystem, whic

For a detailed introduction to journaling, please refer to these two websites:
[Journal(jbd2) document](https://www.kernel.org/doc/html/latest/filesystems/ext4/journal.html)
[Journal(jbd2) api](https://docs.kernel.org/filesystems/journalling.html)
[Journal(jbd2) api](https://docs.kernel.org/filesystems/journalling.html)

External journal device disk layout:

Expand All @@ -193,12 +198,12 @@ Hint:
Each transaction starts with a descriptor block, followed by several metadata blocks or data blocks, and ends with a commit block. Every modified metadata (such as inode, bitmap, etc.) occupies its own block. Currently, simplefs primarily records "extent" metadata.


How to Enable Journaling in simplefs:
How to Enable Journaling in simplefs:

Step 1: Create the Journal Disk Image
To create an 8MB disk image for the journal, use the following make command:

Note:
Note:
Assuming an 8 MB size for the external journal device, which is an arbitrary choice for now, I will set the journal block length to a fixed 2048, calculated by dividing the device size by the block size (4096 bytes).

```shell
Expand Down
3 changes: 2 additions & 1 deletion bitmap.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,9 @@ static inline uint32_t get_free_blocks(struct super_block *sb, uint32_t len)
return 0;

sbi->nr_free_blocks -= len;
struct buffer_head *bh;
for (i = 0; i < len; i++) {
struct buffer_head *bh = sb_bread(sb, ret + i);
bh = sb_bread(sb, ret + i);
if (!bh) {
pr_err("get_free_blocks: sb_bread failed for block %d\n", ret + i);
sbi->nr_free_blocks += len;
Expand Down
59 changes: 42 additions & 17 deletions dir.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ static int simplefs_iterate(struct file *dir, struct dir_context *ctx)
struct buffer_head *bh = NULL, *bh2 = NULL;
struct simplefs_file_ei_block *eblock = NULL;
struct simplefs_dir_block *dblock = NULL;
struct simplefs_file *f = NULL;
int ei = 0, bi = 0, fi = 0;
int ret = 0;

Expand All @@ -43,36 +42,62 @@ static int simplefs_iterate(struct file *dir, struct dir_context *ctx)
return -EIO;
eblock = (struct simplefs_file_ei_block *) bh->b_data;

ei = (ctx->pos - 2) / SIMPLEFS_FILES_PER_EXT;
bi = (ctx->pos - 2) % SIMPLEFS_FILES_PER_EXT / SIMPLEFS_FILES_PER_BLOCK;
fi = (ctx->pos - 2) % SIMPLEFS_FILES_PER_BLOCK;
if (ctx->pos - 2 == eblock->nr_files)
goto release_bh;

/* Iterate over the index block and commit subfiles */
for (; ei < SIMPLEFS_MAX_EXTENTS; ei++) {
int remained_nr_files = eblock->nr_files - (ctx->pos - 2);

int offset = ctx->pos - 2;
for (ei = 0; ei < SIMPLEFS_MAX_EXTENTS; ei++) {
if (eblock->extents[ei].ee_start == 0)
continue;
if (offset > eblock->extents[ei].nr_files) {
offset -= eblock->extents[ei].nr_files;
} else {
break;
}
}

/* Iterate over the index block and commit subfiles */
for (; remained_nr_files && ei < SIMPLEFS_MAX_EXTENTS; ei++) {
if (eblock->extents[ei].ee_start == 0)
continue;

/* Iterate over blocks in one extent */
for (; bi < eblock->extents[ei].ee_len; bi++) {
for (bi = 0; bi < eblock->extents[ei].ee_len && remained_nr_files;
bi++) {
bh2 = sb_bread(sb, eblock->extents[ei].ee_start + bi);
if (!bh2) {
ret = -EIO;
goto release_bh;
}
dblock = (struct simplefs_dir_block *) bh2->b_data;
if (dblock->files[0].inode == 0) {

if (offset > dblock->nr_files) {
offset -= dblock->nr_files;
brelse(bh2);
bh2 = NULL;
break;
continue;
}
/* Iterate every file in one block */
for (; fi < SIMPLEFS_FILES_PER_BLOCK; fi++) {
f = &dblock->files[fi];
if (f->inode &&
!dir_emit(ctx, f->filename, SIMPLEFS_FILENAME_LEN, f->inode,
DT_UNKNOWN))
break;
ctx->pos++;

for (fi = 0; fi < SIMPLEFS_FILES_PER_BLOCK;) {
if (dblock->files[fi].inode != 0) {
if (offset) {
offset--;
} else {
remained_nr_files--;
if (!dir_emit(ctx, dblock->files[fi].filename,
SIMPLEFS_FILENAME_LEN,
dblock->files[fi].inode, DT_UNKNOWN)) {
brelse(bh2);
bh2 = NULL;
goto release_bh;
}

ctx->pos++;
}
}
fi += dblock->files[fi].nr_blk;
}
brelse(bh2);
bh2 = NULL;
Expand Down
8 changes: 4 additions & 4 deletions file.c
Original file line number Diff line number Diff line change
Expand Up @@ -51,14 +51,14 @@ static int simplefs_file_get_block(struct inode *inode,
ret = 0;
goto brelse_index;
}
bno = get_free_blocks(sb, 8);
bno = get_free_blocks(sb, SIMPLEFS_MAX_BLOCKS_PER_EXTENT);
if (!bno) {
ret = -ENOSPC;
goto brelse_index;
}

index->extents[extent].ee_start = bno;
index->extents[extent].ee_len = 8;
index->extents[extent].ee_len = SIMPLEFS_MAX_BLOCKS_PER_EXTENT;
index->extents[extent].ee_block =
extent ? index->extents[extent - 1].ee_block +
index->extents[extent - 1].ee_len
Expand Down Expand Up @@ -386,13 +386,13 @@ static ssize_t simplefs_write(struct file *file,
while (len > 0) {
/* check if block is allocated */
if (ei_block->extents[ei_index].ee_start == 0) {
int bno = get_free_blocks(sb, 8);
int bno = get_free_blocks(sb, SIMPLEFS_MAX_BLOCKS_PER_EXTENT);
if (!bno) {
bytes_write = -ENOSPC;
break;
}
ei_block->extents[ei_index].ee_start = bno;
ei_block->extents[ei_index].ee_len = 8;
ei_block->extents[ei_index].ee_len = SIMPLEFS_MAX_BLOCKS_PER_EXTENT;
ei_block->extents[ei_index].ee_block =
ei_index ? ei_block->extents[ei_index - 1].ee_block +
ei_block->extents[ei_index - 1].ee_len
Expand Down
Loading