lib: fs: implement file cleanup using disconnect and detach events

This commit is contained in:
2026-03-24 20:25:13 +00:00
parent dade9fa81f
commit 329829c0e9
4 changed files with 102 additions and 12 deletions

View File

@@ -141,6 +141,28 @@ kern_handle_t fs_context_get_vm_controller(const struct fs_context *ctx)
return ctx->ctx_vm_controller;
}
static enum fs_status handle_event(struct fs_context *ctx, xpc_msg_t *msg)
{
switch (msg->msg_event) {
case KERN_MSG_EVENT_CONNECTION:
kern_logf("received connection");
break;
case KERN_MSG_EVENT_DISCONNECTION: {
struct fs_file *f
= fs_context_get_file(ctx, msg->msg_sender.e_port);
if (f) {
fs_context_close_file(ctx, f);
}
break;
}
default:
kern_logf("received unknown event");
break;
}
return FS_SUCCESS;
}
static enum fs_status handle_msg(struct fs_context *ctx)
{
xpc_msg_t msg;
@@ -154,6 +176,10 @@ static enum fs_status handle_msg(struct fs_context *ctx)
return FS_ERR_INTERNAL_FAILURE;
}
if (msg.msg_type != KERN_MSG_TYPE_DATA) {
return handle_event(ctx, &msg);
}
switch (msg.msg_header.hdr_interface) {
case INTERFACE_FS:
status = fs_context_dispatch_msg(ctx, &msg);
@@ -169,18 +195,43 @@ static enum fs_status handle_msg(struct fs_context *ctx)
return FS_SUCCESS;
}
static enum fs_status handle_page_request(struct fs_context *ctx)
static enum fs_status handle_page_request_detach(
struct fs_context *ctx,
equeue_packet_page_request_t *packet,
struct file_mapping *mapping)
{
equeue_packet_page_request_t packet;
vm_controller_recv(ctx->ctx_vm_controller, &packet);
struct file_mapping *mapping = (struct file_mapping *)packet.req_vmo;
kern_tracef(
"received page request [%zx-%zx] for file %s",
packet.req_offset,
packet.req_offset + packet.req_length,
kern_logf(
"received page request (detach) for file %s",
mapping->m_file->f_dent->d_name);
size_t length = packet.req_length;
struct fs_file *f = mapping->m_file;
switch (mapping->m_type) {
case FILE_MAPPING_PRIVATE:
queue_delete(&f->f_mappings, &mapping->m_entry);
break;
default:
break;
}
kern_handle_close(mapping->m_vmo);
fs_context_free(ctx, mapping);
fs_context_close_file(ctx, f);
return FS_SUCCESS;
}
static enum fs_status handle_page_request_read(
struct fs_context *ctx,
equeue_packet_page_request_t *packet,
struct file_mapping *mapping)
{
kern_tracef(
"received page request (read) [%zx-%zx] for file %s",
packet->req_offset,
packet->req_offset + packet->req_length,
mapping->m_file->f_dent->d_name);
size_t length = packet->req_length;
if (length > TEMP_OBJECT_SIZE) {
length = TEMP_OBJECT_SIZE;
}
@@ -190,7 +241,7 @@ static enum fs_status handle_page_request(struct fs_context *ctx)
enum fs_status status = fs_file_read_at(
mapping->m_file,
&buf,
packet.req_offset,
packet->req_offset,
length);
if (status != FS_SUCCESS) {
kern_tracef("map-read failed with code %d", status);
@@ -200,10 +251,34 @@ static enum fs_status handle_page_request(struct fs_context *ctx)
vm_controller_supply_pages(
ctx->ctx_vm_controller,
mapping->m_vmo,
packet.req_offset,
packet->req_offset,
ctx->ctx_temp_object,
0,
packet.req_length);
packet->req_length);
return FS_SUCCESS;
}
static enum fs_status handle_page_request(struct fs_context *ctx)
{
equeue_packet_page_request_t packet;
kern_status_t status
= vm_controller_recv(ctx->ctx_vm_controller, &packet);
if (status != KERN_OK) {
return KERN_BAD_STATE;
}
struct file_mapping *mapping = (struct file_mapping *)packet.req_vmo;
switch (packet.req_type) {
case PAGE_REQUEST_READ:
return handle_page_request_read(ctx, &packet, mapping);
case PAGE_REQUEST_DETACH:
return handle_page_request_detach(ctx, &packet, mapping);
default:
kern_logf("unknown page request type %zx", packet.req_type);
break;
}
return FS_SUCCESS;
}
@@ -262,6 +337,16 @@ struct fs_file *fs_context_get_file(struct fs_context *ctx, unsigned long id)
void fs_context_close_file(struct fs_context *ctx, struct fs_file *f)
{
if (f->f_ref > 1) {
kern_logf(
"reference to file '%s' has been closed",
f->f_dent->d_name);
f->f_ref--;
return;
}
kern_logf("file '%s' has been closed", f->f_dent->d_name);
btree_delete(&ctx->ctx_filelist, &f->f_node);
}
static size_t get_first_path_component(const char *in, char *out, size_t max)