source: mainline/uspace/srv/bd/vbd/disk.c@ f57ccb5

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

Set partition type based on selected filesystem type.

  • Property mode set to 100644
File size: 18.4 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 <adt/list.h>
37#include <bd_srv.h>
38#include <block.h>
39#include <errno.h>
40#include <io/log.h>
41#include <loc.h>
42#include <stdio.h>
43#include <stdlib.h>
44#include <task.h>
45#include <vbd.h>
46
47#include "disk.h"
48#include "types/vbd.h"
49
50static list_t vbds_disks; /* of vbds_disk_t */
51static list_t vbds_parts; /* of vbds_part_t */
52
53static int vbds_bd_open(bd_srvs_t *, bd_srv_t *);
54static int vbds_bd_close(bd_srv_t *);
55static int vbds_bd_read_blocks(bd_srv_t *, aoff64_t, size_t, void *, size_t);
56static int vbds_bd_sync_cache(bd_srv_t *, aoff64_t, size_t);
57static int vbds_bd_write_blocks(bd_srv_t *, aoff64_t, size_t, const void *,
58 size_t);
59static int vbds_bd_get_block_size(bd_srv_t *, size_t *);
60static int vbds_bd_get_num_blocks(bd_srv_t *, aoff64_t *);
61
62static int vbds_bsa_translate(vbds_part_t *, aoff64_t, size_t, aoff64_t *);
63
64static int vbds_part_svc_register(vbds_part_t *);
65static int vbds_part_svc_unregister(vbds_part_t *);
66static int vbds_part_indices_update(vbds_disk_t *);
67
68static vbd_part_id_t vbds_part_id = 1;
69
70static bd_ops_t vbds_bd_ops = {
71 .open = vbds_bd_open,
72 .close = vbds_bd_close,
73 .read_blocks = vbds_bd_read_blocks,
74 .sync_cache = vbds_bd_sync_cache,
75 .write_blocks = vbds_bd_write_blocks,
76 .get_block_size = vbds_bd_get_block_size,
77 .get_num_blocks = vbds_bd_get_num_blocks
78};
79
80static vbds_part_t *bd_srv_part(bd_srv_t *bd)
81{
82 return (vbds_part_t *)bd->srvs->sarg;
83}
84
85void vbds_disks_init(void)
86{
87 list_initialize(&vbds_disks);
88 list_initialize(&vbds_parts);
89}
90
91static int vbds_disk_by_svcid(service_id_t sid, vbds_disk_t **rdisk)
92{
93 list_foreach(vbds_disks, ldisks, vbds_disk_t, disk) {
94 if (disk->svc_id == sid) {
95 *rdisk = disk;
96 return EOK;
97 }
98 }
99
100 return ENOENT;
101}
102
103static int vbds_part_by_pid(vbds_part_id_t partid, vbds_part_t **rpart)
104{
105 log_msg(LOG_DEFAULT, LVL_NOTE, "vbds_part_by_pid(%zu)", partid);
106
107 list_foreach(vbds_parts, lparts, vbds_part_t, part) {
108 log_msg(LOG_DEFAULT, LVL_NOTE, "%zu == %zu ?", part->pid, partid);
109 if (part->pid == partid) {
110 log_msg(LOG_DEFAULT, LVL_NOTE, "Found match.");
111 *rpart = part;
112 return EOK;
113 }
114 }
115
116 log_msg(LOG_DEFAULT, LVL_NOTE, "No match.");
117 return ENOENT;
118}
119
120static int vbds_part_by_svcid(service_id_t svcid, vbds_part_t **rpart)
121{
122 log_msg(LOG_DEFAULT, LVL_NOTE, "vbds_part_by_svcid(%zu)", svcid);
123
124 list_foreach(vbds_parts, lparts, vbds_part_t, part) {
125 log_msg(LOG_DEFAULT, LVL_NOTE, "%zu == %zu ?", part->svc_id, svcid);
126 if (part->svc_id == svcid) {
127 log_msg(LOG_DEFAULT, LVL_NOTE, "Found match.");
128 *rpart = part;
129 return EOK;
130 }
131 }
132
133 log_msg(LOG_DEFAULT, LVL_NOTE, "No match.");
134 return ENOENT;
135}
136
137/** Add partition to our inventory based on liblabel partition structure */
138static int vbds_part_add(vbds_disk_t *disk, label_part_t *lpart,
139 vbds_part_t **rpart)
140{
141 vbds_part_t *part;
142 service_id_t psid = 0;
143 label_part_info_t lpinfo;
144 int rc;
145
146 log_msg(LOG_DEFAULT, LVL_NOTE, "vbds_part_add(%s, %p)",
147 disk->svc_name, lpart);
148
149 label_part_get_info(lpart, &lpinfo);
150
151 part = calloc(1, sizeof(vbds_part_t));
152 if (part == NULL) {
153 log_msg(LOG_DEFAULT, LVL_ERROR, "Out of memory.");
154 return ENOMEM;
155 }
156
157 part->lpart = lpart;
158 part->disk = disk;
159 part->pid = ++vbds_part_id;
160 part->svc_id = psid;
161 part->block0 = lpinfo.block0;
162 part->nblocks = lpinfo.nblocks;
163
164 bd_srvs_init(&part->bds);
165 part->bds.ops = &vbds_bd_ops;
166 part->bds.sarg = part;
167
168 if (lpinfo.pkind != lpk_extended) {
169 rc = vbds_part_svc_register(part);
170 if (rc != EOK)
171 return EIO;
172 }
173
174 list_append(&part->ldisk, &disk->parts);
175 list_append(&part->lparts, &vbds_parts);
176
177 if (rpart != NULL)
178 *rpart = part;
179 return EOK;
180}
181
182/** Remove partition from our inventory leaving only the underlying liblabel
183 * partition structure.
184 */
185static int vbds_part_remove(vbds_part_t *part, label_part_t **rlpart)
186{
187 label_part_t *lpart;
188 int rc;
189
190 log_msg(LOG_DEFAULT, LVL_NOTE, "vbds_part_remove(%p)", part);
191
192 lpart = part->lpart;
193
194 if (part->open_cnt > 0)
195 return EBUSY;
196
197 if (part->svc_id != 0) {
198 rc = vbds_part_svc_unregister(part);
199 if (rc != EOK)
200 return EIO;
201 }
202
203 list_remove(&part->ldisk);
204 list_remove(&part->lparts);
205 free(part);
206
207 if (rlpart != NULL)
208 *rlpart = lpart;
209 return EOK;
210}
211
212int vbds_disk_add(service_id_t sid)
213{
214 label_t *label = NULL;
215 label_part_t *part;
216 vbds_disk_t *disk = NULL;
217 bool block_inited = false;
218 size_t block_size;
219 int rc;
220
221 log_msg(LOG_DEFAULT, LVL_NOTE, "vbds_disk_add(%zu)", sid);
222
223 /* Check for duplicates */
224 rc = vbds_disk_by_svcid(sid, &disk);
225 if (rc == EOK)
226 return EEXISTS;
227
228 disk = calloc(1, sizeof(vbds_disk_t));
229 if (disk == NULL)
230 return ENOMEM;
231
232 rc = loc_service_get_name(sid, &disk->svc_name);
233 if (rc != EOK) {
234 log_msg(LOG_DEFAULT, LVL_ERROR, "Failed getting disk service name.");
235 rc = EIO;
236 goto error;
237 }
238
239 log_msg(LOG_DEFAULT, LVL_NOTE, "block_init(%zu)", sid);
240 rc = block_init(EXCHANGE_SERIALIZE, sid, 2048);
241 if (rc != EOK) {
242 log_msg(LOG_DEFAULT, LVL_ERROR, "Failed opening block device %s.",
243 disk->svc_name);
244 rc = EIO;
245 goto error;
246 }
247
248 rc = block_get_bsize(sid, &block_size);
249 if (rc != EOK) {
250 log_msg(LOG_DEFAULT, LVL_ERROR, "Failed getting block size of %s.",
251 disk->svc_name);
252 rc = EIO;
253 goto error;
254 }
255
256 block_inited = true;
257
258 rc = label_open(sid, &label);
259 if (rc != EOK) {
260 log_msg(LOG_DEFAULT, LVL_NOTE, "Label in disk %s not recognized.",
261 disk->svc_name);
262 rc = EIO;
263 goto error;
264 }
265
266 disk->svc_id = sid;
267 disk->label = label;
268 disk->block_size = block_size;
269
270 list_initialize(&disk->parts);
271 list_append(&disk->ldisks, &vbds_disks);
272
273 log_msg(LOG_DEFAULT, LVL_NOTE, "Recognized disk label. Adding partitions.");
274
275 part = label_part_first(label);
276 while (part != NULL) {
277 rc = vbds_part_add(disk, part, NULL);
278 if (rc != EOK) {
279 log_msg(LOG_DEFAULT, LVL_ERROR, "Failed adding partitio "
280 "(disk %s)", disk->svc_name);
281 }
282
283 part = label_part_next(part);
284 }
285
286 return EOK;
287error:
288 label_close(label);
289 if (block_inited) {
290 log_msg(LOG_DEFAULT, LVL_NOTE, "block_fini(%zu)", sid);
291 block_fini(sid);
292 }
293 if (disk != NULL)
294 free(disk->svc_name);
295 free(disk);
296 return rc;
297}
298
299int vbds_disk_remove(service_id_t sid)
300{
301 vbds_disk_t *disk;
302 int rc;
303
304 log_msg(LOG_DEFAULT, LVL_NOTE, "vbds_disk_remove(%zu)", sid);
305
306 rc = vbds_disk_by_svcid(sid, &disk);
307 if (rc != EOK)
308 return rc;
309
310 list_remove(&disk->ldisks);
311 label_close(disk->label);
312 log_msg(LOG_DEFAULT, LVL_NOTE, "block_fini(%zu)", sid);
313 block_fini(sid);
314 free(disk);
315 return EOK;
316}
317
318int vbds_disk_info(service_id_t sid, vbd_disk_info_t *info)
319{
320 vbds_disk_t *disk;
321 label_info_t linfo;
322 int rc;
323
324 log_msg(LOG_DEFAULT, LVL_NOTE, "vbds_disk_info(%zu)", sid);
325
326 rc = vbds_disk_by_svcid(sid, &disk);
327 if (rc != EOK)
328 return rc;
329
330 rc = label_get_info(disk->label, &linfo);
331
332 info->ltype = linfo.ltype;
333 info->flags = linfo.flags;
334 info->ablock0 = linfo.ablock0;
335 info->anblocks = linfo.anblocks;
336 info->block_size = disk->block_size;
337 log_msg(LOG_DEFAULT, LVL_NOTE, "vbds_disk_info - block_size=%zu",
338 info->block_size);
339 return EOK;
340}
341
342int vbds_get_parts(service_id_t sid, service_id_t *id_buf, size_t buf_size,
343 size_t *act_size)
344{
345 vbds_disk_t *disk;
346 size_t act_cnt;
347 size_t buf_cnt;
348 int rc;
349
350 rc = vbds_disk_by_svcid(sid, &disk);
351 if (rc != EOK)
352 return rc;
353
354 buf_cnt = buf_size / sizeof(service_id_t);
355
356 act_cnt = list_count(&disk->parts);
357 *act_size = act_cnt * sizeof(service_id_t);
358
359 if (buf_size % sizeof(service_id_t) != 0)
360 return EINVAL;
361
362 size_t pos = 0;
363 list_foreach(disk->parts, ldisk, vbds_part_t, part) {
364 if (pos < buf_cnt)
365 id_buf[pos] = part->pid;
366 pos++;
367 }
368
369 return EOK;
370}
371
372
373int vbds_label_create(service_id_t sid, label_type_t ltype)
374{
375 label_t *label;
376 vbds_disk_t *disk;
377 bool block_inited = false;
378 size_t block_size;
379 int rc;
380
381 log_msg(LOG_DEFAULT, LVL_NOTE, "vbds_label_create(%zu)", sid);
382
383 log_msg(LOG_DEFAULT, LVL_NOTE, "vbds_label_create(%zu) - chkdup", sid);
384
385 /* Check for duplicates */
386 rc = vbds_disk_by_svcid(sid, &disk);
387 if (rc == EOK)
388 return EEXISTS;
389
390 log_msg(LOG_DEFAULT, LVL_NOTE, "vbds_label_create(%zu) - alloc", sid);
391
392 disk = calloc(1, sizeof(vbds_disk_t));
393 if (disk == NULL)
394 return ENOMEM;
395
396 rc = loc_service_get_name(sid, &disk->svc_name);
397 if (rc != EOK) {
398 log_msg(LOG_DEFAULT, LVL_ERROR, "Failed getting disk service name.");
399 rc = EIO;
400 goto error;
401 }
402
403 log_msg(LOG_DEFAULT, LVL_NOTE, "block_init(%zu)", sid);
404 rc = block_init(EXCHANGE_SERIALIZE, sid, 2048);
405 if (rc != EOK) {
406 log_msg(LOG_DEFAULT, LVL_ERROR, "Failed opening block device %s.",
407 disk->svc_name);
408 rc = EIO;
409 goto error;
410 }
411
412 rc = block_get_bsize(sid, &block_size);
413 if (rc != EOK) {
414 log_msg(LOG_DEFAULT, LVL_ERROR, "Failed getting block size of %s.",
415 disk->svc_name);
416 rc = EIO;
417 goto error;
418 }
419
420 block_inited = true;
421
422 log_msg(LOG_DEFAULT, LVL_NOTE, "vbds_label_create(%zu) - label_create", sid);
423
424 rc = label_create(sid, ltype, &label);
425 if (rc != EOK)
426 goto error;
427
428 disk->svc_id = sid;
429 disk->label = label;
430 disk->block_size = block_size;
431 log_msg(LOG_DEFAULT, LVL_NOTE, "vbds_label_create: block_size=%zu",
432 block_size);
433 list_initialize(&disk->parts);
434
435 list_append(&disk->ldisks, &vbds_disks);
436
437 log_msg(LOG_DEFAULT, LVL_NOTE, "vbds_label_create(%zu) - success", sid);
438 return EOK;
439error:
440 log_msg(LOG_DEFAULT, LVL_NOTE, "vbds_label_create(%zu) - failure", sid);
441 if (block_inited) {
442 log_msg(LOG_DEFAULT, LVL_NOTE, "block_fini(%zu)", sid);
443 block_fini(sid);
444 }
445 if (disk != NULL)
446 free(disk->svc_name);
447 free(disk);
448 return rc;
449}
450
451int vbds_label_delete(service_id_t sid)
452{
453 vbds_disk_t *disk;
454 int rc;
455
456 log_msg(LOG_DEFAULT, LVL_NOTE, "vbds_label_delete(%zu)", sid);
457
458 rc = vbds_disk_by_svcid(sid, &disk);
459 if (rc != EOK)
460 return rc;
461
462 rc = label_destroy(disk->label);
463 if (rc != EOK) {
464 log_msg(LOG_DEFAULT, LVL_ERROR, "Failed deleting label.");
465 return rc;
466 }
467
468 list_remove(&disk->ldisks);
469 log_msg(LOG_DEFAULT, LVL_NOTE, "block_fini(%zu)", sid);
470 block_fini(sid);
471 free(disk);
472 return EOK;
473}
474
475int vbds_part_get_info(vbds_part_id_t partid, vbd_part_info_t *pinfo)
476{
477 vbds_part_t *part;
478 label_part_info_t lpinfo;
479 int rc;
480
481 rc = vbds_part_by_pid(partid, &part);
482 if (rc != EOK)
483 return rc;
484
485 label_part_get_info(part->lpart, &lpinfo);
486
487 pinfo->index = lpinfo.index;
488 pinfo->pkind = lpinfo.pkind;
489 pinfo->block0 = lpinfo.block0;
490 pinfo->nblocks = lpinfo.nblocks;
491 return EOK;
492}
493
494int vbds_part_create(service_id_t sid, vbd_part_spec_t *pspec,
495 vbds_part_id_t *rpart)
496{
497 vbds_disk_t *disk;
498 vbds_part_t *part;
499 label_part_spec_t lpspec;
500 label_part_t *lpart;
501 int rc;
502
503 rc = vbds_disk_by_svcid(sid, &disk);
504 if (rc != EOK) {
505 log_msg(LOG_DEFAULT, LVL_NOTE, "Disk %zu not found",
506 sid);
507 goto error;
508 }
509
510 label_pspec_init(&lpspec);
511 lpspec.index = pspec->index;
512 lpspec.block0 = pspec->block0;
513 lpspec.nblocks = pspec->nblocks;
514 lpspec.hdr_blocks = pspec->hdr_blocks;
515 lpspec.pkind = pspec->pkind;
516 lpspec.ptype = pspec->ptype;
517
518 rc = label_part_create(disk->label, &lpspec, &lpart);
519 if (rc != EOK) {
520 log_msg(LOG_DEFAULT, LVL_ERROR, "Error creating partition.");
521 goto error;
522 }
523
524 rc = vbds_part_indices_update(disk);
525 if (rc != EOK) {
526 log_msg(LOG_DEFAULT, LVL_ERROR, "Error updating partition indices");
527 goto error;
528 }
529
530 rc = vbds_part_add(disk, lpart, &part);
531 if (rc != EOK) {
532 log_msg(LOG_DEFAULT, LVL_ERROR, "Failed while creating "
533 "partition.");
534 rc = label_part_destroy(lpart);
535 if (rc != EOK)
536 log_msg(LOG_DEFAULT, LVL_ERROR,
537 "Cannot roll back partition creation.");
538 rc = EIO;
539 goto error;
540 }
541
542 if (rpart != NULL)
543 *rpart = part->pid;
544 return EOK;
545error:
546 return rc;
547}
548
549int vbds_part_delete(vbds_part_id_t partid)
550{
551 vbds_part_t *part;
552 vbds_disk_t *disk;
553 label_part_t *lpart;
554 int rc;
555
556 rc = vbds_part_by_pid(partid, &part);
557 if (rc != EOK)
558 return rc;
559
560 disk = part->disk;
561
562 rc = vbds_part_remove(part, &lpart);
563 if (rc != EOK)
564 return rc;
565
566 rc = label_part_destroy(lpart);
567 if (rc != EOK) {
568 log_msg(LOG_DEFAULT, LVL_ERROR, "Failed deleting partition");
569
570 /* Try rolling back */
571 rc = vbds_part_add(disk, lpart, NULL);
572 if (rc != EOK)
573 log_msg(LOG_DEFAULT, LVL_ERROR, "Failed rolling back.");
574
575 return EIO;
576 }
577
578 rc = vbds_part_indices_update(disk);
579 if (rc != EOK) {
580 log_msg(LOG_DEFAULT, LVL_ERROR, "Error updating partition indices");
581 return EIO;
582 }
583
584 return EOK;
585}
586
587int vbds_suggest_ptype(service_id_t sid, label_pcnt_t pcnt,
588 label_ptype_t *ptype)
589{
590 vbds_disk_t *disk;
591 int rc;
592
593 rc = vbds_disk_by_svcid(sid, &disk);
594 if (rc != EOK) {
595 log_msg(LOG_DEFAULT, LVL_NOTE, "Disk %zu not found",
596 sid);
597 goto error;
598 }
599
600 rc = label_suggest_ptype(disk->label, pcnt, ptype);
601 if (rc != EOK) {
602 log_msg(LOG_DEFAULT, LVL_NOTE, "label_suggest_ptype() failed");
603 goto error;
604 }
605
606 return EOK;
607error:
608 return rc;
609}
610
611static int vbds_bd_open(bd_srvs_t *bds, bd_srv_t *bd)
612{
613 vbds_part_t *part = bd_srv_part(bd);
614
615 log_msg(LOG_DEFAULT, LVL_NOTE, "vbds_bd_open()");
616 part->open_cnt++;
617 return EOK;
618}
619
620static int vbds_bd_close(bd_srv_t *bd)
621{
622 vbds_part_t *part = bd_srv_part(bd);
623
624 log_msg(LOG_DEFAULT, LVL_NOTE, "vbds_bd_close()");
625 part->open_cnt--;
626 return EOK;
627}
628
629static int vbds_bd_read_blocks(bd_srv_t *bd, aoff64_t ba, size_t cnt,
630 void *buf, size_t size)
631{
632 vbds_part_t *part = bd_srv_part(bd);
633 aoff64_t gba;
634
635 log_msg(LOG_DEFAULT, LVL_NOTE, "vbds_bd_read_blocks()");
636
637 if (cnt * part->disk->block_size < size)
638 return EINVAL;
639
640 if (vbds_bsa_translate(part, ba, cnt, &gba) != EOK)
641 return ELIMIT;
642
643 return block_read_direct(part->disk->svc_id, gba, cnt, buf);
644}
645
646static int vbds_bd_sync_cache(bd_srv_t *bd, aoff64_t ba, size_t cnt)
647{
648 vbds_part_t *part = bd_srv_part(bd);
649 aoff64_t gba;
650
651 log_msg(LOG_DEFAULT, LVL_NOTE, "vbds_bd_sync_cache()");
652
653 /* XXX Allow full-disk sync? */
654 if (ba != 0 || cnt != 0) {
655 if (vbds_bsa_translate(part, ba, cnt, &gba) != EOK)
656 return ELIMIT;
657 } else {
658 gba = 0;
659 }
660
661 return block_sync_cache(part->disk->svc_id, gba, cnt);
662}
663
664static int vbds_bd_write_blocks(bd_srv_t *bd, aoff64_t ba, size_t cnt,
665 const void *buf, size_t size)
666{
667 vbds_part_t *part = bd_srv_part(bd);
668 aoff64_t gba;
669
670 log_msg(LOG_DEFAULT, LVL_NOTE, "vbds_bd_write_blocks()");
671
672 if (cnt * part->disk->block_size < size)
673 return EINVAL;
674
675 if (vbds_bsa_translate(part, ba, cnt, &gba) != EOK)
676 return ELIMIT;
677
678 return block_write_direct(part->disk->svc_id, gba, cnt, buf);
679}
680
681static int vbds_bd_get_block_size(bd_srv_t *bd, size_t *rsize)
682{
683 vbds_part_t *part = bd_srv_part(bd);
684
685 log_msg(LOG_DEFAULT, LVL_NOTE, "vbds_bd_get_block_size()");
686 *rsize = part->disk->block_size;
687 return EOK;
688}
689
690static int vbds_bd_get_num_blocks(bd_srv_t *bd, aoff64_t *rnb)
691{
692 vbds_part_t *part = bd_srv_part(bd);
693
694 log_msg(LOG_DEFAULT, LVL_NOTE, "vbds_bd_get_num_blocks()");
695 *rnb = part->nblocks;
696 return EOK;
697}
698
699void vbds_bd_conn(ipc_callid_t iid, ipc_call_t *icall, void *arg)
700{
701 vbds_part_t *part;
702 int rc;
703 service_id_t svcid;
704
705 log_msg(LOG_DEFAULT, LVL_NOTE, "vbds_bd_conn()");
706
707 svcid = IPC_GET_ARG1(*icall);
708
709 log_msg(LOG_DEFAULT, LVL_NOTE, "vbds_bd_conn() - svcid=%zu", svcid);
710
711 rc = vbds_part_by_svcid(svcid, &part);
712 if (rc != EOK) {
713 log_msg(LOG_DEFAULT, LVL_NOTE, "vbd_bd_conn() - partition "
714 "not found.");
715 async_answer_0(iid, EINVAL);
716 return;
717 }
718
719 log_msg(LOG_DEFAULT, LVL_NOTE, "vbds_bd_conn() - call bd_conn");
720 bd_conn(iid, icall, &part->bds);
721}
722
723/** Translate block segment address with range checking. */
724static int vbds_bsa_translate(vbds_part_t *part, aoff64_t ba, size_t cnt,
725 aoff64_t *gba)
726{
727 if (ba + cnt > part->nblocks)
728 return ELIMIT;
729
730 *gba = part->block0 + ba;
731 return EOK;
732}
733
734/** Register service for partition */
735static int vbds_part_svc_register(vbds_part_t *part)
736{
737 char *name;
738 service_id_t psid;
739 int idx;
740 int rc;
741
742 idx = part->lpart->index;
743
744 rc = asprintf(&name, "%sp%u", part->disk->svc_name, idx);
745 if (rc < 0) {
746 log_msg(LOG_DEFAULT, LVL_ERROR, "Out of memory.");
747 return ENOMEM;
748 }
749
750 rc = loc_service_register(name, &psid);
751 if (rc != EOK) {
752 log_msg(LOG_DEFAULT, LVL_ERROR, "Failed registering "
753 "service %s.", name);
754 free(name);
755 free(part);
756 return EIO;
757 }
758
759 free(name);
760 part->svc_id = psid;
761 part->reg_idx = idx;
762 return EOK;
763}
764
765/** Unregister service for partition */
766static int vbds_part_svc_unregister(vbds_part_t *part)
767{
768 int rc;
769
770 rc = loc_service_unregister(part->svc_id);
771 if (rc != EOK)
772 return EIO;
773
774 part->svc_id = 0;
775 part->reg_idx = 0;
776 return EOK;
777}
778
779/** Update service names for any partition whose index has changed. */
780static int vbds_part_indices_update(vbds_disk_t *disk)
781{
782 label_part_info_t lpinfo;
783 int rc;
784
785 log_msg(LOG_DEFAULT, LVL_NOTE, "vbds_part_indices_update()");
786
787 /* First unregister services for partitions whose index has changed */
788 list_foreach(disk->parts, ldisk, vbds_part_t, part) {
789 if (part->svc_id != 0 && part->lpart->index != part->reg_idx) {
790 rc = vbds_part_svc_unregister(part);
791 if (rc != EOK) {
792 log_msg(LOG_DEFAULT, LVL_NOTE, "Error "
793 "un-registering partition.");
794 return EIO;
795 }
796 }
797 }
798
799 /* Now re-register those services under the new indices */
800 list_foreach(disk->parts, ldisk, vbds_part_t, part) {
801 label_part_get_info(part->lpart, &lpinfo);
802 if (part->svc_id == 0 && lpinfo.pkind != lpk_extended) {
803 rc = vbds_part_svc_register(part);
804 if (rc != EOK) {
805 log_msg(LOG_DEFAULT, LVL_NOTE, "Error "
806 "re-registering partition.");
807 return EIO;
808 }
809 }
810 }
811
812 return EOK;
813}
814
815/** @}
816 */
Note: See TracBrowser for help on using the repository browser.