Imported Upstream version 0.6.3
[platform/upstream/multipath-tools.git] / libmultipath / prioritizers / weightedpath.c
1 /*
2  *
3  *  (C)  Copyright 2008 Hewlett-Packard Development Company, L.P
4  *
5  *  This file is released under the GPL
6  */
7
8 /*
9  * Prioritizer for device mapper multipath, where specific paths and the
10  * corresponding priority values are provided as arguments.
11  *
12  * This prioritizer assigns the priority value provided in the configuration
13  * file based on the comparison made between the specified paths and the path
14  * instance for which this is called.
15  * Paths can be specified as a regular expression of devname of the path or
16  * as hbtl information of the path.
17  *
18  * Examples:
19  *      prio            "weightedpath hbtl 1:.:.:. 2 4:.:.:. 4"
20  *      prio            "weightedpath devname sda 10 sde 20"
21  *
22  * Returns zero as the default priority.
23  */
24
25 #include <stdio.h>
26 #include <string.h>
27
28 #include "prio.h"
29 #include "weightedpath.h"
30 #include "config.h"
31 #include "structs.h"
32 #include "memory.h"
33 #include "debug.h"
34 #include <regex.h>
35 #include "structs_vec.h"
36 #include "print.h"
37
38 char *get_next_string(char **temp, char *split_char)
39 {
40         char *token = NULL;
41         token = strsep(temp, split_char);
42         while (token != NULL && !strcmp(token, ""))
43                 token = strsep(temp, split_char);
44         return token;
45 }
46
47 #define CHECK_LEN \
48 do { \
49         if ((p - str) >= (len - 1)) { \
50                 condlog(0, "%s: %s - buffer size too small", pp->dev, pp->prio.name); \
51                 return -1; \
52         } \
53 } while(0)
54
55 static int
56 build_serial_path(struct path *pp, char *str, int len)
57 {
58         char *p = str;
59
60         p += snprint_path_serial(p, str + len - p, pp);
61         CHECK_LEN;
62         return 0;
63 }
64
65 static int
66 build_wwn_path(struct path *pp, char *str, int len)
67 {
68         char *p = str;
69
70         p += snprint_host_wwnn(p, str + len - p, pp);
71         CHECK_LEN;
72         p += snprintf(p, str + len - p, ":");
73         CHECK_LEN;
74         p += snprint_host_wwpn(p, str + len - p, pp);
75         CHECK_LEN;
76         p += snprintf(p, str + len - p, ":");
77         CHECK_LEN;
78         p += snprint_tgt_wwnn(p, str + len - p, pp);
79         CHECK_LEN;
80         p += snprintf(p, str + len - p, ":");
81         CHECK_LEN;
82         p += snprint_tgt_wwpn(p, str + len - p, pp);
83         CHECK_LEN;
84         return 0;
85 }
86
87 /* main priority routine */
88 int prio_path_weight(struct path *pp, char *prio_args)
89 {
90         char path[FILE_NAME_SIZE];
91         char *arg;
92         char *temp, *regex, *prio;
93         char split_char[] = " \t";
94         int priority = DEFAULT_PRIORITY, path_found = 0;
95         regex_t pathe;
96
97         /* Return default priority if there is no argument */
98         if (!prio_args)
99                 return priority;
100
101         arg = temp = STRDUP(prio_args);
102
103         regex = get_next_string(&temp, split_char);
104
105         /* Return default priority if the argument is not parseable */
106         if (!regex) {
107                 FREE(arg);
108                 return priority;
109         }
110
111         if (!strcmp(regex, HBTL)) {
112                 sprintf(path, "%d:%d:%d:%d", pp->sg_id.host_no,
113                         pp->sg_id.channel, pp->sg_id.scsi_id, pp->sg_id.lun);
114         } else if (!strcmp(regex, DEV_NAME)) {
115                 strcpy(path, pp->dev);
116         } else if (!strcmp(regex, SERIAL)) {
117                 if (build_serial_path(pp, path, FILE_NAME_SIZE) != 0) {
118                         FREE(arg);
119                         return priority;
120                 }
121         } else if (!strcmp(regex, WWN)) {
122                 if (build_wwn_path(pp, path, FILE_NAME_SIZE) != 0) {
123                         FREE(arg);
124                         return priority;
125                 }
126         } else {
127                 condlog(0, "%s: %s - Invalid arguments", pp->dev,
128                         pp->prio.name);
129                 FREE(arg);
130                 return priority;
131         }
132
133         while (!path_found) {
134                 if (!temp)
135                         break;
136                 if (!(regex = get_next_string(&temp, split_char)))
137                         break;
138                 if (!(prio = get_next_string(&temp, split_char)))
139                         break;
140
141                 if (!regcomp(&pathe, regex, REG_EXTENDED|REG_NOSUB)) {
142                         if (!regexec(&pathe, path, 0, NULL, 0)) {
143                                 path_found = 1;
144                                 priority = atoi(prio);
145                         }
146                         regfree(&pathe);
147                 }
148         }
149
150         FREE(arg);
151         return priority;
152 }
153
154 int getprio(struct path *pp, char *args)
155 {
156         return prio_path_weight(pp, args);
157 }