lib: fs: implement private and shared file mappings
This commit is contained in:
@@ -2,12 +2,14 @@
|
|||||||
#define FS_INODE_H_
|
#define FS_INODE_H_
|
||||||
|
|
||||||
#include <fs/status.h>
|
#include <fs/status.h>
|
||||||
|
#include <mango/types.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
|
||||||
struct fs_inode;
|
struct fs_inode;
|
||||||
struct fs_dentry;
|
struct fs_dentry;
|
||||||
struct fs_superblock;
|
struct fs_superblock;
|
||||||
struct fs_file_ops;
|
struct fs_file_ops;
|
||||||
|
struct file_mapping;
|
||||||
|
|
||||||
enum fs_inode_mode {
|
enum fs_inode_mode {
|
||||||
FS_INODE_REG = 0x01u,
|
FS_INODE_REG = 0x01u,
|
||||||
@@ -27,6 +29,7 @@ struct fs_inode {
|
|||||||
const struct fs_inode_ops *i_ops;
|
const struct fs_inode_ops *i_ops;
|
||||||
const struct fs_file_ops *i_fops;
|
const struct fs_file_ops *i_fops;
|
||||||
size_t i_size;
|
size_t i_size;
|
||||||
|
struct file_mapping *i_shared_mapping;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern enum fs_status fs_inode_lookup(
|
extern enum fs_status fs_inode_lookup(
|
||||||
|
|||||||
@@ -11,29 +11,25 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
|
|
||||||
extern kern_status_t fs_msg_map(
|
static int create_file_mapping(
|
||||||
xpc_context_t *xpc,
|
struct fs_context *ctx,
|
||||||
const xpc_endpoint_t *sender,
|
|
||||||
int prot,
|
int prot,
|
||||||
int flags,
|
int flags,
|
||||||
int *out_err,
|
struct fs_file *f,
|
||||||
kern_handle_t *out_vmo,
|
struct file_mapping **out)
|
||||||
void *arg)
|
|
||||||
{
|
{
|
||||||
struct fs_context *ctx = arg;
|
if ((flags & MAP_SHARED) && f->f_inode->i_shared_mapping) {
|
||||||
struct fs_file *f = fs_context_get_file(ctx, sender->e_port);
|
*out = f->f_inode->i_shared_mapping;
|
||||||
if (!f) {
|
return SUCCESS;
|
||||||
*out_err = EBADF;
|
|
||||||
return KERN_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct file_mapping *mapping = fs_context_alloc(ctx, sizeof *mapping);
|
struct file_mapping *mapping = fs_context_alloc(ctx, sizeof *mapping);
|
||||||
if (!mapping) {
|
if (!mapping) {
|
||||||
*out_err = ENOMEM;
|
return ENOMEM;
|
||||||
return KERN_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
kern_logf("mapping file %s", f->f_dent->d_name);
|
memset(mapping, 0x0, sizeof *mapping);
|
||||||
|
|
||||||
vm_prot_t vm_prot = VM_PROT_USER;
|
vm_prot_t vm_prot = VM_PROT_USER;
|
||||||
if (prot & PROT_READ) {
|
if (prot & PROT_READ) {
|
||||||
vm_prot |= VM_PROT_READ;
|
vm_prot |= VM_PROT_READ;
|
||||||
@@ -59,14 +55,56 @@ extern kern_status_t fs_msg_map(
|
|||||||
|
|
||||||
if (status != KERN_OK) {
|
if (status != KERN_OK) {
|
||||||
fs_context_free(ctx, mapping);
|
fs_context_free(ctx, mapping);
|
||||||
*out_err = __errno_from_kern_status(status);
|
return __errno_from_kern_status(status);
|
||||||
return KERN_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mapping->m_file = f;
|
mapping->m_file = f;
|
||||||
mapping->m_file_offset = 0;
|
mapping->m_vmo = vmo;
|
||||||
kern_handle_duplicate(vmo, &mapping->m_vmo);
|
|
||||||
queue_push_back(&f->f_mappings, &mapping->m_entry);
|
if (flags & MAP_SHARED) {
|
||||||
|
mapping->m_type = FILE_MAPPING_SHARED;
|
||||||
|
f->f_inode->i_shared_mapping = mapping;
|
||||||
|
} else {
|
||||||
|
mapping->m_type = FILE_MAPPING_PRIVATE;
|
||||||
|
queue_push_back(&f->f_mappings, &mapping->m_entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
*out = mapping;
|
||||||
|
|
||||||
|
return SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern kern_status_t fs_msg_map(
|
||||||
|
xpc_context_t *xpc,
|
||||||
|
const xpc_endpoint_t *sender,
|
||||||
|
int prot,
|
||||||
|
int flags,
|
||||||
|
int *out_err,
|
||||||
|
kern_handle_t *out_vmo,
|
||||||
|
void *arg)
|
||||||
|
{
|
||||||
|
struct fs_context *ctx = arg;
|
||||||
|
struct fs_file *f = fs_context_get_file(ctx, sender->e_port);
|
||||||
|
if (!f) {
|
||||||
|
*out_err = EBADF;
|
||||||
|
return KERN_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct file_mapping *mapping = NULL;
|
||||||
|
int err = create_file_mapping(ctx, prot, flags, f, &mapping);
|
||||||
|
if (err != SUCCESS) {
|
||||||
|
*out_err = err;
|
||||||
|
return KERN_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
kern_tracef(
|
||||||
|
"mapping file %s (%s) using vmo %zx",
|
||||||
|
f->f_dent->d_name,
|
||||||
|
(flags & MAP_SHARED) ? "shared" : "private",
|
||||||
|
mapping->m_vmo);
|
||||||
|
|
||||||
|
kern_handle_t vmo;
|
||||||
|
kern_handle_duplicate(mapping->m_vmo, &vmo);
|
||||||
|
|
||||||
*out_err = SUCCESS;
|
*out_err = SUCCESS;
|
||||||
*out_vmo = vmo;
|
*out_vmo = vmo;
|
||||||
|
|||||||
@@ -7,10 +7,15 @@
|
|||||||
|
|
||||||
struct fs_file;
|
struct fs_file;
|
||||||
|
|
||||||
|
enum file_mapping_type {
|
||||||
|
FILE_MAPPING_PRIVATE,
|
||||||
|
FILE_MAPPING_SHARED,
|
||||||
|
};
|
||||||
|
|
||||||
struct file_mapping {
|
struct file_mapping {
|
||||||
|
enum file_mapping_type m_type;
|
||||||
struct fs_file *m_file;
|
struct fs_file *m_file;
|
||||||
kern_handle_t m_vmo;
|
kern_handle_t m_vmo;
|
||||||
off_t m_file_offset;
|
|
||||||
struct queue_entry m_entry;
|
struct queue_entry m_entry;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user