VFS with multiple layers

mkdir

src/vfs.c

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
int vfs_mkdir(const char* pathname) {
    struct vnode* target_dir;
    char child_name[128];
    traversal(pathname, &target_dir, child_name);
    struct vnode* child_dir;
    int res = target_dir->v_ops->mkdir(target_dir, &child_dir, child_name);
    if (res < 0) return res; // error
    child_dir->dentry->type = DIRECTORY;
    return 0;
}

src/tmpfs.c

跟 tmpfs_create 很像

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
int tmpfs_mkdir(struct vnode* dir, struct vnode** target, const char* component_name) {
    // create tmpfs internal structure
    struct tmpfs_internal* dir_node = (struct tmpfs_internal*)kmalloc(sizeof(struct tmpfs_internal));

    // create child dentry
    struct dentry* d_child = tmpfs_create_dentry(dir->dentry, component_name, DIRECTORY);
    d_child->vnode->internal = (void*)dir_node;

    *target = d_child->vnode;
    return 0;
}

readdir

src/vfs.c

1
2
3
int vfs_readdir(struct file* fd) {
    return fd->vnode->v_ops->ls(fd->vnode);
}

src/tmpfs.c

1
2
3
4
5
6
7
8
9
int tmpfs_ls(struct vnode* dir) {
    struct list_head* p = &dir->dentry->childs;
    list_for_each(p, &dir->dentry->childs) {
        struct dentry* dentry = list_entry(p, struct dentry, list);
        uart_printf("%s ", dentry->name);
    }
    uart_printf("\n");
    return 0;
}

chdir

include/schedule.h

1
2
3
4
struct task_t {
    ...
    struct dentry* pwd;
};

src/vfs.c

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
int vfs_chdir(const char* pathname) {
    struct vnode* target_dir;
    char path_remain[128];
    traversal(pathname, &target_dir, path_remain);
    if (strcmp(path_remain, "")) { // not found
        return -1;
    }
    else {
        current_task->pwd = target_dir->dentry;
        return 0;
    }
}

mount

src/vfs.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
29
// error: -1: not directory, -2: not found
int vfs_mount(const char* device, const char* mountpoint, const char* filesystem) {
    // check mountpoint is valid
    struct vnode* mount_dir;
    char path_remain[128];
    traversal(mountpoint, &mount_dir, path_remain);
    if (!strcmp(path_remain, "")) {  // found
        if (mount_dir->dentry->type != DIRECTORY) {
            return -1;
        }
    }
    else {
        return -2;
    }

    // mount fs on mountpoint
    struct mount* mt = (struct mount*)kmalloc(sizeof(struct mount));
    if (!strcmp(filesystem, "tmpfs")) {
        struct filesystem* tmpfs = (struct filesystem*)kmalloc(sizeof(struct filesystem));
        tmpfs->name = (char*)kmalloc(sizeof(char) * strlen(device));
        strcpy(tmpfs->name, device);
        tmpfs->setup_mount = tmpfs_setup_mount;
        tmpfs->setup_mount(tmpfs, mt);
        mount_dir->dentry->mountpoint = mt;
        mt->root->mount_origin = mount_dir->dentry;
    }

    return 0;
}

unmount

src/vfs.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
29
// error: -1: not directory, -2: not a mount point, -3: not found
int vfs_umount(const char* mountpoint) {
    // check mountpoint is valid
    struct vnode* mount_dir;
    char path_remain[128];
    traversal(mountpoint, &mount_dir, path_remain);
    if (!strcmp(path_remain, "")) {  // found
        if (mount_dir->dentry->type != DIRECTORY) {
            return -1;
        }
        if (!mount_dir->dentry->mount_origin) {
            return -2;
        }
    }
    else {
        return -3;
    }

    // umount
    struct list_head *p;
    list_for_each(p, &mount_dir->dentry->childs) {
        struct dentry *dentry = list_entry(p, struct dentry, list);
        list_del(p);
        kfree(dentry);
    }
    mount_dir->dentry->mount_origin->mountpoint = NULL;

    return 0;
}
comments powered by Disqus