source: mainline/uspace/srv/sysman/main.c@ 5830c7b

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

Removing rootfs from sysman units

For debugging reasons it's easier to work without an extra mounted root hd.
This commit might need to be rollbacked in the future. But since no rootfs
specific code has been imported from the original repo, it can to been removed

  • Property mode set to 100644
File size: 6.2 KB
Line 
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 <async.h>
30#include <errno.h>
31#include <fibril.h>
32#include <ipc/sysman.h>
33#include <macros.h>
34#include <ns.h>
35#include <stddef.h>
36#include <stdio.h>
37#include <str.h>
38#include <taskman.h>
39
40#include "connection_broker.h"
41#include "connection_ctl.h"
42#include "edge.h"
43#include "job_queue.h"
44#include "log.h"
45#include "repo.h"
46#include "sm_task.h"
47#include "sysman.h"
48#include "unit.h"
49
50#define NAME "sysman"
51
52static const char *target_sequence[] = {
53 TARGET_INIT,
54 //TODO: Mount root fs
55 //TARGET_ROOTFS,
56 TARGET_DEFAULT,
57 NULL
58};
59
60/*
61 * Forward declarations
62 */
63static void prepare_and_run_job(const char **target_name_ptr);
64
65/*
66 * Static functions
67 */
68
69static void sysman_connection(ipc_call_t *icall, void *arg)
70{
71 async_accept_0(icall);
72
73 while (true) {
74 ipc_call_t call;
75 async_get_call(&call);
76
77 if (!ipc_get_imethod(&call)) {
78 async_answer_0(&call, EOK);
79 break;
80 }
81
82 sysman_interface_t iface = ipc_get_arg1(&call);
83 switch (iface) {
84 case SYSMAN_PORT_BROKER:
85 sysman_connection_broker(&call);
86 break;
87 case SYSMAN_PORT_CTL:
88 sysman_connection_ctl(&call);
89 break;
90 default:
91 /* Unknown interface */
92 async_answer_0(&call, ENOENT);
93 }
94 }
95}
96
97/** Build hard coded configuration */
98static errno_t create_entry_configuration(void)
99{
100 errno_t rc;
101 unit_t *mnt_initrd = NULL;
102 unit_t *cfg_init = NULL;
103 unit_t *tgt_init = NULL;
104
105 mnt_initrd = unit_create(UNIT_MOUNT);
106 if (mnt_initrd == NULL) {
107 rc = ENOMEM;
108 goto fail;
109 }
110 mnt_initrd->name = str_dup(UNIT_MNT_INITRD);
111 CAST_MNT(mnt_initrd)->type = str_dup(STRING(RDFMT));
112 CAST_MNT(mnt_initrd)->mountpoint = str_dup(INITRD_MOUNT_POINT);
113 CAST_MNT(mnt_initrd)->device = str_dup(INITRD_DEVICE);
114 CAST_MNT(mnt_initrd)->autostart = false;
115 CAST_MNT(mnt_initrd)->blocking = true;
116
117 cfg_init = unit_create(UNIT_CONFIGURATION);
118 if (cfg_init == NULL) {
119 rc = ENOMEM;
120 goto fail;
121 }
122 cfg_init->name = str_dup(UNIT_CFG_INITRD);
123 CAST_CFG(cfg_init)->path = str_dup(INITRD_CFG_PATH);
124
125 tgt_init = unit_create(UNIT_TARGET);
126 if (tgt_init == NULL) {
127 rc = ENOMEM;
128 goto fail;
129 }
130 tgt_init->name = str_dup(TARGET_INIT);
131
132 /*
133 * Add units to configuration and start the default target.
134 */
135 repo_begin_update();
136
137 repo_add_unit(mnt_initrd);
138 repo_add_unit(cfg_init);
139 repo_add_unit(tgt_init);
140
141 rc = edge_connect(tgt_init, cfg_init);
142 if (rc != EOK) {
143 goto rollback;
144 }
145
146 rc = edge_connect(cfg_init, mnt_initrd);
147 if (rc != EOK) {
148 goto rollback;
149 }
150
151 repo_commit();
152
153 return EOK;
154
155fail:
156 unit_destroy(&tgt_init);
157 unit_destroy(&cfg_init);
158 unit_destroy(&mnt_initrd);
159 return rc;
160
161rollback:
162 repo_rollback();
163 return rc;
164}
165
166static void sequence_job_handler(void *object, void *arg)
167{
168 job_t *job = object;
169 if (job->retval == JOB_FAILED) {
170 sysman_log(LVL_ERROR, "Failed to start '%s'.", unit_name(job->unit));
171 job_del_ref(&job);
172 return;
173 }
174 job_del_ref(&job);
175
176 const char **target_name_ptr = arg;
177 prepare_and_run_job(target_name_ptr + 1);
178}
179
180static void prepare_and_run_job(const char **target_name_ptr)
181{
182 const char *target_name = *target_name_ptr;
183
184 if (target_name == NULL) {
185 sysman_log(LVL_NOTE, "All initial units started.");
186 return;
187 }
188
189 /* Previous targets should have loaded new units */
190 unit_t *tgt = repo_find_unit_by_name(target_name);
191 if (tgt == NULL) {
192 sysman_log(LVL_ERROR,
193 "Expected unit '%s' not found in configuration.",
194 target_name);
195 return;
196 }
197
198 errno_t rc = sysman_run_job(tgt, STATE_STARTED, 0, &sequence_job_handler,
199 target_name_ptr);
200
201 if (rc != EOK) {
202 sysman_log(LVL_FATAL, "Cannot create job for '%s'.", target_name);
203 }
204}
205
206int main(int argc, char *argv[])
207{
208 printf(NAME ": HelenOS system daemon\n");
209
210 /*
211 * Initialize global structures
212 */
213 // TODO check return values and abort start
214 repo_init();
215 sysman_events_init();
216 job_queue_init();
217
218 /*
219 * Create initial configuration while we are in a single fibril
220 */
221 errno_t rc = create_entry_configuration();
222 if (rc != EOK) {
223 sysman_log(LVL_FATAL,
224 "Could not create initial configuration (%i).", rc);
225 return rc;
226 }
227
228 /*
229 * Event loop runs in separate fibril, all consequent access to global
230 * structure is made from this fibril only.
231 */
232 fid_t event_loop_fibril = fibril_create(sysman_events_loop, NULL);
233 fibril_add_ready(event_loop_fibril);
234
235 /* We're service too */
236 rc = service_register(SERVICE_SYSMAN, INTERFACE_SYSMAN, sysman_connection, NULL);
237 if (rc != EOK) {
238 sysman_log(LVL_FATAL,
239 "Cannot register at naming service (%i).", rc);
240 return rc;
241 }
242
243 /* Start listening task events and scan boot time tasks */
244 rc = sm_task_start();
245 if (rc != EOK) {
246 sysman_log(LVL_FATAL,
247 "Cannot scan boot time tasks (%i).", rc);
248 return rc;
249 }
250
251 /* Queue first job from sequence */
252 prepare_and_run_job(&target_sequence[0]);
253
254 /* Start sysman server */
255
256 printf(NAME ": Accepting connections\n");
257 task_retval(0);
258 async_manager();
259
260 /* not reached */
261 return 0;
262}
Note: See TracBrowser for help on using the repository browser.