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;
|
return FS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static enum fs_status handle_page_request_detach(
|
static enum fs_status handle_vm_request_detach(
|
||||||
struct fs_context *ctx,
|
struct fs_context *ctx,
|
||||||
equeue_packet_page_request_t *packet,
|
equeue_packet_vm_request_t *packet,
|
||||||
struct file_mapping *mapping)
|
struct file_mapping *mapping)
|
||||||
{
|
{
|
||||||
if (!mapping) {
|
if (!mapping) {
|
||||||
@@ -210,7 +210,7 @@ static enum fs_status handle_page_request_detach(
|
|||||||
}
|
}
|
||||||
|
|
||||||
kern_tracef(
|
kern_tracef(
|
||||||
"received page request (detach) for file %s",
|
"received vm request (detach) for file %s",
|
||||||
mapping->m_file->f_dent->d_name);
|
mapping->m_file->f_dent->d_name);
|
||||||
|
|
||||||
struct fs_file *f = mapping->m_file;
|
struct fs_file *f = mapping->m_file;
|
||||||
@@ -229,16 +229,19 @@ static enum fs_status handle_page_request_detach(
|
|||||||
return FS_SUCCESS;
|
return FS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static enum fs_status handle_page_request_read(
|
static enum fs_status handle_vm_request_read(
|
||||||
struct fs_context *ctx,
|
struct fs_context *ctx,
|
||||||
equeue_packet_page_request_t *packet,
|
equeue_packet_vm_request_t *packet,
|
||||||
struct file_mapping *mapping)
|
struct file_mapping *mapping)
|
||||||
{
|
{
|
||||||
kern_tracef(
|
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_offset + packet->req_length,
|
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;
|
size_t length = packet->req_length;
|
||||||
if (length > TEMP_OBJECT_SIZE) {
|
if (length > TEMP_OBJECT_SIZE) {
|
||||||
@@ -267,25 +270,76 @@ static enum fs_status handle_page_request_read(
|
|||||||
return FS_SUCCESS;
|
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
|
kern_status_t status
|
||||||
= vm_controller_recv(ctx->ctx_vm_controller, &packet);
|
= vm_controller_recv(ctx->ctx_vm_controller, &packet);
|
||||||
|
|
||||||
if (status != KERN_OK) {
|
if (status != KERN_OK) {
|
||||||
return KERN_BAD_STATE;
|
return FS_ERR_INTERNAL_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct file_mapping *mapping = (struct file_mapping *)packet.req_vmo;
|
struct file_mapping *mapping = (struct file_mapping *)packet.req_vmo;
|
||||||
|
|
||||||
switch (packet.req_type) {
|
switch (packet.req_type) {
|
||||||
case PAGE_REQUEST_READ:
|
case VM_REQUEST_READ:
|
||||||
return handle_page_request_read(ctx, &packet, mapping);
|
return handle_vm_request_read(ctx, &packet, mapping);
|
||||||
case PAGE_REQUEST_DETACH:
|
case VM_REQUEST_DETACH:
|
||||||
return handle_page_request_detach(ctx, &packet, mapping);
|
return handle_vm_request_detach(ctx, &packet, mapping);
|
||||||
|
case VM_REQUEST_ATTACH:
|
||||||
|
return handle_vm_request_attach(ctx, &packet);
|
||||||
default:
|
default:
|
||||||
kern_logf("unknown page request type %zx", packet.req_type);
|
kern_logf("unknown vm request type %zx", packet.req_type);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return FS_SUCCESS;
|
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) {
|
if (waiters[1].w_observed & VM_CONTROLLER_SIGNAL_REQUEST_RECEIVED) {
|
||||||
return handle_page_request(ctx);
|
return handle_vm_request(ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
return FS_SUCCESS;
|
return FS_SUCCESS;
|
||||||
|
|||||||
Reference in New Issue
Block a user