Implement volume unmounting, collecting VFS volume info, usb Add eject command
All checks were successful
Build ISO image / build-and-deploy (push) Successful in 35s
Build documentation / build-and-deploy (push) Successful in 29s

This commit is contained in:
2026-04-07 21:17:49 +02:00
parent 2f186921d6
commit 7091b128df
15 changed files with 266 additions and 21 deletions

View File

@@ -39,5 +39,7 @@
#define SYS_STREAM_READ 36
#define SYS_GET_PROC_INFO 37
#define SYS_GET_DEVICE_INFO 38
#define SYS_GET_VOLUME_INFO 39
#define SYS_VOLUME_DELETE 40
#endif // _M_SYSCALL_DEFS_H

11
include/volume_info.h Normal file
View File

@@ -0,0 +1,11 @@
#ifndef _VOLUME_INFO_H
#define _VOLUME_INFO_H
#include <path_defs.h>
struct volume_info {
char volume_name[VOLUME_MAX];
char device_key[0x100];
};
#endif // _VOLUME_INFO_H

View File

@@ -7,6 +7,8 @@
int name (struct vfs_volume* UNUSED volume, struct proc* UNUSED proc, \
struct reschedule_ctx* UNUSED rctx, bool UNUSED format)
#define DEFINE_VFS_UNMOUNT(name) int name (struct vfs_volume* UNUSED volume)
#define DEFINE_VFS_FORMAT(name) \
int name (struct vfs_volume* UNUSED volume, struct proc* UNUSED proc, \
struct reschedule_ctx* UNUSED rctx)

View File

