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

Last change on this file since f5837524 was f5837524, checked in by Jakub Jermar <jakub@…>, 7 years ago

Use user-defined labels instead of phone hashes

This commit changes the way how the async framework maps incomming calls
to connections. Instead of abusing the kernel addresses of attached
phones as identifiers, the IPC_M_CONNECT_TO_ME and IPC_M_CONNECT_ME_TO
messages allow the server to specify an arbitrary label which is
remembered in the connected phone and consequently imprinted on each
call which is routed through this phone.

The async framework uses the address of the connection structure as the
label. This removes the need for a connection hash table because each
incoming call already remembers the connection in its label.

To disambiguate this new label and the other user-defined label used for
answers, the call structure now has the request_label member for the
former and answer_label member for the latter.

This commit also moves the kernel definition of ipc_data_t to abi/ and
removes the uspace redefinition thereof. Finally, when forwarding the
IPC_M_CONNECT_TO_ME call, the phone capability and the kernel object
allocated in request_process are now correctly disposed of.

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