[multipath] option to use priorities as weights in the round-robin scheduler
authorroot <root@xa-s05.(none)>
Wed, 24 Aug 2005 14:48:40 +0000 (16:48 +0200)
committerroot <root@xa-s05.(none)>
Wed, 24 Aug 2005 14:48:40 +0000 (16:48 +0200)
Disabled by default.

Synthax is "rr_weight = priorities", and is valid in the default{},
device{} and multipath{} blocks.

This is an interim solution before a cleaner "least queued scheduler".

To make this complete, the daemon should be able to "message" DM to
change the path weights when their prio changes. Probably not worth the
effort and spend time on another scheduler.

The core of this patch is in the multipath table setup :

if (mp->rr_weight && pp->priority)
minio = conf->rr_minio * pp->priority;

The rest is the config switch handling, and printing.

libmultipath/config.h
libmultipath/dict.c
libmultipath/print.c
libmultipath/print.h
libmultipath/propsel.c
libmultipath/propsel.h
libmultipath/structs.c
libmultipath/structs.h
multipath/main.c

index aa695fd157c12af256409a67d72de703c4b07191..6d8369cf563048ebe766e609004f81c7f323fed1 100644 (file)
@@ -17,6 +17,7 @@ struct hwentry {
        int pgpolicy;
        int checker_index;
        int pgfailback;
+       int rr_weight;
 
        char * vendor;
        char * product;
@@ -31,6 +32,7 @@ struct mpentry {
        int selector_args;
        int pgpolicy;
        int pgfailback;
+       int rr_weight;
 
        char * wwid;
        char * selector;
@@ -52,6 +54,7 @@ struct config {
        int max_checkint;
        int pgfailback;
        int remove;
+       int rr_weight;
 
        char * dev;
        char * multipath;
index 2280a00e56902ce921bb269ff4efef7f09826330..8e74b5be8fbc050df039bd69a74012ebf5937fe8 100644 (file)
@@ -128,6 +128,25 @@ def_minio_handler(vector strvec)
        return 0;
 }
 
+static int
+def_weight_handler(vector strvec)
+{
+       char * buff;
+
+       buff = set_value(strvec);
+
+       if (!buff)
+               return 1;
+
+       if (strlen(buff) == 10 &&
+           !strcmp(buff, "priorities"))
+               conf->rr_weight = RR_WEIGHT_PRIO;
+
+       FREE(buff);
+
+       return 0;
+}
+
 static int
 default_failback_handler(vector strvec)
 {
@@ -385,6 +404,29 @@ hw_failback_handler(vector strvec)
        return 0;
 }
 
+static int
+hw_weight_handler(vector strvec)
+{
+       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) == 10 &&
+           !strcmp(buff, "priorities"))
+               hwe->rr_weight = RR_WEIGHT_PRIO;
+
+       FREE(buff);
+
+       return 0;
+}
+
 /*
  * multipaths block handlers
  */
@@ -509,6 +551,29 @@ mp_failback_handler(vector strvec)
        return 0;
 }
 
+static int
+mp_weight_handler(vector strvec)
+{
+       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) == 10 &&
+           !strcmp(buff, "priorities"))
+               mpe->rr_weight = RR_WEIGHT_PRIO;
+
+       FREE(buff);
+
+       return 0;
+}
+
 vector
 init_keywords(void)
 {
@@ -525,6 +590,7 @@ init_keywords(void)
        install_keyword("default_features", &def_features_handler);
        install_keyword("failback", &default_failback_handler);
        install_keyword("rr_min_io", &def_minio_handler);
+       install_keyword("rr_weight", &def_weight_handler);
        
        install_keyword_root("devnode_blacklist", &blacklist_handler);
        install_keyword("devnode", &ble_handler);
@@ -543,6 +609,7 @@ init_keywords(void)
        install_keyword("hardware_handler", &hw_handler_handler);
        install_keyword("prio_callout", &prio_callout_handler);
        install_keyword("failback", &hw_failback_handler);
+       install_keyword("rr_weight", &hw_weight_handler);
        install_sublevel_end();
 
        install_keyword_root("multipaths", &multipaths_handler);
@@ -553,6 +620,7 @@ init_keywords(void)
        install_keyword("path_grouping_policy", &mp_pgpolicy_handler);
        install_keyword("path_selector", &mp_selector_handler);
        install_keyword("failback", &mp_failback_handler);
+       install_keyword("rr_weight", &mp_weight_handler);
        install_sublevel_end();
 
        return keywords;
index 0ad4857cc6e81f6167b3176190e4acee0895ab1c..de125262554be2c0475a7fc91cb0c1c4c8dac630 100644 (file)
@@ -242,6 +242,12 @@ snprint_path (char * line, int len, char * format, struct path * pp,
                                      pp->tick, pp->checkint);
                        NOPAD;
                        break;
+               case 'p':
+                       if (pp->priority) {
+                               PRINT(c, TAIL, "%i", pp->priority);
+                       }
+                       NOPAD;
+                       break;
                default:
                        break;
                }
