Root File System (using tmpfs)

configuration for simplicity:

  • Each file’s size is less than 512 byte.
  • Only one root directory and regular files under it.
  • Pathname lookup includes only one component name.

Mount Object

建立 Root File System 的 mount object

include/vfs.h

1
2
3
4
5
6
7
8
9
struct mount {
    struct dentry* root;  // root directory
    struct filesystem* fs;
};

struct filesystem {
    char* name;
    int (*setup_mount)(struct filesystem* fs, struct mount* mount);
};

src/vfs.c

1
struct mount* rootfs;

Root directory’s vnode

在 setup mount 的同時,建立對應的 vnode 與 directory entry (dentry)

include/vfs.h

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
struct vnode {
    struct vnode_operations* v_ops;
    struct file_operations* f_ops;
    struct dentry* dentry;
    void* internal;         // internal representation of a vnode
};

struct dentry {
    char name[32];
    struct dentry* parent;
    struct list_head list;
    struct list_head childs;
    struct vnode* vnode;
    int type;
    struct mount* mountpoint;
    struct dentry* mount_origin;
};

src/vfs.c

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
void rootfs_init() {
    struct filesystem* tmpfs = (struct filesystem*)kmalloc(sizeof(struct filesystem));
    tmpfs->name = (char*)kmalloc(sizeof(char) * 6);
    strcpy(tmpfs->name, "tmpfs");
    tmpfs->setup_mount = tmpfs_setup_mount;
    register_filesystem(tmpfs);

    rootfs = (struct mount*)kmalloc(sizeof(struct mount));
    tmpfs->setup_mount(tmpfs, rootfs);
}

src/tmpfs.c

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
int tmpfs_setup_mount(struct filesystem* fs, struct mount* mount) {
    mount->fs = fs;
    mount->root = tmpfs_create_dentry(NULL, "/", DIRECTORY);
    return 0;
}

struct dentry* tmpfs_create_dentry(struct dentry* parent, const char* name, int type) {
    struct dentry* dentry = (struct dentry*)kmalloc(sizeof(struct dentry));
    strcpy(dentry->name, name);
    dentry->parent = parent;
    list_head_init(&dentry->list);
    list_head_init(&dentry->childs);
    if (parent != NULL) {
        list_add(&dentry->list, &parent->childs);
    }
    dentry->vnode = tmpfs_create_vnode(dentry);
    dentry->mountpoint = NULL;
    dentry->type = type;
    return dentry;
}

struct vnode* tmpfs_create_vnode(struct dentry* dentry) {
    struct vnode* vnode = (struct vnode*)kmalloc(sizeof(struct vnode));
    vnode->dentry = dentry;
    vnode->f_ops = tmpfs_f_ops;
    vnode->v_ops = tmpfs_v_ops;
    return vnode;
}

File System Registration

將對應的 file system 的 object 初始化

src/vfs.c

1
2
3
4
5
6
7
8
9
int register_filesystem(struct filesystem* fs) {
    // register the file system to the kernel.
    // you can also initialize memory pool of the file system here.
    if (!strcmp(fs->name, "tmpfs")) {
        uart_printf("\n[%f] Register tmpfs", get_timestamp());
        return tmpfs_register();
    }
    return -1;
}

src/tmpfs.c

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
struct vnode_operations* tmpfs_v_ops;
struct file_operations* tmpfs_f_ops;

int tmpfs_register() {
    tmpfs_v_ops = (struct vnode_operations*)kmalloc(sizeof(struct vnode_operations));
    tmpfs_v_ops->create = tmpfs_create;
    tmpfs_v_ops->lookup = tmpfs_lookup;
    tmpfs_v_ops->ls = tmpfs_ls;
    tmpfs_v_ops->mkdir = tmpfs_mkdir;
    tmpfs_f_ops = (struct file_operations*)kmalloc(sizeof(struct file_operations));
    tmpfs_f_ops->read = tmpfs_read;
    tmpfs_f_ops->write = tmpfs_write;
    return 0;
}
comments powered by Disqus