[all] Path group timeout handling
authorChristophe Varoqui <cvaroqui@zezette.localdomain>
Thu, 3 May 2007 07:37:33 +0000 (09:37 +0200)
committerChristophe Varoqui <cvaroqui@zezette.localdomain>
Thu, 3 May 2007 07:37:33 +0000 (09:37 +0200)
The config file keyword is pg_timeout.
Takes value in seconds. Default is none.
Can be set in defaults, hardware or multipath configlets.

From Redhat resync.

libmultipath/config.h
libmultipath/configure.c
libmultipath/defaults.h
libmultipath/devmapper.c
libmultipath/devmapper.h
libmultipath/dict.c
libmultipath/propsel.c
libmultipath/propsel.h
libmultipath/structs.h
libmultipath/structs_vec.c

index 61e5adf..7caa11d 100644 (file)
@@ -27,6 +27,7 @@ struct hwentry {
        int rr_weight;
        int no_path_retry;
        int minio;
+       int pg_timeout;
        struct checker * checker;
        char * bl_product;
 };
@@ -42,6 +43,7 @@ struct mpentry {
        int rr_weight;
        int no_path_retry;
        int minio;
+       int pg_timeout;
 };
 
 struct config {
@@ -61,6 +63,7 @@ struct config {
        int rr_weight;
        int no_path_retry;
        int user_friendly_names;
+       int pg_timeout;
 
        char * dev;
        char * udev_dir;
index fba04a4..9632fb4 100644 (file)
@@ -60,6 +60,7 @@ setup_map (struct multipath * mpp)
        select_rr_weight(mpp);
        select_minio(mpp);
        select_no_path_retry(mpp);
+       select_pg_timeout(mpp);
 
        /*
         * assign paths to path groups -- start with no groups and all paths
@@ -174,8 +175,9 @@ select_action (struct multipath * mpp, vector curmp)
                        mpp->alias);
                return;
        }
-       if (!mpp->no_path_retry && /* let features be handled by the daemon */
-           strncmp(cmpp->features, mpp->features, strlen(mpp->features))) {
+       if (!mpp->no_path_retry && !mpp->pg_timeout &&
+           (strlen(cmpp->features) != strlen(mpp->features) ||
+            strcmp(cmpp->features, mpp->features))) {
                mpp->action =  ACT_RELOAD;
                condlog(3, "%s: set ACT_RELOAD (features change)",
                        mpp->alias);
@@ -502,6 +504,12 @@ coalesce_paths (struct vectors * vecs, vector newmp, char * refwwid)
                        else
                                dm_queue_if_no_path(mpp->alias, 1);
                }
+               if (mpp->pg_timeout != PGTIMEOUT_UNDEF) {
+                       if (mpp->pg_timeout == -PGTIMEOUT_NONE)
+                               dm_set_pg_timeout(mpp->alias,  0);
+                       else
+                               dm_set_pg_timeout(mpp->alias, mpp->pg_timeout);
+               }
 
                if (newmp) {
                        if (mpp->action != ACT_REJECT) {
index ab65492..8deeb0f 100644 (file)
@@ -9,6 +9,7 @@
 #define DEFAULT_FAILBACK       -FAILBACK_MANUAL
 #define DEFAULT_RR_WEIGHT      RR_WEIGHT_NONE
 #define DEFAULT_NO_PATH_RETRY  NO_PATH_RETRY_UNDEF
+#define DEFAULT_PGTIMEOUT      -PGTIMEOUT_NONE
 #define DEFAULT_USER_FRIENDLY_NAMES    0
 
 #define DEFAULT_CHECKINT       5
index 468f7a8..dece079 100644 (file)
@@ -565,6 +565,16 @@ dm_queue_if_no_path(char *mapname, int enable)
        return dm_message(mapname, message);
 }
 
+int
+dm_set_pg_timeout(char *mapname, int timeout_val)
+{
+       char message[24];
+
+       if (snprintf(message, 24, "set_pg_timeout %d", timeout_val) >= 24)
+               return 1;
+       return dm_message(mapname, message);
+}
+
 static int
 dm_groupmsg (char * msg, char * mapname, int index)
 {
index c023cd4..59afd01 100644 (file)
@@ -13,6 +13,7 @@ int dm_flush_maps (char *);
 int dm_fail_path(char * mapname, char * path);
 int dm_reinstate_path(char * mapname, char * path);
 int dm_queue_if_no_path(char *mapname, int enable);
+int dm_set_pg_timeout(char *mapname, int timeout_val);
 int dm_switchgroup(char * mapname, int index);
 int dm_enablegroup(char * mapname, int index);
 int dm_disablegroup(char * mapname, int index);
index b924f0f..c705cc6 100644 (file)
@@ -201,6 +201,32 @@ def_no_path_retry_handler(vector strvec)
 }
 
 static int
+def_pg_timeout_handler(vector strvec)
+{
+       int pg_timeout;
+       char * buff;
+
+       buff = set_value(strvec);
+
+       if (!buff)
+               return 1;
+
+       if (strlen(buff) == 4 && !strcmp(buff, "none"))
+               conf->pg_timeout = -PGTIMEOUT_NONE;
+       else if (sscanf(buff, "%d", &pg_timeout) == 1 && pg_timeout >= 0) {
+               if (pg_timeout == 0)
+                       conf->pg_timeout = -PGTIMEOUT_NONE;
+               else
+                       conf->pg_timeout = pg_timeout;
+       }
+       else
+               conf->pg_timeout = PGTIMEOUT_UNDEF;
+
+       FREE(buff);
+       return 0;
+}
+
+static int
 names_handler(vector strvec)
 {
        char * buff;
@@ -240,14 +266,14 @@ blacklist_handler(vector strvec)
 static int
 blacklist_exceptions_handler(vector strvec)
 {
-        conf->elist_devnode = vector_alloc();
-        conf->elist_wwid = vector_alloc();
+       conf->elist_devnode = vector_alloc();
+       conf->elist_wwid = vector_alloc();
        conf->elist_device = vector_alloc();
 
-        if (!conf->elist_devnode || !conf->elist_wwid || !conf->blist_device)
-                return 1;
+       if (!conf->elist_devnode || !conf->elist_wwid || !conf->blist_device)
+               return 1;
 
-        return 0;
+       return 0;
 }
 
 static int
@@ -266,12 +292,12 @@ ble_devnode_handler(vector strvec)
 static int
 ble_except_devnode_handler(vector strvec)
 {
-        char * buff;
+       char * buff;
 
-        buff = set_value(strvec);
+       buff = set_value(strvec);
 
-        if (!buff)
-                return 1;
+       if (!buff)
+               return 1;
 
        return store_ble(conf->elist_devnode, buff, ORIGIN_CONFIG);
 }
@@ -656,6 +682,36 @@ hw_minio_handler(vector strvec)
        return 0;
 }
 
+static int
+hw_pg_timeout_handler(vector strvec)
+{
+       int pg_timeout;
+       struct hwentry *hwe = VECTOR_LAST_SLOT(conf->hwtable);
+       char *buff;
+
+       if (!hwe)
+               return 1;
+
+       buff = set_value(strvec);
+
+       if (!buff)
+               return 1;
+
+       if (strlen(buff) == 4 && !strcmp(buff, "none"))
+               hwe->pg_timeout = -PGTIMEOUT_NONE;
+       else if (sscanf(buff, "%d", &pg_timeout) == 1 && pg_timeout >= 0) {
+               if (pg_timeout == 0)
+                       hwe->pg_timeout = -PGTIMEOUT_NONE;
+               else
+                       hwe->pg_timeout = pg_timeout;
+       }
+       else
+               hwe->pg_timeout = PGTIMEOUT_UNDEF;
+
+       FREE(buff);
+       return 0;
+}
+
 /*
  * multipaths block handlers
  */
@@ -848,6 +904,35 @@ mp_minio_handler(vector strvec)
        return 0;
 }
 
+static int
+mp_pg_timeout_handler(vector strvec)
+{
+       int pg_timeout;
+       struct mpentry *mpe = VECTOR_LAST_SLOT(conf->mptable);
+       char *buff;
+
+       if (!mpe)
+               return 1;
+
+       buff = set_value(strvec);
+
+       if (!buff)
+               return 1;
+       if (strlen(buff) == 4 && !strcmp(buff, "none"))
+               mpe->pg_timeout = -PGTIMEOUT_NONE;
+       else if (sscanf(buff, "%d", &pg_timeout) == 1 && pg_timeout >= 0) {
+               if (pg_timeout == 0)
+                       mpe->pg_timeout = -PGTIMEOUT_NONE;
+               else
+                       mpe->pg_timeout = pg_timeout;
+       }
+       else
+               mpe->pg_timeout = PGTIMEOUT_UNDEF;
+
+       FREE(buff);
+       return 0;
+}
+
 /*
  * config file keywords printing
  */
@@ -967,6 +1052,22 @@ snprint_mp_rr_min_io (char * buff, int len, void * data)
 }
 
 static int
+snprint_mp_pg_timeout (char * buff, int len, void * data)
+{
+       struct mpentry * mpe = (struct mpentry *)data;
+
+       switch (mpe->pg_timeout) {
+       case PGTIMEOUT_UNDEF:
+               break;
+       case -PGTIMEOUT_NONE:
+               return snprintf(buff, len, "none");
+       default:
+               return snprintf(buff, len, "%i", mpe->pg_timeout);
+       }
+       return 0;
+}
+
+static int
 snprint_hw_vendor (char * buff, int len, void * data)
 {
        struct hwentry * hwe = (struct hwentry *)data;
@@ -1168,6 +1269,27 @@ snprint_hw_rr_min_io (char * buff, int len, void * data)
 }
 
 static int
+snprint_hw_pg_timeout (char * buff, int len, void * data)
+{
+       struct hwentry * hwe = (struct hwentry *)data;
+
+       if (!hwe->pg_timeout)
+               return 0;
+       if (hwe->pg_timeout == conf->pg_timeout)
+               return 0;
+
+       switch (hwe->pg_timeout) {
+       case PGTIMEOUT_UNDEF:
+               break;
+       case -PGTIMEOUT_NONE:
+               return snprintf(buff, len, "none");
+       default:
+               return snprintf(buff, len, "%i", hwe->pg_timeout);
+       }
+       return 0;
+}
+
+static int
 snprint_hw_path_checker (char * buff, int len, void * data)
 {
        struct hwentry * hwe = (struct hwentry *)data;
@@ -1339,6 +1461,23 @@ snprint_def_no_path_retry (char * buff, int len, void * data)
 }
 
 static int
+snprint_def_pg_timeout (char * buff, int len, void * data)
+{
+       if (conf->pg_timeout == DEFAULT_PGTIMEOUT)
+               return 0;
+
+       switch (conf->pg_timeout) {
+       case PGTIMEOUT_UNDEF:
+               break;
+       case -PGTIMEOUT_NONE:
+               return snprintf(buff, len, "none");
+       default:
+               return snprintf(buff, len, "%i", conf->pg_timeout);
+       }
+       return 0;
+}
+
+static int
 snprint_def_user_friendly_names (char * buff, int len, void * data)
 {
        if (conf->user_friendly_names == DEFAULT_USER_FRIENDLY_NAMES)
@@ -1391,6 +1530,7 @@ init_keywords(void)
        install_keyword("rr_min_io", &def_minio_handler, &snprint_def_rr_min_io);
        install_keyword("rr_weight", &def_weight_handler, &snprint_def_rr_weight);
        install_keyword("no_path_retry", &def_no_path_retry_handler, &snprint_def_no_path_retry);
+       install_keyword("pg_timeout", &def_pg_timeout_handler, &snprint_def_pg_timeout);
        install_keyword("user_friendly_names", &names_handler, &snprint_def_user_friendly_names);
        __deprecated install_keyword("default_selector", &def_selector_handler, NULL);
        __deprecated install_keyword("default_path_grouping_policy", &def_pgpolicy_handler, NULL);
@@ -1444,6 +1584,7 @@ init_keywords(void)
        install_keyword("rr_weight", &hw_weight_handler, &snprint_hw_rr_weight);
        install_keyword("no_path_retry", &hw_no_path_retry_handler, &snprint_hw_no_path_retry);
        install_keyword("rr_min_io", &hw_minio_handler, &snprint_hw_rr_min_io);
+       install_keyword("pg_timeout", &hw_pg_timeout_handler, &snprint_hw_pg_timeout);
        install_sublevel_end();
 
        install_keyword_root("multipaths", &multipaths_handler);
@@ -1457,5 +1598,6 @@ init_keywords(void)
        install_keyword("rr_weight", &mp_weight_handler, &snprint_mp_rr_weight);
        install_keyword("no_path_retry", &mp_no_path_retry_handler, &snprint_mp_no_path_retry);
        install_keyword("rr_min_io", &mp_minio_handler, &snprint_mp_rr_min_io);
+       install_keyword("pg_timeout", &mp_pg_timeout_handler, &snprint_mp_pg_timeout);
        install_sublevel_end();
 }
index 1f0021a..45a3728 100644 (file)
@@ -330,3 +330,41 @@ select_minio (struct multipath * mp)
        return 0;
 }
 
