Changeset ed5367b in mainline
- Timestamp:
- 2019-08-07T10:01:13Z (5 years ago)
- Children:
- a097c50
- Parents:
- 68ae40a
- git-author:
- Michal Koutný <xm.koutny+hos@…> (2015-11-05 01:52:07)
- git-committer:
- Matthieu Riolo <matthieu.riolo@…> (2019-08-07 10:01:13)
- Location:
- uspace
- Files:
-
- 14 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/app/sysctl/main.c
r68ae40a red5367b 37 37 #include <stdlib.h> 38 38 #include <str.h> 39 #include <str_error.h> 39 40 #include <sysman/ctl.h> 40 41 … … 91 92 continue; 92 93 fail: 93 printf(" -- unit skipped due to IPC error (%i) --\n", rc); 94 printf(" -- unit skipped due to IPC error (%s) --\n", 95 str_error(rc)); 96 } 97 98 return 0; 99 } 100 101 static int stop(int argc, char *argv[]) 102 { 103 unit_handle_t handle; 104 char *unit_name = argv[1]; 105 106 int rc = sysman_unit_handle(unit_name, &handle); 107 if (rc != EOK) { 108 printf("Cannot obtain handle for unit '%s' (%s).\n", 109 unit_name, str_error(rc)); 110 return rc; 111 } 112 113 rc = sysman_unit_stop(handle, IPC_FLAG_BLOCKING); 114 if (rc != EOK) { 115 printf("Error when stopping unit '%s' handle (%s).\n", 116 unit_name, str_error(rc)); 117 return rc; 94 118 } 95 119 … … 99 123 command_t commands[] = { 100 124 { "list-units", 0, &list_units }, 125 { "stop", 1, &stop }, 101 126 { 0 } 102 127 }; -
uspace/lib/c/include/ipc/sysman.h
r68ae40a red5367b 44 44 SYSMAN_BROKER_EXP_ADDED, 45 45 SYSMAN_BROKER_EXP_REMOVED, 46 SYSMAN_CTL_UNIT_HANDLE, 46 47 SYSMAN_CTL_UNIT_START, 48 SYSMAN_CTL_UNIT_STOP, 47 49 SYSMAN_CTL_GET_UNITS, 48 50 SYSMAN_CTL_UNIT_GET_NAME, … … 71 73 STATE_STARTED, 72 74 STATE_STOPPED, 75 STATE_STOPPING, 73 76 STATE_FAILED 74 77 } unit_state_t; -
uspace/lib/sysman/include/sysman/ctl.h
r68ae40a red5367b 33 33 #include <sysman/unit.h> 34 34 35 int sysman_unit_handle(const char *, unit_handle_t *); 36 35 37 int sysman_unit_start(const char *, int); 38 int sysman_unit_stop(unit_handle_t, int); 36 39 37 40 int sysman_get_units(unit_handle_t **, size_t *); -
uspace/lib/sysman/src/ctl.c
r68ae40a red5367b 34 34 #include <sysman/sysman.h> 35 35 36 int sysman_unit_handle(const char *unit_name, unit_handle_t *handle_ptr) 37 { 38 async_exch_t *exch = sysman_exchange_begin(SYSMAN_PORT_CTL); 39 40 ipc_call_t call; 41 aid_t req = async_send_0(exch, SYSMAN_CTL_UNIT_HANDLE, &call); 42 sysarg_t rc = async_data_write_start(exch, unit_name, str_size(unit_name)); 43 sysman_exchange_end(exch); 44 45 if (rc != EOK) { 46 async_forget(req); 47 return rc; 48 } 49 50 async_wait_for(req, &rc); 51 if (rc == EOK) { 52 *handle_ptr = IPC_GET_ARG1(call); 53 } 54 return rc; 55 } 56 36 57 /* 37 58 * TODO … … 41 62 * broker knows when appropriate exposee is created and the request succeeded. 42 63 * Still though, it's necessary to centralize timeout into sysman. 64 * TODO convert to name->handle API 43 65 */ 44 66 int sysman_unit_start(const char *unit_name, int flags) … … 56 78 57 79 async_wait_for(req, &rc); 80 return rc; 81 } 82 83 int sysman_unit_stop(unit_handle_t handle, int flags) 84 { 85 async_exch_t *exch = sysman_exchange_begin(SYSMAN_PORT_CTL); 86 87 int rc = async_req_2_0(exch, SYSMAN_CTL_UNIT_STOP, handle, flags); 88 sysman_exchange_end(exch); 89 58 90 return rc; 59 91 } -
uspace/srv/sysman/connection_ctl.c
r68ae40a red5367b 63 63 job_del_ref(&job); 64 64 } 65 66 static void sysman_unit_handle(ipc_callid_t iid, ipc_call_t *icall) 67 { 68 char *unit_name = NULL; 69 sysarg_t retval; 70 71 int rc = async_data_write_accept((void **) &unit_name, true, 72 0, 0, 0, NULL); 73 if (rc != EOK) { 74 retval = rc; 75 goto fail; 76 } 77 78 // TODO this is connection fibril, UNSYNCHRONIZED access to units! 79 unit_t *unit = repo_find_unit_by_name(unit_name); 80 if (unit == NULL) { 81 retval = ENOENT; 82 goto fail; 83 } 84 85 async_answer_1(iid, EOK, unit->handle); 86 goto finish; 87 88 fail: 89 async_answer_0(iid, retval); 90 finish: 91 free(unit_name); 92 } 93 65 94 static void sysman_unit_start(ipc_callid_t iid, ipc_call_t *icall) 66 95 { … … 109 138 finish: 110 139 free(unit_name); 140 } 141 142 static void sysman_unit_stop(ipc_callid_t iid, ipc_call_t *icall) 143 { 144 sysarg_t retval; 145 146 unit_handle_t handle = IPC_GET_ARG1(*icall); 147 int flags = IPC_GET_ARG2(*icall); 148 sysman_log(LVL_DEBUG2, "%s(%i, %x)", __func__, handle, flags); 149 150 // TODO this is connection fibril, UNSYNCHRONIZED access to units! 151 unit_t *unit = repo_find_unit_by_handle(handle); 152 if (unit == NULL) { 153 retval = ENOENT; 154 goto answer; 155 } 156 157 if (!(flags & IPC_FLAG_BLOCKING)) { 158 retval = sysman_run_job(unit, STATE_STOPPED, NULL, NULL); 159 goto answer; 160 } 161 162 ipc_callid_t *iid_ptr = box_callid(iid); 163 if (iid_ptr == NULL) { 164 retval = ENOMEM; 165 goto answer; 166 } 167 retval = sysman_run_job(unit, STATE_STOPPED, &answer_callback, 168 iid_ptr); 169 if (retval != EOK) { 170 goto answer; 171 } 172 173 /* Answer asynchronously from callback */ 174 return; 175 176 answer: 177 async_answer_0(iid, retval); 111 178 } 112 179 … … 220 287 221 288 switch (IPC_GET_IMETHOD(call)) { 289 case SYSMAN_CTL_UNIT_HANDLE: 290 sysman_unit_handle(callid, &call); 291 break; 222 292 case SYSMAN_CTL_UNIT_START: 223 293 sysman_unit_start(callid, &call); 294 break; 295 case SYSMAN_CTL_UNIT_STOP: 296 sysman_unit_stop(callid, &call); 224 297 break; 225 298 case SYSMAN_CTL_GET_UNITS: -
uspace/srv/sysman/job.c
r68ae40a red5367b 199 199 200 200 int rc; 201 // TODO put here similar evaluation as in job_check 202 // goal is to have job_run "idempotent" 201 203 switch (job->target_state) { 202 204 case STATE_STARTED: 203 // TODO put here same evaluation as in job_check204 // goal is to have job_run "idempotent"205 205 if (u->state == job->target_state) { 206 206 rc = EOK; … … 209 209 } 210 210 break; 211 case STATE_STOPPED: 212 if (u->state == job->target_state) { 213 rc = EOK; 214 } else { 215 rc = unit_stop(u); 216 } 217 break; 211 218 default: 212 // TODO implement other states 219 // TODO implement other states? 213 220 assert(false); 214 221 } -
uspace/srv/sysman/job_closure.c
r68ae40a red5367b 39 39 40 40 /** Struct describes how to traverse units graph */ 41 typedef struct { 41 struct bfs_ops; 42 typedef struct bfs_ops bfs_ops_t; 43 44 struct bfs_ops { 42 45 enum { 43 46 BFS_FORWARD, /**< Follow oriented edges */ … … 46 49 47 50 /** Visit a unit via edge 48 * unit, incoming edge, user data51 * unit, incoming edge, traversing ops, user data 49 52 * return result of visit (error stops further traversal) 50 53 */ 51 int (* visit)(unit_t *, unit_edge_t *, void *);54 int (* visit)(unit_t *, unit_edge_t *, bfs_ops_t *, void *); 52 55 53 56 /** Clean units remaining in BFS queue after error */ 54 void (* clean)(unit_t *, void *);55 } bfs_ops_t;57 void (* clean)(unit_t *, bfs_ops_t *, void *); 58 }; 56 59 57 60 /* … … 83 86 * @return EOK on success 84 87 */ 85 static int start_visit(unit_t *u, unit_edge_t *e, void *arg) 88 static int visit_propagate_job(unit_t *u, unit_edge_t *e, bfs_ops_t *ops, 89 void *arg) 86 90 { 87 91 int rc = EOK; … … 99 103 } 100 104 101 job_t *job = e->input->bfs_data; 105 job_t *job = (ops->direction == BFS_FORWARD) ? 106 e->input->bfs_data : 107 e->output->bfs_data; 108 102 109 assert(job != NULL); 103 110 … … 129 136 } 130 137 131 static void traverse_clean(unit_t *u, void *arg)138 static void traverse_clean(unit_t *u, bfs_ops_t *ops, void *arg) 132 139 { 133 140 job_t *job = u->bfs_data; … … 144 151 unit_t *unit = origin; 145 152 146 rc = ops->visit(unit, NULL, arg);153 rc = ops->visit(unit, NULL, ops, arg); 147 154 if (rc != EOK) { 148 155 goto finish; … … 164 171 list_append(&u->bfs_link, &units_fifo); 165 172 } 166 rc = ops->visit(u, e, arg);173 rc = ops->visit(u, e, ops, arg); 167 174 if (rc != EOK) { 168 175 goto finish; … … 175 182 list_append(&u->bfs_link, &units_fifo); 176 183 } 177 rc = ops->visit(u, e, arg);184 rc = ops->visit(u, e, ops, arg); 178 185 if (rc != EOK) { 179 186 goto finish; … … 187 194 list_foreach_safe(units_fifo, cur_link, next_link) { 188 195 unit_t *u = list_get_instance(cur_link, unit_t, bfs_link); 189 ops->clean(u, arg);196 ops->clean(u, ops, arg); 190 197 list_remove(cur_link); 191 198 } … … 227 234 228 235 static bfs_ops_t ops = { 229 .direction = BFS_FORWARD,230 .visit = start_visit,231 236 .clean = traverse_clean, 237 .visit = visit_propagate_job 232 238 }; 239 240 switch (main_job->target_state) { 241 case STATE_STARTED: 242 ops.direction = BFS_FORWARD; 243 break; 244 case STATE_STOPPED: 245 ops.direction = BFS_BACKWARD; 246 break; 247 default: 248 assert(false); 249 } 250 233 251 int rc = dyn_array_append(job_closure, job_t *, main_job); 234 252 if (rc != EOK) { -
uspace/srv/sysman/sm_task.c
r68ae40a red5367b 101 101 sysman_log(LVL_DEBUG2, "%s, %s(%i)@%" PRIu64 " %i", 102 102 __func__, unit_name(u), u->state, tev->task_id, tev->flags); 103 assert(u->state == STATE_STARTING);104 103 105 104 if (tev->flags & TASK_WAIT_EXIT) { 106 105 // TODO maybe call unit_fail (would be nice to contain reason) 107 u->state = STATE_FAILED; 108 } else { 106 // or move this whole logic to unit_svc.c 107 if (u->state == STATE_STOPPING) { 108 u->state = STATE_STOPPED; 109 } else { 110 // if it has also retval == 0 then it's not fail 111 u->state = STATE_FAILED; 112 } 113 } 114 if (tev->flags & TASK_WAIT_RETVAL) { 115 assert(u->state == STATE_STARTING); 109 116 u->state = STATE_STARTED; 110 117 } -
uspace/srv/sysman/unit.c
r68ae40a red5367b 142 142 } 143 143 144 /** Issue request to restarter to stop a unit 145 * 146 * Same semantics like for unit_start applies. 147 */ 148 int unit_stop(unit_t *unit) 149 { 150 sysman_log(LVL_DEBUG, "%s('%s')", __func__, unit_name(unit)); 151 return UNIT_VMT(unit)->stop(unit); 152 } 153 144 154 void unit_exposee_created(unit_t *unit) 145 155 { -
uspace/srv/sysman/unit.h
r68ae40a red5367b 70 70 job_t *job; 71 71 72 /** Handle for IPC (immutable) */ 72 73 unit_handle_t handle; 74 75 /** Unit type (immutable) */ 73 76 unit_type_t type; 77 78 /** Unit name (immutable) */ 74 79 char *name; 75 80 … … 110 115 int (*start)(unit_t *); 111 116 117 int (*stop)(unit_t *); 118 112 119 void (*exposee_created)(unit_t *); 113 120 … … 124 131 .destroy = &PREFIX##_destroy, \ 125 132 .start = &PREFIX##_start, \ 133 .stop = &PREFIX##_stop, \ 126 134 .exposee_created = &PREFIX##_exposee_created, \ 127 135 .fail = &PREFIX##_fail \ … … 135 143 extern int unit_load(unit_t *, ini_configuration_t *, text_parse_t *); 136 144 extern int unit_start(unit_t *); 145 extern int unit_stop(unit_t *); 137 146 extern void unit_exposee_created(unit_t *); 138 147 extern void unit_fail(unit_t *); -
uspace/srv/sysman/units/unit_cfg.c
r68ae40a red5367b 240 240 } 241 241 242 static int unit_cfg_stop(unit_t *unit) 243 { 244 unit_cfg_t *u_cfg = CAST_CFG(unit); 245 assert(u_cfg); 246 247 /* 248 * It makes no sense to stop configuration (i.e. unload it), however, 249 * lets virtually stop it not to make obstructions for potential 250 * restart = reload of configuration. 251 */ 252 unit->state = STATE_STOPPED; 253 return EOK; 254 } 255 242 256 static void unit_cfg_exposee_created(unit_t *unit) 243 257 { -
uspace/srv/sysman/units/unit_mnt.c
r68ae40a red5367b 229 229 } 230 230 231 static int unit_mnt_stop(unit_t *unit) 232 { 233 unit_mnt_t *u_mnt = CAST_MNT(unit); 234 assert(u_mnt); 235 /* autostart implies blocking */ 236 assert(!u_mnt->autostart || u_mnt->blocking); 237 238 239 // TODO think about unit's lifecycle (is STOPPED only acceptable?) 240 // note: we should never hit STATE_STARTING, since it'd mean there are 241 // two jobs running at once (unless job cancellation is implemented) 242 assert(unit->state == STATE_STARTED); 243 244 /* 245 * We don't expect unmount to be blocking, since if some files are 246 * being used, it'd return EBUSY immediately. That's why we call 247 * unmount synchronously in the event loop fibril. 248 */ 249 int rc = unmount(u_mnt->mountpoint); 250 251 if (rc == EOK) { 252 unit->state = STATE_STOPPED; 253 return EOK; 254 } else if (rc == EBUSY) { 255 assert(unit->state == STATE_STARTED); 256 return EBUSY; 257 } else { 258 /* 259 * Mount may be still usable, but be conservative and mark unit 260 * as failed. 261 */ 262 unit->state = STATE_FAILED; 263 return rc; 264 } 265 } 266 231 267 static void unit_mnt_exposee_created(unit_t *unit) 232 268 { -
uspace/srv/sysman/units/unit_svc.c
r68ae40a red5367b 112 112 } 113 113 114 static int unit_svc_stop(unit_t *unit) 115 { 116 unit_svc_t *u_svc = CAST_SVC(unit); 117 assert(u_svc); 118 119 120 // TODO think about unit's lifecycle (is STOPPED only acceptable?) 121 // note: May change when job cancellation is possible. 122 assert(unit->state == STATE_STARTED); 123 124 int rc = task_kill(u_svc->main_task_id); 125 126 if (rc != EOK) { 127 /* Task may still be running, but be conservative about unit's 128 * state. */ 129 unit->state = STATE_FAILED; 130 return rc; 131 } 132 133 unit->state = STATE_STOPPING; 134 135 return EOK; 136 } 137 138 114 139 static void unit_svc_exposee_created(unit_t *unit) 115 140 { -
uspace/srv/sysman/units/unit_tgt.c
r68ae40a red5367b 63 63 } 64 64 65 static int unit_tgt_stop(unit_t *unit) 66 { 67 unit_tgt_t *u_tgt = CAST_TGT(unit); 68 assert(u_tgt); 69 70 unit->state = STATE_STOPPED; 71 return EOK; 72 } 73 65 74 static void unit_tgt_exposee_created(unit_t *unit) 66 75 {
Note:
See TracChangeset
for help on using the changeset viewer.