Skip to content

Commit

Permalink
✨ 085 文件系统位图操作
Browse files Browse the repository at this point in the history
  • Loading branch information
StevenBaby committed Oct 22, 2022
1 parent 2f57e64 commit 3221772
Show file tree
Hide file tree
Showing 6 changed files with 177 additions and 13 deletions.
14 changes: 14 additions & 0 deletions docs/11 文件系统/085 文件系统位图操作.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# 文件系统位图操作

主要完成以下四个函数:

```c++
idx_t balloc(dev_t dev); // 分配一个文件块
void bfree(dev_t dev, idx_t idx); // 释放一个文件块
idx_t ialloc(dev_t dev); // 分配一个文件系统 inode
void ifree(dev_t dev, idx_t idx); // 释放一个文件系统 inode
```
> 一大禁忌:禁止 if 嵌套!提升代码可读性的最好方式!
- 尽早返回
130 changes: 130 additions & 0 deletions src/fs/bmap.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
#include <onix/fs.h>
#include <onix/debug.h>
#include <onix/bitmap.h>
#include <onix/assert.h>
#include <onix/string.h>
#include <onix/buffer.h>

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

// 分配一个文件块
idx_t balloc(dev_t dev)
{
super_block_t *sb = get_super(dev);
assert(sb);

buffer_t *buf = NULL;
idx_t bit = EOF;
bitmap_t map;

for (size_t i = 0; i < ZMAP_NR; i++)
{
buf = sb->zmaps[i];
assert(buf);

// 将整个缓冲区作为位图
bitmap_make(&map, buf->data, BLOCK_SIZE, i * BLOCK_BITS + sb->desc->firstdatazone - 1);

// 从位图中扫描一位
bit = bitmap_scan(&map, 1);
if (bit != EOF)
{
// 如果扫描成功,则 标记缓冲区脏,中止查找
assert(bit < sb->desc->zones);
buf->dirty = true;
break;
}
}
bwrite(buf); // todo 调试期间强同步
return bit;
}

// 释放一个文件块
void bfree(dev_t dev, idx_t idx)
{
super_block_t *sb = get_super(dev);
assert(sb != NULL);
assert(idx < sb->desc->zones);

buffer_t *buf;
bitmap_t map;
for (size_t i = 0; i < ZMAP_NR; i++)
{
// 跳过开始的块
if (idx > BLOCK_BITS * (i + 1))
{
continue;
}

buf = sb->zmaps[i];
assert(buf);

// 将整个缓冲区作为位图
bitmap_make(&map, buf->data, BLOCK_SIZE, BLOCK_BITS * i + sb->desc->firstdatazone - 1);

// 将 idx 对应的位图置位 0
assert(bitmap_test(&map, idx));
bitmap_set(&map, idx, 0);

// 标记缓冲区脏
buf->dirty = true;
break;
}
bwrite(buf); // todo 调试期间强同步
}

// 分配一个文件系统 inode
idx_t ialloc(dev_t dev)
{
super_block_t *sb = get_super(dev);
assert(sb);

buffer_t *buf = NULL;
idx_t bit = EOF;
bitmap_t map;

for (size_t i = 0; i < IMAP_NR; i++)
{
buf = sb->imaps[i];
assert(buf);

bitmap_make(&map, buf->data, BLOCK_BITS, i * BLOCK_BITS);
bit = bitmap_scan(&map, 1);
if (bit != EOF)
{
assert(bit < sb->desc->inodes);
buf->dirty = true;
break;
}
}
bwrite(buf); // todo 调试期间强同步
return bit;
}

// 释放一个文件系统 inode
void ifree(dev_t dev, idx_t idx)
{
super_block_t *sb = get_super(dev);
assert(sb != NULL);
assert(idx < sb->desc->inodes);

buffer_t *buf;
bitmap_t map;
for (size_t i = 0; i < IMAP_NR; i++)
{
if (idx > BLOCK_BITS * (i + 1))
{
continue;
}

buf = sb->imaps[i];
assert(buf);

bitmap_make(&map, buf->data, BLOCK_BITS, i * BLOCK_BITS);
assert(bitmap_test(&map, idx));
bitmap_set(&map, idx, 0);
buf->dirty = true;
break;
}
bwrite(buf); // todo 调试期间强同步
}
12 changes: 11 additions & 1 deletion src/fs/super.c
Original file line number Diff line number Diff line change
Expand Up @@ -99,8 +99,18 @@ static void mount_root()
device_t *device = device_find(DEV_IDE_PART, 0);
assert(device);

// 读更文件系统超级块
// 读根文件系统超级块
root = read_super(device->dev);

device = device_find(DEV_IDE_PART, 1);
assert(device);
super_block_t *sb = read_super(device->dev);

idx_t idx = ialloc(sb->dev);
ifree(sb->dev, idx);

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

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

#define BLOCK_BITS (BLOCK_SIZE * 8) // 块位图大小

typedef struct inode_desc_t
{
u16 mode; // 文件类型和属性(rwx 位)
Expand Down Expand Up @@ -52,7 +54,7 @@ typedef struct super_desc_t
typedef struct super_block_t
{
super_desc_t *desc; // 超级块描述符
struct buffer_t *buf; // 超级快描述符 buffer
struct buffer_t *buf; // 超级块描述符 buffer
struct buffer_t *imaps[IMAP_NR]; // inode 位图缓冲
struct buffer_t *zmaps[ZMAP_NR]; // 块位图缓冲
dev_t dev; // 设备号
Expand All @@ -71,4 +73,9 @@ typedef struct dentry_t
super_block_t *get_super(dev_t dev); // 获得 dev 对应的超级块
super_block_t *read_super(dev_t dev); // 读取 dev 对应的超级块

idx_t balloc(dev_t dev); // 分配一个文件块
void bfree(dev_t dev, idx_t idx); // 释放一个文件块
idx_t ialloc(dev_t dev); // 分配一个文件系统 inode
void ifree(dev_t dev, idx_t idx); // 释放一个文件系统 inode

#endif
24 changes: 13 additions & 11 deletions src/kernel/buffer.c
Original file line number Diff line number Diff line change
Expand Up @@ -180,21 +180,23 @@ void brelse(buffer_t *bf)
{
if (!bf)
return;
bf->count--;
assert(bf->count >= 0);
if (!bf->count)
{
if (bf->rnode.next)
{
list_remove(&bf->rnode);
}

list_push(&free_list, &bf->rnode);
}
if (bf->dirty)
{
bwrite(bf); // todo need write?
}

bf->count--;
assert(bf->count >= 0);
if (bf->count) // 还有人用,直接返回
return;

// if (bf->rnode.next)
// {
// list_remove(&bf->rnode);
// }
assert(!bf->rnode.next);
assert(!bf->rnode.prev);
list_push(&free_list, &bf->rnode);
if (!list_empty(&wait_list))
{
task_t *task = element_entry(task_t, node, list_popback(&wait_list));
Expand Down
1 change: 1 addition & 0 deletions src/makefile
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ $(BUILD)/kernel.bin: \
$(BUILD)/kernel/keyboard.o \
$(BUILD)/kernel/buffer.o \
$(BUILD)/fs/super.o \
$(BUILD)/fs/bmap.o \
$(BUILD)/lib/bitmap.o \
$(BUILD)/lib/list.o \
$(BUILD)/lib/fifo.o \
Expand Down

0 comments on commit 3221772

Please sign in to comment.