+extern int
+select_pg_timeout(struct multipath *mp)
+{
+       if (mp->mpe && mp->mpe->pg_timeout != PGTIMEOUT_UNDEF) {
+               mp->pg_timeout = mp->mpe->pg_timeout;
+               if (mp->pg_timeout > 0)
+                       condlog(3, "%s: pg_timeout = %d (multipath setting)",
+                               mp->alias, mp->pg_timeout);
+               else
+                       condlog(3, "%s: pg_timeout = NONE (multipath setting)",
+                               mp->alias);
+               return 0;
+       }
+       if (mp->hwe && mp->hwe->pg_timeout != PGTIMEOUT_UNDEF) {
+               mp->pg_timeout = mp->hwe->pg_timeout;
+               if (mp->pg_timeout > 0)
+                       condlog(3, "%s: pg_timeout = %d (controller setting)",
+                               mp->alias, mp->pg_timeout);
+               else
+                       condlog(3, "%s: pg_timeout = NONE (controller setting)",
+                               mp->alias);
+               return 0;
+       }
+       if (conf->pg_timeout != PGTIMEOUT_UNDEF) {
+               mp->pg_timeout = conf->pg_timeout;
+               if (mp->pg_timeout > 0)
+                       condlog(3, "%s: pg_timeout = %d (config file default)",
+                               mp->alias, mp->pg_timeout);
+               else
+                       condlog(3,
+                               "%s: pg_timeout = NONE (config file default)",
+                               mp->alias);
+               return 0;
+       }
+       mp->pg_timeout = PGTIMEOUT_UNDEF;
+       condlog(3, "pg_timeout = NONE (internal default)");
+       return 0;
+}
index f66a598..afd1f88 100644 (file)
@@ -9,4 +9,5 @@ int select_checker(struct path *pp);
 int select_getuid (struct path * pp);
 int select_getprio (struct path * pp);
 int select_no_path_retry(struct multipath *mp);
+int select_pg_timeout(struct multipath *mp);
 int select_minio(struct multipath *mp);
index 77dd4af..46dcdee 100644 (file)
@@ -58,6 +58,11 @@ enum pgstates {
        PGSTATE_ACTIVE
 };
 
+enum pgtimeouts {
+       PGTIMEOUT_UNDEF,
+       PGTIMEOUT_NONE
+};
+
 struct scsi_idlun {
        int dev_id;
        int host_unique_id;
@@ -130,6 +135,7 @@ struct multipath {
        int no_path_retry; /* number of retries after all paths are down */
        int retry_tick;    /* remaining times for retries */
        int minio;
+       int pg_timeout;
        unsigned long long size;
        vector paths;
        vector pg;
index 1a6d8e2..53b7e17 100644 (file)
@@ -278,6 +278,7 @@ retry:
        select_rr_weight(mpp);
        select_pgfailback(mpp);
        set_no_path_retry(mpp);
+       select_pg_timeout(mpp);
 
        return 0;
 out: