source: mainline/uspace/srv/volsrv/volsrv.c

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

loc_service_register() needs to take a port ID argument.

  • Property mode set to 100644
File size: 13.4 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 volsrv
30 * @{
31 */
32/**
33 * @file Volume service
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/vol.h>
42#include <loc.h>
43#include <macros.h>
44#include <stdio.h>
45#include <stdlib.h>
46#include <task.h>
47#include <types/vol.h>
48
49#include "mkfs.h"
50#include "part.h"
51#include "volume.h"
52
53#define NAME "volsrv"
54
55const char *vol_icfg_file = "/cfg/initvol.sif";
56const char *vol_cfg_file = "/w/cfg/volsrv.sif";
57
58static void vol_client_conn(ipc_call_t *, void *);
59
60static errno_t vol_init(void)
61{
62 errno_t rc;
63 vol_volumes_t *volumes = NULL;
64 vol_parts_t *parts = NULL;
65 loc_srv_t *srv = NULL;
66
67 log_msg(LOG_DEFAULT, LVL_DEBUG, "vol_init()");
68
69 rc = vol_volumes_create(vol_icfg_file, &volumes);
70 if (rc != EOK)
71 goto error;
72
73 rc = vol_parts_create(volumes, &parts);
74 if (rc != EOK)
75 goto error;
76
77 rc = vol_part_discovery_start(parts);
78 if (rc != EOK)
79 goto error;
80
81 async_set_fallback_port_handler(vol_client_conn, parts);
82
83 rc = loc_server_register(NAME, &srv);
84 if (rc != EOK) {
85 log_msg(LOG_DEFAULT, LVL_ERROR, "Failed registering server: %s.", str_error(rc));
86 rc = EEXIST;
87 }
88
89 service_id_t sid;
90 rc = loc_service_register(srv, SERVICE_NAME_VOLSRV, fallback_port_id,
91 &sid);
92 if (rc != EOK) {
93 log_msg(LOG_DEFAULT, LVL_ERROR, "Failed registering service: %s.", str_error(rc));
94 rc = EEXIST;
95 goto error;
96 }
97
98 return EOK;
99error:
100 if (srv != NULL)
101 loc_server_unregister(srv);
102 vol_volumes_destroy(volumes);
103 vol_parts_destroy(parts);
104 return rc;
105}
106
107static void vol_get_parts_srv(vol_parts_t *parts, ipc_call_t *icall)
108{
109 ipc_call_t call;
110 size_t size;
111 size_t act_size;
112 errno_t rc;
113
114 if (!async_data_read_receive(&call, &size)) {
115 async_answer_0(&call, EREFUSED);
116 async_answer_0(icall, EREFUSED);
117 return;
118 }
119
120 service_id_t *id_buf = (service_id_t *) malloc(size);
121 if (id_buf == NULL) {
122 async_answer_0(&call, ENOMEM);
123 async_answer_0(icall, ENOMEM);
124 return;
125 }
126
127 rc = vol_part_get_ids(parts, id_buf, size, &act_size);
128 if (rc != EOK) {
129 async_answer_0(&call, rc);
130 async_answer_0(icall, rc);
131 return;
132 }
133
134 errno_t retval = async_data_read_finalize(&call, id_buf, size);
135 free(id_buf);
136
137 async_answer_1(icall, retval, act_size);
138}
139
140static void vol_part_add_srv(vol_parts_t *parts, ipc_call_t *icall)
141{
142 service_id_t sid;
143 errno_t rc;
144
145 sid = ipc_get_arg1(icall);
146
147 rc = vol_part_add_part(parts, sid);
148 if (rc != EOK) {
149 async_answer_0(icall, rc);
150 return;
151 }
152
153 async_answer_0(icall, EOK);
154}
155
156static void vol_part_info_srv(vol_parts_t *parts, ipc_call_t *icall)
157{
158 service_id_t sid;
159 vol_part_t *part;
160 vol_part_info_t pinfo;
161 errno_t rc;
162
163 sid = ipc_get_arg1(icall);
164 log_msg(LOG_DEFAULT, LVL_DEBUG, "vol_part_info_srv(%zu)",
165 sid);
166 rc = vol_part_find_by_id_ref(parts, sid, &part);
167 if (rc != EOK) {
168 async_answer_0(icall, ENOENT);
169 return;
170 }
171
172 rc = vol_part_get_info(part, &pinfo);
173 if (rc != EOK) {
174 async_answer_0(icall, EIO);
175 goto error;
176 }
177
178 ipc_call_t call;
179 size_t size;
180 if (!async_data_read_receive(&call, &size)) {
181 async_answer_0(&call, EREFUSED);
182 async_answer_0(icall, EREFUSED);
183 goto error;
184 }
185
186 if (size != sizeof(vol_part_info_t)) {
187 async_answer_0(&call, EINVAL);
188 async_answer_0(icall, EINVAL);
189 goto error;
190 }
191
192 rc = async_data_read_finalize(&call, &pinfo,
193 min(size, sizeof(pinfo)));
194 if (rc != EOK) {
195 async_answer_0(&call, rc);
196 async_answer_0(icall, rc);
197 goto error;
198 }
199
200 async_answer_0(icall, EOK);
201error:
202 vol_part_del_ref(part);
203}
204
205static void vol_part_eject_srv(vol_parts_t *parts, ipc_call_t *icall)
206{
207 service_id_t sid;
208 vol_eject_flags_t flags;
209 vol_part_t *part;
210 errno_t rc;
211
212 sid = ipc_get_arg1(icall);
213 flags = ipc_get_arg2(icall);
214
215 log_msg(LOG_DEFAULT, LVL_DEBUG, "vol_part_eject_srv(%zu, %x)",
216 sid, flags);
217
218 rc = vol_part_find_by_id_ref(parts, sid, &part);
219 if (rc != EOK) {
220 async_answer_0(icall, ENOENT);
221 return;
222 }
223
224 rc = vol_part_eject_part(part, flags);
225 if (rc != EOK) {
226 async_answer_0(icall, EIO);
227 goto error;
228 }
229
230 async_answer_0(icall, EOK);
231error:
232 vol_part_del_ref(part);
233}
234
235static void vol_part_insert_srv(vol_parts_t *parts, ipc_call_t *icall)
236{
237 service_id_t sid;
238 vol_part_t *part;
239 errno_t rc;
240
241 sid = ipc_get_arg1(icall);
242 log_msg(LOG_DEFAULT, LVL_DEBUG, "vol_part_insert_srv(%zu)", sid);
243
244 rc = vol_part_find_by_id_ref(parts, sid, &part);
245 if (rc != EOK) {
246 async_answer_0(icall, ENOENT);
247 return;
248 }
249
250 rc = vol_part_insert_part(part);
251 if (rc != EOK) {
252 async_answer_0(icall, EIO);
253 goto error;
254 }
255
256 async_answer_0(icall, EOK);
257error:
258 vol_part_del_ref(part);
259}
260
261static void vol_part_insert_by_path_srv(vol_parts_t *parts, ipc_call_t *icall)
262{
263 vol_part_t *part;
264 char *path = NULL;
265 errno_t rc;
266
267 log_msg(LOG_DEFAULT, LVL_DEBUG, "vol_part_insert_by_path_srv()");
268
269 rc = async_data_write_accept((void **)&path, true, 0, VOL_MOUNTP_MAXLEN,
270 0, NULL);
271 if (rc != EOK) {
272 async_answer_0(icall, rc);
273 goto error;
274 }
275
276 rc = vol_part_find_by_path_ref(parts, path, &part);
277 if (rc != EOK) {
278 async_answer_0(icall, ENOENT);
279 goto error;
280 }
281
282 rc = vol_part_insert_part(part);
283 if (rc != EOK) {
284 async_answer_0(icall, rc);
285 vol_part_del_ref(part);
286 goto error;
287 }
288
289 free(path);
290 vol_part_del_ref(part);
291 async_answer_0(icall, EOK);
292
293 return;
294error:
295 if (path != NULL)
296 free(path);
297}
298
299static void vol_part_empty_srv(vol_parts_t *parts, ipc_call_t *icall)
300{
301 service_id_t sid;
302 vol_part_t *part;
303 errno_t rc;
304
305 sid = ipc_get_arg1(icall);
306 log_msg(LOG_DEFAULT, LVL_DEBUG, "vol_part_empty_srv(%zu)", sid);
307
308 rc = vol_part_find_by_id_ref(parts, sid, &part);
309 if (rc != EOK) {
310 async_answer_0(icall, ENOENT);
311 return;
312 }
313
314 rc = vol_part_empty_part(part);
315 if (rc != EOK) {
316 async_answer_0(icall, EIO);
317 goto error;
318 }
319
320 async_answer_0(icall, EOK);
321error:
322 vol_part_del_ref(part);
323}
324
325static void vol_part_get_lsupp_srv(vol_parts_t *parts, ipc_call_t *icall)
326{
327 vol_fstype_t fstype;
328 vol_label_supp_t vlsupp;
329 errno_t rc;
330
331 fstype = ipc_get_arg1(icall);
332 log_msg(LOG_DEFAULT, LVL_DEBUG, "vol_part_get_lsupp_srv(%u)",
333 fstype);
334
335 volsrv_part_get_lsupp(fstype, &vlsupp);
336
337 ipc_call_t call;
338 size_t size;
339 if (!async_data_read_receive(&call, &size)) {
340 async_answer_0(&call, EREFUSED);
341 async_answer_0(icall, EREFUSED);
342 return;
343 }
344
345 if (size != sizeof(vol_label_supp_t)) {
346 async_answer_0(&call, EINVAL);
347 async_answer_0(icall, EINVAL);
348 return;
349 }
350
351 rc = async_data_read_finalize(&call, &vlsupp,
352 min(size, sizeof(vlsupp)));
353 if (rc != EOK) {
354 async_answer_0(&call, rc);
355 async_answer_0(icall, rc);
356 return;
357 }
358
359 async_answer_0(icall, EOK);
360}
361
362static void vol_part_mkfs_srv(vol_parts_t *parts, ipc_call_t *icall)
363{
364 service_id_t sid;
365 vol_part_t *part;
366 vol_fstype_t fstype;
367 char *label = NULL;
368 char *mountp = NULL;
369 errno_t rc;
370
371 log_msg(LOG_DEFAULT, LVL_DEBUG, "vol_part_mkfs_srv()");
372
373 sid = ipc_get_arg1(icall);
374 fstype = ipc_get_arg2(icall);
375
376 rc = async_data_write_accept((void **)&label, true, 0, VOL_LABEL_MAXLEN,
377 0, NULL);
378 if (rc != EOK) {
379 async_answer_0(icall, rc);
380 goto error;
381 }
382
383 if (label != NULL) {
384 log_msg(LOG_DEFAULT, LVL_DEBUG, "vol_part_mkfs_srv: label='%s'",
385 label);
386 }
387
388 rc = async_data_write_accept((void **)&mountp, true, 0, VOL_MOUNTP_MAXLEN,
389 0, NULL);
390 if (rc != EOK) {
391 async_answer_0(icall, rc);
392 goto error;
393 }
394
395 if (mountp != NULL) {
396 log_msg(LOG_DEFAULT, LVL_DEBUG, "vol_part_mkfs_srv: mountp='%s'",
397 mountp);
398 }
399
400 rc = vol_part_find_by_id_ref(parts, sid, &part);
401 if (rc != EOK) {
402 async_answer_0(icall, ENOENT);
403 goto error;
404 }
405
406 rc = vol_part_mkfs_part(part, fstype, label, mountp);
407 if (rc != EOK) {
408 async_answer_0(icall, rc);
409 vol_part_del_ref(part);
410 goto error;
411 }
412
413 free(label);
414 free(mountp);
415 async_answer_0(icall, EOK);
416
417 return;
418error:
419 if (label != NULL)
420 free(label);
421 if (mountp != NULL)
422 free(mountp);
423}
424
425static void vol_part_set_mountp_srv(vol_parts_t *parts,
426 ipc_call_t *icall)
427{
428 service_id_t sid;
429 vol_part_t *part;
430 char *mountp;
431 errno_t rc;
432
433 log_msg(LOG_DEFAULT, LVL_DEBUG, "vol_part_set_mountp_srv()");
434
435 sid = ipc_get_arg1(icall);
436
437 rc = async_data_write_accept((void **)&mountp, true, 0,
438 VOL_MOUNTP_MAXLEN, 0, NULL);
439 if (rc != EOK) {
440 async_answer_0(icall, rc);
441 return;
442 }
443
444 if (mountp != NULL) {
445 log_msg(LOG_DEFAULT, LVL_DEBUG,
446 "vol_part_set_mountp_srv: mountp='%s'", mountp);
447 }
448
449 rc = vol_part_find_by_id_ref(parts, sid, &part);
450 if (rc != EOK) {
451 free(mountp);
452 async_answer_0(icall, ENOENT);
453 return;
454 }
455
456 rc = vol_part_set_mountp_part(part, mountp);
457 if (rc != EOK) {
458 free(mountp);
459 async_answer_0(icall, rc);
460 vol_part_del_ref(part);
461 return;
462 }
463
464 free(mountp);
465 async_answer_0(icall, EOK);
466}
467
468static void vol_get_volumes_srv(vol_parts_t *parts, ipc_call_t *icall)
469{
470 ipc_call_t call;
471 size_t size;
472 size_t act_size;
473 errno_t rc;
474
475 log_msg(LOG_DEFAULT, LVL_DEBUG, "vol_get_volumes_srv()");
476
477 if (!async_data_read_receive(&call, &size)) {
478 async_answer_0(&call, EREFUSED);
479 async_answer_0(icall, EREFUSED);
480 return;
481 }
482
483 volume_id_t *id_buf = (volume_id_t *) malloc(size);
484 if (id_buf == NULL) {
485 async_answer_0(&call, ENOMEM);
486 async_answer_0(icall, ENOMEM);
487 return;
488 }
489
490 rc = vol_get_ids(parts->volumes, id_buf, size, &act_size);
491 if (rc != EOK) {
492 async_answer_0(&call, rc);
493 async_answer_0(icall, rc);
494 return;
495 }
496
497 errno_t retval = async_data_read_finalize(&call, id_buf, size);
498 free(id_buf);
499
500 async_answer_1(icall, retval, act_size);
501}
502
503static void vol_info_srv(vol_parts_t *parts, ipc_call_t *icall)
504{
505 volume_id_t vid;
506 vol_volume_t *volume;
507 vol_info_t vinfo;
508 errno_t rc;
509
510 vid.id = ipc_get_arg1(icall);
511 log_msg(LOG_DEFAULT, LVL_DEBUG, "vol_info_srv(%zu)", vid.id);
512
513 rc = vol_volume_find_by_id_ref(parts->volumes, vid, &volume);
514 if (rc != EOK) {
515 log_msg(LOG_DEFAULT, LVL_DEBUG, "vol_info_srv: volume %zu not found",
516 vid.id);
517 async_answer_0(icall, ENOENT);
518 return;
519 }
520
521 log_msg(LOG_DEFAULT, LVL_DEBUG, "vol_info_srv: vol_volume_get_info");
522 rc = vol_volume_get_info(volume, &vinfo);
523 if (rc != EOK) {
524 async_answer_0(icall, EIO);
525 goto error;
526 }
527
528 ipc_call_t call;
529 size_t size;
530 if (!async_data_read_receive(&call, &size)) {
531 async_answer_0(&call, EREFUSED);
532 async_answer_0(icall, EREFUSED);
533 goto error;
534 }
535
536 if (size != sizeof(vol_info_t)) {
537 async_answer_0(&call, EINVAL);
538 async_answer_0(icall, EINVAL);
539 goto error;
540 }
541
542 rc = async_data_read_finalize(&call, &vinfo,
543 min(size, sizeof(vinfo)));
544 if (rc != EOK) {
545 async_answer_0(&call, rc);
546 async_answer_0(icall, rc);
547 goto error;
548 }
549
550 async_answer_0(icall, EOK);
551error:
552 vol_volume_del_ref(volume);
553}
554
555static void vol_client_conn(ipc_call_t *icall, void *arg)
556{
557 vol_parts_t *parts = (vol_parts_t *) arg;
558
559 log_msg(LOG_DEFAULT, LVL_DEBUG, "vol_client_conn()");
560
561 /* Accept the connection */
562 async_accept_0(icall);
563
564 while (true) {
565 ipc_call_t call;
566 async_get_call(&call);
567 sysarg_t method = ipc_get_imethod(&call);
568
569 if (!method) {
570 /* The other side has hung up */
571 async_answer_0(&call, EOK);
572 return;
573 }
574
575 switch (method) {
576 case VOL_GET_PARTS:
577 vol_get_parts_srv(parts, &call);
578 break;
579 case VOL_PART_ADD:
580 vol_part_add_srv(parts, &call);
581 break;
582 case VOL_PART_INFO:
583 vol_part_info_srv(parts, &call);
584 break;
585 case VOL_PART_EJECT:
586 vol_part_eject_srv(parts, &call);
587 break;
588 case VOL_PART_EMPTY:
589 vol_part_empty_srv(parts, &call);
590 break;
591 case VOL_PART_INSERT:
592 vol_part_insert_srv(parts, &call);
593 break;
594 case VOL_PART_INSERT_BY_PATH:
595 vol_part_insert_by_path_srv(parts, &call);
596 break;
597 case VOL_PART_LSUPP:
598 vol_part_get_lsupp_srv(parts, &call);
599 break;
600 case VOL_PART_MKFS:
601 vol_part_mkfs_srv(parts, &call);
602 break;
603 case VOL_PART_SET_MOUNTP:
604 vol_part_set_mountp_srv(parts, &call);
605 break;
606 case VOL_GET_VOLUMES:
607 vol_get_volumes_srv(parts, &call);
608 break;
609 case VOL_INFO:
610 vol_info_srv(parts, &call);
611 break;
612 default:
613 async_answer_0(&call, EINVAL);
614 }
615 }
616}
617
618int main(int argc, char *argv[])
619{
620 errno_t rc;
621
622 printf("%s: Volume service\n", NAME);
623
624 if (log_init(NAME) != EOK) {
625 printf(NAME ": Failed to initialize logging.\n");
626 return 1;
627 }
628
629 rc = vol_init();
630 if (rc != EOK)
631 return 1;
632
633 printf(NAME ": Accepting connections.\n");
634 task_retval(0);
635 async_manager();
636
637 return 0;
638}
639
640/** @}
641 */
Note: See TracBrowser for help on using the repository browser.