diff --git a/lib/libfs/context.c b/lib/libfs/context.c index db9823c..87a0597 100644 --- a/lib/libfs/context.c +++ b/lib/libfs/context.c @@ -197,20 +197,20 @@ 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) { kern_logf( "received DETACH request from VMO with no associated " - "mapping"); + "mapping"); return FS_ERR_INTERNAL_FAILURE; } 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;