[22fb7ab] | 1 | /*
|
---|
| 2 | * Copyright (c) 2015 Jiri Svoboda
|
---|
| 3 | * All rights reserved.
|
---|
| 4 | *
|
---|
| 5 | * Redistribution and use in source and binary forms, with or without
|
---|
| 6 | * modification, are permitted provided that the following conditions
|
---|
| 7 | * are met:
|
---|
| 8 | *
|
---|
| 9 | * - Redistributions of source code must retain the above copyright
|
---|
| 10 | * notice, this list of conditions and the following disclaimer.
|
---|
| 11 | * - Redistributions in binary form must reproduce the above copyright
|
---|
| 12 | * notice, this list of conditions and the following disclaimer in the
|
---|
| 13 | * documentation and/or other materials provided with the distribution.
|
---|
| 14 | * - The name of the author may not be used to endorse or promote products
|
---|
| 15 | * derived from this software without specific prior written permission.
|
---|
| 16 | *
|
---|
| 17 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
---|
| 18 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
---|
| 19 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
---|
| 20 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
---|
| 21 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
---|
| 22 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
---|
| 23 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
---|
| 24 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
---|
| 25 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
---|
| 26 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
---|
| 27 | */
|
---|
| 28 |
|
---|
| 29 | /** @addtogroup libc
|
---|
| 30 | * @{
|
---|
| 31 | */
|
---|
| 32 | /** @file Virtual Block Device client API
|
---|
| 33 | */
|
---|
| 34 |
|
---|
[ff381a7] | 35 | #include <abi/ipc/interfaces.h>
|
---|
[22fb7ab] | 36 | #include <errno.h>
|
---|
| 37 | #include <ipc/services.h>
|
---|
| 38 | #include <ipc/vbd.h>
|
---|
| 39 | #include <loc.h>
|
---|
[1626cd4] | 40 | #include <macros.h>
|
---|
[28ed0d9] | 41 | #include <mem.h>
|
---|
[22fb7ab] | 42 | #include <stdlib.h>
|
---|
| 43 | #include <types/label.h>
|
---|
| 44 | #include <vbd.h>
|
---|
| 45 |
|
---|
[b7fd2a0] | 46 | static errno_t vbd_get_ids_internal(vbd_t *, sysarg_t, sysarg_t, sysarg_t **,
|
---|
[372df8f] | 47 | size_t *);
|
---|
| 48 |
|
---|
[b7fd2a0] | 49 | errno_t vbd_create(vbd_t **rvbd)
|
---|
[22fb7ab] | 50 | {
|
---|
| 51 | vbd_t *vbd;
|
---|
| 52 | service_id_t vbd_svcid;
|
---|
[b7fd2a0] | 53 | errno_t rc;
|
---|
[22fb7ab] | 54 |
|
---|
| 55 | vbd = calloc(1, sizeof(vbd_t));
|
---|
| 56 | if (vbd == NULL) {
|
---|
| 57 | rc = ENOMEM;
|
---|
| 58 | goto error;
|
---|
| 59 | }
|
---|
| 60 |
|
---|
| 61 | rc = loc_service_get_id(SERVICE_NAME_VBD, &vbd_svcid,
|
---|
| 62 | IPC_FLAG_BLOCKING);
|
---|
| 63 | if (rc != EOK) {
|
---|
| 64 | rc = EIO;
|
---|
| 65 | goto error;
|
---|
| 66 | }
|
---|
| 67 |
|
---|
[ff381a7] | 68 | vbd->sess = loc_service_connect(vbd_svcid, INTERFACE_VBD,
|
---|
[22fb7ab] | 69 | IPC_FLAG_BLOCKING);
|
---|
| 70 | if (vbd->sess == NULL) {
|
---|
| 71 | rc = EIO;
|
---|
| 72 | goto error;
|
---|
| 73 | }
|
---|
| 74 |
|
---|
| 75 | *rvbd = vbd;
|
---|
| 76 | return EOK;
|
---|
| 77 | error:
|
---|
| 78 | free(vbd);
|
---|
| 79 | return rc;
|
---|
| 80 | }
|
---|
| 81 |
|
---|
| 82 | void vbd_destroy(vbd_t *vbd)
|
---|
| 83 | {
|
---|
| 84 | if (vbd == NULL)
|
---|
| 85 | return;
|
---|
| 86 |
|
---|
| 87 | async_hangup(vbd->sess);
|
---|
| 88 | free(vbd);
|
---|
| 89 | }
|
---|
| 90 |
|
---|
[372df8f] | 91 | /** Get list of partitions as array of service IDs.
|
---|
| 92 | *
|
---|
| 93 | * @param vbd Virtual block device service
|
---|
| 94 | * @param data Place to store pointer to array
|
---|
| 95 | * @param count Place to store length of array (number of entries)
|
---|
| 96 | *
|
---|
[cde999a] | 97 | * @return EOK on success or an error code
|
---|
[372df8f] | 98 | */
|
---|
[b7fd2a0] | 99 | errno_t vbd_get_disks(vbd_t *vbd, service_id_t **data, size_t *count)
|
---|
[22fb7ab] | 100 | {
|
---|
[372df8f] | 101 | return vbd_get_ids_internal(vbd, VBD_GET_DISKS, 0, data, count);
|
---|
[22fb7ab] | 102 | }
|
---|
| 103 |
|
---|
| 104 | /** Get disk information. */
|
---|
[b7fd2a0] | 105 | errno_t vbd_disk_info(vbd_t *vbd, service_id_t sid, vbd_disk_info_t *vinfo)
|
---|
[22fb7ab] | 106 | {
|
---|
| 107 | async_exch_t *exch;
|
---|
[b7fd2a0] | 108 | errno_t retval;
|
---|
[1626cd4] | 109 | ipc_call_t answer;
|
---|
[22fb7ab] | 110 |
|
---|
| 111 | exch = async_exchange_begin(vbd->sess);
|
---|
[1626cd4] | 112 | aid_t req = async_send_1(exch, VBD_DISK_INFO, sid, &answer);
|
---|
[b7fd2a0] | 113 | errno_t rc = async_data_read_start(exch, vinfo, sizeof(vbd_disk_info_t));
|
---|
[22fb7ab] | 114 | async_exchange_end(exch);
|
---|
| 115 |
|
---|
[1626cd4] | 116 | if (rc != EOK) {
|
---|
| 117 | async_forget(req);
|
---|
| 118 | return EIO;
|
---|
| 119 | }
|
---|
| 120 |
|
---|
| 121 | async_wait_for(req, &retval);
|
---|
[22fb7ab] | 122 | if (retval != EOK)
|
---|
| 123 | return EIO;
|
---|
| 124 |
|
---|
| 125 | return EOK;
|
---|
| 126 | }
|
---|
| 127 |
|
---|
[b7fd2a0] | 128 | errno_t vbd_label_create(vbd_t *vbd, service_id_t sid, label_type_t ltype)
|
---|
[22fb7ab] | 129 | {
|
---|
| 130 | async_exch_t *exch;
|
---|
[b7fd2a0] | 131 | errno_t retval;
|
---|
[22fb7ab] | 132 |
|
---|
| 133 | exch = async_exchange_begin(vbd->sess);
|
---|
| 134 | retval = async_req_2_0(exch, VBD_LABEL_CREATE, sid, ltype);
|
---|
| 135 | async_exchange_end(exch);
|
---|
| 136 |
|
---|
| 137 | if (retval != EOK)
|
---|
| 138 | return EIO;
|
---|
| 139 |
|
---|
| 140 | return EOK;
|
---|
| 141 | }
|
---|
| 142 |
|
---|
[b7fd2a0] | 143 | errno_t vbd_label_delete(vbd_t *vbd, service_id_t sid)
|
---|
[22fb7ab] | 144 | {
|
---|
| 145 | async_exch_t *exch;
|
---|
[b7fd2a0] | 146 | errno_t retval;
|
---|
[22fb7ab] | 147 |
|
---|
| 148 | exch = async_exchange_begin(vbd->sess);
|
---|
| 149 | retval = async_req_1_0(exch, VBD_LABEL_DELETE, sid);
|
---|
| 150 | async_exchange_end(exch);
|
---|
| 151 |
|
---|
| 152 | if (retval != EOK)
|
---|
| 153 | return EIO;
|
---|
| 154 |
|
---|
| 155 | return EOK;
|
---|
| 156 | }
|
---|
| 157 |
|
---|
[28ed0d9] | 158 | /** Get list of IDs into a buffer of fixed size.
|
---|
| 159 | *
|
---|
| 160 | * @param vbd Virtual Block Device
|
---|
| 161 | * @param method IPC method
|
---|
| 162 | * @param arg1 First argument
|
---|
| 163 | * @param id_buf Buffer to store IDs
|
---|
| 164 | * @param buf_size Buffer size
|
---|
| 165 | * @param act_size Place to store actual size of complete data.
|
---|
| 166 | *
|
---|
[cde999a] | 167 | * @return EOK on success or an error code.
|
---|
[28ed0d9] | 168 | */
|
---|
[b7fd2a0] | 169 | static errno_t vbd_get_ids_once(vbd_t *vbd, sysarg_t method, sysarg_t arg1,
|
---|
[28ed0d9] | 170 | sysarg_t *id_buf, size_t buf_size, size_t *act_size)
|
---|
| 171 | {
|
---|
| 172 | async_exch_t *exch = async_exchange_begin(vbd->sess);
|
---|
| 173 |
|
---|
| 174 | ipc_call_t answer;
|
---|
| 175 | aid_t req = async_send_1(exch, method, arg1, &answer);
|
---|
[b7fd2a0] | 176 | errno_t rc = async_data_read_start(exch, id_buf, buf_size);
|
---|
[28ed0d9] | 177 |
|
---|
| 178 | async_exchange_end(exch);
|
---|
| 179 |
|
---|
| 180 | if (rc != EOK) {
|
---|
| 181 | async_forget(req);
|
---|
| 182 | return rc;
|
---|
| 183 | }
|
---|
| 184 |
|
---|
[b7fd2a0] | 185 | errno_t retval;
|
---|
[28ed0d9] | 186 | async_wait_for(req, &retval);
|
---|
| 187 |
|
---|
| 188 | if (retval != EOK) {
|
---|
| 189 | return retval;
|
---|
| 190 | }
|
---|
| 191 |
|
---|
| 192 | *act_size = IPC_GET_ARG1(answer);
|
---|
| 193 | return EOK;
|
---|
| 194 | }
|
---|
| 195 |
|
---|
| 196 | /** Get list of IDs.
|
---|
| 197 | *
|
---|
| 198 | * Returns an allocated array of service IDs.
|
---|
| 199 | *
|
---|
| 200 | * @param vbd Virtual Block Device
|
---|
| 201 | * @param method IPC method
|
---|
| 202 | * @param arg1 IPC argument 1
|
---|
| 203 | * @param data Place to store pointer to array of IDs
|
---|
| 204 | * @param count Place to store number of IDs
|
---|
[cde999a] | 205 | * @return EOK on success or an error code
|
---|
[28ed0d9] | 206 | */
|
---|
[b7fd2a0] | 207 | static errno_t vbd_get_ids_internal(vbd_t *vbd, sysarg_t method, sysarg_t arg1,
|
---|
[28ed0d9] | 208 | sysarg_t **data, size_t *count)
|
---|
| 209 | {
|
---|
| 210 | *data = NULL;
|
---|
| 211 | *count = 0;
|
---|
| 212 |
|
---|
| 213 | size_t act_size = 0;
|
---|
[b7fd2a0] | 214 | errno_t rc = vbd_get_ids_once(vbd, method, arg1, NULL, 0, &act_size);
|
---|
[28ed0d9] | 215 | if (rc != EOK)
|
---|
| 216 | return rc;
|
---|
| 217 |
|
---|
| 218 | size_t alloc_size = act_size;
|
---|
| 219 | service_id_t *ids = malloc(alloc_size);
|
---|
| 220 | if (ids == NULL)
|
---|
| 221 | return ENOMEM;
|
---|
| 222 |
|
---|
| 223 | while (true) {
|
---|
| 224 | rc = vbd_get_ids_once(vbd, method, arg1, ids, alloc_size,
|
---|
| 225 | &act_size);
|
---|
| 226 | if (rc != EOK)
|
---|
| 227 | return rc;
|
---|
| 228 |
|
---|
| 229 | if (act_size <= alloc_size)
|
---|
| 230 | break;
|
---|
| 231 |
|
---|
| 232 | alloc_size = act_size;
|
---|
| 233 | ids = realloc(ids, alloc_size);
|
---|
| 234 | if (ids == NULL)
|
---|
| 235 | return ENOMEM;
|
---|
| 236 | }
|
---|
| 237 |
|
---|
| 238 | *count = act_size / sizeof(service_id_t);
|
---|
| 239 | *data = ids;
|
---|
| 240 | return EOK;
|
---|
| 241 | }
|
---|
| 242 |
|
---|
| 243 | /** Get list of disks as array of service IDs.
|
---|
| 244 | *
|
---|
| 245 | * @param vbd Virtual Block Device
|
---|
| 246 | * @param data Place to store pointer to array
|
---|
| 247 | * @param count Place to store length of array (number of entries)
|
---|
| 248 | *
|
---|
[cde999a] | 249 | * @return EOK on success or an error code
|
---|
[28ed0d9] | 250 | */
|
---|
[b7fd2a0] | 251 | errno_t vbd_label_get_parts(vbd_t *vbd, service_id_t disk,
|
---|
[28ed0d9] | 252 | service_id_t **data, size_t *count)
|
---|
| 253 | {
|
---|
| 254 | return vbd_get_ids_internal(vbd, VBD_LABEL_GET_PARTS, disk,
|
---|
| 255 | data, count);
|
---|
| 256 | }
|
---|
| 257 |
|
---|
[b7fd2a0] | 258 | errno_t vbd_part_get_info(vbd_t *vbd, vbd_part_id_t part, vbd_part_info_t *pinfo)
|
---|
[28ed0d9] | 259 | {
|
---|
| 260 | async_exch_t *exch;
|
---|
[b7fd2a0] | 261 | errno_t retval;
|
---|
[b7a4d06] | 262 | ipc_call_t answer;
|
---|
[28ed0d9] | 263 |
|
---|
| 264 | exch = async_exchange_begin(vbd->sess);
|
---|
[b7a4d06] | 265 | aid_t req = async_send_1(exch, VBD_PART_GET_INFO, part, &answer);
|
---|
[b7fd2a0] | 266 | errno_t rc = async_data_read_start(exch, pinfo, sizeof(vbd_part_info_t));
|
---|
[28ed0d9] | 267 | async_exchange_end(exch);
|
---|
| 268 |
|
---|
[b7a4d06] | 269 | if (rc != EOK) {
|
---|
| 270 | async_forget(req);
|
---|
| 271 | return EIO;
|
---|
| 272 | }
|
---|
| 273 |
|
---|
| 274 | async_wait_for(req, &retval);
|
---|
[28ed0d9] | 275 | if (retval != EOK)
|
---|
| 276 | return EIO;
|
---|
| 277 |
|
---|
| 278 | return EOK;
|
---|
| 279 | }
|
---|
| 280 |
|
---|
[b7fd2a0] | 281 | errno_t vbd_part_create(vbd_t *vbd, service_id_t disk, vbd_part_spec_t *pspec,
|
---|
[28ed0d9] | 282 | vbd_part_id_t *rpart)
|
---|
| 283 | {
|
---|
| 284 | async_exch_t *exch;
|
---|
[b7fd2a0] | 285 | errno_t retval;
|
---|
[6bc542b] | 286 | ipc_call_t answer;
|
---|
[28ed0d9] | 287 |
|
---|
| 288 | exch = async_exchange_begin(vbd->sess);
|
---|
[6bc542b] | 289 | aid_t req = async_send_1(exch, VBD_PART_CREATE, disk, &answer);
|
---|
[b7fd2a0] | 290 | errno_t rc = async_data_write_start(exch, pspec, sizeof(vbd_part_spec_t));
|
---|
[28ed0d9] | 291 | async_exchange_end(exch);
|
---|
| 292 |
|
---|
[6bc542b] | 293 | if (rc != EOK) {
|
---|
| 294 | async_forget(req);
|
---|
| 295 | return EIO;
|
---|
| 296 | }
|
---|
| 297 |
|
---|
| 298 | async_wait_for(req, &retval);
|
---|
[28ed0d9] | 299 | if (retval != EOK)
|
---|
| 300 | return EIO;
|
---|
| 301 |
|
---|
[6bc542b] | 302 | *rpart = (vbd_part_id_t)IPC_GET_ARG1(answer);
|
---|
[28ed0d9] | 303 | return EOK;
|
---|
[6bc542b] | 304 |
|
---|
[28ed0d9] | 305 | }
|
---|
| 306 |
|
---|
[b7fd2a0] | 307 | errno_t vbd_part_delete(vbd_t *vbd, vbd_part_id_t part)
|
---|
[28ed0d9] | 308 | {
|
---|
| 309 | async_exch_t *exch;
|
---|
[b7fd2a0] | 310 | errno_t retval;
|
---|
[28ed0d9] | 311 |
|
---|
| 312 | exch = async_exchange_begin(vbd->sess);
|
---|
| 313 | retval = async_req_1_0(exch, VBD_PART_DELETE, part);
|
---|
| 314 | async_exchange_end(exch);
|
---|
| 315 |
|
---|
| 316 | if (retval != EOK)
|
---|
| 317 | return EIO;
|
---|
| 318 |
|
---|
| 319 | return EOK;
|
---|
| 320 | }
|
---|
| 321 |
|
---|
| 322 | void vbd_pspec_init(vbd_part_spec_t *pspec)
|
---|
| 323 | {
|
---|
| 324 | memset(pspec, 0, sizeof(vbd_part_spec_t));
|
---|
| 325 | }
|
---|
| 326 |
|
---|
[f57ccb5] | 327 | /** Suggest partition type based on partition content.
|
---|
| 328 | *
|
---|
| 329 | * @param vbd Virtual Block Device
|
---|
| 330 | * @param disk Disk on which the partition will be created
|
---|
| 331 | * @param pcnt Partition content
|
---|
| 332 | * @param ptype Place to store suggested partition type
|
---|
| 333 | *
|
---|
[cde999a] | 334 | * @return EOK on success or an error code
|
---|
[f57ccb5] | 335 | */
|
---|
[b7fd2a0] | 336 | errno_t vbd_suggest_ptype(vbd_t *vbd, service_id_t disk, label_pcnt_t pcnt,
|
---|
[f57ccb5] | 337 | label_ptype_t *ptype)
|
---|
| 338 | {
|
---|
| 339 | async_exch_t *exch;
|
---|
[b7fd2a0] | 340 | errno_t retval;
|
---|
[f57ccb5] | 341 | ipc_call_t answer;
|
---|
| 342 |
|
---|
| 343 | exch = async_exchange_begin(vbd->sess);
|
---|
| 344 | aid_t req = async_send_2(exch, VBD_SUGGEST_PTYPE, disk, pcnt, &answer);
|
---|
[b7fd2a0] | 345 | errno_t rc = async_data_read_start(exch, ptype, sizeof(label_ptype_t));
|
---|
[f57ccb5] | 346 | async_exchange_end(exch);
|
---|
| 347 |
|
---|
| 348 | if (rc != EOK) {
|
---|
| 349 | async_forget(req);
|
---|
| 350 | return EIO;
|
---|
| 351 | }
|
---|
| 352 |
|
---|
| 353 | async_wait_for(req, &retval);
|
---|
| 354 | if (retval != EOK)
|
---|
| 355 | return EIO;
|
---|
| 356 |
|
---|
| 357 | return EOK;
|
---|
| 358 | }
|
---|
| 359 |
|
---|
| 360 |
|
---|
[22fb7ab] | 361 | /** @}
|
---|
| 362 | */
|
---|