summaryrefslogtreecommitdiff
path: root/kernel
diff options
context:
space:
mode:
authorAnton Kling <anton@kling.gg>2024-04-23 14:35:09 +0200
committerAnton Kling <anton@kling.gg>2024-04-23 14:35:09 +0200
commit0305b0abe4ada656462d575a5e0f0618b42def2d (patch)
treeecffe02ac3670457ed2cf0fbb513efbb69867d01 /kernel
parent33663539c2bac856cf2abe79e815ad179dffecdf (diff)
VFS: Fix reference count of file descriptors.
It appears that there was a race condition where the process got closed before the server accepted the incoming request. Causing the file descriptor to have "0" in the reference count but it would still be given when calling accept.
Diffstat (limited to 'kernel')
-rw-r--r--kernel/fs/devfs.c3
-rw-r--r--kernel/fs/fifo.c20
-rw-r--r--kernel/fs/fifo.h1
-rw-r--r--kernel/fs/tmpfs.c6
-rw-r--r--kernel/fs/vfs.c4
-rw-r--r--kernel/socket.c5
6 files changed, 14 insertions, 25 deletions
diff --git a/kernel/fs/devfs.c b/kernel/fs/devfs.c
index a3f13db..c25c996 100644
--- a/kernel/fs/devfs.c
+++ b/kernel/fs/devfs.c
@@ -84,7 +84,8 @@ void add_stdout(void) {
}
vfs_inode_t *devfs_mount(void) {
- vfs_inode_t *root = kmalloc(sizeof(vfs_inode_t));
+ vfs_inode_t *root = kcalloc(1, sizeof(vfs_inode_t));
+ root->ref++;
root->open = devfs_open;
root->read = devfs_read;
root->write = devfs_write;
diff --git a/kernel/fs/fifo.c b/kernel/fs/fifo.c
index a0a9248..5b01616 100644
--- a/kernel/fs/fifo.c
+++ b/kernel/fs/fifo.c
@@ -63,26 +63,6 @@ FIFO_FILE *create_fifo_object(void) {
return n;
}
-int create_fifo(void) {
-
- vfs_fd_t *fd = kmalloc(sizeof(vfs_fd_t));
- int fd_n;
- assert(list_add(&current_task->file_descriptors, fd, &fd_n));
-
- fd->flags = O_RDWR | O_NONBLOCK;
- fd->inode = kmalloc(sizeof(vfs_inode_t));
-
- fd->inode->internal_object = (void *)create_fifo_object();
- fd->inode->open = NULL;
- fd->inode->read = fifo_read;
- fd->inode->write = fifo_write;
- fd->inode->close = fifo_close;
- fd->inode->get_vm_object = NULL;
- fd->inode->is_open = 1;
-
- return fd_n;
-}
-
int fifo_write(u8 *buffer, u64 offset, u64 len, vfs_fd_t *fd) {
(void)offset;
FIFO_FILE *file = (FIFO_FILE *)fd->inode->internal_object;
diff --git a/kernel/fs/fifo.h b/kernel/fs/fifo.h
index 456b85d..450b9b5 100644
--- a/kernel/fs/fifo.h
+++ b/kernel/fs/fifo.h
@@ -14,7 +14,6 @@ struct S_FIFO_FILE {
u8 can_write;
};
-int create_fifo(void);
FIFO_FILE *create_fifo_object(void);
int fifo_object_write(u8 *buffer, u64 offset, u64 len, FIFO_FILE *file);
int fifo_object_read(u8 *buffer, u64 offset, u64 len, FIFO_FILE *file);
diff --git a/kernel/fs/tmpfs.c b/kernel/fs/tmpfs.c
index e31a08e..3ef774c 100644
--- a/kernel/fs/tmpfs.c
+++ b/kernel/fs/tmpfs.c
@@ -58,12 +58,15 @@ void dual_pipe(int fd[2]) {
vfs_create_fd(O_RDWR | O_NONBLOCK, 0, 0 /*is_tty*/, inode, &fd_ptrs[i]);
assert(-1 != fd[i]);
}
+
vfs_inode_t *f_inode = fd_ptrs[0]->inode;
vfs_inode_t *s_inode = fd_ptrs[1]->inode;
tmp_inode *f_pipe = f_inode->internal_object;
tmp_inode *s_pipe = s_inode->internal_object;
f_pipe->read_inode = s_inode;
+ s_inode->ref++;
s_pipe->read_inode = f_inode;
+ f_inode->ref++;
f_pipe->is_closed = 0;
s_pipe->is_closed = 0;
}
@@ -89,12 +92,15 @@ void pipe(int fd[2]) {
fd[i] = vfs_create_fd(O_RDWR, 0, 0 /*is_tty*/, inode, &fd_ptrs[i]);
assert(-1 != fd[i]);
}
+
vfs_inode_t *f_inode = fd_ptrs[0]->inode;
vfs_inode_t *s_inode = fd_ptrs[1]->inode;
tmp_inode *f_pipe = f_inode->internal_object;
tmp_inode *s_pipe = s_inode->internal_object;
f_pipe->read_inode = s_inode;
+ s_inode->ref++;
s_pipe->read_inode = f_inode;
+ f_inode->ref++;
f_pipe->is_closed = 0;
s_pipe->is_closed = 0;
}
diff --git a/kernel/fs/vfs.c b/kernel/fs/vfs.c
index bcc0ce5..a55f78c 100644
--- a/kernel/fs/vfs.c
+++ b/kernel/fs/vfs.c
@@ -55,7 +55,7 @@ vfs_inode_t *vfs_create_inode(
r->truncate = truncate;
r->stat = stat;
r->send_signal = send_signal;
- r->ref = 1;
+ r->ref = 0;
return r;
}
@@ -415,11 +415,13 @@ int vfs_dup2(int org_fd, int new_fd) {
assert(0);
return -1;
}
+ assert(1 <= orig->reference_count);
if (!list_set(&current_task->file_descriptors, new_fd, orig)) {
assert(0);
return -1;
}
orig->reference_count++;
+ assert(2 <= orig->reference_count);
return 1;
}
diff --git a/kernel/socket.c b/kernel/socket.c
index 589d99a..d24e39c 100644
--- a/kernel/socket.c
+++ b/kernel/socket.c
@@ -240,7 +240,8 @@ int uds_open(const char *path) {
s->ptr_socket_fd->inode->has_data = 1;
s->incoming_fd = get_vfs_fd(fd[1], NULL);
- // vfs_close(fd[1]);
+ s->incoming_fd->reference_count++;
+ vfs_close(fd[1]);
return fd[0];
}
@@ -263,7 +264,7 @@ int accept(int socket, struct sockaddr *address, socklen_t *address_len) {
int index;
assert(list_add(&current_task->file_descriptors, s->incoming_fd, &index));
- s->incoming_fd->reference_count++;
+ assert(1 <= s->incoming_fd->reference_count);
s->incoming_fd = NULL;
// for (char c; 0 < vfs_pread(s->fifo_fd, &c, 1, 0);)
// ;