@@ -122,6 +122,14 @@ DEFINE_VFS_MOUNT (fatfs_mount) {
return ST_OK;
}
DEFINE_VFS_UNMOUNT (fatfs_unmount) {
struct fatfs_ctx* fatfs_ctx = volume->udata;
free (fatfs_ctx);
return ST_OK;
}
DEFINE_VFS_FORMAT (fatfs16_format) {
uint64_t fd;

View File

@@ -13,6 +13,8 @@ struct vfs_volume;
DEFINE_VFS_MOUNT (fatfs_mount);
DEFINE_VFS_UNMOUNT (fatfs_unmount);
DEFINE_VFS_FORMAT (fatfs16_format);
DEFINE_VFS_FORMAT (fatfs32_format);

View File

@@ -145,6 +145,14 @@ DEFINE_VFS_MOUNT (iso9660fs_mount) {
return ST_OK;
}
DEFINE_VFS_UNMOUNT (iso9660fs_unmount) {
l9660_fs* fs_ctx = volume->udata;
free (fs_ctx);
return ST_OK;
}
DEFINE_VFS_FORMAT (iso9660fs_format) { return -ST_FORMAT_ERROR; }
DEFINE_VFS_DESCRIBE (iso9660fs_describe) {

View File

@@ -13,6 +13,8 @@ struct vfs_volume;
DEFINE_VFS_MOUNT (iso9660fs_mount);
DEFINE_VFS_UNMOUNT (iso9660fs_unmount);
DEFINE_VFS_FORMAT (iso9660fs_format);
DEFINE_VFS_DESCRIBE (iso9660fs_describe);

View File

@@ -128,6 +128,14 @@ DEFINE_VFS_MOUNT (tarfs_mount) {
return ret;
}
DEFINE_VFS_UNMOUNT (tarfs_unmount) {
struct tarfs* tarfs = volume->udata;
free (tarfs);
return ST_OK;
}
DEFINE_VFS_FORMAT (tarfs_format) { return ST_OK; }
DEFINE_VFS_DESCRIBE (tarfs_describe) {

View File

@@ -37,6 +37,8 @@ struct vfs_volume;
DEFINE_VFS_MOUNT (tarfs_mount);
DEFINE_VFS_UNMOUNT (tarfs_unmount);
DEFINE_VFS_FORMAT (tarfs_format);
DEFINE_VFS_DESCRIBE (tarfs_describe);

View File

@@ -19,9 +19,46 @@
#include <status.h>
#include <sync/spin_lock.h>
#include <sys/debug.h>
#include <volume_info.h>
static struct vfs_volume_table volume_table;
size_t volume_populate_volume_infos (struct volume_info* infos, size_t count) {
uint64_t fvt, fv, fd;
if (count >= lengthof (volume_table.volume_buckets))
count = lengthof (volume_table.volume_buckets);
spin_lock (&volume_table.lock, &fvt);
size_t j = 0;
for (size_t i = 0; i < lengthof (volume_table.volume_buckets); i++) {
struct hash_node_link* hash_link = volume_table.volume_buckets[i];
while (hash_link != NULL && j < count) {
struct vfs_volume* volume = hash_entry (hash_link, struct vfs_volume, volume_table_link);
struct volume_info* info = &infos[j];
spin_lock (&volume->lock, &fv);
spin_lock (&volume->back_device->lock, &fd);
memcpy (info->volume_name, volume->key, sizeof (info->volume_name));
memcpy (info->device_key, volume->back_device->key, sizeof (info->device_key));
spin_unlock (&volume->back_device->lock, fd);
spin_unlock (&volume->lock, fv);
hash_link = hash_link->next;
j++;
}
}
spin_unlock (&volume_table.lock, fvt);
return j;
}
static struct vfs_volume* vfs_find_volume (const char* volume) {
uint64_t fvt;
@@ -62,6 +99,7 @@ int vfs_create_volume (struct proc* proc, struct reschedule_ctx* rctx, const cha
switch (volume->fs_type) {
case FS_TARFS:
volume->driver_ops.mount = &tarfs_mount;
volume->driver_ops.unmount = &tarfs_unmount;
volume->driver_ops.format = &tarfs_format;
volume->driver_ops.describe = &tarfs_describe;
volume->driver_ops.read_file = &tarfs_read_file;
@@ -73,6 +111,7 @@ int vfs_create_volume (struct proc* proc, struct reschedule_ctx* rctx, const cha
break;
case FS_FAT16:
volume->driver_ops.mount = &fatfs_mount;
volume->driver_ops.unmount = &fatfs_unmount;
volume->driver_ops.format = &fatfs16_format;
volume->driver_ops.describe = &fatfs_describe;
volume->driver_ops.read_file = &fatfs_read_file;
@@ -84,6 +123,7 @@ int vfs_create_volume (struct proc* proc, struct reschedule_ctx* rctx, const cha
break;
case FS_FAT32:
volume->driver_ops.mount = &fatfs_mount;
volume->driver_ops.unmount = &fatfs_unmount;
volume->driver_ops.format = &fatfs32_format;
volume->driver_ops.describe = &fatfs_describe;
volume->driver_ops.read_file = &fatfs_read_file;
@@ -95,6 +135,7 @@ int vfs_create_volume (struct proc* proc, struct reschedule_ctx* rctx, const cha
break;
case FS_ISO9660:
volume->driver_ops.mount = &iso9660fs_mount;
volume->driver_ops.unmount = &iso9660fs_unmount;
volume->driver_ops.format = &iso9660fs_format;
volume->driver_ops.describe = &iso9660fs_describe;
volume->driver_ops.read_file = &iso9660fs_read_file;
@@ -128,6 +169,52 @@ int vfs_create_volume (struct proc* proc, struct reschedule_ctx* rctx, const cha
return ST_OK;
}
int vfs_volume_delete (const char* key) {
uint64_t fv, fvt;
struct hash_node_link* found_link = NULL;
size_t key_len = strlen_null (key);
uint32_t hash = hash_fnv32 (key, key_len);
spin_lock (&volume_table.lock, &fvt);
hash_find (&volume_table, key, key_len, hash, lengthof (volume_table.volume_buckets),
volume_buckets, struct vfs_volume, volume_table_link, key, found_link);
if (found_link == NULL) {
spin_unlock (&volume_table.lock, fvt);
return -ST_NOT_FOUND;
}
struct vfs_volume* volume = hash_entry (found_link, struct vfs_volume, volume_table_link);
if (volume == NULL) {
spin_unlock (&volume_table.lock, fvt);
return -ST_NOT_FOUND;
}
spin_lock (&volume->lock, &fv);
if (volume->locked) {
spin_unlock (&volume->lock, fv);
spin_unlock (&volume_table.lock, fvt);
return -ST_TRY_AGAIN;
}
hash_delete (&volume_table, key, strlen_null (key), hash, lengthof (volume_table.volume_buckets),
volume_buckets, struct vfs_volume, volume_table_link, key, found_link);
int ret = volume->driver_ops.unmount (volume);
spin_unlock (&volume->lock, fv);
free (volume);
spin_unlock (&volume_table.lock, fvt);
return ret;
}
int vfs_volume_open (struct proc* proc, const char* volume_name, struct reschedule_ctx* rctx) {
uint64_t fv;

View File

@@ -15,6 +15,7 @@
#include <proc/reschedule.h>
#include <proc/suspension_q.h>
#include <sync/spin_lock.h>
#include <volume_info.h>
struct vfs_volume;
@@ -30,6 +31,8 @@ struct vfs_volume {
int (*mount) (struct vfs_volume* volume, struct proc* proc, struct reschedule_ctx* rctx,
bool format);
int (*unmount) (struct vfs_volume* volume);
int (*format) (struct vfs_volume* volume, struct proc* proc, struct reschedule_ctx* rctx);
int (*describe) (struct vfs_volume* volume, struct proc* proc, struct reschedule_ctx* rctx,
@@ -66,6 +69,8 @@ struct vfs_volume_table {
int vfs_create_volume (struct proc* proc, struct reschedule_ctx* rctx, const char* key, int fs_type,
struct device* back_device, bool format);
int vfs_volume_delete (const char* key);
int vfs_volume_open (struct proc* proc, const char* volume, struct reschedule_ctx* rctx);
int vfs_volume_close (struct proc* proc, const char* volume, struct reschedule_ctx* rctx);
@@ -98,4 +103,6 @@ void vfs_init (void);
void vfs_translate (size_t fs_block, size_t fs_block_count, size_t fs_block_size,
size_t device_sector_size, size_t* out_phys_sector, size_t* out_sector_count);
size_t volume_populate_volume_infos (struct volume_info* infos, size_t count);
#endif // _KERNEL_FS_VFS_H

View File

@@ -23,6 +23,7 @@
#include <sys/proc.h>
#include <syscall/syscall.h>
#include <syscall_defs.h>
#include <volume_info.h>
#include <write_file.h>
#define DEFINE_SYSCALL(name) \
@@ -1097,6 +1098,57 @@ DEFINE_SYSCALL (sys_get_device_info) {
return SYSRESULT (device_populate_device_infos (infos, infos_count));
}
/* int get_volume_info (struct volume_info* infos, size_t count) */
DEFINE_SYSCALL (sys_get_volume_info) {
uint64_t fp;
uintptr_t uvaddr_infos = a1;
size_t infos_count = (size_t)a2;
spin_lock (&proc->lock, &fp);
struct procgroup* procgroup = proc->procgroup;
spin_unlock (&proc->lock, fp);
struct volume_info* infos =
sys_get_user_buffer (procgroup, uvaddr_infos, infos_count * sizeof (struct volume_info));
if (infos == NULL)
return SYSRESULT (-ST_BAD_ADDRESS_SPACE);
return SYSRESULT (volume_populate_volume_infos (infos, infos_count));
}
/* int volume_delete (const char* volume) */
DEFINE_SYSCALL (sys_volume_delete) {
uint64_t fpg, fp;
uintptr_t uvaddr_volume = a1;
struct limine_hhdm_response* hhdm = limine_hhdm_request.response;
uintptr_t out_paddr;
spin_lock (&proc->lock, &fp);
struct procgroup* procgroup = proc->procgroup;
spin_unlock (&proc->lock, fp);
spin_lock (&procgroup->lock, &fpg);
out_paddr = mm_v2p (&procgroup->pd, uvaddr_volume);
spin_unlock (&procgroup->lock, fpg);
if (out_paddr == 0)
return SYSRESULT (-ST_BAD_ADDRESS_SPACE);
const char* volume = (const char*)((uintptr_t)hhdm->offset + out_paddr);
int ret = vfs_volume_delete (volume);
if (ret < 0)
return SYSRESULT (ret);
return SYSRESULT (ST_OK);
}
static syscall_handler_func_t handler_table[] = {
[SYS_QUIT] = &sys_quit,
[SYS_TEST] = &sys_test,
@@ -1136,6 +1188,8 @@ static syscall_handler_func_t handler_table[] = {
[SYS_STREAM_READ] = &sys_stream_read,
[SYS_GET_PROC_INFO] = &sys_get_proc_info,
[SYS_GET_DEVICE_INFO] = &sys_get_device_info,
[SYS_GET_VOLUME_INFO] = &sys_get_volume_info,
[SYS_VOLUME_DELETE] = &sys_volume_delete,
};
syscall_handler_func_t syscall_find_handler (int syscall_num) {

View File

@@ -118,3 +118,9 @@ int get_proc_info (struct proc_info* infos, size_t count) {
int get_device_info (struct device_info* infos, size_t count) {
return (int)do_syscall (SYS_GET_DEVICE_INFO, infos, count);
}
int get_volume_info (struct volume_info* infos, size_t count) {
return (int)do_syscall (SYS_GET_VOLUME_INFO, infos, count);
}
int volume_delete (const char* key) { return (int)do_syscall (SYS_VOLUME_DELETE, key); }

View File

@@ -7,6 +7,7 @@
#include <proc_info.h>
#include <stddef.h>
#include <stdint.h>
#include <volume_info.h>
/* Quit the current running process */
int quit (void);
@@ -122,4 +123,10 @@ int get_proc_info (struct proc_info* infos, size_t count);
/* get device information */
int get_device_info (struct device_info* infos, size_t count);
/* get volume information */
int get_volume_info (struct volume_info* infos, size_t count);
/* delete a volume */
int volume_delete (const char* key);
#endif // _LIBMSL_M_SYSTEM_H

View File

@@ -5,14 +5,68 @@
#include <process.h>
#include <process_self.h>
#include <status.h>
#include <str_status.h>
#include <string.h>
#include <system.h>
#include <volume_info.h>
static void usb_poll (void) {
struct device_info* infos = malloc (sizeof (struct device_info) * 1024);
memset (infos, 0, sizeof (struct device_info) * 1024);
int device_count = get_device_info (infos, 1024);
struct device_info info;
bool found = false;
for (int dev = 0; dev < device_count; dev++) {
info = infos[dev];
if (info.type == DEVICE_TYPE_USB_CTRL) {
found = true;
break;
}
}
if (found) {
mprintf ("Polling device %s\n", info.key);
for (;;) {
device_do (info.key, XUSBCTRL_POLL_DRIVER, NULL, NULL, NULL, NULL);
for (volatile int i = 0; i < 500; i++)
sched ();
}
}
free (infos);
}
static void usb_eject (const char* dev_key) {
struct volume_info* volume_infos = malloc (sizeof (*volume_infos) * 100);
memset (volume_infos, 0, sizeof (*volume_infos) * 100);
size_t count = get_volume_info (volume_infos, 100);
for (size_t i = 0; i < count; i++) {
struct volume_info* info = &volume_infos[i];
if (strcmp (info->device_key, dev_key) == 0) {
int ret = volume_delete (info->volume_name);
mprintf ("Deleted volume %s: %s", info->volume_name, str_status[ret < 0 ? -ret : ret]);
break;
}
}
free (volume_infos);
}
void app_main (void) {
libprocess_self_init ();
char commandbuf[32];
memset (commandbuf, 0, sizeof (commandbuf));
char devnamebuf[32];
memset (devnamebuf, 0, sizeof (devnamebuf));
if (env_get (process_get_pgid (), "C", (void*)commandbuf, sizeof (commandbuf)) != ST_OK) {
mprintf ("ERROR C=???. No command provided\n");
@@ -20,29 +74,14 @@ void app_main (void) {
}
if (strcmp (commandbuf, "poll") == 0) {
struct device_info* infos = malloc (sizeof (struct device_info) * 1024);
memset (infos, 0, sizeof (struct device_info) * 1024);
int device_count = get_device_info (infos, 1024);
for (int dev = 0; dev < device_count; dev++) {
struct device_info* info = &infos[dev];
if (info->type != DEVICE_TYPE_USB_CTRL) {
continue;
}
mprintf ("Polling device %s\n", info->key);
for (;;) {
device_do (info->key, XUSBCTRL_POLL_DRIVER, NULL, NULL, NULL, NULL);
for (volatile int i = 0; i < 500; i++)
sched ();
}
usb_poll ();
} else if (strcmp (commandbuf, "eject") == 0) {
if (env_get (process_get_pgid (), "dev", (void*)devnamebuf, sizeof (devnamebuf)) != ST_OK) {
mprintf ("ERROR No device provided\n");
return;
}
free (infos);
usb_eject (devnamebuf);
} else {
mprintf ("ERROR unknown command %s\n", commandbuf);
}