1 | // SPDX-License-Identifier: GPL-3.0-or-later |
2 | |
3 | #include "layer-gpt.hpp" |
4 | |
5 | #include "blockdev.h" |
6 | #include "gptdisk.hpp" |
7 | |
8 | #include <cstdlib> |
9 | #include <memory> |
10 | |
11 | using namespace std::string_literals; |
12 | |
13 | std::unique_ptr<BlockdevManagerStub> manager = nullptr; |
14 | |
15 | GPTLayerServer::GPTLayerServer(std::shared_ptr<GPTDisk> disk, const std::string &servername) : IBlockdevLayerService(servername), disk(disk) |
16 | { |
17 | const register_layer_server::request req = { |
18 | .server_name = strdup(string: servername.c_str()), |
19 | .partitions_count = disk->get_partition_count(), |
20 | .partitions = new mosrpc_blockdev_partition_info[disk->get_partition_count()], |
21 | }; |
22 | |
23 | for (size_t i = 0; i < disk->get_partition_count(); i++) |
24 | { |
25 | const auto devname = disk->name() + ".p" + std::to_string(val: i); // "virtblk.00:03:00.p1" |
26 | const auto partition = disk->get_partition(index: i); |
27 | req.partitions[i].name = strdup(string: devname.c_str()); |
28 | req.partitions[i].size = (partition.last_lba - partition.first_lba + 1) * disk->get_block_size(); |
29 | req.partitions[i].partid = i; |
30 | } |
31 | |
32 | register_layer_server::response resp; |
33 | const auto result = manager->register_layer_server(request: &req, response: &resp); |
34 | if (result != RPC_RESULT_OK || !resp.result.success) |
35 | throw std::runtime_error("Failed to register GPT layer server"s + (resp.result.error ? ": "s + resp.result.error : ""s )); |
36 | |
37 | free(pointer: req.server_name); |
38 | for (size_t i = 0; i < disk->get_partition_count(); i++) |
39 | free(pointer: req.partitions[i].name); |
40 | delete[] req.partitions; |
41 | } |
42 | |
43 | rpc_result_code_t GPTLayerServer::read_partition_block(rpc_context_t *context, mosrpc_blockdev_read_partition_block_request *req, read_block::response *resp) |
44 | { |
45 | MOS_UNUSED(context); |
46 | const auto datasize = req->n_blocks * disk->get_block_size(); |
47 | resp->data = (pb_bytes_array_t *) malloc(PB_BYTES_ARRAY_T_ALLOCSIZE(datasize)); |
48 | resp->data->size = datasize; |
49 | disk->read_partition_block(partition_index: req->partition.partid, blockoffset: req->n_boffset, buffer: resp->data->bytes, nblocks: req->n_blocks); |
50 | |
51 | resp->result.success = true; |
52 | resp->result.error = nullptr; |
53 | return RPC_RESULT_OK; |
54 | } |
55 | |
56 | rpc_result_code_t GPTLayerServer::write_partition_block(rpc_context_t *context, mosrpc_blockdev_write_partition_block_request *req, write_block::response *resp) |
57 | { |
58 | MOS_UNUSED(context); |
59 | MOS_UNUSED(resp); |
60 | disk->write_partition_block(partition_index: req->partition.partid, blockoffset: req->n_boffset, buffer: req->data->bytes, nblocks: req->n_blocks); |
61 | return RPC_RESULT_OK; |
62 | } |
63 | |