libfs: implement handling of lazy-attach cow-duplicate file mapping vmo
This commit is contained in:
+70
-16
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user