dc26f305cceff6262b33a011c7413214282705ba
[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_wwn_path(struct path *pp, char *str, int len)
57 {
58         char *p = str;
59
60         p += snprint_host_wwnn(p, str + len - p, pp);
61         CHECK_LEN;
62         p += snprintf(p, str + len - p, ":");
63         CHECK_LEN;
64         p += snprint_host_wwpn(p, str + len - p, pp);
65         CHECK_LEN;
66         p += snprintf(p, str + len - p, ":");
67         CHECK_LEN;
68         p += snprint_tgt_wwnn(p, str + len - p, pp);
69         CHECK_LEN;
70         p += snprintf(p, str + len - p, ":");
71         CHECK_LEN;
72         p += snprint_tgt_wwpn(p, str + len - p, pp);
73         CHECK_LEN;
74         return 0;
75 }
76
77 /* main priority routine */
78 int prio_path_weight(struct path *pp, char *prio_args)
79 {
80         char path[FILE_NAME_SIZE];
81         char *arg;
82         char *temp, *regex, *prio;
83         char split_char[] = " \t";
84         int priority = DEFAULT_PRIORITY, path_found = 0;
85         regex_t pathe;
86
87         /* Return default priority if there is no argument */
88         if (!prio_args)
89                 return priority;
90
91         arg = temp = STRDUP(prio_args);
92
93         regex = get_next_string(&temp, split_char);
94
95         /* Return default priority if the argument is not parseable */
96         if (!regex) {
97                 FREE(arg);
98                 return priority;
99         }
100
101         if (!strcmp(regex, HBTL)) {
102                 sprintf(path, "%d:%d:%d:%d", pp->sg_id.host_no,
103                         pp->sg_id.channel, pp->sg_id.scsi_id, pp->sg_id.lun);
104         } else if (!strcmp(regex, DEV_NAME)) {
105                 strcpy(path, pp->dev);
106         } else if (!strcmp(regex, WWN)) {
107                 if (build_wwn_path(pp, path, FILE_NAME_SIZE) != 0) {
108                         FREE(arg);
109                         return priority;
110                 }
111         } else {
112                 condlog(0, "%s: %s - Invalid arguments", pp->dev,
113                         pp->prio.name);
114                 FREE(arg);
115                 return priority;
116         }
117
118         while (!path_found) {
119                 if (!temp)
120                         break;
121                 if (!(regex = get_next_string(&temp, split_char)))
122                         break;
123                 if (!(prio = get_next_string(&temp, split_char)))
124                         break;
125
126                 if (!regcomp(&pathe, regex, REG_EXTENDED|REG_NOSUB)) {
127                         if (!regexec(&pathe, path, 0, NULL, 0)) {
128                                 path_found = 1;
129                                 priority = atoi(prio);
130                         }
131                         regfree(&pathe);
132                 }
133         }
134
135         FREE(arg);
136         return priority;
137 }
138
139 int getprio(struct path *pp, char *args)
140 {
141         return prio_path_weight(pp, args);
142 }