source: mainline/uspace/srv/bd/vbd/vbd.c@ 4b6635a7

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 4b6635a7 was 372df8f, checked in by Jiri Svoboda <jiri@…>, 10 years ago

Let VBD handle unlabeled devices too. Now volsrv only cares about partitions.

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