libfs: implement handling of lazy-attach cow-duplicate file mapping vmo

This commit is contained in:
2026-04-19 20:56:09 +01:00
parent 466af317b2
commit 5b996585d4
+70 -16
View File
@@ -197,9 +197,9 @@ static enum fs_status handle_msg(struct fs_context *ctx)
return FS_SUCCESS;
}
static enum fs_status handle_page_request_detach(
static enum fs_status handle_vm_request_detach(
struct fs_context *ctx,
equeue_packet_page_request_t *packet,
equeue_packet_vm_request_t *packet,
struct file_mapping *mapping)
{
if (!mapping) {
@@ -210,7 +210,7 @@ static enum fs_status handle_page_request_detach(
}
kern_tracef(
"received page request (detach) for file %s",
"received vm request (detach) for file %s",
mapping->m_file->f_dent->d_name);
struct fs_file *f = mapping->m_file;
@@ -229,16 +229,19 @@ static enum fs_status handle_page_request_detach(
return FS_SUCCESS;
}
static enum fs_status handle_page_request_read(
static enum fs_status handle_vm_request_read(
struct fs_context *ctx,
equeue_packet_page_request_t *packet,
equeue_packet_vm_request_t *packet,
struct file_mapping *mapping)
{
kern_tracef(
"received page request (read) [%zx-%zx] for file %s",
"received vm request (read) [%zx-%zx] for file %s",
packet->req_offset,
packet->req_offset + packet->req_length,
mapping->m_file->f_dent->d_name);
mapping ? mapping->m_file->f_dent->d_name : "NULL");
if (!mapping) {
return FS_ERR_INTERNAL_FAILURE;
}
size_t length = packet->req_length;
if (length > TEMP_OBJECT_SIZE) {
@@ -267,25 +270,76 @@ static enum fs_status handle_page_request_read(
return FS_SUCCESS;
}
static enum fs_status handle_page_request(struct fs_context *ctx)
static enum fs_status handle_vm_request_attach(
struct fs_context *ctx,
equeue_packet_vm_request_t *packet)
{
equeue_packet_page_request_t packet;
struct file_mapping *src_mapping
= (struct file_mapping *)packet->req_src_vmo;
kern_logf(
"received attach request [%zx] for cow-duplicate of %s",
packet->req_id,
src_mapping->m_file->f_dent->d_name);
if (src_mapping->m_type == FILE_MAPPING_SHARED) {
kern_logf("cannot attach another shared mapping to file");
return FS_ERR_INVALID_ARGUMENT;
}
kern_handle_t new_vmo = KERN_HANDLE_INVALID;
kern_status_t status = vm_controller_prepare_attach(
ctx->ctx_vm_controller,
packet->req_id,
&new_vmo);
if (status != KERN_OK) {
kern_logf("vm_controller_prepare_attach failed (%d)", status);
return FS_ERR_INTERNAL_FAILURE;
}
struct file_mapping *new_mapping
= fs_context_alloc(ctx, sizeof *new_mapping);
if (!new_mapping) {
return FS_ERR_NO_MEMORY;
}
memset(new_mapping, 0x0, sizeof *new_mapping);
new_mapping->m_vmo = new_vmo;
new_mapping->m_type = src_mapping->m_type;
new_mapping->m_file = src_mapping->m_file;
queue_push_back(
&new_mapping->m_file->f_mappings,
&new_mapping->m_entry);
vm_controller_finish_attach(
ctx->ctx_vm_controller,
packet->req_id,
(equeue_key_t)new_mapping);
return FS_SUCCESS;
}
static enum fs_status handle_vm_request(struct fs_context *ctx)
{
equeue_packet_vm_request_t packet;
kern_status_t status
= vm_controller_recv(ctx->ctx_vm_controller, &packet);
if (status != KERN_OK) {
return KERN_BAD_STATE;
return FS_ERR_INTERNAL_FAILURE;
}
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);
case VM_REQUEST_READ:
return handle_vm_request_read(ctx, &packet, mapping);
case VM_REQUEST_DETACH:
return handle_vm_request_detach(ctx, &packet, mapping);
case VM_REQUEST_ATTACH:
return handle_vm_request_attach(ctx, &packet);
default:
kern_logf("unknown page request type %zx", packet.req_type);
kern_logf("unknown vm request type %zx", packet.req_type);
break;
}
return FS_SUCCESS;
@@ -315,7 +369,7 @@ enum fs_status fs_context_handle_request(struct fs_context *ctx)
}
if (waiters[1].w_observed & VM_CONTROLLER_SIGNAL_REQUEST_RECEIVED) {
return handle_page_request(ctx);
return handle_vm_request(ctx);
}
return FS_SUCCESS;