From: Hannes Reinecke Date: Tue, 4 May 2010 09:02:37 +0000 (+0200) Subject: Serialize startup on large machines X-Git-Tag: upstream/0.5.0~106^2~10 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=44c3a8f98e247cd453d386be82baf1de36d9b2a9;p=platform%2Fupstream%2Fmultipath-tools.git Serialize startup on large machines On large installations the startup can take quite long. So to better integration with the init scripts I've added the CLI command 'show daemon' which returns the internal running state of the daemon. With this the init scripts can wait until the daemon is properly started. Signed-off-by: Hannes Reinecke --- diff --git a/multipathd/cli.c b/multipathd/cli.c index 782d886..4c90ef9 100644 --- a/multipathd/cli.c +++ b/multipathd/cli.c @@ -170,6 +170,7 @@ load_keys (void) r += add_key(keys, "multipath", MAP, 1); r += add_key(keys, "group", GROUP, 1); r += add_key(keys, "reconfigure", RECONFIGURE, 0); + r += add_key(keys, "daemon", DAEMON, 0); r += add_key(keys, "status", STATUS, 0); r += add_key(keys, "stats", STATS, 0); r += add_key(keys, "topology", TOPOLOGY, 0); @@ -419,6 +420,7 @@ cli_init (void) { add_handler(LIST+PATHS, NULL); add_handler(LIST+PATHS+FMT, NULL); add_handler(LIST+STATUS, NULL); + add_handler(LIST+DAEMON, NULL); add_handler(LIST+MAPS, NULL); add_handler(LIST+MAPS+STATUS, NULL); add_handler(LIST+MAPS+STATS, NULL); diff --git a/multipathd/cli.h b/multipathd/cli.h index 8971ff6..7f03bf3 100644 --- a/multipathd/cli.h +++ b/multipathd/cli.h @@ -16,6 +16,7 @@ enum { __MAP, __GROUP, __RECONFIGURE, + __DAEMON, __STATUS, __STATS, __TOPOLOGY, @@ -45,6 +46,7 @@ enum { #define MAP (1 << __MAP) #define GROUP (1 << __GROUP) #define RECONFIGURE (1 << __RECONFIGURE) +#define DAEMON (1 << __DAEMON) #define STATUS (1 << __STATUS) #define STATS (1 << __STATS) #define TOPOLOGY (1 << __TOPOLOGY) diff --git a/multipathd/cli_handlers.c b/multipathd/cli_handlers.c index 3c4d838..39ca6fe 100644 --- a/multipathd/cli_handlers.c +++ b/multipathd/cli_handlers.c @@ -281,6 +281,26 @@ show_status (char ** r, int *len, struct vectors * vecs) return 0; } +int +show_daemon (char ** r, int *len) +{ + char * c; + char * reply; + + unsigned int maxlen = INITIAL_REPLY_LEN; + reply = MALLOC(maxlen); + + if (!reply) + return 1; + + c = reply; + c += snprintf(c, INITIAL_REPLY_LEN, "%s\n", daemon_status()); + + *r = reply; + *len = (int)(c - reply + 1); + return 0; +} + int show_maps (char ** r, int *len, struct vectors * vecs, char * style) { @@ -367,6 +387,14 @@ cli_list_maps_stats (void * v, char ** reply, int * len, void * data) return show_maps(reply, len, vecs, PRINT_MAP_STATS); } +int +cli_list_daemon (void * v, char ** reply, int * len, void * data) +{ + condlog(3, "list daemon (operator)"); + + return show_daemon(reply, len); +} + int cli_add_path (void * v, char ** reply, int * len, void * data) { diff --git a/multipathd/cli_handlers.h b/multipathd/cli_handlers.h index 8fe9e06..eae308d 100644 --- a/multipathd/cli_handlers.h +++ b/multipathd/cli_handlers.h @@ -1,6 +1,7 @@ int cli_list_paths (void * v, char ** reply, int * len, void * data); int cli_list_paths_fmt (void * v, char ** reply, int * len, void * data); int cli_list_status (void * v, char ** reply, int * len, void * data); +int cli_list_daemon (void * v, char ** reply, int * len, void * data); int cli_list_maps (void * v, char ** reply, int * len, void * data); int cli_list_maps_fmt (void * v, char ** reply, int * len, void * data); int cli_list_maps_status (void * v, char ** reply, int * len, void * data); diff --git a/multipathd/main.c b/multipathd/main.c index d11ecdc..9eb534f 100644 --- a/multipathd/main.c +++ b/multipathd/main.c @@ -69,6 +69,7 @@ pthread_cond_t exit_cond = PTHREAD_COND_INITIALIZER; pthread_mutex_t exit_mutex = PTHREAD_MUTEX_INITIALIZER; int logsink; +enum daemon_status running_state; /* * global copy of vecs for use in sig handlers @@ -780,6 +781,7 @@ uxlsnrloop (void * ap) set_handler_callback(LIST+PATHS+FMT, cli_list_paths_fmt); set_handler_callback(LIST+MAPS, cli_list_maps); set_handler_callback(LIST+STATUS, cli_list_status); + set_handler_callback(LIST+DAEMON, cli_list_daemon); set_handler_callback(LIST+MAPS+STATUS, cli_list_maps_status); set_handler_callback(LIST+MAPS+STATS, cli_list_maps_stats); set_handler_callback(LIST+MAPS+FMT, cli_list_maps_fmt); @@ -830,6 +832,24 @@ exit_daemon (int status) return status; } +const char * +daemon_status(void) +{ + switch (running_state) { + case DAEMON_INIT: + return "init"; + case DAEMON_START: + return "startup"; + case DAEMON_CONFIGURE: + return "configure"; + case DAEMON_RUNNING: + return "running"; + case DAEMON_SHUTDOWN: + return "shutdown"; + } + return NULL; +} + static void fail_path (struct path * pp, int del_active) { @@ -1336,6 +1356,9 @@ sighup (int sig) { condlog(2, "reconfigure (SIGHUP)"); + if (running_state != DAEMON_RUNNING) + return; + reconfigure(gvecs); #ifdef _DEBUG_ @@ -1415,6 +1438,8 @@ child (void * param) pthread_attr_destroy(&log_attr); } + running_state = DAEMON_START; + condlog(2, "--------start up--------"); condlog(2, "read " DEFAULT_CONFIGFILE); @@ -1493,10 +1518,16 @@ child (void * param) condlog(0, "failed to create uevent thread: %d", rc); exit(1); } + if ((rc = pthread_create(&uxlsnr_thr, &misc_attr, uxlsnrloop, vecs))) { + condlog(0, "failed to create cli listener: %d", rc); + exit(1); + } /* * fetch and configure both paths and multipaths */ lock(vecs->lock); + running_state = DAEMON_CONFIGURE; + if (configure(vecs, 1)) { unlock(vecs->lock); condlog(0, "failure during configuration"); @@ -1511,10 +1542,6 @@ child (void * param) condlog(0,"failed to create checker loop thread: %d", rc); exit(1); } - if ((rc = pthread_create(&uxlsnr_thr, &misc_attr, uxlsnrloop, vecs))) { - condlog(0, "failed to create cli listener: %d", rc); - exit(1); - } if ((rc = pthread_create(&uevq_thr, &misc_attr, uevqloop, vecs))) { condlog(0, "failed to create uevent dispatcher: %d", rc); exit(1); @@ -1522,11 +1549,20 @@ child (void * param) pthread_attr_destroy(&misc_attr); pthread_mutex_lock(&exit_mutex); + /* Startup complete, create logfile */ + if (pidfile_create(DEFAULT_PIDFILE, getpid())) { + if (logsink) + log_thread_stop(); + + exit(1); + } + running_state = DAEMON_RUNNING; pthread_cond_wait(&exit_cond, &exit_mutex); /* * exit path */ + running_state = DAEMON_SHUTDOWN; block_signal(SIGHUP, NULL); lock(vecs->lock); if (conf->queue_without_daemon == QUE_NO_DAEMON_OFF) @@ -1643,6 +1679,7 @@ main (int argc, char *argv[]) int err; logsink = 1; + running_state = DAEMON_INIT; dm_init(); if (getuid() != 0) { diff --git a/multipathd/main.h b/multipathd/main.h index f8487c0..87f24c7 100644 --- a/multipathd/main.h +++ b/multipathd/main.h @@ -3,7 +3,16 @@ #define MAPGCINT 5 +enum daemon_status { + DAEMON_INIT, + DAEMON_START, + DAEMON_CONFIGURE, + DAEMON_RUNNING, + DAEMON_SHUTDOWN, +}; + int exit_daemon(int); +const char * daemon_status(void); int reconfigure (struct vectors *); int ev_add_path (char *, struct vectors *); int ev_remove_path (char *, struct vectors *); diff --git a/multipathd/multipathd.init.suse b/multipathd/multipathd.init.suse index d851354..9059faa 100644 --- a/multipathd/multipathd.init.suse +++ b/multipathd/multipathd.init.suse @@ -25,6 +25,9 @@ PIDFILE=/var/run/multipathd.pid # Set the maximum number of open files MAX_OPEN_FDS=4096 +# Set to enable asynchronous daemon startup +DAEMON_ASYNC_STARTUP= + test -x $DAEMON || exit 5 . /etc/rc.status @@ -43,13 +46,29 @@ case "$1" in ulimit -n $MAX_OPEN_FDS fi - if [ -f $PIDFILE ]; then - PID="$(cat $PIDFILE)" - PROCNAME="$(ps -o cmd --no-headers $PID)" - fi + $DAEMON $ARGS - if [ "$PROCNAME" != "$DAEMON" ]; then - $DAEMON + if [ -n "$DAEMON_ASYNC_STARTUP" ] ; then + rc_status -v + rc_exit + fi + # Wait for the daemon to start up + timeout=$MPATH_INIT_TIMEOUT + while [ ! -f $PIDFILE ] ; do + sleep 1 + status=$(multipathd -k'show daemon' 2> /dev/null) + if [ "$status" == "configure" ] ; then + # Daemon is still configuring, do not increase + # the timeout + continue + fi + timeout=$(( $timeout - 1 )) + [ $timeout -eq 0 ] && break + done + if [ $timeout -eq 0 ] ; then + echo -n " (no pidfile)" + rc_failed 1 +t.suse fi # Remember status and be verbose @@ -66,7 +85,18 @@ case "$1" in PROCNAME="$(ps -o cmd --no-headers $PID)" fi - if [ "$PROCNAME" == "$DAEMON" ]; then + timeout=$MPATH_INIT_TIMEOUT + while [ $timeout -gt 0 ] ; do + status=$($DAEMON -k'show daemon' 2> /dev/null) + [ "$status" == "configure" ] && continue + [ "$status" == "running" ] && break + sleep 1 + timeout=$(( $timeout - 1 )) + done + + status=$($DAEMON -k'shutdown' 2> /dev/null) + if [ "$status" != "ok" ] ; then + if [ "$PROCNAME" == `basename $DAEMON` ]; then kill -TERM $PID fi