index f9b8f1c0c922f6301bb770ba145c3a453cfb9ac2..c77956f99f187c947925146a331d0c87ab224fb9 100644 (file)
@@ -9,6 +9,7 @@
  * %T : checker path status
  * %s : scsi strings
  * %c : claimed
+ * %p : priority
  * 
  * map format magics :
  * 
@@ -17,9 +18,9 @@
  * %F : failback countdown
  * %C : checker countdown
  */
-#define PRINT_PATH_LONG      "%w %i %d %D %t%T%c %s"
+#define PRINT_PATH_LONG      "%w %i %d %D %p %t%T%c %s"
 #define PRINT_PATH_INDENT    " \\_ %i %d %D %t%T%c"
-#define PRINT_PATH_CHECKER   "%i %d %D %t%T %C"
+#define PRINT_PATH_CHECKER   "%i %d %D %p %t%T %C"
 #define PRINT_MAP_FAILBACK   "%w %d %F"
 
 #define MAX_LINE_LEN 80
index baac2931388b50a213c074c8906e799032043271..e73309e952df1539c7ae7959e416db8205e9422b 100644 (file)
  * traverse the configuration layers from most specific to most generic
  * stop at first explicit setting found
  */
+extern int
+select_rr_weight (struct multipath * mp)
+{
+       if (mp->mpe && mp->mpe->rr_weight) {
+               mp->rr_weight = mp->mpe->rr_weight;
+               condlog(3, "rr_weight = %i (LUN setting)",
+                       mp->rr_weight);
+               return 0;
+       }
+       if (mp->hwe && mp->hwe->rr_weight) {
+               mp->rr_weight = mp->hwe->rr_weight;
+               condlog(3, "rr_weight = %i (controler setting)",
+                       mp->rr_weight);
+               return 0;
+       }
+       if (conf->rr_weight) {
+               mp->rr_weight = conf->rr_weight;
+               condlog(3, "rr_weight = %i (config file default)",
+                       mp->rr_weight);
+               return 0;
+       }
+       mp->rr_weight = RR_WEIGHT_NONE;
+       condlog(3, "rr_weight = %i (internal default)",
+               mp->rr_weight);
+       return 0;
+}
+
 extern int
 select_pgfailback (struct multipath * mp)
 {
index 11d585b7bc38429c569a245fe4f30c63f7c1211f..5e57a3221bf54bb113a933462aa13187aedc29db 100644 (file)
@@ -1,3 +1,4 @@
+int select_rr_weight (struct multipath * mp);
 int select_pgfailback (struct multipath * mp);
 int select_pgpolicy (struct multipath * mp);
 int select_selector (struct multipath * mp);
index 2c1c38ba400f11225e0c9964ad4fc3307c3126ac..4c2698665506ed5e4d70c22ff309e06b14adf48a 100644 (file)
@@ -105,9 +105,9 @@ alloc_multipath (void)
 
        mpp = (struct multipath *)MALLOC(sizeof(struct multipath));
 
-       if (mpp) {
+       if (mpp)
                mpp->nextpg = 1;
-       }
+
        return mpp;
 }
 
