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