source: mainline/uspace/srv/bd/vbd/vbd.c@ 659ebd86

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 659ebd86 was da3bc0e, checked in by Jakub Jermar <jakub@…>, 9 years ago

Fix memory leak in vbds_get_disks_srv()

  • Property mode set to 100644
File size: 9.8 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 vbd
30 * @{
31 */
32/**
33 * @file
34 */
35
36#include <async.h>
37#include <errno.h>
38#include <io/log.h>
39#include <ipc/services.h>
40#include <ipc/vbd.h>
41#include <loc.h>
42#include <macros.h>
43#include <stdio.h>
44#include <stdlib.h>
45#include <task.h>
46#include <vbd.h>
47
48#include "disk.h"
49#include "types/vbd.h"
50
51#define NAME "vbd"
52
53static void vbds_client_conn(ipc_callid_t, ipc_call_t *, void *);
54
55static service_id_t ctl_sid;
56
57static int vbds_init(void)
58{
59 int rc;
60 log_msg(LOG_DEFAULT, LVL_DEBUG, "vbds_init()");
61
62 rc = vbds_disks_init();
63 if (rc != EOK)
64 return rc;
65
66 async_set_fallback_port_handler(vbds_client_conn, NULL);
67
68 rc = loc_server_register(NAME);
69 if (rc != EOK) {
70 log_msg(LOG_DEFAULT, LVL_ERROR, "Failed registering server (%d).", rc);
71 return EEXIST;
72 }
73
74 rc = loc_service_register(SERVICE_NAME_VBD, &ctl_sid);
75 if (rc != EOK) {
76 log_msg(LOG_DEFAULT, LVL_ERROR, "Failed registering service (%d).", rc);
77 return EEXIST;
78 }
79
80 rc = vbds_disk_discovery_start();
81 if (rc != EOK)
82 return rc;
83
84 return EOK;
85}
86
87static void vbds_get_disks_srv(ipc_callid_t iid, ipc_call_t *icall)
88{
89 ipc_callid_t callid;
90 size_t size;
91 size_t act_size;
92 int rc;
93
94 if (!async_data_read_receive(&callid, &size)) {
95 async_answer_0(callid, EREFUSED);
96 async_answer_0(iid, EREFUSED);
97 return;
98 }
99
100 service_id_t *id_buf = (service_id_t *) malloc(size);
101 if (id_buf == NULL) {
102 async_answer_0(callid, ENOMEM);
103 async_answer_0(iid, ENOMEM);
104 return;
105 }
106
107 rc = vbds_disk_get_ids(id_buf, size, &act_size);
108 if (rc != EOK) {
109 free(id_buf);
110 async_answer_0(callid, rc);
111 async_answer_0(iid, rc);
112 return;
113 }
114
115 sysarg_t retval = async_data_read_finalize(callid, id_buf, size);
116 free(id_buf);
117
118 async_answer_1(iid, retval, act_size);
119}
120
121static void vbds_disk_info_srv(ipc_callid_t iid, ipc_call_t *icall)
122{
123 service_id_t disk_sid;
124 vbd_disk_info_t dinfo;
125 int rc;
126
127 log_msg(LOG_DEFAULT, LVL_DEBUG, "vbds_disk_info_srv()");
128
129 disk_sid = IPC_GET_ARG1(*icall);
130 rc = vbds_disk_info(disk_sid, &dinfo);
131 if (rc != EOK) {
132 async_answer_0(iid, rc);
133 return;
134 }
135
136 ipc_callid_t callid;
137 size_t size;
138 if (!async_data_read_receive(&callid, &size)) {
139 async_answer_0(callid, EREFUSED);
140 async_answer_0(iid, EREFUSED);
141 return;
142 }
143
144 if (size != sizeof(vbd_disk_info_t)) {
145 async_answer_0(callid, EINVAL);
146 async_answer_0(iid, EINVAL);
147 return;
148 }
149
150 rc = async_data_read_finalize(callid, &dinfo,
151 min(size, sizeof(dinfo)));
152 if (rc != EOK) {
153 async_answer_0(callid, rc);
154 async_answer_0(iid, rc);
155 return;
156 }
157
158 async_answer_0(iid, EOK);
159}
160
161static void vbds_label_create_srv(ipc_callid_t iid, ipc_call_t *icall)
162{
163 service_id_t disk_sid;
164 label_type_t ltype;
165 int rc;
166
167 log_msg(LOG_DEFAULT, LVL_DEBUG, "vbds_label_create_srv()");
168
169 disk_sid = IPC_GET_ARG1(*icall);
170 ltype = IPC_GET_ARG2(*icall);
171 rc = vbds_label_create(disk_sid, ltype);
172 async_answer_0(iid, (sysarg_t) rc);
173}
174
175static void vbds_label_delete_srv(ipc_callid_t iid, ipc_call_t *icall)
176{
177 service_id_t disk_sid;
178 int rc;
179
180 log_msg(LOG_DEFAULT, LVL_DEBUG, "vbds_label_delete_srv()");
181
182 disk_sid = IPC_GET_ARG1(*icall);
183 rc = vbds_label_delete(disk_sid);
184 async_answer_0(iid, (sysarg_t) rc);
185}
186
187static void vbds_label_get_parts_srv(ipc_callid_t iid, ipc_call_t *icall)
188{
189 ipc_callid_t callid;
190 size_t size;
191 size_t act_size;
192 service_id_t sid;
193 int rc;
194
195 log_msg(LOG_DEFAULT, LVL_DEBUG, "vbds_label_get_parts_srv()");
196
197 if (!async_data_read_receive(&callid, &size)) {
198 async_answer_0(callid, EREFUSED);
199 async_answer_0(iid, EREFUSED);
200 return;
201 }
202
203 sid = IPC_GET_ARG1(*icall);
204
205 category_id_t *id_buf = (category_id_t *) malloc(size);
206 if (id_buf == NULL) {
207 async_answer_0(callid, ENOMEM);
208 async_answer_0(iid, ENOMEM);
209 return;
210 }
211
212 rc = vbds_get_parts(sid, id_buf, size, &act_size);
213 if (rc != EOK) {
214 async_answer_0(callid, rc);
215 async_answer_0(iid, rc);
216 return;
217 }
218
219 sysarg_t retval = async_data_read_finalize(callid, id_buf, size);
220 free(id_buf);
221
222 async_answer_1(iid, retval, act_size);
223}
224
225static void vbds_part_get_info_srv(ipc_callid_t iid, ipc_call_t *icall)
226{
227 vbds_part_id_t part;
228 vbd_part_info_t pinfo;
229 int rc;
230
231 log_msg(LOG_DEFAULT, LVL_DEBUG, "vbds_part_get_info_srv()");
232
233 part = IPC_GET_ARG1(*icall);
234 rc = vbds_part_get_info(part, &pinfo);
235 if (rc != EOK) {
236 async_answer_0(iid, rc);
237 return;
238 }
239
240 ipc_callid_t callid;
241 size_t size;
242 if (!async_data_read_receive(&callid, &size)) {
243 async_answer_0(callid, EREFUSED);
244 async_answer_0(iid, EREFUSED);
245 return;
246 }
247
248 if (size != sizeof(vbd_part_info_t)) {
249 async_answer_0(callid, EINVAL);
250 async_answer_0(iid, EINVAL);
251 return;
252 }
253
254 rc = async_data_read_finalize(callid, &pinfo,
255 min(size, sizeof(pinfo)));
256 if (rc != EOK) {
257 async_answer_0(callid, rc);
258 async_answer_0(iid, rc);
259 return;
260 }
261
262 async_answer_0(iid, EOK);
263}
264
265static void vbds_part_create_srv(ipc_callid_t iid, ipc_call_t *icall)
266{
267 service_id_t disk_sid;
268 vbd_part_spec_t pspec;
269 vbds_part_id_t part;
270 int rc;
271
272 log_msg(LOG_DEFAULT, LVL_DEBUG, "vbds_part_create_srv()");
273
274 disk_sid = IPC_GET_ARG1(*icall);
275
276 ipc_callid_t callid;
277 size_t size;
278 if (!async_data_write_receive(&callid, &size)) {
279 async_answer_0(callid, EREFUSED);
280 async_answer_0(iid, EREFUSED);
281 return;
282 }
283
284 if (size != sizeof(vbd_part_spec_t)) {
285 async_answer_0(callid, EINVAL);
286 async_answer_0(iid, EINVAL);
287 return;
288 }
289
290 rc = async_data_write_finalize(callid, &pspec, sizeof(vbd_part_spec_t));
291 if (rc != EOK) {
292 async_answer_0(callid, rc);
293 async_answer_0(iid, rc);
294 return;
295 }
296
297 rc = vbds_part_create(disk_sid, &pspec, &part);
298 if (rc != EOK) {
299 async_answer_0(iid, rc);
300 return;
301 }
302
303 async_answer_1(iid, (sysarg_t)rc, (sysarg_t)part);
304}
305
306static void vbds_part_delete_srv(ipc_callid_t iid, ipc_call_t *icall)
307{
308 vbds_part_id_t part;
309 int rc;
310
311 log_msg(LOG_DEFAULT, LVL_DEBUG, "vbds_part_delete_srv()");
312
313 part = IPC_GET_ARG1(*icall);
314 rc = vbds_part_delete(part);
315 async_answer_0(iid, (sysarg_t) rc);
316}
317
318static void vbds_suggest_ptype_srv(ipc_callid_t iid, ipc_call_t *icall)
319{
320 service_id_t disk_sid;
321 label_ptype_t ptype;
322 label_pcnt_t pcnt;
323 int rc;
324
325 log_msg(LOG_DEFAULT, LVL_DEBUG, "vbds_suggest_ptype_srv()");
326
327 disk_sid = IPC_GET_ARG1(*icall);
328 pcnt = IPC_GET_ARG2(*icall);
329
330 rc = vbds_suggest_ptype(disk_sid, pcnt, &ptype);
331 if (rc != EOK) {
332 async_answer_0(iid, rc);
333 return;
334 }
335
336 ipc_callid_t callid;
337 size_t size;
338 if (!async_data_read_receive(&callid, &size)) {
339 async_answer_0(callid, EREFUSED);
340 async_answer_0(iid, EREFUSED);
341 return;
342 }
343
344 if (size != sizeof(label_ptype_t)) {
345 async_answer_0(callid, EINVAL);
346 async_answer_0(iid, EINVAL);
347 return;
348 }
349
350 rc = async_data_read_finalize(callid, &ptype, sizeof(label_ptype_t));
351 if (rc != EOK) {
352 async_answer_0(callid, rc);
353 async_answer_0(iid, rc);
354 return;
355 }
356
357 async_answer_0(iid, EOK);
358}
359
360static void vbds_ctl_conn(ipc_callid_t iid, ipc_call_t *icall, void *arg)
361{
362 log_msg(LOG_DEFAULT, LVL_DEBUG, "vbds_client_conn()");
363
364 /* Accept the connection */
365 async_answer_0(iid, EOK);
366
367 while (true) {
368 ipc_call_t call;
369 ipc_callid_t callid = async_get_call(&call);
370 sysarg_t method = IPC_GET_IMETHOD(call);
371
372 if (!method) {
373 /* The other side has hung up */
374 async_answer_0(callid, EOK);
375 return;
376 }
377
378 switch (method) {
379 case VBD_GET_DISKS:
380 vbds_get_disks_srv(callid, &call);
381 break;
382 case VBD_DISK_INFO:
383 vbds_disk_info_srv(callid, &call);
384 break;
385 case VBD_LABEL_CREATE:
386 vbds_label_create_srv(callid, &call);
387 break;
388 case VBD_LABEL_DELETE:
389 vbds_label_delete_srv(callid, &call);
390 break;
391 case VBD_LABEL_GET_PARTS:
392 vbds_label_get_parts_srv(callid, &call);
393 break;
394 case VBD_PART_GET_INFO:
395 vbds_part_get_info_srv(callid, &call);
396 break;
397 case VBD_PART_CREATE:
398 vbds_part_create_srv(callid, &call);
399 break;
400 case VBD_PART_DELETE:
401 vbds_part_delete_srv(callid, &call);
402 break;
403 case VBD_SUGGEST_PTYPE:
404 vbds_suggest_ptype_srv(callid, &call);
405 break;
406 default:
407 async_answer_0(callid, EINVAL);
408 }
409 }
410}
411
412static void vbds_client_conn(ipc_callid_t iid, ipc_call_t *icall, void *arg)
413{
414 service_id_t sid;
415
416 log_msg(LOG_DEFAULT, LVL_DEBUG, "vbds_client_conn()");
417
418 sid = (service_id_t)IPC_GET_ARG2(*icall);
419
420 if (sid == ctl_sid)
421 vbds_ctl_conn(iid, icall, arg);
422 else
423 vbds_bd_conn(iid, icall, arg);
424}
425
426int main(int argc, char *argv[])
427{
428 int rc;
429
430 printf("%s: Virtual Block Device service\n", NAME);
431
432 if (log_init(NAME) != EOK) {
433 printf(NAME ": Failed to initialize logging.\n");
434 return 1;
435 }
436
437 rc = vbds_init();
438 if (rc != EOK)
439 return 1;
440
441 printf(NAME ": Accepting connections.\n");
442 task_retval(0);
443 async_manager();
444
445 return 0;
446}
447
448/** @}
449 */
Note: See TracBrowser for help on using the repository browser.