index 08a2a5edfa28a0018f42ca05a4bea8ada3dd80e9..0aac78906ad60c1a76bd2c008d29c35144236835 100644 (file)
@@ -19,6 +19,12 @@ enum free_path_switch {
        FREE_PATHS
 };
 
+enum rr_weight_mode {
+       RR_WEIGHT_UNDEF,
+       RR_WEIGHT_NONE,
+       RR_WEIGHT_PRIO
+};
+
 enum failback_mode {
        FAILBACK_UNDEF,
        FAILBACK_MANUAL,
@@ -108,6 +114,7 @@ struct multipath {
        int action;
        int pgfailback;
        int failback_tick;
+       int rr_weight;
        unsigned long long size;
        vector paths;
        vector pg;
index 9f6a561b3220c8c09995febd65ab7281d7036fad..b4cda89da66fd95e04cbb52d58629edf81b991d0 100644 (file)
@@ -301,6 +301,7 @@ assemble_map (struct multipath * mp)
 {
        int i, j;
        int shift, freechar;
+       int minio;
        char * p;
        struct pathgroup * pgp;
        struct path * pp;
@@ -331,8 +332,13 @@ assemble_map (struct multipath * mp)
                freechar -= shift;
 
                vector_foreach_slot (pgp->paths, pp, j) {
+                       minio = conf->minio;
+                       
+                       if (mp->rr_weight == RR_WEIGHT_PRIO && pp->priority)
+                               minio *= pp->priority;
+
                        shift = snprintf(p, freechar, " %s %d",
-                                        pp->dev_t, conf->minio);
+                                        pp->dev_t, minio);
                        if (shift >= freechar) {
                                fprintf(stderr, "mp->params too small\n");
                                return 1;
@@ -385,6 +391,7 @@ setup_map (struct multipath * mpp)
        select_selector(mpp);
        select_features(mpp);
        select_hwhandler(mpp);
+       select_rr_weight(mpp);
 
        /*
         * apply selected grouping policy to valid paths
@@ -759,19 +766,27 @@ usage (char * progname)
 }
 
 static int
-update_pathvec (vector pathvec)
+update_paths (struct multipath * mpp)
 {
-       int i;
+       int i, j;
+       struct pathgroup * pgp;
        struct path * pp;
 
-       vector_foreach_slot (pathvec, pp, i) {
-               if (pp->dev && pp->dev_t && strlen(pp->dev) == 0) {
-                       devt2devname(pp->dev, pp->dev_t);
-                       pathinfo(pp, conf->hwtable,
-                               DI_SYSFS | DI_CHECKER | DI_SERIAL | DI_PRIO);
+       vector_foreach_slot (mpp->pg, pgp, i) {
+               vector_foreach_slot (pgp->paths, pp, j) {
+                       if (!strlen(pp->dev)) {
+                               devt2devname(pp->dev, pp->dev_t);
+                               pathinfo(pp, conf->hwtable,
+                                        DI_SYSFS | DI_CHECKER | \
+                                        DI_SERIAL | DI_PRIO);
+                               continue;
+                       }
+                       if (pp->state == PATH_UNCHECKED)
+                               pathinfo(pp, conf->hwtable, DI_CHECKER);
+
+                       if (!pp->priority)
+                               pathinfo(pp, conf->hwtable, DI_PRIO);
                }
-               if (pp->checkfn && pp->state == PATH_UNCHECKED)
-                       pp->state = pp->checkfn(pp->fd, NULL, NULL);
        }
        return 0;
 }
@@ -807,10 +822,12 @@ get_dm_mpvec (vector curmp, vector pathvec, char * refwwid)
                 * If not in "fast list mode", we need to fetch information
                 * about them
                 */
-               if (conf->list != 1) {
-                       update_pathvec(pathvec);
+               if (conf->list != 1)
+                       update_paths(mpp);
+
+               if (conf->list > 1)
                        select_path_group(mpp);
-               }
+
                disassemble_status(mpp->status, mpp);
 
                if (conf->list)