source: mainline/uspace/srv/sysman/units/unit_mnt.c@ 241f1985

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

Correcting failure from previous merge

The commits from Michal Koutný from the branch system-daemon
where built on a old version of Helenos. Because of this
many types and API functions have changed. This commit
upgrades the merge code

  • Property mode set to 100644
File size: 7.5 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 <assert.h>
30#include <errno.h>
31#include <fibril_synch.h>
32#include <stdlib.h>
33#include <vfs/vfs.h>
34#include <str.h>
35
36#include "log.h"
37#include "sysman.h"
38#include "unit.h"
39
40static const char *section_name = "Mount";
41
42static config_item_t unit_configuration[] = {
43 {"What", &config_parse_string, offsetof(unit_mnt_t, device), NULL},
44 {"Where", &config_parse_string, offsetof(unit_mnt_t, mountpoint), NULL},
45 {"Type", &config_parse_string, offsetof(unit_mnt_t, type), NULL},
46 {"Autostart", &config_parse_bool, offsetof(unit_mnt_t, autostart), "true"},
47 {"Blocking", &config_parse_bool, offsetof(unit_mnt_t, blocking), "true"},
48 CONFIGURATION_ITEM_SENTINEL
49};
50
51typedef struct {
52 char *type;
53 char *mountpoint;
54 char *device;
55 char *options;
56 unsigned int flags;
57 unsigned int instance;
58
59 unit_t *unit;
60 bool owner;
61} mount_data_t;
62
63static void mount_data_destroy(mount_data_t **mnt_data_ptr)
64{
65 assert(mnt_data_ptr);
66 if (*mnt_data_ptr == NULL) {
67 return;
68 }
69
70 mount_data_t *mnt_data = *mnt_data_ptr;
71 free(mnt_data->type);
72 free(mnt_data->mountpoint);
73 free(mnt_data->device);
74 free(mnt_data->options);
75
76 free(mnt_data);
77 *mnt_data_ptr = NULL;
78}
79
80static bool mount_data_copy(mount_data_t *src, mount_data_t **dst_ptr)
81{
82 mount_data_t *dst = malloc(sizeof(mount_data_t));
83 if (dst == NULL) {
84 goto fail;
85 }
86
87 dst->type = str_dup(src->type);
88 if (dst->type == NULL)
89 goto fail;
90
91 dst->mountpoint = str_dup(src->mountpoint);
92 if (dst->mountpoint == NULL)
93 goto fail;
94
95 dst->device = str_dup(src->device);
96 if (dst->device == NULL)
97 goto fail;
98
99 dst->options = src->options ? str_dup(src->options) : NULL;
100 if (src->options != NULL && dst->options == NULL)
101 goto fail;
102
103 dst->flags = src->flags;
104 dst->instance = src->instance;
105 dst->unit = src->unit;
106 dst->owner = true;
107
108 *dst_ptr = dst;
109 return true;
110
111fail:
112 mount_data_destroy(&dst);
113 return false;
114}
115
116static void unit_mnt_init(unit_t *unit)
117{
118 unit_mnt_t *u_mnt = CAST_MNT(unit);
119 assert(u_mnt);
120}
121
122static void unit_mnt_destroy(unit_t *unit)
123{
124 assert(unit->type == UNIT_MOUNT);
125 unit_mnt_t *u_mnt = CAST_MNT(unit);
126
127 free(u_mnt->type);
128 free(u_mnt->mountpoint);
129 free(u_mnt->device);
130}
131
132static errno_t unit_mnt_load(unit_t *unit, ini_configuration_t *ini_conf,
133 text_parse_t *text_parse)
134{
135 unit_mnt_t *u_mnt = CAST_MNT(unit);
136 assert(u_mnt);
137
138 ini_section_t *section = ini_get_section(ini_conf, section_name);
139 if (section == NULL) {
140 sysman_log(LVL_ERROR,
141 "Expected section '%s' in configuration of unit '%s'",
142 section_name, unit_name(unit));
143 return ENOENT;
144 }
145
146 return config_load_ini_section(unit_configuration, section, u_mnt,
147 text_parse);
148}
149
150static errno_t mount_exec(void *arg)
151{
152 mount_data_t *mnt_data = arg;
153 sysman_log(LVL_DEBUG2, "%s(%p, %p, %p, %p, %x, %u)",
154 __func__,
155 mnt_data->type, mnt_data->mountpoint, mnt_data->device, mnt_data->options,
156 mnt_data->flags, mnt_data->instance);
157
158 errno_t rc = vfs_mount_path(mnt_data->type, mnt_data->mountpoint, mnt_data->device,
159 mnt_data->options ? mnt_data->options : "",
160 mnt_data->flags, mnt_data->instance);
161
162 if (rc == EOK) {
163 sysman_log(LVL_DEBUG, "Mount ('%s') mounted",
164 unit_name(mnt_data->unit));
165 /*
166 * Emulate future VFS broker fibril that notifies about created
167 * exposee.
168 * Difference: It'll notify exposee name only, we'll have to
169 * match it...
170 */
171 sysman_raise_event(&sysman_event_unit_exposee_created,
172 mnt_data->unit);
173 } else {
174 sysman_log(LVL_ERROR, "Mount ('%s') failed (%i)",
175 unit_name(mnt_data->unit), rc);
176 /*
177 * Think about analogy of this event, probably timeout or sthing
178 */
179 sysman_raise_event(&sysman_event_unit_failed,
180 mnt_data->unit);
181 }
182
183 if (mnt_data->owner) {
184 mount_data_destroy(&mnt_data);
185 }
186
187 return EOK;
188}
189
190static errno_t unit_mnt_start(unit_t *unit)
191{
192 unit_mnt_t *u_mnt = CAST_MNT(unit);
193 assert(u_mnt);
194 /* autostart implies blocking */
195 assert(!u_mnt->autostart || u_mnt->blocking);
196
197
198 assert(unit->state == STATE_STOPPED);
199
200 mount_data_t mnt_data;
201 memset(&mnt_data, 0, sizeof(mnt_data));
202 mnt_data.type = u_mnt->type;
203 mnt_data.mountpoint = u_mnt->mountpoint;
204 mnt_data.device = u_mnt->device;
205 /* TODO use other mount parameters
206 * mnt_data.options = u_mnt->options;
207 * mnt_data.instance = u_mnt->instance;
208 */
209
210 mnt_data.flags |= u_mnt->blocking ? IPC_FLAG_BLOCKING : 0;
211 mnt_data.flags |= u_mnt->autostart ? IPC_AUTOSTART : 0;
212 mnt_data.unit = unit;
213
214 if (u_mnt->blocking) {
215 mount_data_t *heap_mnt_data = NULL;
216 if (!mount_data_copy(&mnt_data, &heap_mnt_data)) {
217 return ENOMEM;
218 }
219 fid_t fib = fibril_create(&mount_exec, heap_mnt_data);
220 unit->state = STATE_STARTING;
221 fibril_add_ready(fib);
222 } else {
223 unit->state = STATE_STARTING;
224 mount_exec(&mnt_data);
225 }
226
227 return EOK;
228}
229
230static errno_t unit_mnt_stop(unit_t *unit)
231{
232 unit_mnt_t *u_mnt = CAST_MNT(unit);
233 assert(u_mnt);
234 /* autostart implies blocking */
235 assert(!u_mnt->autostart || u_mnt->blocking);
236
237
238 // note: we should never hit STATE_STARTING, since it'd mean there are
239 // two jobs running at once (unless job cancellation is implemented)
240 assert(unit->state == STATE_STARTED);
241
242 /*
243 * We don't expect unmount to be blocking, since if some files are
244 * being used, it'd return EBUSY immediately. That's why we call
245 * unmount synchronously in the event loop fibril.
246 */
247 errno_t rc = vfs_unmount_path(u_mnt->mountpoint);
248
249 if (rc == EOK) {
250 unit->state = STATE_STOPPED;
251 return EOK;
252 } else if (rc == EBUSY) {
253 assert(unit->state == STATE_STARTED);
254 return EBUSY;
255 } else {
256 /*
257 * Mount may be still usable, but be conservative and mark unit
258 * as failed.
259 */
260 unit->state = STATE_FAILED;
261 return rc;
262 }
263}
264
265static void unit_mnt_exposee_created(unit_t *unit)
266{
267 assert(CAST_MNT(unit));
268 assert(unit->state == STATE_STOPPED || unit->state == STATE_STARTING);
269
270 if (str_cmp(unit_name(unit), "rootfs.mnt") == 0) {
271 sysman_log_tofile();
272 }
273 unit->state = STATE_STARTED;
274 unit_notify_state(unit);
275}
276
277static void unit_mnt_fail(unit_t *unit)
278{
279 assert(CAST_MNT(unit));
280 assert(unit->state == STATE_STARTING);
281
282 unit->state = STATE_FAILED;
283 unit_notify_state(unit);
284}
285
286
287DEFINE_UNIT_VMT(unit_mnt)
288
Note: See TracBrowser for help on using the repository browser.