Skip to content

Commit

Permalink
Lab 7 C: Complete B3
Browse files Browse the repository at this point in the history
Other changes:

- Disable demand paging/CoW debug log.

- Fix a bug in `free` that causes an incorrect slot to be freed.
  • Loading branch information
abt8601 committed Jun 28, 2023
1 parent 507855e commit 8a64b30
Show file tree
Hide file tree
Showing 29 changed files with 443 additions and 28 deletions.
5 changes: 4 additions & 1 deletion lab7/c/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ CC = aarch64-linux-gnu-gcc
CPP = aarch64-linux-gnu-cpp
OBJCOPY = aarch64-linux-gnu-objcopy

CPPFLAGS_BASE = -Iinclude -DVM_ENABLE_DEBUG_LOG
CPPFLAGS_BASE = -Iinclude

ASFLAGS_DEBUG = -g

Expand Down Expand Up @@ -41,6 +41,9 @@ OBJS = start main console devicetree initrd panic shell \
xcpt/syscall/exit xcpt/syscall/mbox-call xcpt/syscall/kill \
xcpt/syscall/signal xcpt/syscall/signal-kill \
xcpt/syscall/sigreturn xcpt/syscall/sigreturn-check \
xcpt/syscall/open xcpt/syscall/close xcpt/syscall/write \
xcpt/syscall/read xcpt/syscall/mkdir xcpt/syscall/mount \
xcpt/syscall/chdir \
libc/ctype libc/stdio libc/stdlib/qsort libc/string \
utils/core-id utils/fmt utils/heapq utils/rb
LD_SCRIPT = $(SRC_DIR)/linker.ld
Expand Down
16 changes: 16 additions & 0 deletions lab7/c/include/oscos/fs/vfs.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,12 +51,28 @@ extern struct mount rootfs;

int register_filesystem(struct filesystem *fs);
int vfs_open(const char *pathname, int flags, struct file **target);
int vfs_open_relative(struct vnode *cwd, const char *pathname, int flags,
struct file **target);
int vfs_close(struct file *file);
int vfs_write(struct file *file, const void *buf, size_t len);
int vfs_read(struct file *file, void *buf, size_t len);

int vfs_mkdir(const char *pathname);
int vfs_mkdir_relative(struct vnode *cwd, const char *pathname);
int vfs_mount(const char *target, const char *filesystem);
int vfs_mount_relative(struct vnode *cwd, const char *target,
const char *filesystem);
int vfs_lookup(const char *pathname, struct vnode **target);
int vfs_lookup_relative(struct vnode *cwd, const char *pathname,
struct vnode **target);

typedef struct {
struct file *file;
size_t refcnt;
} shared_file_t;

shared_file_t *shared_file_new(struct file *file);
shared_file_t *shared_file_clone(shared_file_t *shared_file);
void shared_file_drop(shared_file_t *shared_file);

#endif
5 changes: 5 additions & 0 deletions lab7/c/include/oscos/sched.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,14 @@
#include <stdint.h>
#include <stdnoreturn.h>

#include "oscos/fs/vfs.h"
#include "oscos/mem/types.h"
#include "oscos/mem/vm.h"
#include "oscos/uapi/signal.h"
#include "oscos/xcpt/trap-frame.h"

#define N_FDS 16

typedef struct thread_list_node_t {
struct thread_list_node_t *prev, *next;
} thread_list_node_t;
Expand Down Expand Up @@ -60,6 +63,8 @@ typedef struct process_t {
thread_t *main_thread;
uint32_t pending_signals, blocked_signals;
sighandler_t signal_handlers[32];
struct vnode *cwd;
shared_file_t *fds[N_FDS];
} process_t;

