source: mainline/uspace/lib/c/generic/vbd.c@ 569a51a

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

Merge mainline changes.

  • Property mode set to 100644
File size: 8.3 KB
Line 
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
35#include <abi/ipc/interfaces.h>
36#include <errno.h>
37#include <ipc/services.h>
38#include <ipc/vbd.h>
39#include <loc.h>
40#include <macros.h>
41#include <mem.h>
42#include <stdlib.h>
43#include <types/label.h>
44#include <vbd.h>
45
46static int vbd_get_ids_internal(vbd_t *, sysarg_t, sysarg_t, sysarg_t **,
47 size_t *);
48
49int vbd_create(vbd_t **rvbd)
50{
51 vbd_t *vbd;
52 service_id_t vbd_svcid;
53 int rc;
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
68 vbd->sess = loc_service_connect(vbd_svcid, INTERFACE_VBD,
69 IPC_FLAG_BLOCKING);
70 if (vbd->sess == NULL) {
71 rc = EIO;
72 goto error;
73 }
74
75 *rvbd = vbd;
76 return EOK;
77error:
78 free(vbd);
79 return rc;
80}
81
82void vbd_destroy(vbd_t *vbd)
83{
84 if (vbd == NULL)
85 return;
86
87 async_hangup(vbd->sess);
88 free(vbd);
89}
90
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 *
97 * @return EOK on success or negative error code
98 */
99int vbd_get_disks(vbd_t *vbd, service_id_t **data, size_t *count)
100{
101 return vbd_get_ids_internal(vbd, VBD_GET_DISKS, 0, data, count);
102}
103
104/** Get disk information. */
105int vbd_disk_info(vbd_t *vbd, service_id_t sid, vbd_disk_info_t *vinfo)
106{
107 async_exch_t *exch;
108 sysarg_t retval;
109 ipc_call_t answer;
110
111 exch = async_exchange_begin(vbd->sess);
112 aid_t req = async_send_1(exch, VBD_DISK_INFO, sid, &answer);
113 int rc = async_data_read_start(exch, vinfo, sizeof(vbd_disk_info_t));
114 async_exchange_end(exch);
115
116 if (rc != EOK) {
117 async_forget(req);
118 return EIO;
119 }
120
121 async_wait_for(req, &retval);
122 if (retval != EOK)
123 return EIO;
124
125 return EOK;
126}
127
128int vbd_label_create(vbd_t *vbd, service_id_t sid, label_type_t ltype)
129{
130 async_exch_t *exch;
131 int retval;
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
143int vbd_label_delete(vbd_t *vbd, service_id_t sid)
144{
145 async_exch_t *exch;
146 int retval;
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
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 *
167 * @return EOK on success or negative error code.
168 */
169static int vbd_get_ids_once(vbd_t *vbd, sysarg_t method, sysarg_t arg1,
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);
176 int rc = async_data_read_start(exch, id_buf, buf_size);
177
178 async_exchange_end(exch);
179
180 if (rc != EOK) {
181 async_forget(req);
182 return rc;
183 }
184
185 sysarg_t retval;
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
205 * @return EOK on success or negative error code
206 */
207static int vbd_get_ids_internal(vbd_t *vbd, sysarg_t method, sysarg_t arg1,
208 sysarg_t **data, size_t *count)
209{
210 *data = NULL;
211 *count = 0;
212
213 size_t act_size = 0;
214 int rc = vbd_get_ids_once(vbd, method, arg1, NULL, 0, &act_size);
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 *
249 * @return EOK on success or negative error code
250 */
251int vbd_label_get_parts(vbd_t *vbd, service_id_t disk,
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
258int vbd_part_get_info(vbd_t *vbd, vbd_part_id_t part, vbd_part_info_t *pinfo)
259{
260 async_exch_t *exch;
261 sysarg_t retval;
262 ipc_call_t answer;
263
264 exch = async_exchange_begin(vbd->sess);
265 aid_t req = async_send_1(exch, VBD_PART_GET_INFO, part, &answer);
266 int rc = async_data_read_start(exch, pinfo, sizeof(vbd_part_info_t));
267 async_exchange_end(exch);
268
269 if (rc != EOK) {
270 async_forget(req);
271 return EIO;
272 }
273
274 async_wait_for(req, &retval);
275 if (retval != EOK)
276 return EIO;
277
278 return EOK;
279}
280
281int vbd_part_create(vbd_t *vbd, service_id_t disk, vbd_part_spec_t *pspec,
282 vbd_part_id_t *rpart)
283{
284 async_exch_t *exch;
285 sysarg_t retval;
286 ipc_call_t answer;
287
288 exch = async_exchange_begin(vbd->sess);
289 aid_t req = async_send_1(exch, VBD_PART_CREATE, disk, &answer);
290 int rc = async_data_write_start(exch, pspec, sizeof(vbd_part_spec_t));
291 async_exchange_end(exch);
292
293 if (rc != EOK) {
294 async_forget(req);
295 return EIO;
296 }
297
298 async_wait_for(req, &retval);
299 if (retval != EOK)
300 return EIO;
301
302 *rpart = (vbd_part_id_t)IPC_GET_ARG1(answer);
303 return EOK;
304
305}
306
307int vbd_part_delete(vbd_t *vbd, vbd_part_id_t part)
308{
309 async_exch_t *exch;
310 int retval;
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
322void vbd_pspec_init(vbd_part_spec_t *pspec)
323{
324 memset(pspec, 0, sizeof(vbd_part_spec_t));
325}
326
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 *
334 * @return EOK on success or negative error code
335 */
336int vbd_suggest_ptype(vbd_t *vbd, service_id_t disk, label_pcnt_t pcnt,
337 label_ptype_t *ptype)
338{
339 async_exch_t *exch;
340 sysarg_t retval;
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);
345 int rc = async_data_read_start(exch, ptype, sizeof(label_ptype_t));
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
361/** @}
362 */
Note: See TracBrowser for help on using the repository browser.