Skip to content

Commit

Permalink
vfs/userfs: support getpage()
Browse files Browse the repository at this point in the history
  • Loading branch information
moodyhunter committed Dec 22, 2023
1 parent 0ae97fc commit 891078d
Show file tree
Hide file tree
Showing 4 changed files with 91 additions and 2 deletions.
52 changes: 51 additions & 1 deletion kernel/filesystem/fs_server/fs_rpc.c
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// filesystem server RPCs
// userspace filesystems

#include "mos/filesystem/dentry.h"
#include "mos/filesystem/vfs.h"
#include "mos/filesystem/vfs_types.h"
#include "mos/filesystem/vfs_utils.h"
#include "mos/mm/mm.h"
#include "mos/mm/physical/pmm.h"
#include "mos/mm/slab_autoinit.h"
#include "mos/printk.h"
#include "mos/setup.h"
Expand Down Expand Up @@ -40,6 +42,7 @@ SLAB_AUTOINIT("userfs", userfs_slab, userfs_t);

static const inode_ops_t userfs_iops;
static const file_ops_t userfs_fops;
static const inode_cache_ops_t userfs_inode_cache_ops;

static inode_t *i_from_pb(const pb_inode *pbi, superblock_t *sb)
{
Expand Down Expand Up @@ -161,6 +164,7 @@ static bool userfs_iop_lookup(inode_t *dir, dentry_t *dentry)
dentry->inode = i;
dentry->superblock = i->superblock = dir->superblock;
i->ops = &userfs_iops;
i->cache.ops = &userfs_inode_cache_ops;
i->file_ops = &userfs_fops;
ret = true;

Expand Down Expand Up @@ -294,6 +298,52 @@ static const file_ops_t userfs_fops = {
.munmap = NULL,
};

static phyframe_t *userfs_inode_cache_fill_cache(inode_cache_t *cache, off_t pgoff)
{
// get a page from the server
userfs_t *userfs = container_of(cache->owner->superblock->fs, userfs_t, fs);
mos_rpc_fs_getpage_request req = { 0 };
i_to_pb(cache->owner, &req.inode);
req.pgoff = pgoff;

mos_rpc_fs_getpage_response resp = { 0 };
userfs_ensure_connected(userfs);
int result = fs_client_getpage(userfs->rpc_server, &req, &resp);
if (result != RPC_RESULT_OK)
{
pr_warn("userfs_inode_cache_fill_cache: failed to getpage %s: %d", dentry_name(cache->owner->superblock->root), result);
goto bail_out;
}

if (!resp.result.success)
{
pr_warn("userfs_inode_cache_fill_cache: failed to getpage %s: %s", dentry_name(cache->owner->superblock->root), resp.result.error);
goto bail_out;
}

// allocate a page
phyframe_t *page = pmm_ref_one(mm_get_free_page());
if (!page)
{
pr_warn("userfs_inode_cache_fill_cache: failed to allocate page");
goto bail_out;
}

// copy the data from the server
memcpy((void *) phyframe_va(page), resp.data->bytes, MIN(resp.data->size, MOS_PAGE_SIZE));
return page;

bail_out:
pb_release(mos_rpc_fs_getpage_response_fields, &resp);
return ERR_PTR(-EIO);
}

static const inode_cache_ops_t userfs_inode_cache_ops = {
.fill_cache = userfs_inode_cache_fill_cache,
.page_write_begin = NULL,
.page_write_end = NULL,
};

static dentry_t *userfs_fsop_mount(filesystem_t *fs, const char *device, const char *options)
{
userfs_t *userfs = container_of(fs, userfs_t, fs);
Expand Down
3 changes: 2 additions & 1 deletion kernel/include/public/mos/proto/fs_server.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,5 @@ RPC_DEFINE_ENUMS(fs_manager, FS_MANAGER, FS_MANAGER_X)
PB(xarg, 0, mount, MOUNT, mos_rpc_fs_mount_request, mos_rpc_fs_mount_response) \
PB(xarg, 1, readdir, READDIR, mos_rpc_fs_readdir_request, mos_rpc_fs_readdir_response) \
PB(xarg, 2, lookup, LOOKUP, mos_rpc_fs_lookup_request, mos_rpc_fs_lookup_response) \
PB(xarg, 3, readlink, READLINK, mos_rpc_fs_readlink_request, mos_rpc_fs_readlink_response)
PB(xarg, 3, readlink, READLINK, mos_rpc_fs_readlink_request, mos_rpc_fs_readlink_response) \
PB(xarg, 4, getpage, GETPAGE, mos_rpc_fs_getpage_request, mos_rpc_fs_getpage_response)
12 changes: 12 additions & 0 deletions proto/filesystem.proto
Original file line number Diff line number Diff line change
Expand Up @@ -122,3 +122,15 @@ message mos_rpc_fs_readlink_response
mos_rpc_result result = 1;
string target = 2; // the target of the symlink
}

message mos_rpc_fs_getpage_request
{
pb_inode inode = 1; // the inode of the file
uint64 pgoff = 2; // the offset of the page, in number of pages
}

message mos_rpc_fs_getpage_response
{
mos_rpc_result result = 1;
bytes data = 2; // the data of the page
}
26 changes: 26 additions & 0 deletions userspace/programs/init/bootstrapper/cpiofs_server.c
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,32 @@ static int cpiofs_readlink(rpc_server_t *server, mos_rpc_fs_readlink_request *re
return RPC_RESULT_OK;
}

static int cpiofs_getpage(rpc_server_t *server, mos_rpc_fs_getpage_request *req, mos_rpc_fs_getpage_response *resp, void *data)
{
MOS_UNUSED(server);
MOS_UNUSED(data);

cpio_inode_t *cpio_i = (cpio_inode_t *) req->inode.private_data;
const size_t bytes_to_read = MIN((size_t) MOS_PAGE_SIZE, cpio_i->pb_i.stat.size - req->pgoff * MOS_PAGE_SIZE);

resp->data = malloc(sizeof(pb_bytes_array_t) + bytes_to_read);
resp->data->size = bytes_to_read;

const size_t read = read_initrd(resp->data->bytes, bytes_to_read, cpio_i->data_offset + req->pgoff * MOS_PAGE_SIZE);
if (read != bytes_to_read)
{
puts("cpiofs_getpage: failed to read page");
resp->result.success = false;
resp->result.error = strdup("failed to read page");

free(resp->data);
return RPC_RESULT_OK;
}

resp->result.success = true;
return RPC_RESULT_OK;
}

void cpiofs_run_server()
{
cpiofs = rpc_server_create(CPIOFS_RPC_SERVER_NAME, NULL);
Expand Down

0 comments on commit 891078d

Please sign in to comment.