/// \brief Initializes the scheduler and creates the idle thread.
Expand Down
2 changes: 2 additions & 0 deletions lab7/c/include/oscos/uapi/errno.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,15 @@
#define ESRCH 3
#define EINTR 4
#define EIO 5
#define EBADF 9
#define ENOMEM 12
#define EBUSY 16
#define EEXIST 17
#define ENODEV 19
#define ENOTDIR 20
#define EISDIR 21
#define EINVAL 22
#define EMFILE 24
#define EFBIG 27
#define ENOSYS 38
#define ELOOP 40
7 changes: 7 additions & 0 deletions lab7/c/include/oscos/uapi/sys/syscall.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,12 @@
#define SYS_signal 8
#define SYS_signal_kill 9
#define SYS_sigreturn 10
#define SYS_open 11
#define SYS_close 12
#define SYS_write 13
#define SYS_read 14
#define SYS_mkdir 15
#define SYS_mount 16
#define SYS_chdir 17

#endif
23 changes: 17 additions & 6 deletions lab7/c/src/fs/tmpfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
typedef enum { TYPE_DIR, TYPE_FILE } tmpfs_internal_type_t;

typedef struct {
struct vnode *parent;
rb_node_t *contents;
} tmpfs_internal_dir_data_t;

Expand Down Expand Up @@ -108,7 +109,8 @@ static struct vnode *_tmpfs_create_file_vnode(struct mount *const mount) {
return result;
}

