source: mainline/uspace/lib/c/generic/vbd.c@ 25a179e

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 25a179e was 25a179e, checked in by Jiří Zárevúcky <zarevucky.jiri@…>, 8 years ago

IPC return values are always errno constants. Adjust types to reflect that.

In principle, IPC server is not allowed to return non-errno values via
the "main" return value, because kernel interprets it (e.g. EHANGUP).
It's still possible to return arbitrary additional return values alongside EOK,
which are not interpreted in normal communication.

  • 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 int 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 int 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 int 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 int 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 int 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.