source: mainline/uspace/srv/bd/vbd/vbd.c@ 5772aa1

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

VBD needs to empty a newly created partition before exposing it to the volume server.

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