1// SPDX-License-Identifier: GPL-3.0-or-later
2
3#pragma once
4
5#include "ext4.h"
6#include "ext4_blockdev.h"
7#include "ext4_types.h"
8#include "proto/blockdev.pb.h"
9#include "proto/blockdev.services.h"
10#include "proto/filesystem.pb.h"
11#include "proto/filesystem.services.h"
12#include "proto/userfs-manager.services.h"
13
14#include <librpc/macro_magic.h>
15#include <librpc/rpc.h>
16#include <librpc/rpc_client.h>
17#include <librpc/rpc_server++.hpp>
18#include <memory>
19#include <mos/filesystem/fs_types.h>
20#include <mos/proto/fs_server.h>
21#include <pb_decode.h>
22
23using namespace std::string_literals;
24
25extern std::unique_ptr<UserFSManagerStub> userfs_manager;
26extern std::unique_ptr<BlockdevManagerStub> blockdev_manager;
27
28struct ext4_context_state
29{
30 mosrpc_blockdev_blockdev blockdev;
31
32 uint8_t ext4_buf[512] = { 0 };
33 ext4_blockdev_iface ext4_dev_iface;
34 ext4_blockdev ext4_dev;
35 ext4_fs *fs;
36 ext4_mountpoint *mp;
37};
38
39class Ext4UserFS : public IUserFSService
40{
41 public:
42 explicit Ext4UserFS(const std::string &name);
43
44 private:
45 virtual void on_connect(rpc_context_t *ctx) override;
46
47 virtual void on_disconnect(rpc_context_t *ctx) override;
48
49 private:
50 template<typename T>
51 static file_type_t ext4_get_file_type(ext4_sblock *sb, T *dentry_or_inode)
52 {
53 if constexpr (std::is_same_v<T, ext4_dir_en>)
54 {
55 const auto type = ext4_dir_en_get_inode_type(sb, dentry_or_inode);
56 switch (type)
57 {
58 case EXT4_DE_FIFO: return FILE_TYPE_NAMED_PIPE;
59 case EXT4_DE_CHRDEV: return FILE_TYPE_CHAR_DEVICE;
60 case EXT4_DE_DIR: return FILE_TYPE_DIRECTORY;
61 case EXT4_DE_BLKDEV: return FILE_TYPE_BLOCK_DEVICE;
62 case EXT4_DE_REG_FILE: return FILE_TYPE_REGULAR;
63 case EXT4_DE_SYMLINK: return FILE_TYPE_SYMLINK;
64 case EXT4_DE_SOCK: return FILE_TYPE_SOCKET;
65 case EXT4_DE_UNKNOWN: return FILE_TYPE_UNKNOWN;
66 default: return FILE_TYPE_UNKNOWN;
67 }
68 }
69 else if constexpr (std::is_same_v<T, ext4_inode>)
70 {
71 const auto type = ext4_inode_type(sb, dentry_or_inode);
72 switch (type)
73 {
74 case EXT4_INODE_MODE_FIFO: return FILE_TYPE_NAMED_PIPE;
75 case EXT4_INODE_MODE_CHARDEV: return FILE_TYPE_CHAR_DEVICE;
76 case EXT4_INODE_MODE_DIRECTORY: return FILE_TYPE_DIRECTORY;
77 case EXT4_INODE_MODE_BLOCKDEV: return FILE_TYPE_BLOCK_DEVICE;
78 case EXT4_INODE_MODE_FILE: return FILE_TYPE_REGULAR;
79 case EXT4_INODE_MODE_SOFTLINK: return FILE_TYPE_SYMLINK;
80 case EXT4_INODE_MODE_SOCKET: return FILE_TYPE_SOCKET;
81 default: return FILE_TYPE_UNKNOWN;
82 }
83 }
84 else
85 {
86 static_assert(false, "Invalid type");
87 }
88 };
89
90 static void populate_mosrpc_fs_inode_info(mosrpc_fs_inode_info &info, ext4_sblock *sb, ext4_inode *inode, int ino);
91 static void save_inode_info(ext4_sblock *sb, ext4_inode *inode, const mosrpc_fs_inode_info &info);
92
93 private:
94 virtual rpc_result_code_t mount(rpc_context_t *ctx, mosrpc_fs_mount_request *req, mosrpc_fs_mount_response *resp) override;
95
96 virtual rpc_result_code_t readdir(rpc_context_t *ctx, mosrpc_fs_readdir_request *req, mosrpc_fs_readdir_response *resp) override;
97
98 virtual rpc_result_code_t lookup(rpc_context_t *ctx, mosrpc_fs_lookup_request *req, mosrpc_fs_lookup_response *resp) override;
99
100 virtual rpc_result_code_t readlink(rpc_context_t *ctx, mosrpc_fs_readlink_request *req, mosrpc_fs_readlink_response *resp) override;
101
102 virtual rpc_result_code_t get_page(rpc_context_t *ctx, mosrpc_fs_getpage_request *req, mosrpc_fs_getpage_response *resp) override;
103
104 virtual rpc_result_code_t create_file(rpc_context_t *ctx, mosrpc_fs_create_file_request *req, mosrpc_fs_create_file_response *resp) override;
105
106 virtual rpc_result_code_t put_page(rpc_context_t *ctx, mosrpc_fs_putpage_request *req, mosrpc_fs_putpage_response *resp) override;
107
108 virtual rpc_result_code_t sync_inode(rpc_context_t *ctx, mosrpc_fs_sync_inode_request *req, mosrpc_fs_sync_inode_response *resp) override;
109
110 virtual rpc_result_code_t unlink(rpc_context_t *ctx, mosrpc_fs_unlink_request *req, mosrpc_fs_unlink_response *resp) override;
111
112 virtual rpc_result_code_t make_dir(rpc_context_t *ctx, mosrpc_fs_make_dir_request *req, mosrpc_fs_make_dir_response *resp) override;
113};
114