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

Last change on this file since d773bea9 was ca127f37, checked in by Jiri Svoboda <jiri@…>, 11 months ago

Persist volume configuration

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