alua: Handle LBA_DEPENDENT state
[multipath-tools/.git] / libmultipath / prioritizers / alua.c
index 1b52b8e..4da3ee7 100644 (file)
 #define ALUA_PRIO_RTPG_FAILED                  2
 #define ALUA_PRIO_GETAAS_FAILED                        3
 #define ALUA_PRIO_TPGS_FAILED                  4
+#define ALUA_PRIO_NO_INFORMATION               5
+
+static const char * aas_string[] = {
+       [AAS_OPTIMIZED]         = "active/optimized",
+       [AAS_NON_OPTIMIZED]     = "active/non-optimized",
+       [AAS_STANDBY]           = "standby",
+       [AAS_UNAVAILABLE]       = "unavailable",
+       [AAS_LBA_DEPENDENT]     = "lba dependent",
+       [AAS_RESERVED]          = "invalid/reserved",
+       [AAS_OFFLINE]           = "offline",
+       [AAS_TRANSITIONING]     = "transitioning between states",
+};
+
+static const char *aas_print_string(int rc)
+{
+       rc &= 0x7f;
+
+       if (rc & 0x70)
+               return aas_string[AAS_RESERVED];
+       rc &= 0x0f;
+       if (rc > AAS_RESERVED && rc < AAS_OFFLINE)
+               return aas_string[AAS_RESERVED];
+       else
+               return aas_string[rc];
+}
 
 int
 get_alua_info(int fd)
 {
-       char *  aas_string[] = {
-               [AAS_OPTIMIZED]         = "active/optimized",
-               [AAS_NON_OPTIMIZED]     = "active/non-optimized",
-               [AAS_STANDBY]           = "standby",
-               [AAS_UNAVAILABLE]       = "unavailable",
-               [AAS_TRANSITIONING]     = "transitioning between states",
-       };
        int     rc;
        int     tpg;
+       int     aas;
 
        rc = get_target_port_group_support(fd);
        if (rc < 0)
@@ -52,29 +71,44 @@ get_alua_info(int fd)
        rc = get_asymmetric_access_state(fd, tpg);
        if (rc < 0)
                return -ALUA_PRIO_GETAAS_FAILED;
+       aas = (rc & 0x0f);
 
-       condlog(3, "aas = [%s]",
-               (aas_string[rc]) ? aas_string[rc] : "invalid/reserved");
+       condlog(3, "aas = %02x [%s]%s", rc, aas_print_string(rc),
+               (rc & 0x80) ? " [preferred]" : "");
        return rc;
 }
 
-int getprio (struct path * pp)
+int getprio (struct path * pp, char * args)
 {
-       int rc = get_alua_info(pp->fd);
+       int rc;
+       int aas;
+       int priopath;
+
+       if (pp->fd < 0)
+               return -ALUA_PRIO_NO_INFORMATION;
+
+       rc = get_alua_info(pp->fd);
        if (rc >= 0) {
-               switch(rc) {
+               aas = (rc & 0x0f);
+               priopath = (rc & 0x80);
+               switch(aas) {
                        case AAS_OPTIMIZED:
                                rc = 50;
                                break;
                        case AAS_NON_OPTIMIZED:
                                rc = 10;
                                break;
+                       case AAS_LBA_DEPENDENT:
+                               rc = 5;
+                               break;
                        case AAS_STANDBY:
                                rc = 1;
                                break;
                        default:
                                rc = 0;
                }
+               if (priopath)
+                       rc += 80;
        } else {
                switch(-rc) {
                        case ALUA_PRIO_NOT_SUPPORTED: