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

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since e89a06a was 984a9ba, checked in by Martin Decky <martin@…>, 7 years ago

do not expose the call capability handler from the async framework

Keep the call capability handler encapsulated within the async framework
and do not expose it explicitly via its API. Use the pointer to
ipc_call_t as the sole object identifying an IPC call in the code that
uses the async framework.

This plugs a major leak in the abstraction and also simplifies both the
async framework (slightly) and all IPC servers.

  • Property mode set to 100644
File size: 9.6 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 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);
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(SERVICE_NAME_VBD, &ctl_sid);
77 if (rc != EOK) {
78 log_msg(LOG_DEFAULT, LVL_ERROR, "Failed registering service: %s.", str_error(rc));
79 return EEXIST;
80 }
81
82 rc = vbds_disk_discovery_start();
83 if (rc != EOK)
84 return rc;
85
86 return EOK;
87}
88
89static void vbds_get_disks_srv(ipc_call_t *icall)
90{
91 ipc_call_t call;
92 size_t size;
93 size_t act_size;
94 errno_t rc;
95
96 if (!async_data_read_receive(&call, &size)) {
97 async_answer_0(&call, EREFUSED);
98 async_answer_0(icall, EREFUSED);
99 return;
100 }
101
102 service_id_t *id_buf = (service_id_t *) malloc(size);
103 if (id_buf == NULL) {
104 async_answer_0(&call, ENOMEM);
105 async_answer_0(icall, ENOMEM);
106 return;
107 }
108
109 rc = vbds_disk_get_ids(id_buf, size, &act_size);
110 if (rc != EOK) {
111 free(id_buf);
112 async_answer_0(&call, rc);
113 async_answer_0(icall, rc);
114 return;
115 }
116
117 errno_t retval = async_data_read_finalize(&call, id_buf, size);
118 free(id_buf);
119
120 async_answer_1(icall, retval, act_size);
121}
122
123static void vbds_disk_info_srv(ipc_call_t *icall)
124{
125 service_id_t disk_sid;
126 vbd_disk_info_t dinfo;
127 errno_t rc;
128
129 log_msg(LOG_DEFAULT, LVL_DEBUG, "vbds_disk_info_srv()");
130
131 disk_sid = IPC_GET_ARG1(*icall);
132 rc = vbds_disk_info(disk_sid, &dinfo);
133 if (rc != EOK) {
134 async_answer_0(icall, rc);
135 return;
136 }
137
138 ipc_call_t call;
139 size_t size;
140 if (!async_data_read_receive(&call, &size)) {
141 async_answer_0(&call, EREFUSED);
142 async_answer_0(icall, EREFUSED);
143 return;
144 }
145
146 if (size != sizeof(vbd_disk_info_t)) {
147 async_answer_0(&call, EINVAL);
148 async_answer_0(icall, EINVAL);
149 return;
150 }
151
152 rc = async_data_read_finalize(&call, &dinfo,
153 min(size, sizeof(dinfo)));
154 if (rc != EOK) {
155 async_answer_0(&call, rc);
156 async_answer_0(icall, rc);
157 return;
158 }
159
160 async_answer_0(icall, EOK);
161}
162
163static void vbds_label_create_srv(ipc_call_t *icall)
164{
165 service_id_t disk_sid;
166 label_type_t ltype;
167 errno_t rc;
168
169 log_msg(LOG_DEFAULT, LVL_DEBUG, "vbds_label_create_srv()");
170
171 disk_sid = IPC_GET_ARG1(*icall);
172 ltype = IPC_GET_ARG2(*icall);
173 rc = vbds_label_create(disk_sid, ltype);
174 async_answer_0(icall, rc);
175}
176
177static void vbds_label_delete_srv(ipc_call_t *icall)
178{
179 service_id_t disk_sid;
180 errno_t rc;
181
182 log_msg(LOG_DEFAULT, LVL_DEBUG, "vbds_label_delete_srv()");
183
184 disk_sid = IPC_GET_ARG1(*icall);
185 rc = vbds_label_delete(disk_sid);
186 async_answer_0(icall, rc);
187}
188
189static void vbds_label_get_parts_srv(ipc_call_t *icall)
190{
191 ipc_call_t call;
192 size_t size;
193 size_t act_size;
194 service_id_t sid;
195 errno_t rc;
196
197 log_msg(LOG_DEFAULT, LVL_DEBUG, "vbds_label_get_parts_srv()");
198
199 if (!async_data_read_receive(&call, &size)) {
200 async_answer_0(&call, EREFUSED);
201 async_answer_0(icall, EREFUSED);
202 return;
203 }
204
205 sid = IPC_GET_ARG1(*icall);
206
207 category_id_t *id_buf = (category_id_t *) malloc(size);
208 if (id_buf == NULL) {
209 async_answer_0(&call, ENOMEM);
210 async_answer_0(icall, ENOMEM);
211 return;
212 }
213
214 rc = vbds_get_parts(sid, id_buf, size, &act_size);
215 if (rc != EOK) {
216 async_answer_0(&call, rc);
217 async_answer_0(icall, rc);
218 return;
219 }
220
221 errno_t retval = async_data_read_finalize(&call, id_buf, size);
222 free(id_buf);
223
224 async_answer_1(icall, retval, act_size);
225}
226
227static void vbds_part_get_info_srv(ipc_call_t *icall)
228{
229 vbds_part_id_t part;
230 vbd_part_info_t pinfo;
231 errno_t rc;
232
233 log_msg(LOG_DEFAULT, LVL_DEBUG, "vbds_part_get_info_srv()");
234
235 part = IPC_GET_ARG1(*icall);
236 rc = vbds_part_get_info(part, &pinfo);
237 if (rc != EOK) {
238 async_answer_0(icall, rc);
239 return;
240 }
241
242 ipc_call_t call;
243 size_t size;
244 if (!async_data_read_receive(&call, &size)) {
245 async_answer_0(&call, EREFUSED);
246 async_answer_0(icall, EREFUSED);
247 return;
248 }
249
250 if (size != sizeof(vbd_part_info_t)) {
251 async_answer_0(&call, EINVAL);
252 async_answer_0(icall, EINVAL);
253 return;
254 }
255
256 rc = async_data_read_finalize(&call, &pinfo,
257 min(size, sizeof(pinfo)));
258 if (rc != EOK) {
259 async_answer_0(&call, rc);
260 async_answer_0(icall, rc);
261 return;
262 }
263
264 async_answer_0(icall, EOK);
265}
266
267static void vbds_part_create_srv(ipc_call_t *icall)
268{
269 service_id_t disk_sid;
270 vbd_part_spec_t pspec;
271 vbds_part_id_t part;
272 errno_t rc;
273
274 log_msg(LOG_DEFAULT, LVL_DEBUG, "vbds_part_create_srv()");
275
276 disk_sid = IPC_GET_ARG1(*icall);
277
278 ipc_call_t call;
279 size_t size;
280 if (!async_data_write_receive(&call, &size)) {
281 async_answer_0(&call, EREFUSED);
282 async_answer_0(icall, EREFUSED);
283 return;
284 }
285
286 if (size != sizeof(vbd_part_spec_t)) {
287 async_answer_0(&call, EINVAL);
288 async_answer_0(icall, EINVAL);
289 return;
290 }
291
292 rc = async_data_write_finalize(&call, &pspec, sizeof(vbd_part_spec_t));
293 if (rc != EOK) {
294 async_answer_0(&call, rc);
295 async_answer_0(icall, rc);
296 return;
297 }
298
299 rc = vbds_part_create(disk_sid, &pspec, &part);
300 if (rc != EOK) {
301 async_answer_0(icall, rc);
302 return;
303 }
304
305 async_answer_1(icall, rc, (sysarg_t)part);
306}
307
308static void vbds_part_delete_srv(ipc_call_t *icall)
309{
310 vbds_part_id_t part;
311 errno_t rc;
312
313 log_msg(LOG_DEFAULT, LVL_DEBUG, "vbds_part_delete_srv()");
314
315 part = IPC_GET_ARG1(*icall);
316 rc = vbds_part_delete(part);
317 async_answer_0(icall, rc);
318}
319
320static void vbds_suggest_ptype_srv(ipc_call_t *icall)
321{
322 service_id_t disk_sid;
323 label_ptype_t ptype;
324 label_pcnt_t pcnt;
325 errno_t rc;
326
327 log_msg(LOG_DEFAULT, LVL_DEBUG, "vbds_suggest_ptype_srv()");
328
329 disk_sid = IPC_GET_ARG1(*icall);
330 pcnt = IPC_GET_ARG2(*icall);
331
332 rc = vbds_suggest_ptype(disk_sid, pcnt, &ptype);
333 if (rc != EOK) {
334 async_answer_0(icall, rc);
335 return;
336 }
337
338 ipc_call_t call;
339 size_t size;
340 if (!async_data_read_receive(&call, &size)) {
341 async_answer_0(&call, EREFUSED);
342 async_answer_0(icall, EREFUSED);
343 return;
344 }
345
346 if (size != sizeof(label_ptype_t)) {
347 async_answer_0(&call, EINVAL);
348 async_answer_0(icall, EINVAL);
349 return;
350 }
351
352 rc = async_data_read_finalize(&call, &ptype, sizeof(label_ptype_t));
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 vbds_ctl_conn(ipc_call_t *icall, void *arg)
363{
364 log_msg(LOG_DEFAULT, LVL_DEBUG, "vbds_client_conn()");
365
366 /* Accept the connection */
367 async_answer_0(icall, EOK);
368
369 while (true) {
370 ipc_call_t call;
371 async_get_call(&call);
372 sysarg_t method = IPC_GET_IMETHOD(call);
373
374 if (!method) {
375 /* The other side has hung up */
376 async_answer_0(&call, EOK);
377 return;
378 }
379
380 switch (method) {
381 case VBD_GET_DISKS:
382 vbds_get_disks_srv(&call);
383 break;
384 case VBD_DISK_INFO:
385 vbds_disk_info_srv(&call);
386 break;
387 case VBD_LABEL_CREATE:
388 vbds_label_create_srv(&call);
389 break;
390 case VBD_LABEL_DELETE:
391 vbds_label_delete_srv(&call);
392 break;
393 case VBD_LABEL_GET_PARTS:
394 vbds_label_get_parts_srv(&call);
395 break;
396 case VBD_PART_GET_INFO:
397 vbds_part_get_info_srv(&call);
398 break;
399 case VBD_PART_CREATE:
400 vbds_part_create_srv(&call);
401 break;
402 case VBD_PART_DELETE:
403 vbds_part_delete_srv(&call);
404 break;
405 case VBD_SUGGEST_PTYPE:
406 vbds_suggest_ptype_srv(&call);
407 break;
408 default:
409 async_answer_0(&call, EINVAL);
410 }
411 }
412}
413
414static void vbds_client_conn(ipc_call_t *icall, void *arg)
415{
416 service_id_t sid;
417
418 log_msg(LOG_DEFAULT, LVL_DEBUG, "vbds_client_conn()");
419
420 sid = (service_id_t) IPC_GET_ARG2(*icall);
421
422 if (sid == ctl_sid)
423 vbds_ctl_conn(icall, arg);
424 else
425 vbds_bd_conn(icall, arg);
426}
427
428int main(int argc, char *argv[])
429{
430 errno_t rc;
431
432 printf("%s: Virtual Block Device service\n", NAME);
433
434 if (log_init(NAME) != EOK) {
435 printf(NAME ": Failed to initialize logging.\n");
436 return 1;
437 }
438
439 rc = vbds_init();
440 if (rc != EOK)
441 return 1;
442
443 printf(NAME ": Accepting connections.\n");
444 task_retval(0);
445 async_manager();
446
447 return 0;
448}
449
450/** @}
451 */
Note: See TracBrowser for help on using the repository browser.