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

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

Fix cstyle: make ccheck-fix and commit only files where all the changes are good.

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