source: mainline/uspace/srv/sysman/connection_ctl.c@ 25697163

Last change on this file since 25697163 was 25697163, checked in by Matthieu Riolo <matthieu.riolo@…>, 6 years ago

Replacing int with errno_t

The merged code from system-daemon still used the type int
for indicating an error instead of using errno_t. This
commit corrects this mistake

  • Property mode set to 100644
File size: 7.8 KB
RevLine 
[5559712]1/*
2 * Copyright (c) 2015 Michal Koutny
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#include <errno.h>
30#include <ipc/sysman.h>
[b55f62a]31#include <macros.h>
[5559712]32#include <stdlib.h>
[b55f62a]33#include <str.h>
[5559712]34
[af92309]35#include "repo.h"
[5559712]36#include "connection_ctl.h"
37#include "job.h"
[8d74fdd]38#include "job_closure.h"
[5559712]39#include "log.h"
[8d74fdd]40#include "shutdown.h"
[5559712]41#include "sysman.h"
42
[e8747bd8]43// TODO possibly provide as type-safe function + macro in sysman.h for generic boxing
[241f1985]44static ipc_call_t *box_callid(ipc_call_t *icall)
[5559712]45{
[241f1985]46 ipc_call_t *copy = malloc(sizeof(ipc_call_t));
47 if (copy) {
48 memcpy(copy, icall, sizeof(ipc_call_t));
[5559712]49 }
[241f1985]50 return copy;
[5559712]51}
52
53static void answer_callback(void *object, void *arg)
54{
55 job_t *job = object;
56 assert(job->state == JOB_FINISHED);
57 assert(job->retval != JOB_UNDEFINED_);
58
[241f1985]59 ipc_call_t *icall = arg;
[5559712]60 // TODO use descriptive return value (probably refactor job retval)
61 sysarg_t retval = (job->retval == JOB_OK) ? EOK : EIO;
[241f1985]62 async_answer_0(icall, retval);
63 free(icall);
[5559712]64 job_del_ref(&job);
65}
[ed5367b]66
[241f1985]67static void sysman_unit_handle(ipc_call_t *icall)
[ed5367b]68{
69 char *unit_name = NULL;
70 sysarg_t retval;
71
[25697163]72 errno_t rc = async_data_write_accept((void **) &unit_name, true,
[ed5367b]73 0, 0, 0, NULL);
74 if (rc != EOK) {
75 retval = rc;
76 goto fail;
77 }
78
79 unit_t *unit = repo_find_unit_by_name(unit_name);
80 if (unit == NULL) {
81 retval = ENOENT;
82 goto fail;
83 }
84
[241f1985]85 async_answer_1(icall, EOK, unit->handle);
[ed5367b]86 goto finish;
87
88fail:
[241f1985]89 async_answer_0(icall, retval);
[ed5367b]90finish:
91 free(unit_name);
92}
93
[241f1985]94static void sysman_unit_start_by_name(ipc_call_t *icall)
[5559712]95{
96 char *unit_name = NULL;
97 sysarg_t retval;
98
[25697163]99 errno_t rc = async_data_write_accept((void **) &unit_name, true,
[5559712]100 0, 0, 0, NULL);
101 if (rc != EOK) {
102 retval = rc;
103 goto answer;
104 }
105
[241f1985]106 int flags = ipc_get_arg1(icall);
[5559712]107 sysman_log(LVL_DEBUG2, "%s(%s, %x)", __func__, unit_name, flags);
108
[af92309]109 unit_t *unit = repo_find_unit_by_name(unit_name);
[5559712]110 if (unit == NULL) {
[dda2602]111 sysman_log(LVL_NOTE, "Unit '%s' not found.", unit_name);
[5559712]112 retval = ENOENT;
113 goto answer;
114 }
115
116 if (!(flags & IPC_FLAG_BLOCKING)) {
[8d74fdd]117 retval = sysman_run_job(unit, STATE_STARTED, 0, NULL, NULL);
[5559712]118 goto answer;
119 }
120
[241f1985]121 ipc_call_t *icall_copy = box_callid(icall);
122 if (icall_copy == NULL) {
[5559712]123 retval = ENOMEM;
124 goto answer;
125 }
[8d74fdd]126 retval = sysman_run_job(unit, STATE_STARTED, 0, &answer_callback,
[241f1985]127 icall_copy);
[5559712]128 if (retval != EOK) {
129 goto answer;
130 }
131
132 /* Answer asynchronously from callback */
133 goto finish;
134
135answer:
[241f1985]136 async_answer_0(icall, retval);
[5559712]137finish:
138 free(unit_name);
139}
140
[241f1985]141static void sysman_unit_operation(ipc_call_t *icall, unit_state_t state)
[ed5367b]142{
143 sysarg_t retval;
144
[241f1985]145 unit_handle_t handle = ipc_get_arg1(icall);
146 sysarg_t flags = ipc_get_arg2(icall);
147 sysman_log(LVL_DEBUG2, "%s(%p, %lx, %i)", __func__, icall->cap_handle, flags, state);
[ed5367b]148
149 unit_t *unit = repo_find_unit_by_handle(handle);
150 if (unit == NULL) {
151 retval = ENOENT;
152 goto answer;
153 }
154
155 if (!(flags & IPC_FLAG_BLOCKING)) {
[8d74fdd]156 retval = sysman_run_job(unit, state, 0, NULL, NULL);
[ed5367b]157 goto answer;
158 }
159
[241f1985]160 ipc_call_t *icall_copy = box_callid(icall);
161 if (icall_copy == NULL) {
[ed5367b]162 retval = ENOMEM;
163 goto answer;
164 }
[8d74fdd]165 retval = sysman_run_job(unit, state, 0, &answer_callback,
[241f1985]166 icall_copy);
[ed5367b]167 if (retval != EOK) {
168 goto answer;
169 }
170
171 /* Answer asynchronously from callback */
172 return;
173
174answer:
[241f1985]175 async_answer_0(icall, retval);
[ed5367b]176}
177
[241f1985]178static void sysman_unit_start(ipc_call_t *icall)
[8fab3f6]179{
[241f1985]180 sysman_unit_operation(icall, STATE_STARTED);
[8fab3f6]181}
182
[241f1985]183static void sysman_unit_stop(ipc_call_t *icall)
[8fab3f6]184{
[241f1985]185 sysman_unit_operation(icall, STATE_STOPPED);
[8fab3f6]186}
187
[25697163]188static errno_t fill_handles_buffer(unit_handle_t *buffer, size_t size,
[b55f62a]189 size_t *act_size)
190{
191 if (size % sizeof(unit_handle_t) != 0) {
192 return EINVAL;
193 }
194
195 size_t filled = 0;
196 size_t to_fill = size / sizeof(unit_handle_t);
197 size_t total = 0;
[ff20afc]198 repo_rlock();
[015b147]199 repo_foreach(u) {
[b55f62a]200 if (filled < to_fill) {
201 buffer[filled++] = u->handle;
202 }
203 ++total;
204 }
[ff20afc]205 repo_runlock();
[b55f62a]206 *act_size = total * sizeof(unit_handle_t);
207 return EOK;
208}
209
[241f1985]210static void sysman_get_units(ipc_call_t *icall)
[b55f62a]211{
[241f1985]212 ipc_call_t call;
[b55f62a]213 size_t size;
214 size_t act_size;
[25697163]215 errno_t rc;
[102f641]216
[241f1985]217 if (!async_data_read_receive(&call, &size)) {
218 async_answer_0(&call, EREFUSED);
219 async_answer_0(icall, EREFUSED);
[b55f62a]220 return;
221 }
[102f641]222
[b55f62a]223 unit_handle_t *handles = malloc(size);
224 if (handles == NULL && size > 0) {
[241f1985]225 async_answer_0(&call, ENOMEM);
226 async_answer_0(icall, ENOMEM);
[b55f62a]227 return;
228 }
[102f641]229
[b55f62a]230 rc = fill_handles_buffer(handles, size, &act_size);
231 if (rc != EOK) {
[241f1985]232 async_answer_0(&call, rc);
233 async_answer_0(icall, rc);
[b55f62a]234 return;
235 }
[102f641]236
[b55f62a]237 size_t real_size = min(act_size, size);
[241f1985]238 sysarg_t retval = async_data_read_finalize(&call, handles, real_size);
[b55f62a]239 free(handles);
[102f641]240
[241f1985]241 async_answer_1(icall, retval, act_size);
[b55f62a]242}
243
[241f1985]244static void sysman_unit_get_name(ipc_call_t *icall)
[b55f62a]245{
[241f1985]246 ipc_call_t call;
[b55f62a]247 size_t size;
[102f641]248
[241f1985]249 if (!async_data_read_receive(&call, &size)) {
250 async_answer_0(&call, EREFUSED);
251 async_answer_0(icall, EREFUSED);
[b55f62a]252 return;
253 }
[102f641]254
[241f1985]255 unit_t *u = repo_find_unit_by_handle(ipc_get_arg1(icall));
[b55f62a]256 if (u == NULL) {
[241f1985]257 async_answer_0(&call, ENOENT);
258 async_answer_0(icall, ENOENT);
[b55f62a]259 return;
260 }
[102f641]261
[b55f62a]262 size_t real_size = min(str_size(u->name) + 1, size);
[241f1985]263 sysarg_t retval = async_data_read_finalize(&call, u->name, real_size);
[102f641]264
[241f1985]265 async_answer_0(icall, retval);
[b55f62a]266}
267
[241f1985]268static void sysman_unit_get_state(ipc_call_t *icall)
[b55f62a]269{
[241f1985]270 unit_t *u = repo_find_unit_by_handle(ipc_get_arg1(icall));
[b55f62a]271 if (u == NULL) {
[241f1985]272 async_answer_0(icall, ENOENT);
[b55f62a]273 } else {
[241f1985]274 async_answer_1(icall, EOK, u->state);
[b55f62a]275 }
276}
277
[241f1985]278static void sysman_shutdown(ipc_call_t *icall)
[8d74fdd]279{
[241f1985]280 errno_t retval;
[8d74fdd]281 unit_t *u = repo_find_unit_by_name(TARGET_SHUTDOWN);
282 if (u == NULL) {
283 retval = ENOENT;
284 goto finish;
285 }
286
287 retval = sysman_run_job(u, STATE_STARTED, CLOSURE_ISOLATE,
288 shutdown_cb, NULL);
289
290finish:
[241f1985]291 async_answer_0(icall, retval);
[8d74fdd]292}
293
[241f1985]294void sysman_connection_ctl(ipc_call_t *icall)
[5559712]295{
296 sysman_log(LVL_DEBUG2, "%s", __func__);
297 /* First, accept connection */
[241f1985]298 async_answer_0(icall, EOK);
[5559712]299
300 while (true) {
301 ipc_call_t call;
[102f641]302
[241f1985]303 if (!async_get_call(&call) || !ipc_get_imethod(&call)) {
[5559712]304 /* Client disconnected */
305 break;
306 }
307
[241f1985]308 switch (ipc_get_imethod(&call)) {
[ed5367b]309 case SYSMAN_CTL_UNIT_HANDLE:
[241f1985]310 sysman_unit_handle(&call);
[ed5367b]311 break;
[504d103]312 case SYSMAN_CTL_UNIT_START_BY_NAME:
[241f1985]313 sysman_unit_start_by_name(&call);
[5559712]314 break;
[8fab3f6]315 case SYSMAN_CTL_UNIT_START:
[241f1985]316 sysman_unit_start(&call);
[8fab3f6]317 break;
[ed5367b]318 case SYSMAN_CTL_UNIT_STOP:
[241f1985]319 sysman_unit_stop(&call);
[ed5367b]320 break;
[b55f62a]321 case SYSMAN_CTL_GET_UNITS:
[241f1985]322 sysman_get_units(&call);
[b55f62a]323 break;
324 case SYSMAN_CTL_UNIT_GET_NAME:
[241f1985]325 sysman_unit_get_name(&call);
[b55f62a]326 break;
327 case SYSMAN_CTL_UNIT_GET_STATE:
[241f1985]328 sysman_unit_get_state(&call);
[b55f62a]329 break;
[8d74fdd]330 case SYSMAN_CTL_SHUTDOWN:
[241f1985]331 sysman_shutdown(&call);
[8d74fdd]332 break;
[5559712]333 default:
[241f1985]334 async_answer_0(&call, ENOENT);
[5559712]335 }
336 }
337}
Note: See TracBrowser for help on using the repository browser.