Remove building with NOCRYPTO option
[minix.git] / minix / servers / rs / request.c
blobabe371d5ddf0a7c81d8d199644cab4a9416de6d2
1 /*
2 * Changes:
3 * Jan 22, 2010: Created (Cristiano Giuffrida)
4 */
6 #include "inc.h"
8 #include "kernel/proc.h"
10 static int check_request(struct rs_start *rs_start);
12 /*===========================================================================*
13 * do_up *
14 *===========================================================================*/
15 int do_up(m_ptr)
16 message *m_ptr; /* request message pointer */
18 /* A request was made to start a new system service. */
19 struct rproc *rp;
20 struct rprocpub *rpub;
21 int i, r;
22 struct rs_start rs_start;
23 int noblock;
24 int init_flags = 0;
26 /* Check if the call can be allowed. */
27 if((r = check_call_permission(m_ptr->m_source, RS_UP, NULL)) != OK)
28 return r;
30 /* Allocate a new system service slot. */
31 r = alloc_slot(&rp);
32 if(r != OK) {
33 printf("RS: do_up: unable to allocate a new slot: %d\n", r);
34 return r;
36 rpub = rp->r_pub;
38 /* Copy the request structure. */
39 r = copy_rs_start(m_ptr->m_source, m_ptr->m_rs_req.addr, &rs_start);
40 if (r != OK) {
41 return r;
43 r = check_request(&rs_start);
44 if (r != OK) {
45 return r;
48 /* Check flags. */
49 noblock = (rs_start.rss_flags & RSS_NOBLOCK);
50 if(rs_start.rss_flags & RSS_FORCE_INIT_CRASH) {
51 init_flags |= SEF_INIT_CRASH;
53 if(rs_start.rss_flags & RSS_FORCE_INIT_FAIL) {
54 init_flags |= SEF_INIT_FAIL;
56 if(rs_start.rss_flags & RSS_FORCE_INIT_TIMEOUT) {
57 init_flags |= SEF_INIT_TIMEOUT;
59 if(rs_start.rss_flags & RSS_FORCE_INIT_DEFCB) {
60 init_flags |= SEF_INIT_DEFCB;
63 /* Initialize the slot as requested. */
64 r = init_slot(rp, &rs_start, m_ptr->m_source);
65 if(r != OK) {
66 printf("RS: do_up: unable to init the new slot: %d\n", r);
67 return r;
70 /* Check for duplicates */
71 if(lookup_slot_by_label(rpub->label)) {
72 printf("RS: service with the same label '%s' already exists\n",
73 rpub->label);
74 return EBUSY;
76 if(rpub->dev_nr>0 && lookup_slot_by_dev_nr(rpub->dev_nr)) {
77 printf("RS: service with the same device number %d already exists\n",
78 rpub->dev_nr);
79 return EBUSY;
81 for (i = 0; i < rpub->nr_domain; i++) {
82 if (lookup_slot_by_domain(rpub->domain[i]) != NULL) {
83 printf("RS: service with the same domain %d already exists\n",
84 rpub->domain[i]);
85 return EBUSY;
89 /* All information was gathered. Now try to start the system service. */
90 r = start_service(rp, init_flags);
91 if(r != OK) {
92 return r;
95 /* Unblock the caller immediately if requested. */
96 if(noblock) {
97 return OK;
100 /* Late reply - send a reply when service completes initialization. */
101 rp->r_flags |= RS_LATEREPLY;
102 rp->r_caller = m_ptr->m_source;
103 rp->r_caller_request = RS_UP;
105 return EDONTREPLY;
108 /*===========================================================================*
109 * do_down *
110 *===========================================================================*/
111 int do_down(message *m_ptr)
113 register struct rproc *rp;
114 int s;
115 char label[RS_MAX_LABEL_LEN];
117 /* Copy label. */
118 s = copy_label(m_ptr->m_source, m_ptr->m_rs_req.addr,
119 m_ptr->m_rs_req.len, label, sizeof(label));
120 if(s != OK) {
121 return s;
124 /* Lookup slot by label. */
125 rp = lookup_slot_by_label(label);
126 if(!rp) {
127 if(rs_verbose)
128 printf("RS: do_down: service '%s' not found\n", label);
129 return(ESRCH);
132 /* Check if the call can be allowed. */
133 if((s = check_call_permission(m_ptr->m_source, RS_DOWN, rp)) != OK)
134 return s;
136 /* Stop service. */
137 if (rp->r_flags & RS_TERMINATED) {
138 /* A recovery script is requesting us to bring down the service.
139 * The service is already gone, simply perform cleanup.
141 if(rs_verbose)
142 printf("RS: recovery script performs service down...\n");
143 unpublish_service(rp);
144 cleanup_service(rp);
145 return(OK);
147 stop_service(rp,RS_EXITING);
149 /* Late reply - send a reply when service dies. */
150 rp->r_flags |= RS_LATEREPLY;
151 rp->r_caller = m_ptr->m_source;
152 rp->r_caller_request = RS_DOWN;
154 return EDONTREPLY;
157 /*===========================================================================*
158 * do_restart *
159 *===========================================================================*/
160 int do_restart(message *m_ptr)
162 struct rproc *rp;
163 int s, r;
164 char label[RS_MAX_LABEL_LEN];
165 char script[MAX_SCRIPT_LEN];
167 /* Copy label. */
168 s = copy_label(m_ptr->m_source, m_ptr->m_rs_req.addr,
169 m_ptr->m_rs_req.len, label, sizeof(label));
170 if(s != OK) {
171 return s;
174 /* Lookup slot by label. */
175 rp = lookup_slot_by_label(label);
176 if(!rp) {
177 if(rs_verbose)
178 printf("RS: do_restart: service '%s' not found\n", label);
179 return(ESRCH);
182 /* Check if the call can be allowed. */
183 if((r = check_call_permission(m_ptr->m_source, RS_RESTART, rp)) != OK)
184 return r;
186 /* We can only be asked to restart a service from a recovery script. */
187 if (! (rp->r_flags & RS_TERMINATED) ) {
188 if(rs_verbose)
189 printf("RS: %s is still running\n", srv_to_string(rp));
190 return EBUSY;
193 if(rs_verbose)
194 printf("RS: recovery script performs service restart...\n");
196 /* Restart the service, but make sure we don't call the script again. */
197 strcpy(script, rp->r_script);
198 rp->r_script[0] = '\0';
199 restart_service(rp);
200 strcpy(rp->r_script, script);
202 return OK;
205 /*===========================================================================*
206 * do_clone *
207 *===========================================================================*/
208 int do_clone(message *m_ptr)
210 struct rproc *rp;
211 struct rprocpub *rpub;
212 int s, r;
213 char label[RS_MAX_LABEL_LEN];
215 /* Copy label. */
216 s = copy_label(m_ptr->m_source, m_ptr->m_rs_req.addr,
217 m_ptr->m_rs_req.len, label, sizeof(label));
218 if(s != OK) {
219 return s;
222 /* Lookup slot by label. */
223 rp = lookup_slot_by_label(label);
224 if(!rp) {
225 if(rs_verbose)
226 printf("RS: do_clone: service '%s' not found\n", label);
227 return(ESRCH);
229 rpub = rp->r_pub;
231 /* Check if the call can be allowed. */
232 if((r = check_call_permission(m_ptr->m_source, RS_CLONE, rp)) != OK)
233 return r;
235 /* Don't clone if a replica is already available. */
236 if(rp->r_next_rp) {
237 return EEXIST;
240 /* Clone the service as requested. */
241 rpub->sys_flags |= SF_USE_REPL;
242 if ((r = clone_service(rp, RST_SYS_PROC, 0)) != OK) {
243 rpub->sys_flags &= ~SF_USE_REPL;
244 return r;
247 return OK;
250 /*===========================================================================*
251 * do_unclone *
252 *===========================================================================*/
253 int do_unclone(message *m_ptr)
255 struct rproc *rp;
256 struct rprocpub *rpub;
257 int s, r;
258 char label[RS_MAX_LABEL_LEN];
260 /* Copy label. */
261 s = copy_label(m_ptr->m_source, m_ptr->m_rs_req.addr,
262 m_ptr->m_rs_req.len, label, sizeof(label));
263 if(s != OK) {
264 return s;
267 /* Lookup slot by label. */
268 rp = lookup_slot_by_label(label);
269 if(!rp) {
270 if(rs_verbose)
271 printf("RS: do_unclone: service '%s' not found\n", label);
272 return(ESRCH);
274 rpub = rp->r_pub;
276 /* Check if the call can be allowed. */
277 if((r = check_call_permission(m_ptr->m_source, RS_UNCLONE, rp)) != OK)
278 return r;
280 /* Don't unclone if no replica is available. */
281 if(!(rpub->sys_flags & SF_USE_REPL)) {
282 return ENOENT;
285 /* Unclone the service as requested. */
286 rpub->sys_flags &= ~SF_USE_REPL;
287 if(rp->r_next_rp) {
288 cleanup_service_now(rp->r_next_rp);
289 rp->r_next_rp = NULL;
292 return OK;
295 /*===========================================================================*
296 * do_edit *
297 *===========================================================================*/
298 int do_edit(message *m_ptr)
300 struct rproc *rp;
301 struct rprocpub *rpub;
302 struct rs_start rs_start;
303 int r;
304 char label[RS_MAX_LABEL_LEN];
306 /* Copy the request structure. */
307 r = copy_rs_start(m_ptr->m_source, m_ptr->m_rs_req.addr, &rs_start);
308 if (r != OK) {
309 return r;
312 /* Copy label. */
313 r = copy_label(m_ptr->m_source, rs_start.rss_label.l_addr,
314 rs_start.rss_label.l_len, label, sizeof(label));
315 if(r != OK) {
316 return r;
319 /* Lookup slot by label. */
320 rp = lookup_slot_by_label(label);
321 if(!rp) {
322 if(rs_verbose)
323 printf("RS: do_edit: service '%s' not found\n", label);
324 return ESRCH;
326 rpub = rp->r_pub;
328 /* Check if the call can be allowed. */
329 if((r = check_call_permission(m_ptr->m_source, RS_EDIT, rp)) != OK)
330 return r;
332 if(rs_verbose)
333 printf("RS: %s edits settings\n", srv_to_string(rp));
335 /* Synch the privilege structure with the kernel. */
336 if ((r = sys_getpriv(&rp->r_priv, rpub->endpoint)) != OK) {
337 printf("RS: do_edit: unable to synch privilege structure: %d\n", r);
338 return r;
341 /* Tell scheduler this process is finished */
342 if ((r = sched_stop(rp->r_scheduler, rpub->endpoint)) != OK) {
343 printf("RS: do_edit: scheduler won't give up process: %d\n", r);
344 return r;
347 /* Edit the slot as requested. */
348 if((r = edit_slot(rp, &rs_start, m_ptr->m_source)) != OK) {
349 printf("RS: do_edit: unable to edit the existing slot: %d\n", r);
350 return r;
353 /* Update privilege structure. */
354 r = sys_privctl(rpub->endpoint, SYS_PRIV_UPDATE_SYS, &rp->r_priv);
355 if(r != OK) {
356 printf("RS: do_edit: unable to update privilege structure: %d\n", r);
357 return r;
360 /* Update VM calls. */
361 if ((r = vm_set_priv(rpub->endpoint, &rpub->vm_call_mask[0],
362 !!(rp->r_priv.s_flags & SYS_PROC))) != OK) {
363 printf("RS: do_edit: failed: %d\n", r);
364 return r;
367 /* Reinitialize scheduling. */
368 if ((r = sched_init_proc(rp)) != OK) {
369 printf("RS: do_edit: unable to reinitialize scheduling: %d\n", r);
370 return r;
373 /* Cleanup old replicas and create a new one, if necessary. */
374 if(rpub->sys_flags & SF_USE_REPL) {
375 if(rp->r_next_rp) {
376 cleanup_service(rp->r_next_rp);
377 rp->r_next_rp = NULL;
379 if ((r = clone_service(rp, RST_SYS_PROC, 0)) != OK) {
380 printf("RS: warning: unable to clone %s\n", srv_to_string(rp));
384 return OK;
387 /*===========================================================================*
388 * do_refresh *
389 *===========================================================================*/
390 int do_refresh(message *m_ptr)
392 register struct rproc *rp;
393 int s;
394 char label[RS_MAX_LABEL_LEN];
396 /* Copy label. */
397 s = copy_label(m_ptr->m_source, m_ptr->m_rs_req.addr,
398 m_ptr->m_rs_req.len, label, sizeof(label));
399 if(s != OK) {
400 return s;
403 /* Lookup slot by label. */
404 rp = lookup_slot_by_label(label);
405 if(!rp) {
406 if(rs_verbose)
407 printf("RS: do_refresh: service '%s' not found\n", label);
408 return(ESRCH);
411 /* Check if the call can be allowed. */
412 if((s = check_call_permission(m_ptr->m_source, RS_REFRESH, rp)) != OK)
413 return s;
415 /* Refresh service. */
416 if(rs_verbose)
417 printf("RS: %s refreshing\n", srv_to_string(rp));
418 stop_service(rp,RS_REFRESHING);
420 /* Late reply - send a reply when refresh completes. */
421 rp->r_flags |= RS_LATEREPLY;
422 rp->r_caller = m_ptr->m_source;
423 rp->r_caller_request = RS_REFRESH;
425 return EDONTREPLY;
428 /*===========================================================================*
429 * do_shutdown *
430 *===========================================================================*/
431 int do_shutdown(message *m_ptr)
433 int slot_nr;
434 struct rproc *rp;
435 int r;
437 /* Check if the call can be allowed. */
438 if (m_ptr != NULL) {
439 if((r = check_call_permission(m_ptr->m_source, RS_SHUTDOWN, NULL)) != OK)
440 return r;
443 if(rs_verbose)
444 printf("RS: shutting down...\n");
446 /* Set flag to tell RS we are shutting down. */
447 shutting_down = TRUE;
449 /* Don't restart dead services. */
450 for (slot_nr = 0; slot_nr < NR_SYS_PROCS; slot_nr++) {
451 rp = &rproc[slot_nr];
452 if (rp->r_flags & RS_IN_USE) {
453 rp->r_flags |= RS_EXITING;
456 return(OK);
459 /*===========================================================================*
460 * do_init_ready *
461 *===========================================================================*/
462 int do_init_ready(message *m_ptr)
464 int who_p;
465 message m;
466 struct rproc *rp, *new_rp;
467 struct rprocpub *rpub;
468 int result;
469 int r;
471 who_p = _ENDPOINT_P(m_ptr->m_source);
472 result = m_ptr->m_rs_init.result;
474 rp = rproc_ptr[who_p];
475 rpub = rp->r_pub;
477 /* Make sure the originating service was requested to initialize. */
478 if(! (rp->r_flags & RS_INITIALIZING) ) {
479 if(rs_verbose)
480 printf("RS: do_init_ready: got unexpected init ready msg from %d\n",
481 m_ptr->m_source);
482 return EINVAL;
485 /* Check if something went wrong and the service failed to init.
486 * In that case, kill the service.
488 if(result != OK) {
489 if(rs_verbose)
490 printf("RS: %s initialization error: %s\n", srv_to_string(rp),
491 init_strerror(result));
492 if (result == ERESTART && !SRV_IS_UPDATING(rp))
493 rp->r_flags |= RS_REINCARNATE;
494 crash_service(rp); /* simulate crash */
495 rp->r_init_err = result;
496 return EDONTREPLY;
499 if(rs_verbose)
500 printf("RS: %s initialized\n", srv_to_string(rp));
502 /* If updating, check if there is no service to update left. In that case,
503 * end the update process. If VM has completed initialization as part of
504 * multi-component live update, let the other services under update run now.
506 if(SRV_IS_UPDATING(rp)) {
507 rupdate.num_init_ready_pending--;
508 rp->r_flags |= RS_INIT_DONE;
509 if(rupdate.num_init_ready_pending == 0) {
510 printf("RS: update succeeded\n");
511 end_update(OK, RS_REPLY);
514 else {
515 /* Mark the slot as no longer initializing. */
516 rp->r_flags &= ~RS_INITIALIZING;
517 rp->r_check_tm = 0;
518 rp->r_alive_tm = getticks();
520 /* Reply and unblock the service before doing anything else. */
521 m.m_type = OK;
522 reply(rpub->endpoint, rp, &m);
524 /* Finalize initialization. */
525 end_srv_init(rp);
528 return EDONTREPLY;
531 /*===========================================================================*
532 * do_update *
533 *===========================================================================*/
534 int do_update(message *m_ptr)
536 struct rproc *rp;
537 struct rproc *trg_rp;
538 struct rproc *new_rp;
539 struct rprocpub *rpub;
540 struct rprocupd *rpupd;
541 struct rs_start rs_start;
542 int noblock, do_self_update, force_self_update, batch_mode, prepare_only;
543 int s;
544 char label[RS_MAX_LABEL_LEN];
545 int prepare_state, prepare_maxtime;
546 endpoint_t state_endpoint;
547 int lu_flags = 0;
548 int init_flags = 0;
549 int allow_retries = 0;
551 /* Copy the request structure. */
552 s = copy_rs_start(m_ptr->m_source, m_ptr->m_rs_req.addr, &rs_start);
553 if (s != OK) {
554 return s;
557 /* Copy label. */
558 s = copy_label(m_ptr->m_source, rs_start.rss_label.l_addr,
559 rs_start.rss_label.l_len, label, sizeof(label));
560 if(s != OK) {
561 return s;
564 /* Lookup slot by label. */
565 rp = lookup_slot_by_label(label);
566 if(!rp) {
567 if(rs_verbose)
568 printf("RS: do_update: service '%s' not found\n", label);
569 return ESRCH;
571 rpub = rp->r_pub;
573 /* Check flags. */
574 noblock = (rs_start.rss_flags & RSS_NOBLOCK);
575 do_self_update = (rs_start.rss_flags & RSS_SELF_LU);
576 force_self_update = (rs_start.rss_flags & RSS_FORCE_SELF_LU);
577 batch_mode = (rs_start.rss_flags & RSS_BATCH);
578 prepare_only = (rs_start.rss_flags & RSS_PREPARE_ONLY_LU);
579 if(do_self_update || force_self_update) {
580 lu_flags |= SEF_LU_SELF;
582 if(prepare_only) {
583 lu_flags |= SEF_LU_PREPARE_ONLY;
585 if(rs_start.rss_flags & RSS_ASR_LU) {
586 lu_flags |= SEF_LU_ASR;
588 if(!prepare_only && (rs_start.rss_flags & RSS_DETACH)) {
589 lu_flags |= SEF_LU_DETACHED;
591 if(rs_start.rss_map_prealloc_bytes <= 0
592 && rpub->endpoint == VM_PROC_NR
593 && (((lu_flags & (SEF_LU_SELF|SEF_LU_ASR)) != SEF_LU_SELF) || rs_start.rss_flags & RSS_FORCE_INIT_ST)
594 && RS_VM_DEFAULT_MAP_PREALLOC_LEN > 0) {
595 /* Give VM some mmapped regions by default on non-identical updates.*/
596 rs_start.rss_map_prealloc_bytes = RS_VM_DEFAULT_MAP_PREALLOC_LEN;
597 if(rs_verbose)
598 printf("RS: %s gets %ld default mmap bytes\n", srv_to_string(rp),
599 rs_start.rss_map_prealloc_bytes);
601 if((rs_start.rss_flags & RSS_NOMMAP_LU) || rs_start.rss_map_prealloc_bytes) {
602 /* Don't inherit mmapped regions at update time if requested or if
603 * mmap preallocation is used.
605 lu_flags |= SEF_LU_NOMMAP;
607 if(rs_start.rss_flags & RSS_FORCE_INIT_CRASH) {
608 init_flags |= SEF_INIT_CRASH;
610 if(rs_start.rss_flags & RSS_FORCE_INIT_FAIL) {
611 init_flags |= SEF_INIT_FAIL;
613 if(rs_start.rss_flags & RSS_FORCE_INIT_TIMEOUT) {
614 init_flags |= SEF_INIT_TIMEOUT;
616 if(rs_start.rss_flags & RSS_FORCE_INIT_DEFCB) {
617 init_flags |= SEF_INIT_DEFCB;
619 if(rs_start.rss_flags & RSS_FORCE_INIT_ST) {
620 init_flags |= SEF_INIT_ST;
622 init_flags |= lu_flags;
624 /* Lookup target label (if any). */
625 trg_rp = NULL;
626 state_endpoint = NONE;
627 if(rs_start.rss_trg_label.l_len > 0) {
628 s = copy_label(m_ptr->m_source, rs_start.rss_trg_label.l_addr,
629 rs_start.rss_trg_label.l_len, label, sizeof(label));
630 if(s != OK) {
631 return s;
633 trg_rp = lookup_slot_by_label(label);
634 if(!trg_rp) {
635 if(rs_verbose)
636 printf("RS: do_update: target service '%s' not found\n", label);
637 return ESRCH;
639 state_endpoint = trg_rp->r_pub->endpoint;
642 /* Check if the call can be allowed. */
643 if((s = check_call_permission(m_ptr->m_source, RS_UPDATE, rp)) != OK)
644 return s;
646 /* Retrieve live update state. */
647 prepare_state = m_ptr->m_rs_update.state;
648 if(prepare_state == SEF_LU_STATE_NULL) {
649 return(EINVAL);
652 /* Retrieve prepare max time. */
653 prepare_maxtime = m_ptr->m_rs_update.prepare_maxtime;
654 if(prepare_maxtime == 0) {
655 prepare_maxtime = RS_DEFAULT_PREPARE_MAXTIME;
658 /* Make sure we are not already updating. */
659 if(RUPDATE_IS_UPDATING()) {
660 printf("RS: an update is already in progress\n");
661 return EBUSY;
664 /* If an update is already scheduled, check constraints. */
665 if(RUPDATE_IS_UPD_SCHEDULED()) {
666 if(!batch_mode) {
667 printf("RS: an update is already scheduled, cannot start a new one\n");
668 return EBUSY;
670 if(SRV_IS_UPD_SCHEDULED(rp)) {
671 printf("RS: the specified process is already part of the currently scheduled update\n");
672 return EINVAL;
676 /* Prepare-only update for VM, PM, and VFS is only supported with an unreachable state. */
677 if(prepare_only
678 && (rp->r_pub->endpoint == VM_PROC_NR || rp->r_pub->endpoint == PM_PROC_NR || rp->r_pub->endpoint == VFS_PROC_NR)) {
679 if(prepare_state != SEF_LU_STATE_UNREACHABLE) {
680 printf("RS: prepare-only update for VM, PM and VFS is only supported with state %d\n", SEF_LU_STATE_UNREACHABLE);
681 return EINVAL;
685 /* Prepare-only update for RS is not supported. */
686 if(prepare_only && rp->r_pub->endpoint == RS_PROC_NR) {
687 printf("RS: prepare-only update for RS is not supported\n");
688 return EINVAL;
691 /* Initialize update descriptor. */
692 rpupd = &rp->r_upd;
693 rupdate_upd_init(rpupd, rp);
694 rpupd->lu_flags |= lu_flags;
695 rpupd->init_flags |= init_flags;
696 rupdate_set_new_upd_flags(rpupd);
698 /* A self update live updates a service instance into a replica, a regular
699 * update live updates a service instance into a new version, as specified
700 * by the given binary.
702 if(!prepare_only) {
703 if(do_self_update) {
704 if(rs_verbose)
705 printf("RS: %s requested to perform self update\n", srv_to_string(rp));
707 /* Clone the system service and use the replica as the new version. */
708 s = clone_service(rp, LU_SYS_PROC, rpupd->init_flags);
709 if(s != OK) {
710 printf("RS: do_update: unable to clone service: %d\n", s);
711 return s;
713 new_rp = rp->r_new_rp;
715 else {
716 if(rs_verbose)
717 printf("RS: %s requested to perform %s update\n", srv_to_string(rp),
718 force_self_update ? "(forced) self" : "regular");
720 /* Allocate a system service slot for the new version. */
721 s = alloc_slot(&new_rp);
722 if(s != OK) {
723 printf("RS: do_update: unable to allocate a new slot: %d\n", s);
724 return s;
727 /* Initialize the slot as requested. */
728 s = init_slot(new_rp, &rs_start, m_ptr->m_source);
729 if(s != OK) {
730 printf("RS: do_update: unable to init the new slot: %d\n", s);
731 return s;
734 /* Let the new version inherit defaults from the old one. */
735 inherit_service_defaults(rp, new_rp);
737 /* Link the two versions. */
738 rp->r_new_rp = new_rp;
739 new_rp->r_old_rp = rp;
741 /* Create new version of the service but don't let it run. */
742 new_rp->r_priv.s_flags |= LU_SYS_PROC;
743 new_rp->r_priv.s_init_flags |= rpupd->init_flags;
744 s = create_service(new_rp);
745 if(s != OK) {
746 printf("RS: do_update: unable to create a new service: %d\n", s);
747 return s;
751 /* Set default state endpoint. */
752 if(state_endpoint == NONE) {
753 state_endpoint = new_rp->r_pub->endpoint;
756 /* If RS is updating, set up signal managers for the new instance.
757 * The current RS instance must be made the backup signal manager to
758 * support rollback in case of a crash during initialization.
760 if(rp->r_priv.s_flags & ROOT_SYS_PROC) {
761 s = update_sig_mgrs(new_rp, SELF, new_rp->r_pub->endpoint);
762 if(s != OK) {
763 cleanup_service(new_rp);
764 return s;
768 /* Preallocate heap regions if requested. */
769 if(rs_start.rss_heap_prealloc_bytes < 0) {
770 rs_start.rss_heap_prealloc_bytes = 0;
772 if(rs_start.rss_heap_prealloc_bytes) {
773 size_t len;
774 if(rs_verbose)
775 printf("RS: %s preallocating %ld heap bytes\n", srv_to_string(new_rp),
776 rs_start.rss_heap_prealloc_bytes);
778 len = rs_start.rss_heap_prealloc_bytes;
779 s = vm_memctl(new_rp->r_pub->endpoint, VM_RS_MEM_HEAP_PREALLOC,
780 NULL, &len);
781 if(s != OK) {
782 printf("vm_memctl(VM_RS_MEM_HEAP_PREALLOC) failed: %d\n", s);
783 cleanup_service(new_rp);
784 return s;
786 if(rp->r_priv.s_flags & ROOT_SYS_PROC) {
787 vm_memctl(new_rp->r_pub->endpoint, VM_RS_MEM_PIN, 0, 0);
791 /* Preallocate mmapped regions if requested. */
792 if(rs_start.rss_map_prealloc_bytes < 0) {
793 rs_start.rss_map_prealloc_bytes = 0;
795 if(rs_start.rss_map_prealloc_bytes) {
796 void *addr = NULL;
797 if(rs_verbose)
798 printf("RS: %s preallocating %ld mmap bytes\n", srv_to_string(new_rp),
799 rs_start.rss_map_prealloc_bytes);
801 new_rp->r_map_prealloc_len = rs_start.rss_map_prealloc_bytes;
802 s = vm_memctl(new_rp->r_pub->endpoint, VM_RS_MEM_MAP_PREALLOC,
803 &addr, &new_rp->r_map_prealloc_len);
804 if(s != OK) {
805 printf("vm_memctl(VM_RS_MEM_MAP_PREALLOC) failed: %d\n", s);
806 cleanup_service(new_rp);
807 return s;
809 new_rp->r_map_prealloc_addr = (vir_bytes) addr;
813 /* Process state data. */
814 s = init_state_data(m_ptr->m_source, prepare_state, &rs_start.rss_state_data, &rpupd->prepare_state_data);
815 if(s != OK) {
816 rupdate_upd_clear(rpupd);
817 return s;
820 /* Create update grants. */
821 if(rpupd->prepare_state_data.size > 0) {
822 struct rs_state_data *state_data = &rpupd->prepare_state_data;
823 rpupd->prepare_state_data_gid = cpf_grant_direct(rpub->endpoint, (vir_bytes) state_data,
824 state_data->size, CPF_READ);
825 if(rpupd->prepare_state_data_gid == GRANT_INVALID) {
826 rupdate_upd_clear(rpupd);
827 return ENOMEM;
829 state_data->ipcf_els_gid = GRANT_INVALID;
830 if(state_data->ipcf_els) {
831 state_data->ipcf_els_gid = (int) cpf_grant_direct(rpub->endpoint, (vir_bytes) state_data->ipcf_els,
832 state_data->ipcf_els_size, CPF_READ);
833 if(state_data->ipcf_els_gid == GRANT_INVALID) {
834 rupdate_upd_clear(rpupd);
835 return ENOMEM;
838 state_data->eval_gid = GRANT_INVALID;
839 if(state_data->eval_addr) {
840 state_data->eval_gid = (int) cpf_grant_direct(rpub->endpoint, (vir_bytes) state_data->eval_addr,
841 state_data->eval_len, CPF_READ);
842 if(state_data->eval_gid == GRANT_INVALID) {
843 rupdate_upd_clear(rpupd);
844 return ENOMEM;
849 /* Fill the new update descriptor and add it to the update chain. */
850 rpupd->prepare_state = prepare_state;
851 rpupd->state_endpoint = state_endpoint;
852 rpupd->prepare_tm = getticks();
853 rpupd->prepare_maxtime = prepare_maxtime;
854 rupdate_add_upd(rpupd);
856 if(rs_verbose)
857 printf("RS: %s scheduled for %s\n", srv_to_string(rp), srv_upd_to_string(rpupd));
859 /* If batch mode, reply immediately. More services to update will follow. */
860 if(batch_mode) {
861 return OK;
864 /* Start preparing for the update process. */
865 s = start_update_prepare(allow_retries);
866 if(s == ESRCH) {
867 /* No process left in the update chain. We are done already. */
868 return OK;
870 if(s != OK) {
871 return s;
874 /* Unblock the caller immediately if requested. */
875 if(noblock) {
876 return OK;
879 /* Otherwise, send a reply when the new version completes initialization. */
880 rupdate.last_rpupd->rp->r_flags |= RS_LATEREPLY;
881 rupdate.last_rpupd->rp->r_caller = m_ptr->m_source;
882 rupdate.last_rpupd->rp->r_caller_request = RS_UPDATE;
884 return EDONTREPLY;
887 /*===========================================================================*
888 * do_upd_ready *
889 *===========================================================================*/
890 int do_upd_ready(message *m_ptr)
892 struct rproc *rp;
893 struct rprocupd *prev_rpupd, *rpupd;
894 int who_p;
895 int result;
896 int is_rs;
897 int i;
899 who_p = _ENDPOINT_P(m_ptr->m_source);
900 rp = rproc_ptr[who_p];
901 result = m_ptr->m_rs_update.result;
903 /* Make sure the originating service was requested to prepare for update. */
904 rpupd = rupdate.curr_rpupd;
905 if(!rpupd || rp != rpupd->rp || RUPDATE_IS_INITIALIZING()) {
906 if(rs_verbose)
907 printf("RS: %s sent late/unexpected update ready msg\n",
908 srv_to_string(rp));
909 return EINVAL;
911 rp->r_flags |= RS_PREPARE_DONE;
913 /* Check if something went wrong and the service failed to prepare
914 * for the update. In that case, end the update process. The old version will
915 * be replied to and continue executing.
917 if(result != OK) {
918 printf("RS: update failed: %s\n", lu_strerror(result));
919 end_update(result, RS_REPLY);
921 return EDONTREPLY;
924 if(rs_verbose)
925 printf("RS: %s ready to update\n", srv_to_string(rp));
927 /* If this is a multi-component update and this is not the last service
928 * in the update, request the next process to update.
930 if(start_update_prepare_next() != NULL) {
931 return EDONTREPLY;
934 /* Now perform the update and request each new instance to initialize. */
935 start_update();
937 return EDONTREPLY;
940 /*===========================================================================*
941 * do_period *
942 *===========================================================================*/
943 void do_period(m_ptr)
944 message *m_ptr;
946 register struct rproc *rp;
947 register struct rprocpub *rpub;
948 clock_t now = m_ptr->m_notify.timestamp;
949 int s;
950 long period;
952 /* If an update is in progress, check its status. */
953 if(RUPDATE_IS_UPDATING() && !RUPDATE_IS_INITIALIZING()) {
954 update_period(m_ptr);
957 /* Search system services table. Only check slots that are in use and not
958 * updating.
960 for (rp=BEG_RPROC_ADDR; rp<END_RPROC_ADDR; rp++) {
961 rpub = rp->r_pub;
963 if ((rp->r_flags & RS_ACTIVE) && (!SRV_IS_UPDATING(rp) || ((rp->r_flags & (RS_INITIALIZING|RS_INIT_DONE|RS_INIT_PENDING)) == RS_INITIALIZING))) {
965 /* Compute period. */
966 period = rp->r_period;
967 if(rp->r_flags & RS_INITIALIZING) {
968 period = SRV_IS_UPDATING(rp) ? UPD_INIT_MAXTIME(&rp->r_upd) : RS_INIT_T;
971 /* If the service is to be revived (because it repeatedly exited,
972 * and was not directly restarted), the binary backoff field is
973 * greater than zero.
975 if (rp->r_backoff > 0) {
976 rp->r_backoff -= 1;
977 if (rp->r_backoff == 0) {
978 restart_service(rp);
982 /* If the service was signaled with a SIGTERM and fails to respond,
983 * kill the system service with a SIGKILL signal.
985 else if (rp->r_stop_tm > 0 && now - rp->r_stop_tm > 2*RS_DELTA_T
986 && rp->r_pid > 0) {
987 rp->r_stop_tm = 0;
988 crash_service(rp); /* simulate crash */
991 /* There seems to be no special conditions. If the service has a
992 * period assigned check its status.
994 else if (period > 0) {
996 /* Check if an answer to a status request is still pending. If
997 * the service didn't respond within time, kill it to simulate
998 * a crash. The failure will be detected and the service will
999 * be restarted automatically. Give the service a free pass if
1000 * somebody is initializing. There may be some weird dependencies
1001 * if another service is, for example, restarting at the same
1002 * time.
1004 if (rp->r_alive_tm < rp->r_check_tm) {
1005 if (now - rp->r_alive_tm > 2*period &&
1006 rp->r_pid > 0 && !(rp->r_flags & RS_NOPINGREPLY)) {
1007 struct rproc *rp2;
1008 int init_flag;
1009 if(rs_verbose)
1010 printf("RS: %s reported late\n", srv_to_string(rp));
1011 init_flag = rp->r_flags & RS_INITIALIZING;
1012 rp->r_flags &= ~RS_INITIALIZING;
1013 rp2 = lookup_slot_by_flags(RS_INITIALIZING);
1014 rp->r_flags |= init_flag;
1015 if(rp2 != NULL && !SRV_IS_UPDATING(rp)) {
1016 /* Skip for now. */
1017 if(rs_verbose)
1018 printf("RS: %s gets a free pass\n",
1019 srv_to_string(rp));
1020 rp->r_alive_tm = now;
1021 rp->r_check_tm = now+1;
1022 continue;
1024 rp->r_flags |= RS_NOPINGREPLY;
1025 crash_service(rp); /* simulate crash */
1026 if(rp->r_flags & RS_INITIALIZING) {
1027 rp->r_init_err = EINTR;
1032 /* No answer pending. Check if a period expired since the last
1033 * check and, if so request the system service's status.
1035 else if (now - rp->r_check_tm > rp->r_period) {
1036 ipc_notify(rpub->endpoint); /* request status */
1037 rp->r_check_tm = now; /* mark time */
1043 /* Reschedule a synchronous alarm for the next period. */
1044 if (OK != (s=sys_setalarm(RS_DELTA_T, 0)))
1045 panic("couldn't set alarm: %d", s);
1048 /*===========================================================================*
1049 * do_sigchld *
1050 *===========================================================================*/
1051 void do_sigchld()
1053 /* PM informed us that there are dead children to cleanup. Go get them. */
1054 pid_t pid;
1055 int status;
1056 struct rproc *rp;
1057 struct rproc **rps;
1058 int i, nr_rps, found;
1060 if(rs_verbose)
1061 printf("RS: got SIGCHLD signal, cleaning up dead children\n");
1063 while ( (pid = waitpid(-1, &status, WNOHANG)) != 0 ) {
1064 rp = lookup_slot_by_pid(pid);
1065 if(rp != NULL) {
1067 if(rs_verbose)
1068 printf("RS: %s exited via another signal manager\n",
1069 srv_to_string(rp));
1071 /* The slot is still there. This means RS is not the signal
1072 * manager assigned to the process. Ignore the event but
1073 * free slots for all the service instances and send a late
1074 * reply if necessary.
1076 found = 0;
1077 get_service_instances(rp, &rps, &nr_rps);
1078 for(i=0;i<nr_rps;i++) {
1079 if(SRV_IS_UPDATING(rps[i])) {
1080 rps[i]->r_flags &= ~(RS_UPDATING|RS_PREPARE_DONE|RS_INIT_DONE|RS_INIT_PENDING);
1081 found = 1;
1083 free_slot(rps[i]);
1085 if(found) {
1086 rupdate_clear_upds();
1092 /*===========================================================================*
1093 * do_getsysinfo *
1094 *===========================================================================*/
1095 int do_getsysinfo(m_ptr)
1096 message *m_ptr;
1098 vir_bytes src_addr, dst_addr;
1099 int dst_proc;
1100 size_t size, len;
1101 int s;
1103 /* Check if the call can be allowed. */
1104 if((s = check_call_permission(m_ptr->m_source, 0, NULL)) != OK)
1105 return s;
1107 dst_proc = m_ptr->m_source;
1108 dst_addr = m_ptr->m_lsys_getsysinfo.where;
1109 size = m_ptr->m_lsys_getsysinfo.size;
1111 switch(m_ptr->m_lsys_getsysinfo.what) {
1112 case SI_PROC_TAB:
1113 src_addr = (vir_bytes) rproc;
1114 len = sizeof(struct rproc) * NR_SYS_PROCS;
1115 break;
1116 case SI_PROCALL_TAB:
1117 /* Copy out both tables, one after the other. */
1118 src_addr = (vir_bytes) rproc;
1119 len = sizeof(struct rproc) * NR_SYS_PROCS;
1120 if (len > size)
1121 return EINVAL;
1122 if ((s = sys_datacopy(SELF, src_addr, dst_proc, dst_addr, len)) != OK)
1123 return s;
1124 dst_addr += len;
1125 size -= len;
1126 /* FALLTHROUGH */
1127 case SI_PROCPUB_TAB:
1128 src_addr = (vir_bytes) rprocpub;
1129 len = sizeof(struct rprocpub) * NR_SYS_PROCS;
1130 break;
1131 default:
1132 return(EINVAL);
1135 if (len != size)
1136 return(EINVAL);
1138 return sys_datacopy(SELF, src_addr, dst_proc, dst_addr, len);
1141 /*===========================================================================*
1142 * do_lookup *
1143 *===========================================================================*/
1144 int do_lookup(m_ptr)
1145 message *m_ptr;
1147 static char namebuf[100];
1148 int len, r;
1149 struct rproc *rrp;
1150 struct rprocpub *rrpub;
1152 len = m_ptr->m_rs_req.name_len;
1154 if(len < 2 || len >= sizeof(namebuf)) {
1155 printf("RS: len too weird (%d)\n", len);
1156 return EINVAL;
1159 if((r=sys_datacopy(m_ptr->m_source, (vir_bytes) m_ptr->m_rs_req.name,
1160 SELF, (vir_bytes) namebuf, len)) != OK) {
1161 printf("RS: name copy failed\n");
1162 return r;
1166 namebuf[len] = '\0';
1168 rrp = lookup_slot_by_label(namebuf);
1169 if(!rrp) {
1170 return ESRCH;
1172 rrpub = rrp->r_pub;
1173 m_ptr->m_rs_req.endpoint = rrpub->endpoint;
1175 return OK;
1178 /*===========================================================================*
1179 * do_sysctl *
1180 *===========================================================================*/
1181 int do_sysctl(message *m_ptr)
1183 int request_type = m_ptr->m_rs_req.subtype;
1184 int r, allow_retries = 1;
1185 switch(request_type) {
1186 case RS_SYSCTL_SRV_STATUS:
1187 print_services_status();
1188 break;
1189 case RS_SYSCTL_UPD_START:
1190 case RS_SYSCTL_UPD_RUN:
1191 r = start_update_prepare(allow_retries);
1192 print_update_status();
1193 if(r != OK) {
1194 if(r == ESRCH) {
1195 /* We are done already. */
1196 r = OK;
1198 return r;
1200 if(request_type == RS_SYSCTL_UPD_START) {
1201 return OK;
1203 /* Send a reply when done. */
1204 rupdate.last_rpupd->rp->r_flags |= RS_LATEREPLY;
1205 rupdate.last_rpupd->rp->r_caller = m_ptr->m_source;
1206 rupdate.last_rpupd->rp->r_caller_request = RS_UPDATE;
1207 return EDONTREPLY;
1208 break;
1209 case RS_SYSCTL_UPD_STOP:
1210 r = abort_update_proc(EINTR);
1211 print_update_status();
1212 return r;
1213 break;
1214 case RS_SYSCTL_UPD_STATUS:
1215 print_update_status();
1216 break;
1217 default:
1218 printf("RS: bad sysctl type\n");
1219 return EINVAL;
1220 break;
1223 return OK;
1226 /*===========================================================================*
1227 * do_fi *
1228 *===========================================================================*/
1229 int do_fi(message *m_ptr)
1231 struct rproc *rp;
1232 struct rprocpub *rpub;
1233 int s, r;
1234 char label[RS_MAX_LABEL_LEN];
1236 /* Copy label. */
1237 s = copy_label(m_ptr->m_source, m_ptr->m_rs_req.addr,
1238 m_ptr->m_rs_req.len, label, sizeof(label));
1239 if(s != OK) {
1240 return s;
1243 /* Lookup slot by label. */
1244 rp = lookup_slot_by_label(label);
1245 if(!rp) {
1246 if(rs_verbose)
1247 printf("RS: do_fi: service '%s' not found\n", label);
1248 return(ESRCH);
1250 rpub = rp->r_pub;
1252 /* Check if the call can be allowed. */
1253 if((r = check_call_permission(m_ptr->m_source, RS_FI, rp)) != OK)
1254 return r;
1256 /* Inject fault into the service as requested. */
1257 s = fi_service(rp);
1259 return s;
1262 /*===========================================================================*
1263 * check_request *
1264 *===========================================================================*/
1265 static int check_request(struct rs_start *rs_start)
1267 /* Verify scheduling parameters */
1268 if (rs_start->rss_scheduler != KERNEL &&
1269 (rs_start->rss_scheduler < 0 ||
1270 rs_start->rss_scheduler > LAST_SPECIAL_PROC_NR)) {
1271 printf("RS: check_request: invalid scheduler %d\n",
1272 rs_start->rss_scheduler);
1273 return EINVAL;
1275 if (rs_start->rss_priority >= NR_SCHED_QUEUES) {
1276 printf("RS: check_request: priority %u out of range\n",
1277 rs_start->rss_priority);
1278 return EINVAL;
1280 if (rs_start->rss_quantum <= 0) {
1281 printf("RS: check_request: quantum %u out of range\n",
1282 rs_start->rss_quantum);
1283 return EINVAL;
1286 if (rs_start->rss_cpu == RS_CPU_BSP)
1287 rs_start->rss_cpu = machine.bsp_id;
1288 else if (rs_start->rss_cpu == RS_CPU_DEFAULT) {
1289 /* keep the default value */
1290 } else if (rs_start->rss_cpu < 0)
1291 return EINVAL;
1292 else if (rs_start->rss_cpu > machine.processors_count) {
1293 printf("RS: cpu number %d out of range 0-%d, using BSP\n",
1294 rs_start->rss_cpu, machine.processors_count);
1295 rs_start->rss_cpu = machine.bsp_id;
1298 /* Verify signal manager. */
1299 if (rs_start->rss_sigmgr != SELF &&
1300 (rs_start->rss_sigmgr < 0 ||
1301 rs_start->rss_sigmgr > LAST_SPECIAL_PROC_NR)) {
1302 printf("RS: check_request: invalid signal manager %d\n",
1303 rs_start->rss_sigmgr);
1304 return EINVAL;
1307 return OK;