VFS in a multitasking scenario

Task’s VFS information

存 file descriptor table 與 pwd

include/schedule.h

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

include/vfs.h

1
2
3
4
5
6
struct files_struct {
    int count;
    int next_fd;
    struct file** fd;
    struct file* fd_array[NR_OPEN_DEFAULT]; // default array of file objects
};

System Call

維護 file descriptor table

src/exception.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
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
void sys_open(struct trapframe* trapframe) {
    const char* pathname = (char*) trapframe->x[0];
    int flags = trapframe->x[1];
    struct file* f = vfs_open(pathname, flags);
    // open failed
    if (f == NULL) {
        trapframe->x[0] = -1;
        return;
    }
    // store fd in task struct
    int fd_num = current_task->files.next_fd;
    // open files more than fd array
    if (fd_num >= current_task->files.count) {
        int new_fd_array_size = current_task->files.count + NR_OPEN_DEFAULT;
        struct file** new_fd_array = (struct file**)kmalloc(sizeof(struct file*) * new_fd_array_size);
        for (int i = 0; i < current_task->files.count; i++) {
            new_fd_array[i] = current_task->files.fd[i];
        }
        current_task->files.fd = new_fd_array;
        current_task->files.count = new_fd_array_size;
    }
    current_task->files.fd[fd_num] = f;
    current_task->files.next_fd++;
    trapframe->x[0] = fd_num;
}

void sys_close(struct trapframe* trapframe) {
    int fd_num = (int)trapframe->x[0];
    if (fd_num < 0) {
        trapframe->x[0] = -1;
        return;
    }
    struct file* f = current_task->files.fd[fd_num];
    trapframe->x[0] = vfs_close(f);
    current_task->files.fd[fd_num] = NULL;
}

void sys_write(struct trapframe* trapframe) {
    int fd_num = (int)trapframe->x[0];
    char* buf = (char*)trapframe->x[1];
    if (fd_num < 0) {
        trapframe->x[0] = -1;
        return;
    }
    uint64_t len = (uint64_t)trapframe->x[2];
    struct file* f = current_task->files.fd[fd_num];
    if (f == NULL) {
        trapframe->x[0] = 0;
        return;
    }
    trapframe->x[0] = vfs_write(f, buf, len);
}

void sys_read(struct trapframe* trapframe) {
    int fd_num = (int)trapframe->x[0];
    char* buf = (char*)trapframe->x[1];
    if (fd_num < 0) {
        trapframe->x[0] = -1;
        return;
    }
    uint64_t len = (uint64_t)trapframe->x[2];
    struct file* f = current_task->files.fd[fd_num];
    if (f == NULL) {
        trapframe->x[0] = 0;
        return;
    }
    trapframe->x[0] = vfs_read(f, buf, len);
}

void sys_readdir(struct trapframe* trapframe) {
    int fd_num = (int)trapframe->x[0];
    if (fd_num < 0) {
        trapframe->x[0] = -1;
        return;
    }
    struct file* f = current_task->files.fd[fd_num];
    trapframe->x[0] = vfs_readdir(f);
}

void sys_mkdir(struct trapframe* trapframe) {
    const char* pathname = (char*) trapframe->x[0];
    trapframe->x[0] = vfs_mkdir(pathname);
}

void sys_chdir(struct trapframe* trapframe) {
    const char* pathname = (char*) trapframe->x[0];
    trapframe->x[0] = vfs_chdir(pathname);
}

void sys_mount(struct trapframe* trapframe) {
    const char* device = (char*) trapframe->x[0];
    const char* mountpoint = (char*) trapframe->x[1];
    const char* filesystem = (char*) trapframe->x[2];
    trapframe->x[0] = vfs_mount(device, mountpoint, filesystem);
}

void sys_umount(struct trapframe* trapframe) {
    const char* mountpoint = (char*) trapframe->x[0];
    trapframe->x[0] = vfs_umount(mountpoint);
}
comments powered by Disqus