1 | // SPDX-License-Identifier: GPL-3.0-or-later |
2 | |
3 | #include "blockdev.h" |
4 | #include "proto/blockdev.services.h" |
5 | #include "ramdisk.hpp" |
6 | |
7 | #include <iostream> |
8 | #include <librpc/macro_magic.h> |
9 | #include <librpc/rpc_client.h> |
10 | #include <librpc/rpc_server++.hpp> |
11 | #include <librpc/rpc_server.h> |
12 | #include <memory> |
13 | #include <mos/mos_global.h> |
14 | #include <pb_decode.h> |
15 | #include <pb_encode.h> |
16 | |
17 | class RAMDiskServer |
18 | : public IBlockdevDeviceService |
19 | , public RAMDisk |
20 | { |
21 | public: |
22 | explicit RAMDiskServer(const std::string &servername, const size_t nbytes) : IBlockdevDeviceService(servername), RAMDisk(nbytes) |
23 | { |
24 | } |
25 | |
26 | rpc_result_code_t read_block(rpc_context_t *, mosrpc_blockdev_read_block_request *req, mosrpc_blockdev_read_block_response *resp) override |
27 | { |
28 | if (req->n_boffset + req->n_blocks > nblocks()) |
29 | { |
30 | resp->result.success = false; |
31 | resp->result.error = strdup(string: "Out of bounds" ); |
32 | return RPC_RESULT_OK; |
33 | } |
34 | |
35 | resp->data = (pb_bytes_array_t *) malloc(PB_BYTES_ARRAY_T_ALLOCSIZE(req->n_blocks * block_size())); |
36 | const auto read = RAMDisk::read_block(block: req->n_boffset, nblocks: req->n_blocks, buf: resp->data->bytes); |
37 | resp->data->size = read * block_size(); |
38 | |
39 | resp->result.success = true; |
40 | resp->result.error = nullptr; |
41 | |
42 | return RPC_RESULT_OK; |
43 | } |
44 | |
45 | rpc_result_code_t write_block(rpc_context_t *, mosrpc_blockdev_write_block_request *req, mosrpc_blockdev_write_block_response *resp) override |
46 | { |
47 | RAMDisk::write_block(block: req->n_boffset, nblocks: req->n_blocks, buf: req->data->bytes); |
48 | |
49 | resp->result.success = true; |
50 | resp->result.error = nullptr; |
51 | |
52 | resp->n_blocks = req->n_blocks; |
53 | |
54 | return RPC_RESULT_OK; |
55 | } |
56 | }; |
57 | |
58 | int main(int argc, char **argv) |
59 | { |
60 | std::cout << "RAMDisk for MOS" << std::endl; |
61 | |
62 | std::string blockdev_name; |
63 | size_t size = 0; |
64 | |
65 | const auto get_size = [](const char *str) -> size_t |
66 | { |
67 | size_t size = 0; |
68 | if (sscanf(buffer: str, format: "%zu" , &size) != 1) |
69 | std::cerr << "Invalid size" << std::endl, exit(status: 1); |
70 | |
71 | if (strstr(pattern: str, s: "K" )) |
72 | size *= 1 KB; |
73 | else if (strstr(pattern: str, s: "M" )) |
74 | size *= 1 MB; |
75 | else if (strstr(pattern: str, s: "G" )) |
76 | size *= 1 GB; |
77 | |
78 | return size; |
79 | }; |
80 | |
81 | switch (argc) |
82 | { |
83 | case 1: blockdev_name = "ramdisk" , size = 1 MB; break; |
84 | case 2: |
85 | { |
86 | size = get_size(argv[1]); |
87 | blockdev_name = "ramdisk" ; |
88 | break; |
89 | } |
90 | case 3: |
91 | { |
92 | size = get_size(argv[1]); |
93 | blockdev_name = argv[2]; |
94 | break; |
95 | } |
96 | default: |
97 | { |
98 | std::cerr << "Usage: " << argv[0] << " <size> [name]" << std::endl; |
99 | std::cerr << " " << argv[0] << " 1024" << std::endl; |
100 | std::cerr << " " << argv[0] << " 1M my_disk" << std::endl; |
101 | std::cerr << " " << argv[0] << " 5G my_disk2" << std::endl; |
102 | return 1; |
103 | } |
104 | } |
105 | |
106 | RAMDiskServer ramdisk_server("ramdisk." + blockdev_name, size); |
107 | |
108 | const auto blockdev_manager = std::make_unique<BlockdevManagerStub>(BLOCKDEV_MANAGER_RPC_SERVER_NAME); |
109 | |
110 | mosrpc_blockdev_register_device_request req{ .server_name = strdup(string: ramdisk_server.get_name().c_str()), |
111 | .device_info = { |
112 | .name = strdup(string: blockdev_name.c_str()), |
113 | .size = ramdisk_server.nblocks() * ramdisk_server.block_size(), |
114 | .block_size = ramdisk_server.block_size(), |
115 | .n_blocks = ramdisk_server.nblocks(), |
116 | } }; |
117 | mosrpc_blockdev_register_device_response resp; |
118 | blockdev_manager->register_device(request: &req, response: &resp); |
119 | if (!resp.result.success) |
120 | { |
121 | if (!resp.result.error) |
122 | { |
123 | std::cerr << "Failed to register blockdev: unknown error" << std::endl; |
124 | return -1; |
125 | } |
126 | |
127 | std::cerr << "Failed to register blockdev: " << resp.result.error << std::endl; |
128 | return -1; |
129 | } |
130 | |
131 | // int ret = resp.id; |
132 | ramdisk_server.run(); |
133 | std::cout << "RAMDisk server terminated" << std::endl; |
134 | return 0; |
135 | } |
136 | |