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

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

Fix vertical spacing with new Ccheck revision.

  • Property mode set to 100644
File size: 29.2 KB
RevLine 
[28ed0d95]1/*
[e11c527]2 * Copyright (c) 2016 Jiri Svoboda
[28ed0d95]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>
[78d50bd]37#include <bd_srv.h>
38#include <block.h>
[28ed0d95]39#include <errno.h>
[c1694b6b]40#include <str_error.h>
[28ed0d95]41#include <io/log.h>
[5772aa1]42#include <label/empty.h>
43#include <label/label.h>
[78d50bd]44#include <loc.h>
45#include <stdio.h>
[28ed0d95]46#include <stdlib.h>
47#include <task.h>
[6a0d4ce2]48#include <vbd.h>
[28ed0d95]49
50#include "disk.h"
51#include "types/vbd.h"
52
[372df8f]53static fibril_mutex_t vbds_disks_lock;
[28ed0d95]54static list_t vbds_disks; /* of vbds_disk_t */
[e11c527]55static fibril_mutex_t vbds_parts_lock;
[78d50bd]56static list_t vbds_parts; /* of vbds_part_t */
57
[372df8f]58static category_id_t part_cid;
59
[b7fd2a0]60static errno_t vbds_disk_parts_add(vbds_disk_t *, label_t *);
61static errno_t vbds_disk_parts_remove(vbds_disk_t *, vbds_rem_flag_t);
62
63static errno_t vbds_bd_open(bd_srvs_t *, bd_srv_t *);
64static errno_t vbds_bd_close(bd_srv_t *);
65static errno_t vbds_bd_read_blocks(bd_srv_t *, aoff64_t, size_t, void *, size_t);
66static errno_t vbds_bd_sync_cache(bd_srv_t *, aoff64_t, size_t);
67static errno_t vbds_bd_write_blocks(bd_srv_t *, aoff64_t, size_t, const void *,
[78d50bd]68 size_t);
[b7fd2a0]69static errno_t vbds_bd_get_block_size(bd_srv_t *, size_t *);
70static errno_t vbds_bd_get_num_blocks(bd_srv_t *, aoff64_t *);
[78d50bd]71
[b7fd2a0]72static errno_t vbds_bsa_translate(vbds_part_t *, aoff64_t, size_t, aoff64_t *);
[78d50bd]73
[b7fd2a0]74static errno_t vbds_part_svc_register(vbds_part_t *);
75static errno_t vbds_part_svc_unregister(vbds_part_t *);
76static errno_t vbds_part_indices_update(vbds_disk_t *);
[6439741]77
[c43db5f]78static vbd_part_id_t vbds_part_id = 1;
79
[b7fd2a0]80static errno_t vbds_label_get_bsize(void *, size_t *);
81static errno_t vbds_label_get_nblocks(void *, aoff64_t *);
82static errno_t vbds_label_read(void *, aoff64_t, size_t, void *);
83static errno_t vbds_label_write(void *, aoff64_t, size_t, const void *);
[deacc58d]84
85/** Block device operations provided by VBD */
[78d50bd]86static bd_ops_t vbds_bd_ops = {
87 .open = vbds_bd_open,
88 .close = vbds_bd_close,
89 .read_blocks = vbds_bd_read_blocks,
90 .sync_cache = vbds_bd_sync_cache,
91 .write_blocks = vbds_bd_write_blocks,
92 .get_block_size = vbds_bd_get_block_size,
93 .get_num_blocks = vbds_bd_get_num_blocks
94};
95
[deacc58d]96/** Provide disk access to liblabel */
97static label_bd_ops_t vbds_label_bd_ops = {
98 .get_bsize = vbds_label_get_bsize,
99 .get_nblocks = vbds_label_get_nblocks,
100 .read = vbds_label_read,
101 .write = vbds_label_write
102};
103
[78d50bd]104static vbds_part_t *bd_srv_part(bd_srv_t *bd)
105{
106 return (vbds_part_t *)bd->srvs->sarg;
107}
[28ed0d95]108
[3a9cf35]109static vbds_disk_t *vbds_disk_first(void)
110{
111 link_t *link;
112
113 link = list_first(&vbds_disks);
114 if (link == NULL)
115 return NULL;
116
117 return list_get_instance(link, vbds_disk_t, ldisks);
118}
119
120static vbds_disk_t *vbds_disk_next(vbds_disk_t *disk)
121{
122 link_t *link;
123
124 if (disk == NULL)
125 return NULL;
126
127 link = list_next(&disk->ldisks, &vbds_disks);
128 if (link == NULL)
129 return NULL;
130
131 return list_get_instance(link, vbds_disk_t, ldisks);
132}
133
[b7fd2a0]134errno_t vbds_disks_init(void)
[28ed0d95]135{
[b7fd2a0]136 errno_t rc;
[372df8f]137
138 fibril_mutex_initialize(&vbds_disks_lock);
[28ed0d95]139 list_initialize(&vbds_disks);
[e11c527]140 fibril_mutex_initialize(&vbds_parts_lock);
[78d50bd]141 list_initialize(&vbds_parts);
[372df8f]142
143 rc = loc_category_get_id("partition", &part_cid, 0);
144 if (rc != EOK) {
145 log_msg(LOG_DEFAULT, LVL_ERROR, "Error looking up partition "
146 "category.");
147 return EIO;
148 }
149
150 return EOK;
151}
152
[3a9cf35]153/** Check for new/removed disk devices */
[b7fd2a0]154static errno_t vbds_disks_check_new(void)
[372df8f]155{
156 bool already_known;
157 category_id_t disk_cat;
158 service_id_t *svcs;
159 size_t count, i;
[3a9cf35]160 vbds_disk_t *cur, *next;
[b7fd2a0]161 errno_t rc;
[372df8f]162
[3a9cf35]163 log_msg(LOG_DEFAULT, LVL_DEBUG, "vbds_disks_check_new()");
164
[372df8f]165 fibril_mutex_lock(&vbds_disks_lock);
166
167 rc = loc_category_get_id("disk", &disk_cat, IPC_FLAG_BLOCKING);
168 if (rc != EOK) {
169 log_msg(LOG_DEFAULT, LVL_ERROR, "Failed resolving category 'disk'.");
170 fibril_mutex_unlock(&vbds_disks_lock);
171 return ENOENT;
172 }
173
174 rc = loc_category_get_svcs(disk_cat, &svcs, &count);
175 if (rc != EOK) {
176 log_msg(LOG_DEFAULT, LVL_ERROR, "Failed getting list of disk "
177 "devices.");
178 fibril_mutex_unlock(&vbds_disks_lock);
179 return EIO;
180 }
181
[3a9cf35]182 list_foreach(vbds_disks, ldisks, vbds_disk_t, disk)
[774aa332]183 disk->present = false;
[3a9cf35]184
[372df8f]185 for (i = 0; i < count; i++) {
186 already_known = false;
187
188 list_foreach(vbds_disks, ldisks, vbds_disk_t, disk) {
189 if (disk->svc_id == svcs[i]) {
190 already_known = true;
[3a9cf35]191 disk->present = true;
[372df8f]192 break;
193 }
194 }
195
196 if (!already_known) {
197 log_msg(LOG_DEFAULT, LVL_NOTE, "Found disk '%lu'",
198 (unsigned long) svcs[i]);
199 rc = vbds_disk_add(svcs[i]);
200 if (rc != EOK) {
201 log_msg(LOG_DEFAULT, LVL_ERROR, "Could not add "
202 "disk.");
203 }
[3a9cf35]204 } else {
205 log_msg(LOG_DEFAULT, LVL_DEBUG, "Disk %lu already known",
206 (unsigned long) svcs[i]);
[372df8f]207 }
208 }
209
[3a9cf35]210 cur = vbds_disk_first();
211 while (cur != NULL) {
212 next = vbds_disk_next(cur);
213 if (!cur->present) {
214 log_msg(LOG_DEFAULT, LVL_NOTE, "Disk '%lu' is gone",
215 (unsigned long) cur->svc_id);
216 rc = vbds_disk_remove(cur->svc_id);
217 if (rc != EOK) {
218 log_msg(LOG_DEFAULT, LVL_ERROR, "Could not "
219 "remove disk.");
220 }
221 }
222
223 cur = next;
224 }
225
[372df8f]226 fibril_mutex_unlock(&vbds_disks_lock);
227 return EOK;
[28ed0d95]228}
229
[b7fd2a0]230static errno_t vbds_disk_by_svcid(service_id_t sid, vbds_disk_t **rdisk)
[28ed0d95]231{
232 list_foreach(vbds_disks, ldisks, vbds_disk_t, disk) {
233 if (disk->svc_id == sid) {
234 *rdisk = disk;
235 return EOK;
236 }
237 }
238
239 return ENOENT;
240}
241
[e11c527]242static void vbds_part_add_ref(vbds_part_t *part)
243{
244 log_msg(LOG_DEFAULT, LVL_DEBUG2, "vbds_part_add_ref");
[498ced1]245 refcount_up(&part->refcnt);
[e11c527]246}
247
248static void vbds_part_del_ref(vbds_part_t *part)
249{
250 log_msg(LOG_DEFAULT, LVL_DEBUG2, "vbds_part_del_ref");
[498ced1]251 if (refcount_down(&part->refcnt)) {
[e11c527]252 log_msg(LOG_DEFAULT, LVL_DEBUG2, " - free part");
253 free(part);
254 }
255}
256
[b7fd2a0]257static errno_t vbds_part_by_pid(vbds_part_id_t partid, vbds_part_t **rpart)
[c43db5f]258{
[55f8c6e7]259 log_msg(LOG_DEFAULT, LVL_DEBUG, "vbds_part_by_pid(%zu)", partid);
[c43db5f]260
[e11c527]261 fibril_mutex_lock(&vbds_parts_lock);
262
[c43db5f]263 list_foreach(vbds_parts, lparts, vbds_part_t, part) {
[55f8c6e7]264 log_msg(LOG_DEFAULT, LVL_DEBUG, "%zu == %zu ?", part->pid, partid);
[c43db5f]265 if (part->pid == partid) {
[55f8c6e7]266 log_msg(LOG_DEFAULT, LVL_DEBUG, "Found match.");
[e11c527]267 vbds_part_add_ref(part);
268 fibril_mutex_unlock(&vbds_parts_lock);
[c43db5f]269 *rpart = part;
270 return EOK;
271 }
272 }
273
[e11c527]274 fibril_mutex_unlock(&vbds_parts_lock);
[55f8c6e7]275 log_msg(LOG_DEFAULT, LVL_DEBUG, "No match.");
[c43db5f]276 return ENOENT;
277}
278
[b7fd2a0]279static errno_t vbds_part_by_svcid(service_id_t svcid, vbds_part_t **rpart)
[78d50bd]280{
[55f8c6e7]281 log_msg(LOG_DEFAULT, LVL_DEBUG, "vbds_part_by_svcid(%zu)", svcid);
[3faa03d]282
[e11c527]283 fibril_mutex_lock(&vbds_parts_lock);
284
[78d50bd]285 list_foreach(vbds_parts, lparts, vbds_part_t, part) {
[55f8c6e7]286 log_msg(LOG_DEFAULT, LVL_DEBUG, "%zu == %zu ?", part->svc_id, svcid);
[c43db5f]287 if (part->svc_id == svcid) {
[55f8c6e7]288 log_msg(LOG_DEFAULT, LVL_DEBUG, "Found match.");
[e11c527]289 vbds_part_add_ref(part);
290 fibril_mutex_unlock(&vbds_parts_lock);
[78d50bd]291 *rpart = part;
292 return EOK;
293 }
294 }
295
[e11c527]296 fibril_mutex_unlock(&vbds_parts_lock);
[55f8c6e7]297 log_msg(LOG_DEFAULT, LVL_DEBUG, "No match.");
[78d50bd]298 return ENOENT;
299}
300
[99c23405]301/** Add partition to our inventory based on liblabel partition structure */
[b7fd2a0]302static errno_t vbds_part_add(vbds_disk_t *disk, label_part_t *lpart,
[6bc542b]303 vbds_part_t **rpart)
[28ed0d95]304{
305 vbds_part_t *part;
[c43db5f]306 service_id_t psid = 0;
[78d50bd]307 label_part_info_t lpinfo;
[b7fd2a0]308 errno_t rc;
[28ed0d95]309
[55f8c6e7]310 log_msg(LOG_DEFAULT, LVL_DEBUG, "vbds_part_add(%s, %p)",
[78d50bd]311 disk->svc_name, lpart);
[28ed0d95]312
[b7a4d06]313 label_part_get_info(lpart, &lpinfo);
314
[28ed0d95]315 part = calloc(1, sizeof(vbds_part_t));
316 if (part == NULL) {
317 log_msg(LOG_DEFAULT, LVL_ERROR, "Out of memory.");
318 return ENOMEM;
319 }
320
[e11c527]321 fibril_rwlock_initialize(&part->lock);
322
[28ed0d95]323 part->lpart = lpart;
324 part->disk = disk;
[c43db5f]325 part->pid = ++vbds_part_id;
326 part->svc_id = psid;
[78d50bd]327 part->block0 = lpinfo.block0;
328 part->nblocks = lpinfo.nblocks;
[498ced1]329 refcount_init(&part->refcnt);
[78d50bd]330
331 bd_srvs_init(&part->bds);
332 part->bds.ops = &vbds_bd_ops;
333 part->bds.sarg = part;
334
[6439741]335 if (lpinfo.pkind != lpk_extended) {
336 rc = vbds_part_svc_register(part);
[e11c527]337 if (rc != EOK) {
338 free(part);
[6439741]339 return EIO;
[e11c527]340 }
[6439741]341 }
342
[28ed0d95]343 list_append(&part->ldisk, &disk->parts);
[e11c527]344 fibril_mutex_lock(&vbds_parts_lock);
[78d50bd]345 list_append(&part->lparts, &vbds_parts);
[e11c527]346 fibril_mutex_unlock(&vbds_parts_lock);
[28ed0d95]347
[55f8c6e7]348 log_msg(LOG_DEFAULT, LVL_DEBUG, "vbds_part_add -> %p", part);
[3a43785]349
[6bc542b]350 if (rpart != NULL)
351 *rpart = part;
[28ed0d95]352 return EOK;
353}
354
[99c23405]355/** Remove partition from our inventory leaving only the underlying liblabel
356 * partition structure.
[e11c527]357 *
[58563585]358 * @param part Partition
359 * @param flag If set to @c vrf_force, force removal even if partition is in use
[e11c527]360 * @param rlpart Place to store pointer to liblabel partition
[58563585]361 *
[99c23405]362 */
[b7fd2a0]363static errno_t vbds_part_remove(vbds_part_t *part, vbds_rem_flag_t flag,
[e11c527]364 label_part_t **rlpart)
[99c23405]365{
366 label_part_t *lpart;
[b7fd2a0]367 errno_t rc;
[99c23405]368
[55f8c6e7]369 log_msg(LOG_DEFAULT, LVL_DEBUG, "vbds_part_remove(%p)", part);
[99c23405]370
[e11c527]371 fibril_rwlock_write_lock(&part->lock);
[99c23405]372 lpart = part->lpart;
373
[e11c527]374 if ((flag & vrf_force) == 0 && part->open_cnt > 0) {
375 fibril_rwlock_write_unlock(&part->lock);
[55f8c6e7]376 log_msg(LOG_DEFAULT, LVL_DEBUG, "part->open_cnt = %d",
[3a43785]377 part->open_cnt);
[99c23405]378 return EBUSY;
[3a43785]379 }
[99c23405]380
[c43db5f]381 if (part->svc_id != 0) {
[6439741]382 rc = vbds_part_svc_unregister(part);
[e11c527]383 if (rc != EOK) {
384 fibril_rwlock_write_unlock(&part->lock);
[c43db5f]385 return EIO;
[e11c527]386 }
[c43db5f]387 }
[99c23405]388
389 list_remove(&part->ldisk);
[e11c527]390 fibril_mutex_lock(&vbds_parts_lock);
[99c23405]391 list_remove(&part->lparts);
[e11c527]392 fibril_mutex_unlock(&vbds_parts_lock);
393
394 vbds_part_del_ref(part);
395 part->lpart = NULL;
396 fibril_rwlock_write_unlock(&part->lock);
[99c23405]397
398 if (rlpart != NULL)
399 *rlpart = lpart;
400 return EOK;
401}
402
[3a43785]403/** Remove all disk partitions from our inventory leaving only the underlying
[7c3fb9b]404 * liblabel partition structures.
405 */
[b7fd2a0]406static errno_t vbds_disk_parts_add(vbds_disk_t *disk, label_t *label)
[3a43785]407{
408 label_part_t *part;
[b7fd2a0]409 errno_t rc;
[3a43785]410
411 part = label_part_first(label);
412 while (part != NULL) {
413 rc = vbds_part_add(disk, part, NULL);
414 if (rc != EOK) {
415 log_msg(LOG_DEFAULT, LVL_ERROR, "Failed adding partition "
416 "(disk %s)", disk->svc_name);
417 return rc;
418 }
419
420 part = label_part_next(part);
421 }
422
423 return EOK;
424}
425
426/** Remove all disk partitions from our inventory leaving only the underlying
[7c3fb9b]427 * liblabel partition structures.
428 */
[b7fd2a0]429static errno_t vbds_disk_parts_remove(vbds_disk_t *disk, vbds_rem_flag_t flag)
[3a43785]430{
431 link_t *link;
432 vbds_part_t *part;
[b7fd2a0]433 errno_t rc;
[3a43785]434
435 link = list_first(&disk->parts);
436 while (link != NULL) {
437 part = list_get_instance(link, vbds_part_t, ldisk);
[e11c527]438 rc = vbds_part_remove(part, flag, NULL);
[3a43785]439 if (rc != EOK)
440 return rc;
441
442 link = list_first(&disk->parts);
443 }
444
445 return EOK;
446}
447
[e89a06a]448static void vbds_disk_cat_change_cb(void *arg)
[372df8f]449{
450 (void) vbds_disks_check_new();
451}
452
[b7fd2a0]453errno_t vbds_disk_discovery_start(void)
[372df8f]454{
[b7fd2a0]455 errno_t rc;
[372df8f]456
[e89a06a]457 rc = loc_register_cat_change_cb(vbds_disk_cat_change_cb, NULL);
[372df8f]458 if (rc != EOK) {
459 log_msg(LOG_DEFAULT, LVL_ERROR, "Failed registering callback "
[c1694b6b]460 "for disk discovery: %s.", str_error(rc));
[372df8f]461 return rc;
462 }
463
464 return vbds_disks_check_new();
465}
466
[b7fd2a0]467errno_t vbds_disk_add(service_id_t sid)
[28ed0d95]468{
[3faa03d]469 label_t *label = NULL;
[deacc58d]470 label_bd_t lbd;
[78d50bd]471 vbds_disk_t *disk = NULL;
472 bool block_inited = false;
473 size_t block_size;
[53e3950]474 aoff64_t nblocks;
[b7fd2a0]475 errno_t rc;
[28ed0d95]476
[55f8c6e7]477 log_msg(LOG_DEFAULT, LVL_DEBUG, "vbds_disk_add(%zu)", sid);
[28ed0d95]478
479 /* Check for duplicates */
480 rc = vbds_disk_by_svcid(sid, &disk);
481 if (rc == EOK)
[ff381a7]482 return EEXIST;
[28ed0d95]483
484 disk = calloc(1, sizeof(vbds_disk_t));
485 if (disk == NULL)
486 return ENOMEM;
487
[deacc58d]488 /* Must be set before calling label_open */
489 disk->svc_id = sid;
490
[78d50bd]491 rc = loc_service_get_name(sid, &disk->svc_name);
492 if (rc != EOK) {
493 log_msg(LOG_DEFAULT, LVL_ERROR, "Failed getting disk service name.");
494 rc = EIO;
495 goto error;
496 }
497
[55f8c6e7]498 log_msg(LOG_DEFAULT, LVL_DEBUG, "block_init(%zu)", sid);
[ff381a7]499 rc = block_init(sid, 2048);
[78d50bd]500 if (rc != EOK) {
501 log_msg(LOG_DEFAULT, LVL_ERROR, "Failed opening block device %s.",
502 disk->svc_name);
503 rc = EIO;
504 goto error;
505 }
506
507 rc = block_get_bsize(sid, &block_size);
508 if (rc != EOK) {
509 log_msg(LOG_DEFAULT, LVL_ERROR, "Failed getting block size of %s.",
510 disk->svc_name);
511 rc = EIO;
512 goto error;
513 }
514
[53e3950]515 rc = block_get_nblocks(sid, &nblocks);
516 if (rc != EOK) {
517 log_msg(LOG_DEFAULT, LVL_ERROR, "Failed getting number of "
518 "blocks of %s.", disk->svc_name);
519 rc = EIO;
520 goto error;
521 }
522
[78d50bd]523 block_inited = true;
524
[deacc58d]525 lbd.ops = &vbds_label_bd_ops;
526 lbd.arg = (void *) disk;
527
528 rc = label_open(&lbd, &label);
[78d50bd]529 if (rc != EOK) {
[55f8c6e7]530 log_msg(LOG_DEFAULT, LVL_ERROR, "Failed to open label in disk %s.",
[3faa03d]531 disk->svc_name);
[78d50bd]532 rc = EIO;
[28ed0d95]533 goto error;
[78d50bd]534 }
[28ed0d95]535
536 disk->label = label;
[78d50bd]537 disk->block_size = block_size;
[53e3950]538 disk->nblocks = nblocks;
[3a9cf35]539 disk->present = true;
[78d50bd]540
[28ed0d95]541 list_initialize(&disk->parts);
542 list_append(&disk->ldisks, &vbds_disks);
543
[3faa03d]544 log_msg(LOG_DEFAULT, LVL_NOTE, "Recognized disk label. Adding partitions.");
545
[3a43785]546 (void) vbds_disk_parts_add(disk, label);
[28ed0d95]547 return EOK;
548error:
[78d50bd]549 label_close(label);
[603c1d1f]550 if (block_inited) {
[55f8c6e7]551 log_msg(LOG_DEFAULT, LVL_DEBUG, "block_fini(%zu)", sid);
[78d50bd]552 block_fini(sid);
[603c1d1f]553 }
[78d50bd]554 if (disk != NULL)
555 free(disk->svc_name);
[28ed0d95]556 free(disk);
557 return rc;
558}
559
[b7fd2a0]560errno_t vbds_disk_remove(service_id_t sid)
[28ed0d95]561{
562 vbds_disk_t *disk;
[b7fd2a0]563 errno_t rc;
[28ed0d95]564
[55f8c6e7]565 log_msg(LOG_DEFAULT, LVL_DEBUG, "vbds_disk_remove(%zu)", sid);
[28ed0d95]566
567 rc = vbds_disk_by_svcid(sid, &disk);
568 if (rc != EOK)
569 return rc;
570
[e11c527]571 rc = vbds_disk_parts_remove(disk, vrf_force);
[3a43785]572 if (rc != EOK) {
573 log_msg(LOG_DEFAULT, LVL_ERROR, "Failed removing disk.");
574 return rc;
575 }
576
[28ed0d95]577 list_remove(&disk->ldisks);
578 label_close(disk->label);
[55f8c6e7]579 log_msg(LOG_DEFAULT, LVL_DEBUG, "block_fini(%zu)", sid);
[603c1d1f]580 block_fini(sid);
[28ed0d95]581 free(disk);
582 return EOK;
583}
584
[372df8f]585/** Get list of disks as array of service IDs. */
[b7fd2a0]586errno_t vbds_disk_get_ids(service_id_t *id_buf, size_t buf_size, size_t *act_size)
[372df8f]587{
588 size_t act_cnt;
589 size_t buf_cnt;
590
591 fibril_mutex_lock(&vbds_disks_lock);
592
593 buf_cnt = buf_size / sizeof(service_id_t);
594
595 act_cnt = list_count(&vbds_disks);
596 *act_size = act_cnt * sizeof(service_id_t);
597
598 if (buf_size % sizeof(service_id_t) != 0) {
599 fibril_mutex_unlock(&vbds_disks_lock);
600 return EINVAL;
601 }
602
603 size_t pos = 0;
604 list_foreach(vbds_disks, ldisks, vbds_disk_t, disk) {
605 if (pos < buf_cnt)
606 id_buf[pos] = disk->svc_id;
607 pos++;
608 }
609
610 fibril_mutex_unlock(&vbds_disks_lock);
611 return EOK;
612}
613
[b7fd2a0]614errno_t vbds_disk_info(service_id_t sid, vbd_disk_info_t *info)
[28ed0d95]615{
[1626cd4]616 vbds_disk_t *disk;
617 label_info_t linfo;
[b7fd2a0]618 errno_t rc;
[1626cd4]619
[55f8c6e7]620 log_msg(LOG_DEFAULT, LVL_DEBUG, "vbds_disk_info(%zu)", sid);
[1626cd4]621
622 rc = vbds_disk_by_svcid(sid, &disk);
623 if (rc != EOK)
624 return rc;
625
626 rc = label_get_info(disk->label, &linfo);
[6a0db524]627 if (rc != EOK)
628 return rc;
[1626cd4]629
630 info->ltype = linfo.ltype;
[b7a4d06]631 info->flags = linfo.flags;
[1626cd4]632 info->ablock0 = linfo.ablock0;
633 info->anblocks = linfo.anblocks;
634 info->block_size = disk->block_size;
[53e3950]635 info->nblocks = disk->nblocks;
[55f8c6e7]636 log_msg(LOG_DEFAULT, LVL_DEBUG, "vbds_disk_info - block_size=%zu",
[c02d098]637 info->block_size);
[1626cd4]638 return EOK;
639}
640
[b7fd2a0]641errno_t vbds_get_parts(service_id_t sid, service_id_t *id_buf, size_t buf_size,
[1626cd4]642 size_t *act_size)
643{
644 vbds_disk_t *disk;
645 size_t act_cnt;
646 size_t buf_cnt;
[b7fd2a0]647 errno_t rc;
[1626cd4]648
649 rc = vbds_disk_by_svcid(sid, &disk);
650 if (rc != EOK)
651 return rc;
652
653 buf_cnt = buf_size / sizeof(service_id_t);
654
655 act_cnt = list_count(&disk->parts);
656 *act_size = act_cnt * sizeof(service_id_t);
657
658 if (buf_size % sizeof(service_id_t) != 0)
659 return EINVAL;
660
661 size_t pos = 0;
662 list_foreach(disk->parts, ldisk, vbds_part_t, part) {
663 if (pos < buf_cnt)
[c43db5f]664 id_buf[pos] = part->pid;
[1626cd4]665 pos++;
666 }
667
[28ed0d95]668 return EOK;
669}
670
[b7fd2a0]671errno_t vbds_label_create(service_id_t sid, label_type_t ltype)
[28ed0d95]672{
673 label_t *label;
[deacc58d]674 label_bd_t lbd;
[6a0db524]675 label_info_t linfo;
[28ed0d95]676 vbds_disk_t *disk;
[b7fd2a0]677 errno_t rc, rc2;
[28ed0d95]678
[55f8c6e7]679 log_msg(LOG_DEFAULT, LVL_DEBUG, "vbds_label_create(%zu)", sid);
[28ed0d95]680
[3a43785]681 /* Find disk */
[28ed0d95]682 rc = vbds_disk_by_svcid(sid, &disk);
[3a43785]683 if (rc != EOK)
684 return rc;
[28ed0d95]685
[55f8c6e7]686 log_msg(LOG_DEFAULT, LVL_DEBUG, "vbds_label_create(%zu) - label_close", sid);
[603c1d1f]687
[6a0db524]688 /* Verify that current label is a dummy label */
689 rc = label_get_info(disk->label, &linfo);
690 if (rc != EOK)
691 return rc;
692
693 if (linfo.ltype != lt_none) {
694 log_msg(LOG_DEFAULT, LVL_ERROR, "Label already exists.");
695 return EEXIST;
696 }
697
[3a43785]698 /* Close dummy label first */
[e11c527]699 rc = vbds_disk_parts_remove(disk, vrf_none);
[603c1d1f]700 if (rc != EOK) {
[3a43785]701 log_msg(LOG_DEFAULT, LVL_ERROR, "Failed removing disk.");
702 return rc;
[603c1d1f]703 }
704
[3a43785]705 label_close(disk->label);
706 disk->label = NULL;
[603c1d1f]707
[55f8c6e7]708 log_msg(LOG_DEFAULT, LVL_DEBUG, "vbds_label_create(%zu) - label_create", sid);
[603c1d1f]709
[deacc58d]710 lbd.ops = &vbds_label_bd_ops;
711 lbd.arg = (void *) disk;
712
713 rc = label_create(&lbd, ltype, &label);
[28ed0d95]714 if (rc != EOK)
715 goto error;
716
[3a43785]717 (void) vbds_disk_parts_add(disk, label);
[28ed0d95]718 disk->label = label;
[603c1d1f]719
[55f8c6e7]720 log_msg(LOG_DEFAULT, LVL_DEBUG, "vbds_label_create(%zu) - success", sid);
[28ed0d95]721 return EOK;
722error:
[55f8c6e7]723 log_msg(LOG_DEFAULT, LVL_DEBUG, "vbds_label_create(%zu) - failure", sid);
[3a43785]724 if (disk->label == NULL) {
[deacc58d]725 lbd.ops = &vbds_label_bd_ops;
726 lbd.arg = (void *) disk;
727
728 rc2 = label_open(&lbd, &label);
[f63a0073]729 if (rc2 != EOK) {
[55f8c6e7]730 log_msg(LOG_DEFAULT, LVL_ERROR, "Failed to open label in disk %s.",
[3a43785]731 disk->svc_name);
[f63a0073]732 return rc2;
[3a43785]733 }
[f63a0073]734
735 disk->label = label;
736 (void) vbds_disk_parts_add(disk, label);
[603c1d1f]737 }
[3a43785]738
[28ed0d95]739 return rc;
740}
741
[b7fd2a0]742errno_t vbds_label_delete(service_id_t sid)
[28ed0d95]743{
744 vbds_disk_t *disk;
[3a43785]745 label_t *label;
[deacc58d]746 label_bd_t lbd;
[b7fd2a0]747 errno_t rc;
[28ed0d95]748
[55f8c6e7]749 log_msg(LOG_DEFAULT, LVL_DEBUG, "vbds_label_delete(%zu)", sid);
[28ed0d95]750
751 rc = vbds_disk_by_svcid(sid, &disk);
752 if (rc != EOK)
753 return rc;
754
[e11c527]755 rc = vbds_disk_parts_remove(disk, vrf_none);
[3a43785]756 if (rc != EOK) {
757 log_msg(LOG_DEFAULT, LVL_ERROR, "Failed deleting label.");
758 return rc;
759 }
760
[28ed0d95]761 rc = label_destroy(disk->label);
762 if (rc != EOK) {
763 log_msg(LOG_DEFAULT, LVL_ERROR, "Failed deleting label.");
764 return rc;
765 }
766
[3a43785]767 disk->label = NULL;
768
[deacc58d]769 lbd.ops = &vbds_label_bd_ops;
770 lbd.arg = (void *) disk;
771
772 rc = label_open(&lbd, &label);
[3a43785]773 if (rc != EOK) {
[55f8c6e7]774 log_msg(LOG_DEFAULT, LVL_ERROR, "Failed to open label in disk %s.",
[3a43785]775 disk->svc_name);
776 return EIO;
777 }
778
779 (void) vbds_disk_parts_add(disk, label);
780 disk->label = label;
[28ed0d95]781 return EOK;
782}
783
[b7fd2a0]784errno_t vbds_part_get_info(vbds_part_id_t partid, vbd_part_info_t *pinfo)
[28ed0d95]785{
[78d50bd]786 vbds_part_t *part;
[1626cd4]787 label_part_info_t lpinfo;
[b7fd2a0]788 errno_t rc;
[78d50bd]789
[c43db5f]790 rc = vbds_part_by_pid(partid, &part);
[78d50bd]791 if (rc != EOK)
792 return rc;
793
[e11c527]794 fibril_rwlock_read_lock(&part->lock);
795 if (part->lpart == NULL) {
796 fibril_rwlock_read_unlock(&part->lock);
797 return ENOENT;
798 }
799
[1626cd4]800 label_part_get_info(part->lpart, &lpinfo);
801
802 pinfo->index = lpinfo.index;
[b7a4d06]803 pinfo->pkind = lpinfo.pkind;
[1626cd4]804 pinfo->block0 = lpinfo.block0;
805 pinfo->nblocks = lpinfo.nblocks;
[4b6635a7]806 pinfo->svc_id = part->svc_id;
[e11c527]807 vbds_part_del_ref(part);
808 fibril_rwlock_read_unlock(&part->lock);
809
[28ed0d95]810 return EOK;
811}
812
[b7fd2a0]813errno_t vbds_part_create(service_id_t sid, vbd_part_spec_t *pspec,
[6bc542b]814 vbds_part_id_t *rpart)
[28ed0d95]815{
[78d50bd]816 vbds_disk_t *disk;
817 vbds_part_t *part;
[6bc542b]818 label_part_spec_t lpspec;
[78d50bd]819 label_part_t *lpart;
[b7fd2a0]820 errno_t rc;
[78d50bd]821
[55f8c6e7]822 log_msg(LOG_DEFAULT, LVL_DEBUG, "vbds_part_create(%zu)", sid);
[44fe800]823
[78d50bd]824 rc = vbds_disk_by_svcid(sid, &disk);
825 if (rc != EOK) {
[55f8c6e7]826 log_msg(LOG_DEFAULT, LVL_ERROR, "Disk %zu not found",
[78d50bd]827 sid);
828 goto error;
829 }
830
[55f8c6e7]831 log_msg(LOG_DEFAULT, LVL_DEBUG, "vbds_part_crate(%zu): "
[b598460a]832 "index=%d block0=%" PRIu64 " nblocks=%" PRIu64
833 " hdr_blocks=%" PRIu64 " pkind=%d",
834 sid, pspec->index, pspec->block0, pspec->nblocks, pspec->hdr_blocks,
835 pspec->pkind);
836
[6bc542b]837 label_pspec_init(&lpspec);
838 lpspec.index = pspec->index;
839 lpspec.block0 = pspec->block0;
840 lpspec.nblocks = pspec->nblocks;
[c02d098]841 lpspec.hdr_blocks = pspec->hdr_blocks;
[b7a4d06]842 lpspec.pkind = pspec->pkind;
[6bc542b]843 lpspec.ptype = pspec->ptype;
844
845 rc = label_part_create(disk->label, &lpspec, &lpart);
[78d50bd]846 if (rc != EOK) {
847 log_msg(LOG_DEFAULT, LVL_ERROR, "Error creating partition.");
[5772aa1]848 goto error;
849 }
850
851 rc = label_part_empty(lpart);
852 if (rc != EOK) {
853 log_msg(LOG_DEFAULT, LVL_ERROR, "Error emptying partition.");
[78d50bd]854 goto error;
855 }
856
[6439741]857 rc = vbds_part_indices_update(disk);
858 if (rc != EOK) {
859 log_msg(LOG_DEFAULT, LVL_ERROR, "Error updating partition indices");
860 goto error;
861 }
862
[6bc542b]863 rc = vbds_part_add(disk, lpart, &part);
[78d50bd]864 if (rc != EOK) {
865 log_msg(LOG_DEFAULT, LVL_ERROR, "Failed while creating "
866 "partition.");
867 rc = label_part_destroy(lpart);
868 if (rc != EOK)
869 log_msg(LOG_DEFAULT, LVL_ERROR,
870 "Cannot roll back partition creation.");
871 rc = EIO;
872 goto error;
873 }
874
[6bc542b]875 if (rpart != NULL)
[c43db5f]876 *rpart = part->pid;
[28ed0d95]877 return EOK;
[78d50bd]878error:
879 return rc;
[28ed0d95]880}
881
[b7fd2a0]882errno_t vbds_part_delete(vbds_part_id_t partid)
[28ed0d95]883{
[78d50bd]884 vbds_part_t *part;
[99c23405]885 vbds_disk_t *disk;
886 label_part_t *lpart;
[b7fd2a0]887 errno_t rc;
[78d50bd]888
[c43db5f]889 rc = vbds_part_by_pid(partid, &part);
[78d50bd]890 if (rc != EOK)
891 return rc;
892
[99c23405]893 disk = part->disk;
894
[e11c527]895 rc = vbds_part_remove(part, vrf_none, &lpart);
[78d50bd]896 if (rc != EOK)
897 return rc;
898
[99c23405]899 rc = label_part_destroy(lpart);
[e11c527]900 vbds_part_del_ref(part);
[99c23405]901 if (rc != EOK) {
902 log_msg(LOG_DEFAULT, LVL_ERROR, "Failed deleting partition");
903
904 /* Try rolling back */
905 rc = vbds_part_add(disk, lpart, NULL);
906 if (rc != EOK)
907 log_msg(LOG_DEFAULT, LVL_ERROR, "Failed rolling back.");
908
909 return EIO;
910 }
911
[6439741]912 rc = vbds_part_indices_update(disk);
913 if (rc != EOK) {
914 log_msg(LOG_DEFAULT, LVL_ERROR, "Error updating partition indices");
915 return EIO;
916 }
917
[78d50bd]918 return EOK;
919}
920
[b7fd2a0]921errno_t vbds_suggest_ptype(service_id_t sid, label_pcnt_t pcnt,
[f57ccb5]922 label_ptype_t *ptype)
923{
924 vbds_disk_t *disk;
[b7fd2a0]925 errno_t rc;
[f57ccb5]926
927 rc = vbds_disk_by_svcid(sid, &disk);
928 if (rc != EOK) {
[55f8c6e7]929 log_msg(LOG_DEFAULT, LVL_DEBUG, "Disk %zu not found",
[f57ccb5]930 sid);
931 goto error;
932 }
933
934 rc = label_suggest_ptype(disk->label, pcnt, ptype);
935 if (rc != EOK) {
[55f8c6e7]936 log_msg(LOG_DEFAULT, LVL_DEBUG, "label_suggest_ptype() failed");
[f57ccb5]937 goto error;
938 }
939
940 return EOK;
941error:
942 return rc;
943}
944
[b7fd2a0]945static errno_t vbds_bd_open(bd_srvs_t *bds, bd_srv_t *bd)
[78d50bd]946{
947 vbds_part_t *part = bd_srv_part(bd);
948
[55f8c6e7]949 log_msg(LOG_DEFAULT, LVL_DEBUG, "vbds_bd_open()");
[e11c527]950 fibril_rwlock_write_lock(&part->lock);
[78d50bd]951 part->open_cnt++;
[e11c527]952 fibril_rwlock_write_unlock(&part->lock);
[78d50bd]953 return EOK;
954}
955
[b7fd2a0]956static errno_t vbds_bd_close(bd_srv_t *bd)
[78d50bd]957{
958 vbds_part_t *part = bd_srv_part(bd);
959
[55f8c6e7]960 log_msg(LOG_DEFAULT, LVL_DEBUG, "vbds_bd_close()");
[e11c527]961
962 /* Grabbing writer lock also forces all I/O to complete */
963
964 fibril_rwlock_write_lock(&part->lock);
[78d50bd]965 part->open_cnt--;
[e11c527]966 fibril_rwlock_write_unlock(&part->lock);
[78d50bd]967 return EOK;
968}
969
[b7fd2a0]970static errno_t vbds_bd_read_blocks(bd_srv_t *bd, aoff64_t ba, size_t cnt,
[78d50bd]971 void *buf, size_t size)
972{
973 vbds_part_t *part = bd_srv_part(bd);
974 aoff64_t gba;
[b7fd2a0]975 errno_t rc;
[78d50bd]976
[55f8c6e7]977 log_msg(LOG_DEFAULT, LVL_DEBUG2, "vbds_bd_read_blocks()");
[e11c527]978 fibril_rwlock_read_lock(&part->lock);
[78d50bd]979
[e11c527]980 if (cnt * part->disk->block_size < size) {
981 fibril_rwlock_read_unlock(&part->lock);
[78d50bd]982 return EINVAL;
[e11c527]983 }
[78d50bd]984
[e11c527]985 if (vbds_bsa_translate(part, ba, cnt, &gba) != EOK) {
986 fibril_rwlock_read_unlock(&part->lock);
[78d50bd]987 return ELIMIT;
[e11c527]988 }
989
990 rc = block_read_direct(part->disk->svc_id, gba, cnt, buf);
991 fibril_rwlock_read_unlock(&part->lock);
[78d50bd]992
[e11c527]993 return rc;
[78d50bd]994}
995
[b7fd2a0]996static errno_t vbds_bd_sync_cache(bd_srv_t *bd, aoff64_t ba, size_t cnt)
[78d50bd]997{
998 vbds_part_t *part = bd_srv_part(bd);
999 aoff64_t gba;
[b7fd2a0]1000 errno_t rc;
[78d50bd]1001
[55f8c6e7]1002 log_msg(LOG_DEFAULT, LVL_DEBUG2, "vbds_bd_sync_cache()");
[e11c527]1003 fibril_rwlock_read_lock(&part->lock);
[78d50bd]1004
1005 /* XXX Allow full-disk sync? */
1006 if (ba != 0 || cnt != 0) {
[e11c527]1007 if (vbds_bsa_translate(part, ba, cnt, &gba) != EOK) {
1008 fibril_rwlock_read_unlock(&part->lock);
[78d50bd]1009 return ELIMIT;
[e11c527]1010 }
[78d50bd]1011 } else {
1012 gba = 0;
1013 }
1014
[e11c527]1015 rc = block_sync_cache(part->disk->svc_id, gba, cnt);
1016 fibril_rwlock_read_unlock(&part->lock);
1017 return rc;
[78d50bd]1018}
1019
[b7fd2a0]1020static errno_t vbds_bd_write_blocks(bd_srv_t *bd, aoff64_t ba, size_t cnt,
[78d50bd]1021 const void *buf, size_t size)
1022{
1023 vbds_part_t *part = bd_srv_part(bd);
1024 aoff64_t gba;
[b7fd2a0]1025 errno_t rc;
[78d50bd]1026
[55f8c6e7]1027 log_msg(LOG_DEFAULT, LVL_DEBUG2, "vbds_bd_write_blocks()");
[e11c527]1028 fibril_rwlock_read_lock(&part->lock);
[78d50bd]1029
[e11c527]1030 if (cnt * part->disk->block_size < size) {
1031 fibril_rwlock_read_unlock(&part->lock);
[78d50bd]1032 return EINVAL;
[e11c527]1033 }
[78d50bd]1034
[e11c527]1035 if (vbds_bsa_translate(part, ba, cnt, &gba) != EOK) {
1036 fibril_rwlock_read_unlock(&part->lock);
[78d50bd]1037 return ELIMIT;
[e11c527]1038 }
[78d50bd]1039
[e11c527]1040 rc = block_write_direct(part->disk->svc_id, gba, cnt, buf);
1041 fibril_rwlock_read_unlock(&part->lock);
1042 return rc;
[78d50bd]1043}
1044
[b7fd2a0]1045static errno_t vbds_bd_get_block_size(bd_srv_t *bd, size_t *rsize)
[78d50bd]1046{
[3faa03d]1047 vbds_part_t *part = bd_srv_part(bd);
1048
[55f8c6e7]1049 log_msg(LOG_DEFAULT, LVL_DEBUG2, "vbds_bd_get_block_size()");
[e11c527]1050
1051 fibril_rwlock_read_lock(&part->lock);
[3faa03d]1052 *rsize = part->disk->block_size;
[e11c527]1053 fibril_rwlock_read_unlock(&part->lock);
1054
[78d50bd]1055 return EOK;
1056}
1057
[b7fd2a0]1058static errno_t vbds_bd_get_num_blocks(bd_srv_t *bd, aoff64_t *rnb)
[78d50bd]1059{
[3faa03d]1060 vbds_part_t *part = bd_srv_part(bd);
1061
[55f8c6e7]1062 log_msg(LOG_DEFAULT, LVL_DEBUG2, "vbds_bd_get_num_blocks()");
[e11c527]1063
1064 fibril_rwlock_read_lock(&part->lock);
[3faa03d]1065 *rnb = part->nblocks;
[e11c527]1066 fibril_rwlock_read_unlock(&part->lock);
1067
[78d50bd]1068 return EOK;
1069}
1070
[984a9ba]1071void vbds_bd_conn(ipc_call_t *icall, void *arg)
[78d50bd]1072{
1073 vbds_part_t *part;
[b7fd2a0]1074 errno_t rc;
[c43db5f]1075 service_id_t svcid;
[78d50bd]1076
[55f8c6e7]1077 log_msg(LOG_DEFAULT, LVL_DEBUG, "vbds_bd_conn()");
[3faa03d]1078
[ff381a7]1079 svcid = IPC_GET_ARG2(*icall);
[78d50bd]1080
[55f8c6e7]1081 log_msg(LOG_DEFAULT, LVL_DEBUG, "vbds_bd_conn() - svcid=%zu", svcid);
[3faa03d]1082
[c43db5f]1083 rc = vbds_part_by_svcid(svcid, &part);
[78d50bd]1084 if (rc != EOK) {
[55f8c6e7]1085 log_msg(LOG_DEFAULT, LVL_DEBUG, "vbd_bd_conn() - partition "
[3faa03d]1086 "not found.");
[984a9ba]1087 async_answer_0(icall, EINVAL);
[78d50bd]1088 return;
1089 }
1090
[55f8c6e7]1091 log_msg(LOG_DEFAULT, LVL_DEBUG, "vbds_bd_conn() - call bd_conn");
[984a9ba]1092 bd_conn(icall, &part->bds);
[e11c527]1093 vbds_part_del_ref(part);
[78d50bd]1094}
1095
1096/** Translate block segment address with range checking. */
[b7fd2a0]1097static errno_t vbds_bsa_translate(vbds_part_t *part, aoff64_t ba, size_t cnt,
[78d50bd]1098 aoff64_t *gba)
1099{
1100 if (ba + cnt > part->nblocks)
1101 return ELIMIT;
1102
1103 *gba = part->block0 + ba;
[28ed0d95]1104 return EOK;
1105}
1106
[6439741]1107/** Register service for partition */
[b7fd2a0]1108static errno_t vbds_part_svc_register(vbds_part_t *part)
[6439741]1109{
1110 char *name;
1111 service_id_t psid;
1112 int idx;
[b7fd2a0]1113 errno_t rc;
[6439741]1114
1115 idx = part->lpart->index;
1116
[d5c1051]1117 if (asprintf(&name, "%sp%u", part->disk->svc_name, idx) < 0) {
[6439741]1118 log_msg(LOG_DEFAULT, LVL_ERROR, "Out of memory.");
1119 return ENOMEM;
1120 }
1121
[55f8c6e7]1122 log_msg(LOG_DEFAULT, LVL_DEBUG, "loc_service_register('%s')",
[edebb4a1]1123 name);
[6439741]1124 rc = loc_service_register(name, &psid);
1125 if (rc != EOK) {
1126 log_msg(LOG_DEFAULT, LVL_ERROR, "Failed registering "
[c1694b6b]1127 "service %s: %s.", name, str_error(rc));
[6439741]1128 free(name);
1129 free(part);
1130 return EIO;
1131 }
1132
[372df8f]1133 rc = loc_service_add_to_cat(psid, part_cid);
1134 if (rc != EOK) {
1135 log_msg(LOG_DEFAULT, LVL_ERROR, "Failled adding partition "
1136 "service %s to partition category.", name);
1137 free(name);
1138 free(part);
1139
1140 rc = loc_service_unregister(psid);
1141 if (rc != EOK) {
1142 log_msg(LOG_DEFAULT, LVL_ERROR, "Error unregistering "
1143 "service. Rollback failed.");
1144 }
1145 return EIO;
1146 }
1147
[6439741]1148 free(name);
1149 part->svc_id = psid;
1150 part->reg_idx = idx;
1151 return EOK;
1152}
1153
1154/** Unregister service for partition */
[b7fd2a0]1155static errno_t vbds_part_svc_unregister(vbds_part_t *part)
[6439741]1156{
[b7fd2a0]1157 errno_t rc;
[6439741]1158
[55f8c6e7]1159 log_msg(LOG_DEFAULT, LVL_DEBUG, "vbds_part_svc_unregister("
[3a43785]1160 "disk->svc_name='%s', id=%zu)", part->disk->svc_name, part->svc_id);
1161
[6439741]1162 rc = loc_service_unregister(part->svc_id);
1163 if (rc != EOK)
1164 return EIO;
1165
1166 part->svc_id = 0;
1167 part->reg_idx = 0;
1168 return EOK;
1169}
1170
1171/** Update service names for any partition whose index has changed. */
[b7fd2a0]1172static errno_t vbds_part_indices_update(vbds_disk_t *disk)
[6439741]1173{
1174 label_part_info_t lpinfo;
[b7fd2a0]1175 errno_t rc;
[6439741]1176
[55f8c6e7]1177 log_msg(LOG_DEFAULT, LVL_DEBUG, "vbds_part_indices_update()");
[6439741]1178
[e11c527]1179 fibril_mutex_lock(&vbds_parts_lock);
1180
[6439741]1181 /* First unregister services for partitions whose index has changed */
1182 list_foreach(disk->parts, ldisk, vbds_part_t, part) {
[e11c527]1183 fibril_rwlock_write_lock(&part->lock);
[6439741]1184 if (part->svc_id != 0 && part->lpart->index != part->reg_idx) {
1185 rc = vbds_part_svc_unregister(part);
1186 if (rc != EOK) {
[e11c527]1187 fibril_rwlock_write_unlock(&part->lock);
1188 fibril_mutex_unlock(&vbds_parts_lock);
[55f8c6e7]1189 log_msg(LOG_DEFAULT, LVL_ERROR, "Error "
[6439741]1190 "un-registering partition.");
1191 return EIO;
1192 }
1193 }
[e11c527]1194
1195 fibril_rwlock_write_unlock(&part->lock);
[6439741]1196 }
1197
1198 /* Now re-register those services under the new indices */
1199 list_foreach(disk->parts, ldisk, vbds_part_t, part) {
[e11c527]1200 fibril_rwlock_write_lock(&part->lock);
[6439741]1201 label_part_get_info(part->lpart, &lpinfo);
1202 if (part->svc_id == 0 && lpinfo.pkind != lpk_extended) {
1203 rc = vbds_part_svc_register(part);
1204 if (rc != EOK) {
[e11c527]1205 fibril_rwlock_write_unlock(&part->lock);
1206 fibril_mutex_unlock(&vbds_parts_lock);
[55f8c6e7]1207 log_msg(LOG_DEFAULT, LVL_ERROR, "Error "
[6439741]1208 "re-registering partition.");
1209 return EIO;
1210 }
1211 }
[e11c527]1212
1213 fibril_rwlock_write_unlock(&part->lock);
[6439741]1214 }
1215
[e11c527]1216 fibril_mutex_unlock(&vbds_parts_lock);
1217
[6439741]1218 return EOK;
1219}
1220
[deacc58d]1221/** Get block size wrapper for liblabel */
[b7fd2a0]1222static errno_t vbds_label_get_bsize(void *arg, size_t *bsize)
[deacc58d]1223{
1224 vbds_disk_t *disk = (vbds_disk_t *)arg;
1225 return block_get_bsize(disk->svc_id, bsize);
1226}
1227
1228/** Get number of blocks wrapper for liblabel */
[b7fd2a0]1229static errno_t vbds_label_get_nblocks(void *arg, aoff64_t *nblocks)
[deacc58d]1230{
1231 vbds_disk_t *disk = (vbds_disk_t *)arg;
1232 return block_get_nblocks(disk->svc_id, nblocks);
1233}
1234
1235/** Read blocks wrapper for liblabel */
[b7fd2a0]1236static errno_t vbds_label_read(void *arg, aoff64_t ba, size_t cnt, void *buf)
[deacc58d]1237{
1238 vbds_disk_t *disk = (vbds_disk_t *)arg;
1239 return block_read_direct(disk->svc_id, ba, cnt, buf);
1240}
1241
1242/** Write blocks wrapper for liblabel */
[b7fd2a0]1243static errno_t vbds_label_write(void *arg, aoff64_t ba, size_t cnt, const void *data)
[deacc58d]1244{
1245 vbds_disk_t *disk = (vbds_disk_t *)arg;
1246 return block_write_direct(disk->svc_id, ba, cnt, data);
1247}
1248
[28ed0d95]1249/** @}
1250 */
Note: See TracBrowser for help on using the repository browser.