static struct vnode *_tmpfs_create_dir_vnode(struct mount *const mount) {
static struct vnode *_tmpfs_create_dir_vnode(struct mount *const mount,
struct vnode *const parent) {
struct vnode *const result = malloc(sizeof(struct vnode));
if (!result)
return NULL;
Expand All @@ -119,9 +121,9 @@ static struct vnode *_tmpfs_create_dir_vnode(struct mount *const mount) {
return NULL;
}

*internal = (tmpfs_internal_t){
.type = TYPE_DIR,
.dir_data = (tmpfs_internal_dir_data_t){.contents = NULL}};
*internal = (tmpfs_internal_t){.type = TYPE_DIR,
.dir_data = (tmpfs_internal_dir_data_t){
.parent = parent, .contents = NULL}};
*result = (struct vnode){.mount = mount,
.v_ops = &_tmpfs_vnode_operations,
.f_ops = &_tmpfs_file_operations,
Expand All @@ -131,7 +133,7 @@ static struct vnode *_tmpfs_create_dir_vnode(struct mount *const mount) {

static int _tmpfs_setup_mount(struct filesystem *const fs,
struct mount *const mount) {
struct vnode *const root_vnode = _tmpfs_create_dir_vnode(mount);
struct vnode *const root_vnode = _tmpfs_create_dir_vnode(mount, NULL);
if (!root_vnode)
return -ENOMEM;

Expand Down Expand Up @@ -254,6 +256,14 @@ static int _tmpfs_lookup(struct vnode *const dir_node,
int result;
tmpfs_internal_dir_data_t *const dir_data = &internal->dir_data;

if (strcmp(component_name, ".") == 0) {
*target = dir_node;
return 0;
} else if (strcmp(component_name, "..") == 0) {
*target = dir_data->parent;
return 0;
}

uint64_t daif_val;
CRITICAL_SECTION_ENTER(daif_val);

Expand Down Expand Up @@ -353,7 +363,8 @@ static int _tmpfs_mkdir(struct vnode *const dir_node,
goto end;
}

struct vnode *const vnode = _tmpfs_create_dir_vnode(dir_node->mount);
struct vnode *const vnode =
_tmpfs_create_dir_vnode(dir_node->mount, dir_node);
if (!vnode) {
result = -ENOMEM;
goto end;
Expand Down
113 changes: 98 additions & 15 deletions lab7/c/src/fs/vfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -96,9 +96,29 @@ int register_filesystem(struct filesystem *const fs) {
return 0;
}

static int _vfs_lookup_step(struct vnode *const curr_vnode,
static int _vfs_lookup_step(struct vnode *curr_vnode,
struct vnode **const target,
const char *const component_name) {
if (strcmp(component_name, "..") == 0 &&
curr_vnode == curr_vnode->mount->root) {
if (curr_vnode == rootfs.root) {
*target = curr_vnode;
return 0;
} else {
uint64_t daif_val;
CRITICAL_SECTION_ENTER(daif_val);

const mount_entry_t *const entry = rb_search(
_mounts_by_root, curr_vnode,
(int (*)(const void *, const void *, void *))_vfs_cmp_root_and_mount,
NULL);

CRITICAL_SECTION_LEAVE(daif_val);

curr_vnode = entry->mountpoint;
}
}

const int result =
curr_vnode->v_ops->lookup(curr_vnode, target, component_name);
if (result < 0)
Expand All @@ -125,12 +145,16 @@ static int _vfs_lookup_step(struct vnode *const curr_vnode,
return 0;
}

static int
_vfs_lookup_sans_last_level(const char *const pathname,
struct vnode **const target,
const char **const last_pathname_component) {
struct vnode *curr_vnode = rootfs.root;
const char *curr_pathname_component = pathname + 1;
static int _vfs_lookup_sans_last_level_relative(
struct vnode *const cwd, const char *const pathname,
struct vnode **const target, const char **const last_pathname_component) {
struct vnode *curr_vnode = cwd;
const char *curr_pathname_component = pathname;
if (*curr_pathname_component == '/') {
curr_vnode = rootfs.root;
curr_pathname_component += 1;
}

for (const char *curr_pathname_component_end;
(curr_pathname_component_end = strchr(curr_pathname_component, '/'));
curr_pathname_component = curr_pathname_component_end + 1) {
Expand All @@ -156,10 +180,15 @@ _vfs_lookup_sans_last_level(const char *const pathname,

int vfs_open(const char *const pathname, const int flags,
struct file **const target) {
return vfs_open_relative(rootfs.root, pathname, flags, target);
}

int vfs_open_relative(struct vnode *const cwd, const char *const pathname,
const int flags, struct file **const target) {
const char *last_pathname_component;
struct vnode *parent_vnode;
const int lookup_result = _vfs_lookup_sans_last_level(
pathname, &parent_vnode, &last_pathname_component);
const int lookup_result = _vfs_lookup_sans_last_level_relative(
cwd, pathname, &parent_vnode, &last_pathname_component);
if (lookup_result < 0)
return lookup_result;

Expand Down Expand Up @@ -189,10 +218,14 @@ int vfs_read(struct file *const file, void *const buf, const size_t len) {
}

int vfs_mkdir(const char *const pathname) {
return vfs_mkdir_relative(rootfs.root, pathname);
}

int vfs_mkdir_relative(struct vnode *const cwd, const char *const pathname) {
const char *last_pathname_component;
struct vnode *parent_vnode;
const int lookup_result = _vfs_lookup_sans_last_level(
pathname, &parent_vnode, &last_pathname_component);
const int lookup_result = _vfs_lookup_sans_last_level_relative(
cwd, pathname, &parent_vnode, &last_pathname_component);
if (lookup_result < 0)
return lookup_result;

Expand All @@ -202,8 +235,13 @@ int vfs_mkdir(const char *const pathname) {
}

int vfs_mount(const char *const target, const char *const filesystem) {
return vfs_mount_relative(rootfs.root, target, filesystem);
}

int vfs_mount_relative(struct vnode *const cwd, const char *const target,
const char *const filesystem) {
struct vnode *mountpoint;
const int result = vfs_lookup(target, &mountpoint);
const int result = vfs_lookup_relative(cwd, target, &mountpoint);
if (result < 0)
return result;

Expand Down Expand Up @@ -250,12 +288,57 @@ int vfs_mount(const char *const target, const char *const filesystem) {
}

int vfs_lookup(const char *const pathname, struct vnode **const target) {
return vfs_lookup_relative(rootfs.root, pathname, target);
}

int vfs_lookup_relative(struct vnode *const cwd, const char *const pathname,
struct vnode **const target) {
const char *last_pathname_component;
struct vnode *parent_vnode;
const int lookup_result = _vfs_lookup_sans_last_level(
pathname, &parent_vnode, &last_pathname_component);
const int lookup_result = _vfs_lookup_sans_last_level_relative(
cwd, pathname, &parent_vnode, &last_pathname_component);
if (lookup_result < 0)
return lookup_result;

return _vfs_lookup_step(parent_vnode, target, last_pathname_component);
if (*last_pathname_component == '\0') {
*target = parent_vnode;
return 0;
} else {
return _vfs_lookup_step(parent_vnode, target, last_pathname_component);
}
}

shared_file_t *shared_file_new(struct file *const file) {
shared_file_t *const shared_file = malloc(sizeof(shared_file_t));
if (!shared_file)
return NULL;

*shared_file = (shared_file_t){.file = file, .refcnt = 1};
return shared_file;
}

shared_file_t *shared_file_clone(shared_file_t *const shared_file) {
uint64_t daif_val;
CRITICAL_SECTION_ENTER(daif_val);

shared_file->refcnt++;

CRITICAL_SECTION_LEAVE(daif_val);

return shared_file;
}

void shared_file_drop(shared_file_t *const shared_file) {
uint64_t daif_val;
CRITICAL_SECTION_ENTER(daif_val);

shared_file->refcnt--;
const bool drop = shared_file->refcnt == 0;

CRITICAL_SECTION_LEAVE(daif_val);

if (drop) {
vfs_close(shared_file->file);
free(shared_file);
}
}
2 changes: 1 addition & 1 deletion lab7/c/src/mem/malloc.c
Original file line number Diff line number Diff line change
Expand Up @@ -270,7 +270,7 @@ static void _free_to_slab(slab_t *const slab, void *const ptr) {
// Mark the slot as available.

slab->n_slots_reserved--;
slab->slots_reserved_bitset[slot_ix / 64] &= ~(1 << (slot_ix % 64));
slab->slots_reserved_bitset[slot_ix / 64] &= ~(1ULL << (slot_ix % 64));

// Return the slab to the page frame allocator if it has no reserved slots.

Expand Down
14 changes: 14 additions & 0 deletions lab7/c/src/sched/sched.c
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,10 @@ bool process_create(void) {
for (size_t i = 0; i < 32; i++) {
process->signal_handlers[i] = SIG_DFL;
}
process->cwd = rootfs.root;
for (size_t i = 0; i < N_FDS; i++) {
process->fds[i] = NULL;
}
curr_thread->process = process;
curr_thread->ctx.fp_simd_ctx = fp_simd_ctx;

Expand Down Expand Up @@ -331,6 +335,11 @@ void exec(const void *const text_start, const size_t text_len) {
static void _thread_cleanup(thread_t *const thread) {
if (thread->process) {
vm_drop_pgd(thread->process->addr_space.pgd);
for (size_t i = 0; i < N_FDS; i++) {
if (thread->process->fds[i]) {
shared_file_drop(thread->process->fds[i]);
}
}
free(thread->process);
}
free_pages(thread->stack_page_id);
Expand Down Expand Up @@ -388,6 +397,11 @@ process_t *fork(const extended_trap_frame_t *const trap_frame) {
new_process->blocked_signals = 0;
memcpy(new_process->signal_handlers, curr_process->signal_handlers,
32 * sizeof(sighandler_t));
new_process->cwd = curr_process->cwd;
for (size_t i = 0; i < N_FDS; i++) {
new_process->fds[i] =
curr_process->fds[i] ? shared_file_clone(curr_process->fds[i]) : NULL;
}

// Set execution context.

Expand Down
Loading

0 comments on commit 8a64b30

Please sign in to comment.