From: Cristiano Giuffrida Date: Mon, 28 Jun 2010 21:38:29 +0000 (+0000) Subject: service clone command to clone system services on demand. X-Git-Tag: v3.1.8~318 X-Git-Url: http://zhaoyanbai.com/repos/Bv9ARM.ch08.html?a=commitdiff_plain;h=869a223d43eaf97cd5bc7ceaf2dbc5b48b2b043c;p=minix.git service clone command to clone system services on demand. --- diff --git a/commands/service/service.c b/commands/service/service.c index 8ff08c2c8..b885df961 100644 --- a/commands/service/service.c +++ b/commands/service/service.c @@ -41,6 +41,7 @@ PRIVATE char *known_requests[] = { "restart", "shutdown", "update", + "clone", "catch for illegal requests" }; #define ILLEGAL_REQUEST sizeof(known_requests)/sizeof(char *) @@ -130,6 +131,7 @@ PRIVATE void print_usage(char *app_name, char *problem) fprintf(stderr, " %s down label\n", app_name); fprintf(stderr, " %s refresh label\n", app_name); fprintf(stderr, " %s restart label\n", app_name); + fprintf(stderr, " %s clone label\n", app_name); fprintf(stderr, " %s shutdown\n", app_name); fprintf(stderr, "\n"); } @@ -351,11 +353,12 @@ PRIVATE int parse_arguments(int argc, char **argv) } } } - else if (req_nr == RS_DOWN || req_nr == RS_REFRESH || req_nr == RS_RESTART) { + else if (req_nr == RS_DOWN || req_nr == RS_REFRESH || req_nr == RS_RESTART + || req_nr == RS_CLONE) { /* Verify argument count. */ if (argc - 1 < optind+ARG_LABEL) { - print_usage(argv[ARG_NAME], "action requires a label to stop"); + print_usage(argv[ARG_NAME], "action requires a target label"); exit(EINVAL); } req_label= argv[optind+ARG_LABEL]; @@ -1122,6 +1125,7 @@ PUBLIC int main(int argc, char **argv) case RS_DOWN: case RS_REFRESH: case RS_RESTART: + case RS_CLONE: m.RS_CMD_ADDR = req_label; m.RS_CMD_LEN = strlen(req_label); break; diff --git a/include/minix/com.h b/include/minix/com.h index bb7820b9c..4b3c1df34 100644 --- a/include/minix/com.h +++ b/include/minix/com.h @@ -668,6 +668,7 @@ #define RS_RESTART (RS_RQ_BASE + 3) /* restart system service */ #define RS_SHUTDOWN (RS_RQ_BASE + 4) /* alert about shutdown */ #define RS_UPDATE (RS_RQ_BASE + 5) /* update system service */ +#define RS_CLONE (RS_RQ_BASE + 6) /* clone system service */ #define RS_LOOKUP (RS_RQ_BASE + 8) /* lookup server name */ diff --git a/servers/rs/main.c b/servers/rs/main.c index 02214e0eb..e862e6ffb 100644 --- a/servers/rs/main.c +++ b/servers/rs/main.c @@ -112,6 +112,7 @@ PUBLIC int main(void) case RS_RESTART: result = do_restart(&m); break; case RS_SHUTDOWN: result = do_shutdown(&m); break; case RS_UPDATE: result = do_update(&m); break; + case RS_CLONE: result = do_clone(&m); break; case GETSYSINFO: result = do_getsysinfo(&m); break; case RS_LOOKUP: result = do_lookup(&m); break; /* Ready messages. */ diff --git a/servers/rs/proto.h b/servers/rs/proto.h index 89d37174d..03d075ac6 100644 --- a/servers/rs/proto.h +++ b/servers/rs/proto.h @@ -15,6 +15,7 @@ _PROTOTYPE( int do_up, (message *m)); _PROTOTYPE( int do_down, (message *m)); _PROTOTYPE( int do_refresh, (message *m)); _PROTOTYPE( int do_restart, (message *m)); +_PROTOTYPE( int do_clone, (message *m)); _PROTOTYPE( int do_shutdown, (message *m)); _PROTOTYPE( void do_period, (message *m)); _PROTOTYPE( int do_init_ready, (message *m)); diff --git a/servers/rs/request.c b/servers/rs/request.c index d18d25ccd..ad3de02dd 100755 --- a/servers/rs/request.c +++ b/servers/rs/request.c @@ -174,6 +174,51 @@ PUBLIC int do_restart(message *m_ptr) return OK; } +/*===========================================================================* + * do_clone * + *===========================================================================*/ +PUBLIC int do_clone(message *m_ptr) +{ + struct rproc *rp; + struct rprocpub *rpub; + int s, r; + char label[RS_MAX_LABEL_LEN]; + char script[MAX_SCRIPT_LEN]; + + /* Copy label. */ + s = copy_label(m_ptr->m_source, m_ptr->RS_CMD_ADDR, + m_ptr->RS_CMD_LEN, label, sizeof(label)); + if(s != OK) { + return s; + } + + /* Lookup slot by label. */ + rp = lookup_slot_by_label(label); + if(!rp) { + if(rs_verbose) + printf("RS: do_clone: service '%s' not found\n", label); + return(ESRCH); + } + rpub = rp->r_pub; + + /* Check if the call can be allowed. */ + if((r = check_call_permission(m_ptr->m_source, RS_CLONE, rp)) != OK) + return r; + + /* Don't clone if a replica is already available. */ + if(rp->r_next_rp) { + return EEXIST; + } + + /* Clone the service as requested. */ + rpub->sys_flags |= SF_USE_REPL; + if ((r = clone_service(rp)) != OK) { + rpub->sys_flags &= ~SF_USE_REPL; + return r; + } + + return OK; +} /*===========================================================================* * do_refresh * @@ -516,7 +561,7 @@ message *m_ptr; */ for (rp=BEG_RPROC_ADDR; rpr_pub; - if ((rp->r_flags & RS_IN_USE) && !(rp->r_flags & RS_UPDATING)) { + if ((rp->r_flags & RS_ACTIVE) && !(rp->r_flags & RS_UPDATING)) { /* Compute period. */ period = rpub->period;