Skip to content

Commit

Permalink
✨ 086 文件系统 inode
Browse files Browse the repository at this point in the history
  • Loading branch information
StevenBaby committed Oct 22, 2022
1 parent 3221772 commit eed0812
Show file tree
Hide file tree
Showing 12 changed files with 386 additions and 125 deletions.
2 changes: 2 additions & 0 deletions docs/11 文件系统/083 文件系统简介.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ typedef struct inode_desc_t
} inode_desc_t;
```

**勘误:**:文件系统块索引数量应该是 512 个,而不是 64 个

![](./images/inode.drawio.svg)

## 超级块
Expand Down
12 changes: 12 additions & 0 deletions docs/11 文件系统/086 文件系统 inode.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# 文件系统 inode

主要完成以下几个函数:

```c++
inode_t *iget(dev_t dev, idx_t nr); // 获得设备 dev 的 nr inode
void iput(inode_t *inode); // 释放 inode

// 获取 inode 第 block 块的索引值
// 如果不存在 且 create 为 true,则创建
idx_t bmap(inode_t *inode, idx_t block, bool create);
```
228 changes: 114 additions & 114 deletions docs/11 文件系统/images/inode.drawio.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
74 changes: 74 additions & 0 deletions src/fs/bmap.c
Original file line number Diff line number Diff line change
Expand Up @@ -128,3 +128,77 @@ void ifree(dev_t dev, idx_t idx)
}
bwrite(buf); // todo 调试期间强同步
}

// 获取 inode 第 block 块的索引值
// 如果不存在 且 create 为 true,则创建
idx_t bmap(inode_t *inode, idx_t block, bool create)
{
// 确保 block 合法
assert(block >= 0 && block < TOTAL_BLOCK);

// 数组索引
u16 index = block;

// 数组
u16 *array = inode->desc->zone;

// 缓冲区
buffer_t *buf = inode->buf;

// 用于下面的 brelse,传入参数 inode 的 buf 不应该释放
buf->count += 1;

// 当前处理级别
int level = 0;

// 当前子级别块数量
int divider = 1;

// 直接块
if (block < DIRECT_BLOCK)
{
goto reckon;
}

block -= DIRECT_BLOCK;

if (block < INDIRECT1_BLOCK)
{
index = DIRECT_BLOCK;
level = 1;
divider = 1;
goto reckon;
}

block -= INDIRECT1_BLOCK;
assert(block < INDIRECT2_BLOCK);
index = DIRECT_BLOCK + 1;
level = 2;
divider = BLOCK_INDEXES;

reckon:
for (; level >= 0; level--)
{
// 如果不存在 且 create 则申请一块文件块
if (!array[index] && create)
{
array[index] = balloc(inode->dev);
buf->dirty = true;
}

brelse(buf);

// 如果 level == 0 或者 索引不存在,直接返回
if (level == 0 || !array[index])
{
return array[index];
}

// level 不为 0,处理下一级索引
buf = bread(inode->dev, array[index]);
index = block / divider;
block = block % divider;
divider /= BLOCK_INDEXES;
array = (u16 *)buf->data;
}
}
138 changes: 138 additions & 0 deletions src/fs/inode.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
#include <onix/fs.h>
#include <onix/syscall.h>
#include <onix/assert.h>
#include <onix/debug.h>
#include <onix/buffer.h>
#include <onix/arena.h>
#include <onix/string.h>
#include <onix/stdlib.h>

#define LOGK(fmt, args...) DEBUGK(fmt, ##args)

#define INODE_NR 64

static inode_t inode_table[INODE_NR];

// 申请一个 inode
static inode_t *get_free_inode()
{
for (size_t i = 0; i < INODE_NR; i++)
{
inode_t *inode = &inode_table[i];
if (inode->dev == EOF)
{
return inode;
}
}
panic("no more inode!!!");
}

// 释放一个 inode
static void put_free_inode(inode_t *inode)
{
assert(inode != inode_table);
assert(inode->count == 0);
inode->dev = EOF;
}

// 获取根 inode
inode_t *get_root_inode()
{
return inode_table;
}

// 计算 inode nr 对应的块号
static inline idx_t inode_block(super_block_t *sb, idx_t nr)
{
// inode 编号 从 1 开始
return 2 + sb->desc->imap_blocks + sb->desc->zmap_blocks + (nr - 1) / BLOCK_INODES;
}

// 从已有 inode 中查找编号为 nr 的 inode
static inode_t *find_inode(dev_t dev, idx_t nr)
{
super_block_t *sb = get_super(dev);
assert(sb);
list_t *list = &sb->inode_list;

for (list_node_t *node = list->head.next; node != &list->tail; node = node->next)
{
inode_t *inode = element_entry(inode_t, node, node);
if (inode->nr == nr)
{
return inode;
}
}
return NULL;
}

// 获得设备 dev 的 nr inode
inode_t *iget(dev_t dev, idx_t nr)
{
inode_t *inode = find_inode(dev, nr);
if (inode)
{
inode->count++;
inode->atime = time();

return inode;
}

super_block_t *sb = get_super(dev);
assert(sb);

assert(nr <= sb->desc->inodes);

inode = get_free_inode();
inode->dev = dev;
inode->nr = nr;
inode->count = 1;

// 加入超级块 inode 链表
list_push(&sb->inode_list, &inode->node);

idx_t block = inode_block(sb, inode->nr);
buffer_t *buf = bread(inode->dev, block);

inode->buf = buf;

// 将缓冲视为一个 inode 描述符数组,获取对应的指针;
inode->desc = &((inode_desc_t *)buf->data)[(inode->nr - 1) % BLOCK_INODES];

inode->ctime = inode->desc->mtime;
inode->atime = time();

return inode;
}

// 释放 inode
void iput(inode_t *inode)
{
if (!inode)
return;

inode->count--;

if (inode->count)
{
return;
}

// 释放 inode 对应的缓冲
brelse(inode->buf);

// 从超级块链表中移除
list_remove(&inode->node);

// 释放 inode 内存
put_free_inode(inode);
}

void inode_init()
{
for (size_t i = 0; i < INODE_NR; i++)
{
inode_t *inode = &inode_table[i];
inode->dev = EOF;
}
}
22 changes: 15 additions & 7 deletions src/fs/super.c
Original file line number Diff line number Diff line change
Expand Up @@ -102,15 +102,23 @@ static void mount_root()
// 读根文件系统超级块
root = read_super(device->dev);

device = device_find(DEV_IDE_PART, 1);
assert(device);
super_block_t *sb = read_super(device->dev);
// 初始化根目录 inode
root->iroot = iget(device->dev, 1); // 获得根目录 inode
root->imount = iget(device->dev, 1); // 根目录挂载 inode

idx_t idx = 0;
inode_t *inode = iget(device->dev, 1);

// 直接块
idx = bmap(inode, 3, true);

// 一级间接块
idx = bmap(inode, 7 + 7, true);

idx_t idx = ialloc(sb->dev);
ifree(sb->dev, idx);
// 二级间接块
idx = bmap(inode, 7 + 512 * 3 + 510, true);

idx = balloc(sb->dev);
bfree(sb->dev, idx);
iput(inode);
}

void super_init()
Expand Down
18 changes: 17 additions & 1 deletion src/include/onix/fs.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,15 @@
#define IMAP_NR 8 // inode 位图块,最大值
#define ZMAP_NR 8 // 块位图块,最大值

#define BLOCK_BITS (BLOCK_SIZE * 8) // 块位图大小
#define BLOCK_BITS (BLOCK_SIZE * 8) // 块位图大小
#define BLOCK_INODES (BLOCK_SIZE / sizeof(inode_desc_t)) // 块 inode 数量
#define BLOCK_DENTRIES (BLOCK_SIZE / sizeof(dentry_t)) // 块 dentry 数量
#define BLOCK_INDEXES (BLOCK_SIZE / sizeof(u16)) // 块索引数量

#define DIRECT_BLOCK (7) // 直接块数量
#define INDIRECT1_BLOCK BLOCK_INDEXES // 一级间接块数量
#define INDIRECT2_BLOCK (INDIRECT1_BLOCK * INDIRECT1_BLOCK) // 二级间接块数量
#define TOTAL_BLOCK (DIRECT_BLOCK + INDIRECT1_BLOCK + INDIRECT2_BLOCK) // 全部块数量

typedef struct inode_desc_t
{
Expand Down Expand Up @@ -78,4 +86,12 @@ void bfree(dev_t dev, idx_t idx); // 释放一个文件块
idx_t ialloc(dev_t dev); // 分配一个文件系统 inode
void ifree(dev_t dev, idx_t idx); // 释放一个文件系统 inode

// 获取 inode 第 block 块的索引值
// 如果不存在 且 create 为 true,则创建
idx_t bmap(inode_t *inode, idx_t block, bool create);

inode_t *get_root_inode(); // 获取根目录 inode
inode_t *iget(dev_t dev, idx_t nr); // 获得设备 dev 的 nr inode
void iput(inode_t *inode); // 释放 inode

#endif
2 changes: 2 additions & 0 deletions src/include/onix/task.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ typedef struct task_t
u32 brk; // 进程堆内存最高地址
int status; // 进程特殊状态
pid_t waitpid; // 进程等待的 pid
struct inode_t *ipwd; // 进程当前目录 inode program work directory
struct inode_t *iroot; // 进程根目录 inode
u32 magic; // 内核魔数,用于检测栈溢出
} task_t;

Expand Down
3 changes: 3 additions & 0 deletions src/kernel/buffer.c
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,10 @@ buffer_t *getblk(dev_t dev, idx_t block)
{
buffer_t *bf = get_from_hash_table(dev, block);
if (bf)
{
assert(bf->valid);
return bf;
}

bf = get_free_buffer();
assert(bf->count == 0);
Expand Down
7 changes: 4 additions & 3 deletions src/kernel/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ extern void syscall_init();
extern void tss_init();
extern void buffer_init();
extern void super_init();
extern void inode_init();
extern void hang();

void kernel_init()
Expand All @@ -34,11 +35,11 @@ void kernel_init()
// rtc_init();
ide_init();

buffer_init();

task_init();
syscall_init();
task_init();

buffer_init();
inode_init();
super_init();

set_interrupt_state(true);
Expand Down
4 changes: 4 additions & 0 deletions src/kernel/task.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include <onix/list.h>
#include <onix/global.h>
#include <onix/arena.h>
#include <onix/fs.h>

#define LOGK(fmt, args...) DEBUGK(fmt, ##args)

Expand Down Expand Up @@ -251,6 +252,9 @@ static task_t *task_create(target_t target, const char *name, u32 priority, u32
task->vmap = &kernel_map;
task->pde = KERNEL_PAGE_DIR; // page directory entry
task->brk = KERNEL_MEMORY_SIZE;
task->iroot = get_root_inode();
task->ipwd = get_root_inode();

task->magic = ONIX_MAGIC;

return task;
Expand Down
1 change: 1 addition & 0 deletions src/makefile
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ $(BUILD)/kernel.bin: \
$(BUILD)/kernel/buffer.o \
$(BUILD)/fs/super.o \
$(BUILD)/fs/bmap.o \
$(BUILD)/fs/inode.o \
$(BUILD)/lib/bitmap.o \
$(BUILD)/lib/list.o \
$(BUILD)/lib/fifo.o \
Expand Down

0 comments on commit eed0812

Please sign in to comment.