Changeset 5559712 in mainline
- Timestamp:
- 2019-08-03T09:28:50Z (5 years ago)
- Children:
- c0e4fc50
- Parents:
- 2dda1d4
- git-author:
- Michal Koutný <xm.koutny+hos@…> (2015-05-07 11:49:47)
- git-committer:
- Matthieu Riolo <matthieu.riolo@…> (2019-08-03 09:28:50)
- Location:
- uspace
- Files:
-
- 15 added
- 23 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/c/include/ipc/common.h
r2dda1d4 r5559712 39 39 #include <abi/ipc/ipc.h> 40 40 41 #define IPC_FLAG_BLOCKING 0x01 41 #define IPC_FLAG_BLOCKING 0x01 42 // TODO autostart flag may be united with blocking, this should be later made 43 // implicit, documented or refactor pairs of xxx and xxx_blocking methods 44 #define IPC_FLAG_AUTOSTART 0x02 42 45 43 46 typedef ipc_data_t ipc_call_t; -
uspace/lib/c/include/ipc/services.h
r2dda1d4 r5559712 40 40 #include <abi/fourcc.h> 41 41 42 /** Name of service brokered by NS */ 42 43 typedef enum { 43 44 SERVICE_NONE = 0, … … 45 46 SERVICE_VFS = FOURCC('v', 'f', 's', ' '), 46 47 SERVICE_LOC = FOURCC('l', 'o', 'c', ' '), 48 SERVICE_SYSMAN = FOURCC('s', 'y', 's', 'm'), 47 49 SERVICE_LOGGER = FOURCC('l', 'o', 'g', 'g'), 48 50 SERVICE_DEVMAN = FOURCC('d', 'e', 'v', 'n'), … … 64 66 #define SERVICE_NAME_VOLSRV "volsrv" 65 67 68 #define LOC_DEVICE_NAMESPACE "devices" 69 #define LOC_UNIT_NAMESPACE_SEPARATOR "__" 70 66 71 #endif 67 72 -
uspace/srv/devman/devman.h
r2dda1d4 r5559712 48 48 #define NAME "devman" 49 49 50 #define LOC_DEVICE_NAMESPACE "devices"51 50 #define LOC_SEPARATOR '\\' 52 51 -
uspace/srv/devman/loc.c
r2dda1d4 r5559712 31 31 */ 32 32 33 #include <ipc/services.h> 33 34 #include <loc.h> 34 35 #include <stdio.h> -
uspace/srv/locsrv/Makefile
r2dda1d4 r5559712 29 29 30 30 USPACE_PREFIX = ../.. 31 LIBS = $(LIBSYSMAN_PREFIX)/libsysman.a 32 EXTRA_CFLAGS += -I$(LIBSYSMAN_PREFIX)/include 31 33 BINARY = locsrv 32 34 STATIC_NEEDED = y -
uspace/srv/locsrv/locsrv.c
r2dda1d4 r5559712 36 36 */ 37 37 38 #include <assert.h> 39 #include <async.h> 40 #include <errno.h> 41 #include <ipc/loc.h> 38 42 #include <ipc/services.h> 39 #include <ns.h>40 #include <async.h>41 #include <stdio.h>42 #include <errno.h>43 #include <stdbool.h>44 43 #include <fibril_synch.h> 45 44 #include <macros.h> 45 #include <ns.h> 46 #include <stdbool.h> 47 #include <stdio.h> 46 48 #include <stdlib.h> 47 49 #include <str.h> 48 50 #include <str_error.h> 49 #include < ipc/loc.h>50 #include < assert.h>51 #include <sysman/broker.h> 52 #include <sysman/ctl.h> 51 53 52 54 #include "category.h" … … 331 333 free(service->name); 332 334 free(service); 335 } 336 337 static int loc_service_request_start(const char *ns_name, const char *name) 338 { 339 char *service_name = NULL; 340 341 if (str_cmp(ns_name, LOC_DEVICE_NAMESPACE) == 0) { 342 asprintf(&service_name, "%s", SERVICE_NAME_DEVMAN); 343 } else if (str_cmp(ns_name, "") == 0) { 344 asprintf(&service_name, "%s", name); 345 } else { 346 asprintf(&service_name, "%s%s%s", 347 ns_name, LOC_UNIT_NAMESPACE_SEPARATOR, name); 348 } 349 if (service_name == NULL) { 350 return ENOMEM; 351 } 352 353 char *unit_name; 354 asprintf(&unit_name, "%s%c%s", 355 service_name, UNIT_NAME_SEPARATOR, UNIT_SVC_TYPE_NAME); 356 if (unit_name == NULL) { 357 free(service_name); 358 return ENOMEM; 359 } 360 361 printf("%s(%s) before\n", __func__, unit_name); 362 int rc = sysman_unit_start(unit_name, IPC_FLAG_BLOCKING); 363 printf("%s(%s) after %i\n", __func__, unit_name, rc); 364 free(unit_name); 365 free(service_name); 366 return rc; 333 367 } 334 368 … … 531 565 532 566 list_append(&service->server_services, &service->server->services); 567 568 printf("%s: broadcast new service '%s/%s'\n", NAME, namespace->name, 569 service->name); 533 570 534 571 fibril_mutex_unlock(&service->server->services_mutex); … … 542 579 * 543 580 */ 544 static void loc_service_unregister(ipc_call_t *icall, loc_server_t *server) 581 static void loc_service_unregister(ipc_callid_t iid, ipc_call_t *icall, 582 loc_server_t *server) 545 583 { 546 584 loc_service_t *svc; … … 762 800 fibril_mutex_lock(&services_list_mutex); 763 801 const loc_service_t *svc; 764 802 int flags = ipc_get_arg1(*icall); 803 765 804 recheck: 766 805 … … 771 810 772 811 /* 773 * Device was not found.812 * Service was not found. 774 813 */ 775 814 if (svc == NULL) { 776 if (ipc_get_arg1(icall) & IPC_FLAG_BLOCKING) { 777 /* Blocking lookup */ 815 printf("%s: service '%s/%s' not found\n", NAME, ns_name, name); 816 if (flags & (IPC_FLAG_AUTOSTART | IPC_FLAG_BLOCKING)) { 817 /* TODO: 818 * consider non-blocking service start, return 819 * some dummy id and block only after connection 820 * request (actually makes more sense as those who asks 821 * for ID might be someone else than those connecting) 822 */ 823 if (flags & IPC_FLAG_AUTOSTART) { 824 rc = loc_service_request_start(ns_name, name); 825 if (rc != EOK) { 826 goto finish; 827 } 828 } 829 778 830 fibril_condvar_wait(&services_list_cv, 779 831 &services_list_mutex); 780 832 goto recheck; 781 833 } 782 783 async_answer_0(icall, ENOENT); 784 free(ns_name); 785 free(name); 786 fibril_mutex_unlock(&services_list_mutex); 787 return; 788 } 789 790 async_answer_1(icall, EOK, svc->id); 791 834 rc = ENOENT; 835 } else { 836 printf("%s: service '%s/%s' FOUND\n", NAME, ns_name, name); 837 rc = EOK; 838 } 839 840 finish: 841 if (rc == EOK) { 842 async_answer_1(iid, EOK, svc->id); 843 } else { 844 async_answer_0(iid, rc); 845 } 846 792 847 fibril_mutex_unlock(&services_list_mutex); 793 848 free(ns_name); … … 1565 1620 if (rc != EOK) { 1566 1621 printf("%s: Error while registering broker service: %s\n", NAME, str_error(rc)); 1622 1623 /* Let sysman know we are broker */ 1624 printf("%s: sysman_broker_register : pre\n", NAME); 1625 rc = sysman_broker_register(); 1626 printf("%s: sysman_broker_register : post\n", NAME); 1627 if (rc != EOK) { 1628 printf("%s: Error registering at sysman (%i)\n", NAME, rc); 1567 1629 return rc; 1568 1630 } -
uspace/srv/sysman/Makefile
r2dda1d4 r5559712 30 30 USPACE_PREFIX = ../.. 31 31 LIBS = $(LIBCONF_PREFIX)/libconf.a 32 EXTRA_CFLAGS += -I. -I./units -I$(LIBCONF_PREFIX)/include 32 EXTRA_CFLAGS += -I. \ 33 -I./units \ 34 -I$(LIBCONF_PREFIX)/include \ 35 -I$(LIBSYSMAN_PREFIX)/include 33 36 BINARY = sysman 34 37 STATIC_NEEDED = y … … 36 39 SOURCES = \ 37 40 configuration.c \ 41 connection_broker.c \ 42 connection_ctl.c \ 38 43 dep.c \ 39 44 job.c \ … … 44 49 units/unit_mnt.c \ 45 50 units/unit_tgt.c \ 51 units/unit_svc.c \ 46 52 util.c 47 53 -
uspace/srv/sysman/configuration.c
r2dda1d4 r5559712 148 148 } 149 149 150 /** Remove all uncommited units and edges from configuratio 151 * 152 * Memory used by removed object is released. 153 */ 150 154 void configuration_rollback(void) 151 155 { … … 186 190 * 187 191 * @return EOK on success 188 * @return ENO NENT when one or more resolution fails, information is logged192 * @return ENOENT when one or more resolution fails, information is logged 189 193 */ 190 194 int configuration_resolve_dependecies(void) -
uspace/srv/sysman/dep.c
r2dda1d4 r5559712 36 36 static void dep_dependency_init(unit_dependency_t *dep) 37 37 { 38 memset(dep, 0, sizeof(*dep)); 38 39 link_initialize(&dep->dependants); 39 40 link_initialize(&dep->dependencies); 40 41 41 dep->dependency_name = NULL;42 42 dep->state = DEP_EMBRYO; 43 43 } -
uspace/srv/sysman/job.c
r2dda1d4 r5559712 73 73 assert(job); 74 74 assert(u); 75 memset(job, 0, sizeof(*job)); 75 76 76 77 link_initialize(&job->job_queue); … … 101 102 return false; 102 103 } 103 }104 105 static bool job_is_runnable(job_t *job)106 {107 return job->state == JOB_QUEUED && job->blocking_jobs == 0;108 104 } 109 105 … … 126 122 } 127 123 128 129 130 131 124 static void job_destroy(job_t **job_ptr) 132 125 { … … 145 138 free(job); 146 139 *job_ptr = NULL; 140 } 141 142 static bool job_is_runnable(job_t *job) 143 { 144 return job->state == JOB_QUEUED && job->blocking_jobs == 0; 145 } 146 147 /** Pop next runnable job 148 * 149 * @return runnable job or NULL when there's none 150 */ 151 static job_t *job_queue_pop_runnable(void) 152 { 153 job_t *result = NULL; 154 155 /* Select first runnable job */ 156 list_foreach(job_queue, job_queue, job_t, candidate) { 157 if (job_is_runnable(candidate)) { 158 result = candidate; 159 break; 160 } 161 } 162 if (result) { 163 /* Remove job from queue and pass reference to caller */ 164 list_remove(&result->job_queue); 165 result->state = JOB_DEQUEUED; 166 } 167 168 return result; 147 169 } 148 170 … … 163 185 /* 164 186 * Currently we have strict strategy not permitting 165 * multiple jobs for one unit in the queue .187 * multiple jobs for one unit in the queue at a time. 166 188 */ 167 189 if ((*new_job_it)->unit == queued_job->unit) { 168 190 sysman_log(LVL_ERROR, 169 "Cannot queue multiple jobs fo or unit '%s'",191 "Cannot queue multiple jobs for unit '%s'", 170 192 unit_name((*new_job_it)->unit)); 171 193 return EEXIST; … … 184 206 } 185 207 186 /** Pop next runnable job 187 * 188 * @return runnable job or NULL when there's none 189 */ 190 job_t *job_queue_pop_runnable(void) 191 { 192 job_t *result = NULL; 193 link_t *first_link = list_first(&job_queue); 194 bool first_iteration = true; 195 196 list_foreach_safe(job_queue, cur_link, next_link) { 197 result = list_get_instance(cur_link, job_t, job_queue); 198 if (job_is_runnable(result)) { 199 break; 200 } else if (!first_iteration && cur_link == first_link) { 201 result = NULL; 202 break; 203 } else { 204 /* 205 * We make no assuptions about ordering of jobs in the 206 * queue, so just move the job to the end of the queue. 207 * If there are exist topologic ordering, eventually 208 * jobs will be reordered. Furthermore when if there 209 * exists any runnable job, it's always found. 210 */ 211 list_remove(cur_link); 212 list_append(cur_link, &job_queue); 213 } 214 first_iteration = false; 215 } 216 217 if (result) { 218 /* Remove job from queue and pass refernce to caller */ 219 list_remove(&result->job_queue); 220 result->state = JOB_DEQUEUED; 221 } 222 223 return result; 208 /** Process all jobs that aren't transitively blocked 209 * 210 * Job can be blocked either by another job or by an incoming event, that will 211 * be queued after this job_queue_process call. 212 * 213 * TODO Write down rules from where this function can be called, to avoid stack 214 * overflow. 215 */ 216 void job_queue_process(void) 217 { 218 job_t *job; 219 while ((job = job_queue_pop_runnable())) { 220 job_run(job); 221 job_del_ref(&job); 222 } 224 223 } 225 224 … … 242 241 */ 243 242 fifo_push(jobs_fifo, main_job); 244 job_t *job;245 243 job_add_ref(main_job); 246 while ((job = fifo_pop(jobs_fifo)) != NULL) { 247 /* No refcount increase, pass it to the closure */ 248 dyn_array_append(job_closure, job_ptr_t, job); 244 while (jobs_fifo.head != jobs_fifo.tail) { 245 job_t *job = fifo_pop(jobs_fifo); 246 247 // TODO more sophisticated check? (unit that is in transitional 248 // state cannot have currently multiple jobs queued) 249 if (job->target_state == job->unit->state) { 250 /* 251 * Job would do nothing, finish it on spot. 252 * No need to continue BFS search from it. 253 */ 254 job->retval = JOB_OK; 255 job_finish(job); 256 job_del_ref(&job); 257 continue; 258 } else { 259 /* No refcount increase, pass it to the closure */ 260 dyn_array_append(job_closure, job_ptr_t, job); 261 } 249 262 250 263 /* Traverse dependencies edges */ … … 379 392 /* Add reference for the event */ 380 393 job_add_ref(job); 381 sysman_raise_event(&sysman_event_job_ changed, job);382 } 383 394 sysman_raise_event(&sysman_event_job_finished, job); 395 } 396 -
uspace/srv/sysman/job.h
r2dda1d4 r5559712 37 37 #include "unit.h" 38 38 39 // TODO simplify queue states 39 40 /** Run state of job */ 40 41 typedef enum { … … 77 78 extern void job_queue_init(void); 78 79 extern int job_queue_add_jobs(dyn_array_t *); 79 extern job_t *job_queue_pop_runnable(void);80 extern void job_queue_process(void); 80 81 81 82 extern int job_create_closure(job_t *, dyn_array_t *); -
uspace/srv/sysman/log.h
r2dda1d4 r5559712 37 37 * that would use logger as soon as it's ready. 38 38 */ 39 #define sysman_log(level, fmt, ...) printf("sysman: " fmt "\n", __VA_ARGS__)39 #define sysman_log(level, fmt, ...) printf("sysman: " fmt "\n", ##__VA_ARGS__) 40 40 41 41 #endif -
uspace/srv/sysman/main.c
r2dda1d4 r5559712 30 30 #include <errno.h> 31 31 #include <fibril.h> 32 #include <ipc/sysman.h> 33 #include <macros.h> 34 #include <ns.h> 32 35 #include <stddef.h> 33 36 #include <stdio.h> … … 35 38 36 39 #include "configuration.h" 40 #include "connection_broker.h" 41 #include "connection_ctl.h" 37 42 #include "dep.h" 38 43 #include "job.h" … … 43 48 #define NAME "sysman" 44 49 45 static void sysman_connection(ipc_callid_t callid, ipc_call_t *call, void *arg) 46 { 47 /* TODO handle client connections */ 50 #define INITRD_DEVICE "bd/initrd" 51 #define INITRD_MOUNT_POINT "/" 52 #define INITRD_CFG_PATH "/cfg/sysman" 53 54 #define TARGET_INIT "initrd.tgt" 55 #define TARGET_ROOTFS "rootfs.tgt" 56 #define TARGET_DEFAULT "default.tgt" 57 58 #define UNIT_MNT_INITRD "initrd.mnt" 59 #define UNIT_CFG_INITRD "init.cfg" 60 61 static const char *target_sequence[] = { 62 TARGET_INIT, 63 TARGET_ROOTFS, 64 TARGET_DEFAULT, 65 NULL 66 }; 67 68 /* 69 * Forward declarations 70 */ 71 static void prepare_and_run_job(const char **target_name_ptr); 72 73 /* 74 * Static functions 75 */ 76 77 static void sysman_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg) 78 { 79 sysman_interface_t iface = IPC_GET_ARG1(*icall); 80 switch (iface) { 81 case SYSMAN_PORT_BROKER: 82 sysman_connection_broker(iid, icall); 83 break; 84 case SYSMAN_PORT_CTL: 85 sysman_connection_ctl(iid, icall); 86 break; 87 default: 88 /* Unknown interface */ 89 async_answer_0(iid, ENOENT); 90 } 48 91 } 49 92 50 93 /** Build hard coded configuration */ 51 static job_t *create_entry_configuration(void) {52 int r esult = EOK;94 static int create_entry_configuration(void) { 95 int rc; 53 96 unit_t *mnt_initrd = NULL; 54 97 unit_t *cfg_init = NULL; 55 unit_t *tgt_ default = NULL;98 unit_t *tgt_init = NULL; 56 99 57 100 mnt_initrd = unit_create(UNIT_MOUNT); 58 101 if (mnt_initrd == NULL) { 59 r esult= ENOMEM;102 rc = ENOMEM; 60 103 goto fail; 61 104 } 62 mnt_initrd->name = str_dup("initrd.mnt"); 63 // TODO Use RDFMT 64 CAST_MNT(mnt_initrd)->type = str_dup("ext4fs"); 65 CAST_MNT(mnt_initrd)->mountpoint = str_dup("/"); 66 CAST_MNT(mnt_initrd)->device = str_dup("bd/initrd"); 105 mnt_initrd->name = str_dup(UNIT_MNT_INITRD); 106 CAST_MNT(mnt_initrd)->type = str_dup(STRING(RDFMT)); 107 CAST_MNT(mnt_initrd)->mountpoint = str_dup(INITRD_MOUNT_POINT); 108 CAST_MNT(mnt_initrd)->device = str_dup(INITRD_DEVICE); 109 CAST_MNT(mnt_initrd)->autostart = false; 110 CAST_MNT(mnt_initrd)->blocking = true; 67 111 68 112 cfg_init = unit_create(UNIT_CONFIGURATION); 69 113 if (cfg_init == NULL) { 70 r esult= ENOMEM;114 rc = ENOMEM; 71 115 goto fail; 72 116 } 73 cfg_init->name = str_dup( "init.cfg");74 CAST_CFG(cfg_init)->path = str_dup( "/cfg/sysman");117 cfg_init->name = str_dup(UNIT_CFG_INITRD); 118 CAST_CFG(cfg_init)->path = str_dup(INITRD_CFG_PATH); 75 119 76 tgt_ default = unit_create(UNIT_TARGET);77 if (tgt_ default == NULL) {78 r esult= ENOMEM;120 tgt_init = unit_create(UNIT_TARGET); 121 if (tgt_init == NULL) { 122 rc = ENOMEM; 79 123 goto fail; 80 124 } 81 tgt_ default->name = str_dup("default.tgt");125 tgt_init->name = str_dup(TARGET_INIT); 82 126 83 127 … … 89 133 configuration_add_unit(mnt_initrd); 90 134 configuration_add_unit(cfg_init); 91 configuration_add_unit(tgt_ default);92 93 r esult = dep_add_dependency(tgt_default, cfg_init);94 if (r esult!= EOK) {95 goto fail;96 } 97 98 r esult= dep_add_dependency(cfg_init, mnt_initrd);99 if (r esult!= EOK) {100 goto fail;135 configuration_add_unit(tgt_init); 136 137 rc = dep_add_dependency(tgt_init, cfg_init); 138 if (rc != EOK) { 139 goto rollback; 140 } 141 142 rc = dep_add_dependency(cfg_init, mnt_initrd); 143 if (rc != EOK) { 144 goto rollback; 101 145 } 102 146 103 147 configuration_commit(); 104 148 105 job_t *first_job = job_create(tgt_default, STATE_STARTED); 106 if (first_job == NULL) { 107 goto fail; 108 } 109 return first_job; 149 return EOK; 110 150 111 151 fail: 112 // TODO cannot destroy units after they're added to configuration 113 unit_destroy(&tgt_default); 152 unit_destroy(&tgt_init); 114 153 unit_destroy(&cfg_init); 115 154 unit_destroy(&mnt_initrd); 116 return NULL; 117 } 118 119 static void first_job_handler(void *object, void *unused) 155 return rc; 156 157 rollback: 158 configuration_rollback(); 159 return rc; 160 } 161 162 static void sequence_job_handler(void *object, void *arg) 120 163 { 121 164 job_t *job = object; 122 sysman_log(LVL_DEBUG, "First job retval: %i.", job->retval); 165 if (job->retval == JOB_FAILED) { 166 sysman_log(LVL_ERROR, "Failed to start '%s'.", unit_name(job->unit)); 167 job_del_ref(&job); 168 return; 169 } 123 170 job_del_ref(&job); 171 172 const char **target_name_ptr = arg; 173 prepare_and_run_job(target_name_ptr + 1); 174 } 175 176 static void prepare_and_run_job(const char **target_name_ptr) 177 { 178 const char *target_name = *target_name_ptr; 179 180 if (target_name == NULL) { 181 sysman_log(LVL_NOTE, "All initial units started."); 182 return; 183 } 184 185 /* Previous targets should have loaded new units */ 186 unit_t *tgt = configuration_find_unit_by_name(target_name); 187 if (tgt == NULL) { 188 sysman_log(LVL_ERROR, 189 "Expected unit '%s' not found in configuration.", 190 target_name); 191 return; 192 } 193 194 int rc = sysman_queue_job(tgt, STATE_STARTED, &sequence_job_handler, 195 target_name_ptr); 196 197 if (rc != EOK) { 198 sysman_log(LVL_FATAL, "Cannot create job for '%s'.", target_name); 199 } 124 200 } 125 201 … … 136 212 137 213 /* 138 * Create initial configuration while we are in a single fibril, keep 139 * the job and run it when event loop is running. 140 */ 141 job_t *first_job = create_entry_configuration(); 214 * Create initial configuration while we are in a single fibril 215 */ 216 int rc = create_entry_configuration(); 217 if (rc != EOK) { 218 sysman_log(LVL_FATAL, 219 "Could not create initial configuration (%i).", rc); 220 return rc; 221 } 142 222 143 223 /* … … 148 228 fibril_add_ready(event_loop_fibril); 149 229 150 /* Queue first job for processing */ 151 job_add_ref(first_job); 152 sysman_object_observer(first_job, &first_job_handler, NULL); 153 job_add_ref(first_job); 154 sysman_raise_event(&sysman_event_job_process, first_job); 155 156 /* 157 * Releasing our own reference (could be merged with previous add_ref, 158 * this is more explicit though. 159 */ 160 job_del_ref(&first_job); 230 /* Queue first job from sequence */ 231 prepare_and_run_job(&target_sequence[0]); 232 233 /* We're service too */ 234 rc = service_register(SERVICE_SYSMAN); 235 if (rc != EOK) { 236 sysman_log(LVL_FATAL, 237 "Cannot register at naming service (%i).", rc); 238 return rc; 239 } 161 240 162 241 /* Start sysman server */ -
uspace/srv/sysman/sysman.c
r2dda1d4 r5559712 35 35 #include "log.h" 36 36 #include "sysman.h" 37 #include "unit.h" 37 38 38 39 … … 150 151 151 152 /* Process event */ 152 sysman_log(LVL_DEBUG2, "process(%p, %p)", event->handler, event->data); 153 sysman_log(LVL_DEBUG2, "process_event(%p, %p)", 154 event->handler, event->data); 153 155 event->handler(event->data); 154 156 free(event); 155 157 } 158 } 159 160 /** Create and queue job for unit 161 * 162 * @param[in] callback callback must explicitly delete reference to job 163 */ 164 int sysman_queue_job(unit_t *unit, unit_state_t target_state, 165 callback_handler_t callback, void *callback_arg) 166 { 167 job_t *job = job_create(unit, target_state); 168 if (job == NULL) { 169 return ENOMEM; 170 } 171 172 job_add_ref(job); 173 sysman_object_observer(job, callback, callback_arg); 174 175 job_add_ref(job); 176 sysman_raise_event(&sysman_event_job_process, job); 177 178 job_del_ref(&job); 179 return EOK; 156 180 } 157 181 … … 226 250 227 251 // NOTE must run in main event loop fibril 228 void sysman_event_job_process(void * arg)229 { 230 job_t *job = arg;252 void sysman_event_job_process(void *data) 253 { 254 job_t *job = data; 231 255 dyn_array_t job_closure; 232 256 dyn_array_initialize(&job_closure, job_ptr_t, 0); … … 250 274 job_del_ref(&job); 251 275 252 // TODO explain why calling asynchronously 253 sysman_raise_event(&sysman_event_job_queue_run, NULL); 276 job_queue_process(); 254 277 return; 255 278 … … 265 288 } 266 289 267 268 void sysman_event_job_queue_run(void *unused) 269 { 270 job_t *job; 271 while ((job = job_queue_pop_runnable())) { 272 job_run(job); 273 job_del_ref(&job); 274 } 275 } 276 277 void sysman_event_job_changed(void *object) 278 { 279 notify_observers(object); 290 void sysman_event_job_finished(void *data) 291 { 292 notify_observers(data); 280 293 /* Unreference the event data */ 281 job_t *job = object;294 job_t *job = data; 282 295 job_del_ref(&job); 283 } 296 297 /* The finished job, might have been blocking */ 298 job_queue_process(); 299 } 300 301 void sysman_event_unit_exposee_created(void *data) 302 { 303 unit_t *unit = data; 304 unit_exposee_created(unit); 305 } 306 307 void sysman_event_unit_failed(void *data) 308 { 309 unit_t *unit = data; 310 unit_fail(unit); 311 } 312 313 void sysman_event_unit_state_changed(void *data) 314 { 315 notify_observers(data); 316 } -
uspace/srv/sysman/sysman.h
r2dda1d4 r5559712 37 37 38 38 extern void sysman_events_init(void); 39 extern int sysman_events_loop(void *); 40 extern int sysman_queue_job(unit_t *, unit_state_t, callback_handler_t, void *); 39 41 40 extern int sysman_events_loop(void *);41 42 42 43 extern void sysman_raise_event(event_handler_t, void *); 43 44 44 extern int sysman_object_observer(void *, callback_handler_t, void *); 45 45 46 46 47 47 extern void sysman_event_job_process(void *); 48 extern void sysman_event_job_queue_run(void *); 49 extern void sysman_event_job_changed(void *); 48 extern void sysman_event_job_finished(void *); 49 extern void sysman_event_unit_exposee_created(void *); 50 extern void sysman_event_unit_failed(void *); 51 extern void sysman_event_unit_state_changed(void *); 50 52 51 53 #endif -
uspace/srv/sysman/unit.c
r2dda1d4 r5559712 37 37 #include <stdlib.h> 38 38 #include <str.h> 39 #include <sysman/unit.h> 39 40 40 41 #include "dep.h" 41 42 #include "log.h" 43 #include "sysman.h" 42 44 #include "unit.h" 43 45 44 46 /** Virtual method table for each unit type */ 45 47 unit_vmt_t *unit_type_vmts[] = { 46 [UNIT_TARGET] = &unit_tgt_ops, 47 [UNIT_MOUNT] = &unit_mnt_ops, 48 [UNIT_CONFIGURATION] = &unit_cfg_ops 48 [UNIT_CONFIGURATION] = &unit_cfg_vmt, 49 [UNIT_MOUNT] = &unit_mnt_vmt, 50 [UNIT_TARGET] = &unit_tgt_vmt, 51 [UNIT_SERVICE] = &unit_svc_vmt 49 52 }; 50 53 … … 61 64 assert(unit); 62 65 63 // TODO is this necessary?64 memset(unit, 0, size of(unit_t));66 size_t size = unit_type_vmts[type]->size; 67 memset(unit, 0, size); 65 68 66 69 unit->type = type; 67 unit->name = NULL;68 69 70 unit->state = STATE_EMBRYO; 70 71 … … 103 104 } 104 105 105 106 /** Issue request to restarter to start a unit107 *108 * Ideally this function is non-blocking synchronous, however, some units109 * cannot be started synchronously and thus return from this function generally110 * means that start was requested.111 *112 * Check state of the unit for actual result, start method can end in states:113 * - STATE_STARTED, (succesful synchronous start)114 * - STATE_STARTING, (succesful asynchronous start request)115 * - STATE_FAILED. (error occured)116 */117 int unit_start(unit_t *unit)118 {119 sysman_log(LVL_DEBUG, "%s('%s')", __func__, unit_name(unit));120 return UNIT_VMT(unit)->start(unit);121 }122 123 106 int unit_load(unit_t *unit, ini_configuration_t *ini_conf, 124 107 text_parse_t *text_parse) … … 140 123 } 141 124 125 /** Issue request to restarter to start a unit 126 * 127 * Ideally this function is non-blocking synchronous, however, some units 128 * cannot be started synchronously and thus return from this function generally 129 * means that start was requested. 130 * 131 * Check state of the unit for actual result, start method can end in states: 132 * - STATE_STARTED, (succesful synchronous start) 133 * - STATE_STARTING, (succesful asynchronous start request) 134 * - STATE_FAILED. (unit state changed and error occured) 135 */ 136 int unit_start(unit_t *unit) 137 { 138 sysman_log(LVL_DEBUG, "%s('%s')", __func__, unit_name(unit)); 139 return UNIT_VMT(unit)->start(unit); 140 } 141 142 void unit_exposee_created(unit_t *unit) 143 { 144 sysman_log(LVL_DEBUG, "%s('%s')", __func__, unit_name(unit)); 145 return UNIT_VMT(unit)->exposee_created(unit); 146 } 147 148 void unit_fail(unit_t *unit) 149 { 150 sysman_log(LVL_DEBUG, "%s('%s')", __func__, unit_name(unit)); 151 return UNIT_VMT(unit)->fail(unit); 152 } 153 154 void unit_notify_state(unit_t *unit) 155 { 156 sysman_raise_event(&sysman_event_unit_state_changed, unit); 157 } 158 142 159 unit_type_t unit_type_name_to_type(const char *type_name) 143 160 { 144 if (str_cmp(type_name, "cfg") == 0)161 if (str_cmp(type_name, UNIT_CFG_TYPE_NAME) == 0) 145 162 return UNIT_CONFIGURATION; 146 163 147 else if (str_cmp(type_name, "mnt") == 0)164 else if (str_cmp(type_name, UNIT_MNT_TYPE_NAME) == 0) 148 165 return UNIT_MOUNT; 149 166 150 else if (str_cmp(type_name, "tgt") == 0)167 else if (str_cmp(type_name, UNIT_TGT_TYPE_NAME) == 0) 151 168 return UNIT_TARGET; 169 170 else if (str_cmp(type_name, UNIT_SVC_TYPE_NAME) == 0) 171 return UNIT_SERVICE; 152 172 153 173 else … … 160 180 return unit->name ? unit->name : ""; 161 181 } 162 163 164 165 182 166 183 bool unit_parse_unit_list(const char *value, void *dst, text_parse_t *parse, -
uspace/srv/sysman/unit.h
r2dda1d4 r5559712 45 45 UNIT_MOUNT, 46 46 UNIT_CONFIGURATION, 47 UNIT_SERVICE 47 48 } unit_type_t; 48 49 … … 73 74 #include "unit_mnt.h" 74 75 #include "unit_tgt.h" 76 #include "unit_svc.h" 75 77 76 #define DEFINE_CAST(NAME, TYPE, ENUM_TYPE) \77 static inline TYPE *CAST_##NAME(unit_t *u) \78 { \79 if (u->type == ENUM_TYPE) \80 return (TYPE *)u; \81 else \82 return NULL; \83 } \78 #define DEFINE_CAST(NAME, TYPE, ENUM_TYPE) \ 79 static inline TYPE *CAST_##NAME(unit_t *u) \ 80 { \ 81 if (u->type == ENUM_TYPE) \ 82 return (TYPE *)u; \ 83 else \ 84 return NULL; \ 85 } \ 84 86 85 87 DEFINE_CAST(CFG, unit_cfg_t, UNIT_CONFIGURATION) 86 88 DEFINE_CAST(MNT, unit_mnt_t, UNIT_MOUNT) 87 89 DEFINE_CAST(TGT, unit_tgt_t, UNIT_TARGET) 90 DEFINE_CAST(SVC, unit_svc_t, UNIT_SERVICE) 88 91 89 92 struct unit_vmt { … … 97 100 98 101 int (*start)(unit_t *); 102 103 void (*exposee_created)(unit_t *); 104 105 void (*fail)(unit_t *); 99 106 }; 100 107 101 108 extern unit_vmt_t *unit_type_vmts[]; 102 109 103 #define DEFINE_UNIT_VMT(PREFIX) \ 104 unit_vmt_t PREFIX##_ops = { \ 105 .size = sizeof(PREFIX##_t), \ 106 .init = &PREFIX##_init, \ 107 .load = &PREFIX##_load, \ 108 .destroy = &PREFIX##_destroy, \ 109 .start = &PREFIX##_start \ 110 #define DEFINE_UNIT_VMT(PREFIX) \ 111 unit_vmt_t PREFIX##_vmt = { \ 112 .size = sizeof(PREFIX##_t), \ 113 .init = &PREFIX##_init, \ 114 .load = &PREFIX##_load, \ 115 .destroy = &PREFIX##_destroy, \ 116 .start = &PREFIX##_start, \ 117 .exposee_created = &PREFIX##_exposee_created, \ 118 .fail = &PREFIX##_fail \ 110 119 }; 111 120 … … 115 124 extern void unit_destroy(unit_t **); 116 125 117 // TODO add flags argument with explicit notification?118 extern void unit_set_state(unit_t *, unit_state_t);119 120 126 extern int unit_load(unit_t *, ini_configuration_t *, text_parse_t *); 121 127 extern int unit_start(unit_t *); 128 extern void unit_exposee_created(unit_t *); 129 extern void unit_fail(unit_t *); 130 131 extern void unit_notify_state(unit_t *); 122 132 123 133 extern unit_type_t unit_type_name_to_type(const char *); -
uspace/srv/sysman/units/unit_cfg.c
r2dda1d4 r5559712 36 36 #include <stdlib.h> 37 37 #include <str.h> 38 #include <sysman/unit.h> 38 39 39 40 #include "configuration.h" … … 66 67 text_parse_init(&text_parse); 67 68 68 const char *last_ dot = str_rchr(filename, '.');69 if (last_ dot== NULL) {69 const char *last_sep = str_rchr(filename, UNIT_NAME_SEPARATOR); 70 if (last_sep == NULL) { 70 71 rc = EINVAL; 71 72 goto finish; … … 73 74 74 75 const char *unit_name = filename; 75 const char *unit_type_name = last_ dot+ 1;76 const char *unit_type_name = last_sep + 1; 76 77 77 78 unit_type_t unit_type = unit_type_name_to_type(unit_type_name); … … 195 196 unit_cfg_t *u_cfg = CAST_CFG(unit); 196 197 assert(u_cfg); 197 198 u_cfg->path = NULL; 199 } 200 201 198 } 202 199 203 200 static void unit_cfg_destroy(unit_t *unit) … … 243 240 } 244 241 242 static void unit_cfg_exposee_created(unit_t *unit) 243 { 244 /* Configuration has no exposees. */ 245 assert(false); 246 } 247 248 static void unit_cfg_fail(unit_t *unit) 249 { 250 /* Configuration cannot async fail. */ 251 assert(false); 252 } 253 245 254 DEFINE_UNIT_VMT(unit_cfg) 246 255 -
uspace/srv/sysman/units/unit_cfg.h
r2dda1d4 r5559712 38 38 } unit_cfg_t; 39 39 40 extern unit_vmt_t unit_cfg_ ops;40 extern unit_vmt_t unit_cfg_vmt; 41 41 42 42 #endif -
uspace/srv/sysman/units/unit_mnt.c
r2dda1d4 r5559712 32 32 #include <stdlib.h> 33 33 #include <vfs/vfs.h> 34 #include <str.h> 34 35 35 36 #include "log.h" 37 #include "sysman.h" 36 38 #include "unit.h" 37 39 … … 39 41 40 42 static config_item_t unit_configuration[] = { 41 {"What", &config_parse_string, offsetof(unit_mnt_t, device), NULL}, 42 {"Where", &config_parse_string, offsetof(unit_mnt_t, mountpoint), NULL}, 43 {"Type", &config_parse_string, offsetof(unit_mnt_t, type), NULL}, 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"}, 44 48 CONFIGURATION_ITEM_SENTINEL 45 49 }; 46 50 51 typedef 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 63 static 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 80 static 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 111 fail: 112 mount_data_destroy(&dst); 113 return false; 114 } 115 47 116 static void unit_mnt_init(unit_t *unit) 48 117 { 49 118 unit_mnt_t *u_mnt = CAST_MNT(unit); 50 119 assert(u_mnt); 51 52 u_mnt->type = NULL;53 u_mnt->mountpoint = NULL;54 u_mnt->device = NULL;55 120 } 56 121 … … 60 125 unit_mnt_t *u_mnt = CAST_MNT(unit); 61 126 62 sysman_log(LVL_DEBUG2, "%s, %p, %p, %p", __func__,63 u_mnt->type, u_mnt->mountpoint, u_mnt->device);64 127 free(u_mnt->type); 65 128 free(u_mnt->mountpoint); … … 85 148 } 86 149 150 static int 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 int rc = mount(mnt_data->type, mnt_data->mountpoint, mnt_data->device, 158 mnt_data->options ? mnt_data->options : "", 159 mnt_data->flags, mnt_data->instance); 160 161 if (rc == EOK) { 162 sysman_log(LVL_DEBUG, "Mount ('%s') mounted", 163 unit_name(mnt_data->unit)); 164 /* 165 * Emulate future VFS broker fibril that notifies about created 166 * exposee. 167 * Difference: It'll notify exposee name only, we'll have to 168 * match it... 169 */ 170 sysman_raise_event(&sysman_event_unit_exposee_created, 171 mnt_data->unit); 172 } else { 173 sysman_log(LVL_ERROR, "Mount ('%s') failed (%i)", 174 unit_name(mnt_data->unit), rc); 175 /* 176 * Think about analogy of this event, probably timeout or sthing 177 */ 178 sysman_raise_event(&sysman_event_unit_failed, 179 mnt_data->unit); 180 } 181 182 if (mnt_data->owner) { 183 mount_data_destroy(&mnt_data); 184 } 185 186 return EOK; 187 } 188 87 189 static int unit_mnt_start(unit_t *unit) 88 190 { 89 // TODO replace with non-blocking90 const bool blocking = true;91 191 unit_mnt_t *u_mnt = CAST_MNT(unit); 92 192 assert(u_mnt); 193 /* autostart implies blocking */ 194 assert(!u_mnt->autostart || u_mnt->blocking); 93 195 94 196 … … 96 198 assert(unit->state == STATE_STOPPED); 97 199 98 99 // TODO use other mount parameters 100 int rc = mount(u_mnt->type, u_mnt->mountpoint, u_mnt->device, "", 101 blocking ? IPC_FLAG_BLOCKING : 0, 0); 102 103 if (blocking) { 104 if (rc == EOK) { 105 sysman_log(LVL_DEBUG, "Mount ('%s') mounted", unit_name(unit)); 106 unit->state = STATE_STARTED; 107 } else { 108 sysman_log(LVL_ERROR, "Mount ('%s') failed (%i)", 109 unit_name(unit), rc); 110 unit->state = STATE_FAILED; 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_FLAG_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; 111 218 } 219 fid_t fib = fibril_create(&mount_exec, heap_mnt_data); 220 unit->state = STATE_STARTING; 221 fibril_add_ready(fib); 112 222 } else { 113 if (rc == EOK) { 114 sysman_log(LVL_DEBUG, "Mount ('%s') requested", unit_name(unit)); 115 unit->state = STATE_STARTING; 116 } else { 117 sysman_log(LVL_ERROR, "Mount ('%s') request failed (%i)", 118 unit_name(unit), rc); 119 unit->state = STATE_FAILED; 120 } 121 } 122 123 return rc; 124 } 223 unit->state = STATE_STARTING; 224 mount_exec(&mnt_data); 225 } 226 227 return EOK; 228 } 229 230 static void unit_mnt_exposee_created(unit_t *unit) 231 { 232 assert(CAST_MNT(unit)); 233 assert(unit->state == STATE_STOPPED || unit->state == STATE_STARTING); 234 235 unit->state = STATE_STARTED; 236 unit_notify_state(unit); 237 } 238 239 static void unit_mnt_fail(unit_t *unit) 240 { 241 assert(CAST_MNT(unit)); 242 assert(unit->state == STATE_STARTING); 243 244 unit->state = STATE_FAILED; 245 unit_notify_state(unit); 246 } 247 125 248 126 249 DEFINE_UNIT_VMT(unit_mnt) -
uspace/srv/sysman/units/unit_mnt.h
r2dda1d4 r5559712 38 38 char *mountpoint; 39 39 char *device; 40 41 /** Should be underlying units (FS server, device) be autostarted */ 42 bool autostart; 43 44 /** Should mount call be blocking */ 45 bool blocking; 40 46 } unit_mnt_t; 41 47 42 extern unit_vmt_t unit_mnt_ ops;48 extern unit_vmt_t unit_mnt_vmt; 43 49 44 50 #endif -
uspace/srv/sysman/units/unit_tgt.c
r2dda1d4 r5559712 63 63 } 64 64 65 static void unit_tgt_exposee_created(unit_t *unit) 66 { 67 /* Target has no exposees. */ 68 assert(false); 69 } 70 71 static void unit_tgt_fail(unit_t *unit) 72 { 73 // TODO define semantics and implement 74 } 75 76 65 77 DEFINE_UNIT_VMT(unit_tgt) 66 78 -
uspace/srv/sysman/units/unit_tgt.h
r2dda1d4 r5559712 36 36 } unit_tgt_t; 37 37 38 extern unit_vmt_t unit_tgt_ ops;38 extern unit_vmt_t unit_tgt_vmt; 39 39 40 40 #endif
Note:
See TracChangeset
for help on using the changeset viewer.