2 * Copyright (c) 2023 Jiri Svoboda
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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.
29 /** @addtogroup volsrv
33 * @file Volume service
38 #include <str_error.h>
40 #include <ipc/services.h>
47 #include <types/vol.h>
55 const char *vol_cfg_file
= "/cfg/volsrv.sif";
57 static void vol_client_conn(ipc_call_t
*, void *);
59 static errno_t
vol_init(void)
62 vol_volumes_t
*volumes
= NULL
;
63 vol_parts_t
*parts
= NULL
;
64 loc_srv_t
*srv
= NULL
;
66 log_msg(LOG_DEFAULT
, LVL_DEBUG
, "vol_init()");
68 rc
= vol_volumes_create(vol_cfg_file
, &volumes
);
72 rc
= vol_parts_create(volumes
, &parts
);
76 rc
= vol_part_discovery_start(parts
);
80 async_set_fallback_port_handler(vol_client_conn
, parts
);
82 rc
= loc_server_register(NAME
, &srv
);
84 log_msg(LOG_DEFAULT
, LVL_ERROR
, "Failed registering server: %s.", str_error(rc
));
89 rc
= loc_service_register(srv
, SERVICE_NAME_VOLSRV
, &sid
);
91 log_msg(LOG_DEFAULT
, LVL_ERROR
, "Failed registering service: %s.", str_error(rc
));
99 loc_server_unregister(srv
);
100 vol_volumes_destroy(volumes
);
101 vol_parts_destroy(parts
);
105 static void vol_get_parts_srv(vol_parts_t
*parts
, ipc_call_t
*icall
)
112 if (!async_data_read_receive(&call
, &size
)) {
113 async_answer_0(&call
, EREFUSED
);
114 async_answer_0(icall
, EREFUSED
);
118 service_id_t
*id_buf
= (service_id_t
*) malloc(size
);
119 if (id_buf
== NULL
) {
120 async_answer_0(&call
, ENOMEM
);
121 async_answer_0(icall
, ENOMEM
);
125 rc
= vol_part_get_ids(parts
, id_buf
, size
, &act_size
);
127 async_answer_0(&call
, rc
);
128 async_answer_0(icall
, rc
);
132 errno_t retval
= async_data_read_finalize(&call
, id_buf
, size
);
135 async_answer_1(icall
, retval
, act_size
);
138 static void vol_part_add_srv(vol_parts_t
*parts
, ipc_call_t
*icall
)
143 sid
= ipc_get_arg1(icall
);
145 rc
= vol_part_add_part(parts
, sid
);
147 async_answer_0(icall
, rc
);
151 async_answer_0(icall
, EOK
);
154 static void vol_part_info_srv(vol_parts_t
*parts
, ipc_call_t
*icall
)
158 vol_part_info_t pinfo
;
161 sid
= ipc_get_arg1(icall
);
162 log_msg(LOG_DEFAULT
, LVL_DEBUG
, "vol_part_info_srv(%zu)",
164 rc
= vol_part_find_by_id_ref(parts
, sid
, &part
);
166 async_answer_0(icall
, ENOENT
);
170 rc
= vol_part_get_info(part
, &pinfo
);
172 async_answer_0(icall
, EIO
);
178 if (!async_data_read_receive(&call
, &size
)) {
179 async_answer_0(&call
, EREFUSED
);
180 async_answer_0(icall
, EREFUSED
);
184 if (size
!= sizeof(vol_part_info_t
)) {
185 async_answer_0(&call
, EINVAL
);
186 async_answer_0(icall
, EINVAL
);
190 rc
= async_data_read_finalize(&call
, &pinfo
,
191 min(size
, sizeof(pinfo
)));
193 async_answer_0(&call
, rc
);
194 async_answer_0(icall
, rc
);
198 async_answer_0(icall
, EOK
);
200 vol_part_del_ref(part
);
203 static void vol_part_eject_srv(vol_parts_t
*parts
, ipc_call_t
*icall
)
209 sid
= ipc_get_arg1(icall
);
210 log_msg(LOG_DEFAULT
, LVL_DEBUG
, "vol_part_eject_srv(%zu)", sid
);
212 rc
= vol_part_find_by_id_ref(parts
, sid
, &part
);
214 async_answer_0(icall
, ENOENT
);
218 rc
= vol_part_eject_part(part
);
220 async_answer_0(icall
, EIO
);
224 async_answer_0(icall
, EOK
);
226 vol_part_del_ref(part
);
229 static void vol_part_insert_srv(vol_parts_t
*parts
, ipc_call_t
*icall
)
235 sid
= ipc_get_arg1(icall
);
236 log_msg(LOG_DEFAULT
, LVL_DEBUG
, "vol_part_insert_srv(%zu)", sid
);
238 rc
= vol_part_find_by_id_ref(parts
, sid
, &part
);
240 async_answer_0(icall
, ENOENT
);
244 rc
= vol_part_insert_part(part
);
246 async_answer_0(icall
, EIO
);
250 async_answer_0(icall
, EOK
);
252 vol_part_del_ref(part
);
255 static void vol_part_insert_by_path_srv(vol_parts_t
*parts
, ipc_call_t
*icall
)
261 log_msg(LOG_DEFAULT
, LVL_DEBUG
, "vol_part_insert_by_path_srv()");
263 rc
= async_data_write_accept((void **)&path
, true, 0, VOL_MOUNTP_MAXLEN
,
266 async_answer_0(icall
, rc
);
270 rc
= vol_part_find_by_path_ref(parts
, path
, &part
);
272 async_answer_0(icall
, ENOENT
);
276 rc
= vol_part_insert_part(part
);
278 async_answer_0(icall
, rc
);
279 vol_part_del_ref(part
);
284 vol_part_del_ref(part
);
285 async_answer_0(icall
, EOK
);
293 static void vol_part_empty_srv(vol_parts_t
*parts
, ipc_call_t
*icall
)
299 sid
= ipc_get_arg1(icall
);
300 log_msg(LOG_DEFAULT
, LVL_DEBUG
, "vol_part_empty_srv(%zu)", sid
);
302 rc
= vol_part_find_by_id_ref(parts
, sid
, &part
);
304 async_answer_0(icall
, ENOENT
);
308 rc
= vol_part_empty_part(part
);
310 async_answer_0(icall
, EIO
);
314 async_answer_0(icall
, EOK
);
316 vol_part_del_ref(part
);
319 static void vol_part_get_lsupp_srv(vol_parts_t
*parts
, ipc_call_t
*icall
)
322 vol_label_supp_t vlsupp
;
325 fstype
= ipc_get_arg1(icall
);
326 log_msg(LOG_DEFAULT
, LVL_DEBUG
, "vol_part_get_lsupp_srv(%u)",
329 volsrv_part_get_lsupp(fstype
, &vlsupp
);
333 if (!async_data_read_receive(&call
, &size
)) {
334 async_answer_0(&call
, EREFUSED
);
335 async_answer_0(icall
, EREFUSED
);
339 if (size
!= sizeof(vol_label_supp_t
)) {
340 async_answer_0(&call
, EINVAL
);
341 async_answer_0(icall
, EINVAL
);
345 rc
= async_data_read_finalize(&call
, &vlsupp
,
346 min(size
, sizeof(vlsupp
)));
348 async_answer_0(&call
, rc
);
349 async_answer_0(icall
, rc
);
353 async_answer_0(icall
, EOK
);
356 static void vol_part_mkfs_srv(vol_parts_t
*parts
, ipc_call_t
*icall
)
365 log_msg(LOG_DEFAULT
, LVL_DEBUG
, "vol_part_mkfs_srv()");
367 sid
= ipc_get_arg1(icall
);
368 fstype
= ipc_get_arg2(icall
);
370 rc
= async_data_write_accept((void **)&label
, true, 0, VOL_LABEL_MAXLEN
,
373 async_answer_0(icall
, rc
);
378 log_msg(LOG_DEFAULT
, LVL_DEBUG
, "vol_part_mkfs_srv: label='%s'",
382 rc
= async_data_write_accept((void **)&mountp
, true, 0, VOL_MOUNTP_MAXLEN
,
385 async_answer_0(icall
, rc
);
389 if (mountp
!= NULL
) {
390 log_msg(LOG_DEFAULT
, LVL_DEBUG
, "vol_part_mkfs_srv: mountp='%s'",
394 rc
= vol_part_find_by_id_ref(parts
, sid
, &part
);
396 async_answer_0(icall
, ENOENT
);
400 rc
= vol_part_mkfs_part(part
, fstype
, label
, mountp
);
402 async_answer_0(icall
, rc
);
403 vol_part_del_ref(part
);
409 async_answer_0(icall
, EOK
);
419 static void vol_part_set_mountp_srv(vol_parts_t
*parts
,
427 log_msg(LOG_DEFAULT
, LVL_DEBUG
, "vol_part_set_mountp_srv()");
429 sid
= ipc_get_arg1(icall
);
431 rc
= async_data_write_accept((void **)&mountp
, true, 0,
432 VOL_MOUNTP_MAXLEN
, 0, NULL
);
434 async_answer_0(icall
, rc
);
438 if (mountp
!= NULL
) {
439 log_msg(LOG_DEFAULT
, LVL_DEBUG
,
440 "vol_part_set_mountp_srv: mountp='%s'", mountp
);
443 rc
= vol_part_find_by_id_ref(parts
, sid
, &part
);
446 async_answer_0(icall
, ENOENT
);
450 rc
= vol_part_set_mountp_part(part
, mountp
);
453 async_answer_0(icall
, rc
);
454 vol_part_del_ref(part
);
459 async_answer_0(icall
, EOK
);
462 static void vol_get_volumes_srv(vol_parts_t
*parts
, ipc_call_t
*icall
)
469 log_msg(LOG_DEFAULT
, LVL_DEBUG
, "vol_get_volumes_srv()");
471 if (!async_data_read_receive(&call
, &size
)) {
472 async_answer_0(&call
, EREFUSED
);
473 async_answer_0(icall
, EREFUSED
);
477 volume_id_t
*id_buf
= (volume_id_t
*) malloc(size
);
478 if (id_buf
== NULL
) {
479 async_answer_0(&call
, ENOMEM
);
480 async_answer_0(icall
, ENOMEM
);
484 rc
= vol_get_ids(parts
->volumes
, id_buf
, size
, &act_size
);
486 async_answer_0(&call
, rc
);
487 async_answer_0(icall
, rc
);
491 errno_t retval
= async_data_read_finalize(&call
, id_buf
, size
);
494 async_answer_1(icall
, retval
, act_size
);
497 static void vol_info_srv(vol_parts_t
*parts
, ipc_call_t
*icall
)
500 vol_volume_t
*volume
;
504 vid
.id
= ipc_get_arg1(icall
);
505 log_msg(LOG_DEFAULT
, LVL_DEBUG
, "vol_info_srv(%zu)", vid
.id
);
507 rc
= vol_volume_find_by_id_ref(parts
->volumes
, vid
, &volume
);
509 log_msg(LOG_DEFAULT
, LVL_DEBUG
, "vol_info_srv: volume %zu not found",
511 async_answer_0(icall
, ENOENT
);
515 log_msg(LOG_DEFAULT
, LVL_DEBUG
, "vol_info_srv: vol_volume_get_info");
516 rc
= vol_volume_get_info(volume
, &vinfo
);
518 async_answer_0(icall
, EIO
);
524 if (!async_data_read_receive(&call
, &size
)) {
525 async_answer_0(&call
, EREFUSED
);
526 async_answer_0(icall
, EREFUSED
);
530 if (size
!= sizeof(vol_info_t
)) {
531 async_answer_0(&call
, EINVAL
);
532 async_answer_0(icall
, EINVAL
);
536 rc
= async_data_read_finalize(&call
, &vinfo
,
537 min(size
, sizeof(vinfo
)));
539 async_answer_0(&call
, rc
);
540 async_answer_0(icall
, rc
);
544 async_answer_0(icall
, EOK
);
546 vol_volume_del_ref(volume
);
549 static void vol_client_conn(ipc_call_t
*icall
, void *arg
)
551 vol_parts_t
*parts
= (vol_parts_t
*) arg
;
553 log_msg(LOG_DEFAULT
, LVL_DEBUG
, "vol_client_conn()");
555 /* Accept the connection */
556 async_accept_0(icall
);
560 async_get_call(&call
);
561 sysarg_t method
= ipc_get_imethod(&call
);
564 /* The other side has hung up */
565 async_answer_0(&call
, EOK
);
571 vol_get_parts_srv(parts
, &call
);
574 vol_part_add_srv(parts
, &call
);
577 vol_part_info_srv(parts
, &call
);
580 vol_part_eject_srv(parts
, &call
);
583 vol_part_empty_srv(parts
, &call
);
585 case VOL_PART_INSERT
:
586 vol_part_insert_srv(parts
, &call
);
588 case VOL_PART_INSERT_BY_PATH
:
589 vol_part_insert_by_path_srv(parts
, &call
);
592 vol_part_get_lsupp_srv(parts
, &call
);
595 vol_part_mkfs_srv(parts
, &call
);
597 case VOL_PART_SET_MOUNTP
:
598 vol_part_set_mountp_srv(parts
, &call
);
600 case VOL_GET_VOLUMES
:
601 vol_get_volumes_srv(parts
, &call
);
604 vol_info_srv(parts
, &call
);
607 async_answer_0(&call
, EINVAL
);
612 int main(int argc
, char *argv
[])
616 printf("%s: Volume service\n", NAME
);
618 if (log_init(NAME
) != EOK
) {
619 printf(NAME
": Failed to initialize logging.\n");
627 printf(NAME
": Accepting connections.\n");