e33e17c931cebe56c3908e124bac65eadcee0387
[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 int
29 get_alua_info(int fd)
30 {
31         char *  aas_string[] = {
32                 [AAS_OPTIMIZED]         = "active/optimized",
33                 [AAS_NON_OPTIMIZED]     = "active/non-optimized",
34                 [AAS_STANDBY]           = "standby",
35                 [AAS_UNAVAILABLE]       = "unavailable",
36                 [AAS_TRANSITIONING]     = "transitioning between states",
37         };
38         int     rc;
39         int     tpg;
40         int     aas;
41
42         rc = get_target_port_group_support(fd);
43         if (rc < 0)
44                 return -ALUA_PRIO_TPGS_FAILED;
45
46         if (rc == TPGS_NONE)
47                 return -ALUA_PRIO_NOT_SUPPORTED;
48
49         tpg = get_target_port_group(fd);
50         if (tpg < 0)
51                 return -ALUA_PRIO_RTPG_FAILED;
52
53         condlog(3, "reported target port group is %i", tpg);
54         rc = get_asymmetric_access_state(fd, tpg);
55         if (rc < 0)
56                 return -ALUA_PRIO_GETAAS_FAILED;
57         aas = (rc & 0x0f);
58
59         condlog(3, "aas = [%s]",
60                 (aas < 4) ? aas_string[aas] : "invalid/reserved");
61         return rc;
62 }
63
64 int getprio (struct path * pp, char * args)
65 {
66         int rc;
67         int aas;
68         int priopath;
69
70         if (pp->fd < 0)
71                 return -ALUA_PRIO_NO_INFORMATION;
72
73         rc = get_alua_info(pp->fd);
74         if (rc >= 0) {
75                 aas = (rc & 0x0f);
76                 priopath = (rc & 0x80);
77                 switch(aas) {
78                         case AAS_OPTIMIZED:
79                                 rc = 50;
80                                 break;
81                         case AAS_NON_OPTIMIZED:
82                                 rc = 10;
83                                 break;
84                         case AAS_STANDBY:
85                                 rc = 1;
86                                 break;
87                         default:
88                                 rc = 0;
89                 }
90                 if (priopath)
91                         rc += 80;
92         } else {
93                 switch(-rc) {
94                         case ALUA_PRIO_NOT_SUPPORTED:
95                                 condlog(0, "%s: alua not supported", pp->dev);
96                                 break;
97                         case ALUA_PRIO_RTPG_FAILED:
98                                 condlog(0, "%s: couldn't get target port group", pp->dev);
99                                 break;
100                         case ALUA_PRIO_GETAAS_FAILED:
101                                 condlog(0, "%s: couln't get asymmetric access state", pp->dev);
102                                 break;
103                         case ALUA_PRIO_TPGS_FAILED:
104                                 condlog(3, "%s: couln't get supported alua states", pp->dev);
105                                 break;
106                 }
107         }
108         return rc;
109 }