]> Zhao Yanbai Git Server - minix.git/commitdiff
Self update support in RS.
authorCristiano Giuffrida <cristiano@minix3.org>
Thu, 1 Jul 2010 18:48:25 +0000 (18:48 +0000)
committerCristiano Giuffrida <cristiano@minix3.org>
Thu, 1 Jul 2010 18:48:25 +0000 (18:48 +0000)
commands/service/service.c
include/minix/rs.h
servers/rs/manager.c
servers/rs/request.c

index 077da6fb00dc07f3cf12bbee8a843a42758bf4de..bfd7431e0c43d278d805b96e3bf0989686fd4358 100644 (file)
@@ -55,6 +55,8 @@ PRIVATE char *known_requests[] = {
 
 #define RUN_CMD                "run"
 #define RUN_SCRIPT     "/etc/rs.single"        /* Default script for 'run' */
+#define SELF_BINARY     "self"
+#define SELF_REQ_PATH   "/dev/null"
 #define PATH_CONFIG    _PATH_SYSTEM_CONF       /* Default config file */
 #define DEFAULT_LU_STATE   SEF_LU_STATE_WORK_FREE /* Default lu state */
 #define DEFAULT_LU_MAXTIME 0                    /* Default lu max time */
@@ -63,6 +65,7 @@ PRIVATE char *known_requests[] = {
 #define OPT_COPY       "-c"            /* copy executable image */
 #define OPT_REUSE      "-r"            /* reuse executable image */
 #define OPT_NOBLOCK    "-n"            /* unblock caller immediately */
+#define OPT_REPLICA    "-p"            /* create replica for the service */
 
 /* Define names for arguments provided to this utility. The first few 
  * arguments are required and have a known index. Thereafter, some optional
@@ -104,6 +107,7 @@ PRIVATE int req_type;
 PRIVATE int do_run= 0;         /* 'run' command instead of 'up' */
 PRIVATE char *req_label = NULL;
 PRIVATE char *req_path = NULL;
+PRIVATE char *req_path_self = SELF_REQ_PATH;
 PRIVATE char *req_args = "";
 PRIVATE int req_major = 0;
 PRIVATE int req_dev_style = STYLE_NDEV;
@@ -128,8 +132,8 @@ PRIVATE void print_usage(char *app_name, char *problem)
   fprintf(stderr, "Warning, %s\n", problem);
   fprintf(stderr, "Usage:\n");
   fprintf(stderr,
-  "    %s [%s %s %s] (up|run|update) <binary> [%s <args>] [%s <special>] [%s <style>] [%s <ticks>] [%s <path>] [%s <name>] [%s <path>] [%s <state>] [%s <time>]\n", 
-       app_name, OPT_COPY, OPT_REUSE, OPT_NOBLOCK,
+  "    %s [%s %s %s %s] (up|run|update) <binary|%s> [%s <args>] [%s <special>] [%s <style>] [%s <ticks>] [%s <path>] [%s <name>] [%s <path>] [%s <state>] [%s <time>]\n", 
+       app_name, OPT_COPY, OPT_REUSE, OPT_NOBLOCK, OPT_REPLICA, SELF_BINARY,
        ARG_ARGS, ARG_DEV, ARG_DEVSTYLE, ARG_PERIOD, ARG_SCRIPT,
        ARG_LABELNAME, ARG_CONFIG, ARG_LU_STATE, ARG_LU_MAXTIME);
   fprintf(stderr, "    %s down label\n", app_name);
@@ -233,6 +237,13 @@ PRIVATE int parse_arguments(int argc, char **argv)
       if(p_flag)
         rs_start.rss_flags |= RSS_REPLICA;
 
+      req_path = argv[optind+ARG_PATH];
+      if(req_nr == RS_UPDATE && !strcmp(req_path, SELF_BINARY)) {
+          req_config = NULL;
+          req_path = req_path_self;
+          rs_start.rss_flags |= RSS_SELF_LU;
+      }
+
       if (do_run)
       {
        /* Set default recovery script for RUN */
@@ -246,20 +257,20 @@ PRIVATE int parse_arguments(int argc, char **argv)
       }
 
       /* Verify the name of the binary of the system service. */
-      req_path = argv[optind+ARG_PATH];
-      if (req_path[0] != '/') {
-          print_usage(argv[ARG_NAME], "binary should be absolute path");
-          exit(EINVAL);
-      }
-
-      if (stat(req_path, &stat_buf) == -1) {
-         perror(req_path);
-          fprintf(stderr, "couldn't get stat binary\n");
-          exit(errno);
-      }
-      if (! (stat_buf.st_mode & S_IFREG)) {
-          print_usage(argv[ARG_NAME], "binary is not a regular file");
-          exit(EINVAL);
+      if(!(rs_start.rss_flags & RSS_SELF_LU)) {
+          if (req_path[0] != '/') {
+              print_usage(argv[ARG_NAME], "binary should be absolute path");
+              exit(EINVAL);
+          }
+          if (stat(req_path, &stat_buf) == -1) {
+             perror(req_path);
+              fprintf(stderr, "couldn't get stat binary\n");
+              exit(errno);
+          }
+          if (! (stat_buf.st_mode & S_IFREG)) {
+              print_usage(argv[ARG_NAME], "binary is not a regular file");
+              exit(EINVAL);
+          }
       }
 
       /* Get HZ. */
@@ -371,6 +382,11 @@ PRIVATE int parse_arguments(int argc, char **argv)
         /* no extra arguments required */
   }
 
+  if((rs_start.rss_flags & RSS_SELF_LU) && !req_label) {
+      print_usage(argv[ARG_NAME], "label option mandatory for target action");
+      exit(EINVAL);
+  }
+
   /* Return the request number if no error were found. */
   return(req_nr);
 }
index 06a87005fef9e5996d6234b8ef318c059770b1bf..a124e63775a31c3c6fd4ae3cba2743de16ad5888 100644 (file)
@@ -20,6 +20,7 @@ Interface to the reincarnation server
 #define RSS_REUSE      0x04    /* Try to reuse previously copied binary */
 #define RSS_NOBLOCK    0x08    /* unblock caller immediately */
 #define RSS_REPLICA    0x10    /* keep a replica of the service */
+#define RSS_SELF_LU    0x20    /* perform self update */
 
 /* Common definitions. */
 #define RS_NR_CONTROL           8
index cb5c9a07c8361957c36739d9d5743c8747d5f3e9..a13dfe5d8eb2293dc6a58ac65e2e77dd8d338b43 100644 (file)
@@ -292,6 +292,8 @@ PUBLIC void end_update(int result)
  *    service has a period, a status request will be forced in the next period.
  */
   struct rproc *old_rp, *new_rp, *exiting_rp, *surviving_rp;
+  struct rproc **rps;
+  int nr_rps, i;
 
   old_rp = rupdate.rp;
   new_rp = old_rp->r_new_rp;
@@ -314,14 +316,17 @@ PUBLIC void end_update(int result)
   /* Send a late reply if necessary. */
   late_reply(old_rp, result);
 
-  /* Unpublish and cleanup the version that has to die out and mark the other
+  /* Cleanup the version that has to die out and mark the other
    * version as no longer updating.
    */
   surviving_rp->r_flags &= ~RS_UPDATING;
-  cleanup_service(exiting_rp);
+  get_service_instances(exiting_rp, &rps, &nr_rps);
+  for(i=0;i<nr_rps;i++) {
+      cleanup_service(rps[i]);
+  }
 
   if(rs_verbose)
-      printf("RS: service %s ended the update\n", srv_to_string(surviving_rp));
+      printf("RS: %s ended the update\n", srv_to_string(surviving_rp));
 }
 
 /*===========================================================================*
index 105c900273713048e9f2d496d7992c8c8dcc046e..3bf330a4dbf136efecd257e20e68361cf716f2a0 100755 (executable)
@@ -381,7 +381,7 @@ PUBLIC int do_update(message *m_ptr)
   struct rproc *new_rp;
   struct rprocpub *rpub;
   struct rs_start rs_start;
-  int noblock;
+  int noblock, do_self_update;
   int s;
   char label[RS_MAX_LABEL_LEN];
   int lu_state;
@@ -393,6 +393,7 @@ PUBLIC int do_update(message *m_ptr)
       return s;
   }
   noblock = (rs_start.rss_flags & RSS_NOBLOCK);
+  do_self_update = (rs_start.rss_flags & RSS_SELF_LU);
   s = check_request(&rs_start);
   if (s != OK) {
       return s;
@@ -442,28 +443,58 @@ PUBLIC int do_update(message *m_ptr)
       return EBUSY;
   }
 
-  /* Allocate a system service slot for the new version. */
-  s = alloc_slot(&new_rp);
-  if(s != OK) {
-      printf("RS: do_update: unable to allocate a new slot: %d\n", s);
-      return s;
-  }
+  /* A self update live updates a service instance into a replica, a regular
+   * update live updates a service instance into a new version, as specified
+   * by the given binary.
+   */
+  if(do_self_update) {
+      struct rproc *r_next_rp;
+      if(rs_verbose)
+          printf("RS: %s performs self update\n", srv_to_string(rp));
 
-  /* Initialize the slot as requested. */
-  s = init_slot(new_rp, &rs_start, m_ptr->m_source);
-  if(s != OK) {
-      printf("RS: do_update: unable to init the new slot: %d\n", s);
-      return s;
+      /* Save information about existing replica (if any). */
+      r_next_rp = rp->r_next_rp;
+      rp->r_next_rp = NULL;
+
+      /* Clone the system service and use the replica as the new version. */
+      s = clone_service(rp);
+      if(s != OK) {
+          printf("RS: do_update: unable to clone service: %d\n", s);
+          return s;
+      }
+      new_rp = rp->r_next_rp;
+      new_rp->r_prev_rp = NULL;
+
+      /* Restore information about existing replica (if any). */
+      rp->r_next_rp = r_next_rp;
   }
+  else {
+      if(rs_verbose)
+          printf("RS: %s performs regular update\n", srv_to_string(rp));
 
-  /* Let the new version inherit defaults from the old one. */
-  inherit_service_defaults(rp, new_rp);
+      /* Allocate a system service slot for the new version. */
+      s = alloc_slot(&new_rp);
+      if(s != OK) {
+          printf("RS: do_update: unable to allocate a new slot: %d\n", s);
+          return s;
+      }
 
-  /* Create new version of the service but don't let it run. */
-  s = create_service(new_rp);
-  if(s != OK) {
-      printf("RS: do_update: unable to create a new service: %d\n", s);
-      return s;
+      /* Initialize the slot as requested. */
+      s = init_slot(new_rp, &rs_start, m_ptr->m_source);
+      if(s != OK) {
+          printf("RS: do_update: unable to init the new slot: %d\n", s);
+          return s;
+      }
+
+      /* Let the new version inherit defaults from the old one. */
+      inherit_service_defaults(rp, new_rp);
+
+      /* Create new version of the service but don't let it run. */
+      s = create_service(new_rp);
+      if(s != OK) {
+          printf("RS: do_update: unable to create a new service: %d\n", s);
+          return s;
+      }
   }
 
   /* Link old version to new version and mark both as updating. */