alua: Handle LBA_DEPENDENT state
[multipath-tools/.git] / libmultipath / prioritizers / alua.c
1 /*
2  * (C) Copyright IBM Corp. 2004, 2005   All Rights Reserved.
3  *
4  * main.c
5  *
6  * Tool to make use of a SCSI-feature called Asymmetric Logical Unit Access.
7  * It determines the ALUA state of a device and prints a priority value to
8  * stdout.
9  *
10  * Author(s): Jan Kunigk
11  *            S. Bader <shbader@de.ibm.com>
12  * 
13  * This file is released under the GPL.
14  */
15 #include <stdio.h>
16
17 #include <debug.h>
18 #include <prio.h>
19
20 #include "alua.h"
21
22 #define ALUA_PRIO_NOT_SUPPORTED                 1
23 #define ALUA_PRIO_RTPG_FAILED                   2
24 #define ALUA_PRIO_GETAAS_FAILED                 3
25 #define ALUA_PRIO_TPGS_FAILED                   4
26 #define ALUA_PRIO_NO_INFORMATION                5
27
28 static const char * aas_string[] = {
29         [AAS_OPTIMIZED]         = "active/optimized",
30         [AAS_NON_OPTIMIZED]     = "active/non-optimized",
31         [AAS_STANDBY]           = "standby",
32         [AAS_UNAVAILABLE]       = "unavailable",
33         [AAS_LBA_DEPENDENT]     = "lba dependent",
34         [AAS_RESERVED]          = "invalid/reserved",
35         [AAS_OFFLINE]           = "offline",
36         [AAS_TRANSITIONING]     = "transitioning between states",
37 };
38
39 static const char *aas_print_string(int rc)
40 {
41         rc &= 0x7f;
42
43         if (rc & 0x70)
44                 return aas_string[AAS_RESERVED];
45         rc &= 0x0f;
46         if (rc > AAS_RESERVED && rc < AAS_OFFLINE)
47                 return aas_string[AAS_RESERVED];
48         else
49                 return aas_string[rc];
50 }
51
52 int
53 get_alua_info(int fd)
54 {
55         int     rc;
56         int     tpg;
57         int     aas;
58
59         rc = get_target_port_group_support(fd);
60         if (rc < 0)
61                 return -ALUA_PRIO_TPGS_FAILED;
62
63         if (rc == TPGS_NONE)
64                 return -ALUA_PRIO_NOT_SUPPORTED;
65
66         tpg = get_target_port_group(fd);
67         if (tpg < 0)
68                 return -ALUA_PRIO_RTPG_FAILED;
69
70         condlog(3, "reported target port group is %i", tpg);
71         rc = get_asymmetric_access_state(fd, tpg);
72         if (rc < 0)
73                 return -ALUA_PRIO_GETAAS_FAILED;
74         aas = (rc & 0x0f);
75
76         condlog(3, "aas = %02x [%s]%s", rc, aas_print_string(rc),
77                 (rc & 0x80) ? " [preferred]" : "");
78         return rc;
79 }
80
81 int getprio (struct path * pp, char * args)
82 {
83         int rc;
84         int aas;
85         int priopath;
86
87         if (pp->fd < 0)
88                 return -ALUA_PRIO_NO_INFORMATION;
89
90         rc = get_alua_info(pp->fd);
91         if (rc >= 0) {
92                 aas = (rc & 0x0f);
93                 priopath = (rc & 0x80);
94                 switch(aas) {
95                         case AAS_OPTIMIZED:
96                                 rc = 50;
97                                 break;
98                         case AAS_NON_OPTIMIZED:
99                                 rc = 10;
100                                 break;
101                         case AAS_LBA_DEPENDENT:
102                                 rc = 5;
103                                 break;
104                         case AAS_STANDBY:
105                                 rc = 1;
106                                 break;
107                         default:
108                                 rc = 0;
109                 }
110                 if (priopath)
111                         rc += 80;
112         } else {
113                 switch(-rc) {
114                         case ALUA_PRIO_NOT_SUPPORTED:
115                                 condlog(0, "%s: alua not supported", pp->dev);
116                                 break;
117                         case ALUA_PRIO_RTPG_FAILED:
118                                 condlog(0, "%s: couldn't get target port group", pp->dev);
119                                 break;
120                         case ALUA_PRIO_GETAAS_FAILED:
121                                 condlog(0, "%s: couln't get asymmetric access state", pp->dev);
122                                 break;
123                         case ALUA_PRIO_TPGS_FAILED:
124                                 condlog(3, "%s: couln't get supported alua states", pp->dev);
125                                 break;
126                 }
127         }
128         return rc;
129 }