source: mainline/uspace/srv/bd/vbd/vbd.c

Last change on this file was ca48672, checked in by Jiri Svoboda <jiri@…>, 4 weeks ago

loc_service_register() needs to take a port ID argument.

  • Property mode set to 100644
File size: 9.6 KB
Line 
1/*
2 * Copyright (c) 2025 Jiri Svoboda
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup vbd
30 * @{
31 */
32/**
33 * @file
34 */
35
36#include <async.h>
37#include <errno.h>
38#include <str_error.h>
39#include <io/log.h>
40#include <ipc/services.h>
41#include <ipc/vbd.h>
42#include <label/label.h>
43#include <loc.h>
44#include <macros.h>
45#include <stdio.h>
46#include <stdlib.h>
47#include <task.h>
48#include <vbd.h>
49
50#include "disk.h"
51#include "types/vbd.h"
52
53#define NAME "vbd"
54
55static void vbds_client_conn(ipc_call_t *, void *);
56
57static service_id_t ctl_sid;
58
59static errno_t vbds_init(void)
60{
61 errno_t rc;
62 log_msg(LOG_DEFAULT, LVL_DEBUG, "vbds_init()");
63
64 rc = vbds_disks_init();
65 if (rc != EOK)
66 return rc;
67
68 async_set_fallback_port_handler(vbds_client_conn, NULL);
69
70 rc = loc_server_register(NAME, &vbds_srv);
71 if (rc != EOK) {
72 log_msg(LOG_DEFAULT, LVL_ERROR, "Failed registering server: %s.", str_error(rc));
73 return EEXIST;
74 }
75
76 rc = loc_service_register(vbds_srv, SERVICE_NAME_VBD,
77 fallback_port_id, &ctl_sid);
78 if (rc != EOK) {
79 log_msg(LOG_DEFAULT, LVL_ERROR, "Failed registering service: %s.", str_error(rc));
80 return EEXIST;
81 }
82
83 rc = vbds_disk_discovery_start();
84 if (rc != EOK)
85 return rc;
86
87 return EOK;
88}
89
90static void vbds_get_disks_srv(ipc_call_t *icall)
91{
92 ipc_call_t call;
93 size_t size;
94 size_t act_size;
95 errno_t rc;
96
97 if (!async_data_read_receive(&call, &size)) {
98 async_answer_0(&call, EREFUSED);
99 async_answer_0(icall, EREFUSED);
100 return;
101 }
102
103 service_id_t *id_buf = (service_id_t *) malloc(size);
104 if (id_buf == NULL) {
105 async_answer_0(&call, ENOMEM);
106 async_answer_0(icall, ENOMEM);
107 return;
108 }
109
110 rc = vbds_disk_get_ids(id_buf, size, &act_size);
111 if (rc != EOK) {
112 free(id_buf);
113 async_answer_0(&call, rc);
114 async_answer_0(icall, rc);
115 return;
116 }
117
118 errno_t retval = async_data_read_finalize(&call, id_buf, size);
119 free(id_buf);
120
121 async_answer_1(icall, retval, act_size);
122}
123
124static void vbds_disk_info_srv(ipc_call_t *icall)
125{
126 service_id_t disk_sid;
127 vbd_disk_info_t dinfo;
128 errno_t rc;
129
130 log_msg(LOG_DEFAULT, LVL_DEBUG, "vbds_disk_info_srv()");
131
132 disk_sid = ipc_get_arg1(icall);
133 rc = vbds_disk_info(disk_sid, &dinfo);
134 if (rc != EOK) {
135 async_answer_0(icall, rc);
136 return;
137 }
138
139 ipc_call_t call;
140 size_t size;
141 if (!async_data_read_receive(&call, &size)) {
142 async_answer_0(&call, EREFUSED);
143 async_answer_0(icall, EREFUSED);
144 return;
145 }
146
147 if (size != sizeof(vbd_disk_info_t)) {
148 async_answer_0(&call, EINVAL);
149 async_answer_0(icall, EINVAL);
150 return;
151 }
152
153 rc = async_data_read_finalize(&call, &dinfo,
154 min(size, sizeof(dinfo)));
155 if (rc != EOK) {
156 async_answer_0(&call, rc);
157 async_answer_0(icall, rc);
158 return;
159 }
160
161 async_answer_0(icall, EOK);
162}
163
164static void vbds_label_create_srv(ipc_call_t *icall)
165{
166 service_id_t disk_sid;
167 label_type_t ltype;
168 errno_t rc;
169
170 log_msg(LOG_DEFAULT, LVL_DEBUG, "vbds_label_create_srv()");
171
172 disk_sid = ipc_get_arg1(icall);
173 ltype = ipc_get_arg2(icall);
174 rc = vbds_label_create(disk_sid, ltype);
175 async_answer_0(icall, rc);
176}
177
178static void vbds_label_delete_srv(ipc_call_t *icall)
179{
180 service_id_t disk_sid;
181 errno_t rc;
182
183 log_msg(LOG_DEFAULT, LVL_DEBUG, "vbds_label_delete_srv()");
184
185 disk_sid = ipc_get_arg1(icall);
186 rc = vbds_label_delete(disk_sid);
187 async_answer_0(icall, rc);
188}
189
190static void vbds_label_get_parts_srv(ipc_call_t *icall)
191{
192 ipc_call_t call;
193 size_t size;
194 size_t act_size;
195 service_id_t sid;
196 errno_t rc;
197
198 log_msg(LOG_DEFAULT, LVL_DEBUG, "vbds_label_get_parts_srv()");
199
200 if (!async_data_read_receive(&call, &size)) {
201 async_answer_0(&call, EREFUSED);
202 async_answer_0(icall, EREFUSED);
203 return;
204 }
205
206 sid = ipc_get_arg1(icall);
207
208 category_id_t *id_buf = (category_id_t *) malloc(size);
209 if (id_buf == NULL) {
210 async_answer_0(&call, ENOMEM);
211 async_answer_0(icall, ENOMEM);
212 return;
213 }
214
215 rc = vbds_get_parts(sid, id_buf, size, &act_size);
216 if (rc != EOK) {
217 async_answer_0(&call, rc);
218 async_answer_0(icall, rc);
219 return;
220 }
221
222 errno_t retval = async_data_read_finalize(&call, id_buf, size);
223 free(id_buf);
224
225 async_answer_1(icall, retval, act_size);
226}
227
228static void vbds_part_get_info_srv(ipc_call_t *icall)
229{
230 vbds_part_id_t part;
231 vbd_part_info_t pinfo;
232 errno_t rc;
233
234 log_msg(LOG_DEFAULT, LVL_DEBUG, "vbds_part_get_info_srv()");
235
236 part = ipc_get_arg1(icall);
237 rc = vbds_part_get_info(part, &pinfo);
238 if (rc != EOK) {
239 async_answer_0(icall, rc);
240 return;
241 }
242
243 ipc_call_t call;
244 size_t size;
245 if (!async_data_read_receive(&call, &size)) {
246 async_answer_0(&call, EREFUSED);
247 async_answer_0(icall, EREFUSED);
248 return;
249 }
250
251 if (size != sizeof(vbd_part_info_t)) {
252 async_answer_0(&call, EINVAL);
253 async_answer_0(icall, EINVAL);
254 return;
255 }
256
257 rc = async_data_read_finalize(&call, &pinfo,
258 min(size, sizeof(pinfo)));
259 if (rc != EOK) {
260 async_answer_0(&call, rc);
261 async_answer_0(icall, rc);
262 return;
263 }
264
265 async_answer_0(icall, EOK);
266}
267
268static void vbds_part_create_srv(ipc_call_t *icall)
269{
270 service_id_t disk_sid;
271 vbd_part_spec_t pspec;
272 vbds_part_id_t part;
273 errno_t rc;
274
275 log_msg(LOG_DEFAULT, LVL_DEBUG, "vbds_part_create_srv()");
276
277 disk_sid = ipc_get_arg1(icall);
278
279 ipc_call_t call;
280 size_t size;
281 if (!async_data_write_receive(&call, &size)) {
282 async_answer_0(&call, EREFUSED);
283 async_answer_0(icall, EREFUSED);
284 return;
285 }
286
287 if (size != sizeof(vbd_part_spec_t)) {
288 async_answer_0(&call, EINVAL);
289 async_answer_0(icall, EINVAL);
290 return;
291 }
292
293 rc = async_data_write_finalize(&call, &pspec, sizeof(vbd_part_spec_t));
294 if (rc != EOK) {
295 async_answer_0(&call, rc);
296 async_answer_0(icall, rc);
297 return;
298 }
299
300 rc = vbds_part_create(disk_sid, &pspec, &part);
301 if (rc != EOK) {
302 async_answer_0(icall, rc);
303 return;
304 }
305
306 async_answer_1(icall, rc, (sysarg_t)part);
307}
308
309static void vbds_part_delete_srv(ipc_call_t *icall)
310{
311 vbds_part_id_t part;
312 errno_t rc;
313
314 log_msg(LOG_DEFAULT, LVL_DEBUG, "vbds_part_delete_srv()");
315
316 part = ipc_get_arg1(icall);
317 rc = vbds_part_delete(part);
318 async_answer_0(icall, rc);
319}
320
321static void vbds_suggest_ptype_srv(ipc_call_t *icall)
322{
323 service_id_t disk_sid;
324 label_ptype_t ptype;
325 label_pcnt_t pcnt;
326 errno_t rc;
327
328 log_msg(LOG_DEFAULT, LVL_DEBUG, "vbds_suggest_ptype_srv()");
329
330 disk_sid = ipc_get_arg1(icall);
331 pcnt = ipc_get_arg2(icall);
332
333 rc = vbds_suggest_ptype(disk_sid, pcnt, &ptype);
334 if (rc != EOK) {
335 async_answer_0(icall, rc);
336 return;
337 }
338
339 ipc_call_t call;
340 size_t size;
341 if (!async_data_read_receive(&call, &size)) {
342 async_answer_0(&call, EREFUSED);
343 async_answer_0(icall, EREFUSED);
344 return;
345 }
346
347 if (size != sizeof(label_ptype_t)) {
348 async_answer_0(&call, EINVAL);
349 async_answer_0(icall, EINVAL);
350 return;
351 }
352
353 rc = async_data_read_finalize(&call, &ptype, sizeof(label_ptype_t));
354 if (rc != EOK) {
355 async_answer_0(&call, rc);
356 async_answer_0(icall, rc);
357 return;
358 }
359
360 async_answer_0(icall, EOK);
361}
362
363static void vbds_ctl_conn(ipc_call_t *icall, void *arg)
364{
365 log_msg(LOG_DEFAULT, LVL_DEBUG, "vbds_client_conn()");
366
367 /* Accept the connection */
368 async_accept_0(icall);
369
370 while (true) {
371 ipc_call_t call;
372 async_get_call(&call);
373 sysarg_t method = ipc_get_imethod(&call);
374
375 if (!method) {
376 /* The other side has hung up */
377 async_answer_0(&call, EOK);
378 return;
379 }
380
381 switch (method) {
382 case VBD_GET_DISKS:
383 vbds_get_disks_srv(&call);
384 break;
385 case VBD_DISK_INFO:
386 vbds_disk_info_srv(&call);
387 break;
388 case VBD_LABEL_CREATE:
389 vbds_label_create_srv(&call);
390 break;
391 case VBD_LABEL_DELETE:
392 vbds_label_delete_srv(&call);
393 break;
394 case VBD_LABEL_GET_PARTS:
395 vbds_label_get_parts_srv(&call);
396 break;
397 case VBD_PART_GET_INFO:
398 vbds_part_get_info_srv(&call);
399 break;
400 case VBD_PART_CREATE:
401 vbds_part_create_srv(&call);
402 break;
403 case VBD_PART_DELETE:
404 vbds_part_delete_srv(&call);
405 break;
406 case VBD_SUGGEST_PTYPE:
407 vbds_suggest_ptype_srv(&call);
408 break;
409 default:
410 async_answer_0(&call, EINVAL);
411 }
412 }
413}
414
415static void vbds_client_conn(ipc_call_t *icall, void *arg)
416{
417 service_id_t sid;
418
419 log_msg(LOG_DEFAULT, LVL_DEBUG, "vbds_client_conn()");
420
421 sid = (service_id_t) ipc_get_arg2(icall);
422
423 if (sid == ctl_sid)
424 vbds_ctl_conn(icall, arg);
425 else
426 vbds_bd_conn(icall, arg);
427}
428
429int main(int argc, char *argv[])
430{
431 errno_t rc;
432
433 printf("%s: Virtual Block Device service\n", NAME);
434
435 if (log_init(NAME) != EOK) {
436 printf(NAME ": Failed to initialize logging.\n");
437 return 1;
438 }
439
440 rc = vbds_init();
441 if (rc != EOK)
442 return 1;
443
444 printf(NAME ": Accepting connections.\n");
445 task_retval(0);
446 async_manager();
447
448 return 0;
449}
450
451/** @}
452 */
Note: See TracBrowser for help on using the repository browser.