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

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

Encapsulate partitions list in volume server. (Global state is not good coding practice.)

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