Fix error
[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 "debug.h"
33 #include <regex.h>
34 #include "structs_vec.h"
35 #include "print.h"
36 #include "util.h"
37 #include "strbuf.h"
38
39 static int
40 build_serial_path(struct path *pp, struct strbuf *buf)
41 {
42         int rc = snprint_path_serial(buf, pp);
43
44         return rc < 0 ? rc : 0;
45 }
46
47 static int
48 build_wwn_path(struct path *pp, struct strbuf *buf)
49 {
50         int rc;
51
52         if ((rc = snprint_host_wwnn(buf, pp)) < 0 ||
53             (rc = fill_strbuf(buf, ':', 1)) < 0 ||
54             (rc = snprint_host_wwpn(buf, pp)) < 0 ||
55             (rc = fill_strbuf(buf, ':', 1)) < 0 ||
56             (rc = snprint_tgt_wwnn(buf, pp) < 0) ||
57             (rc = fill_strbuf(buf, ':', 1) < 0) ||
58             (rc = snprint_tgt_wwpn(buf, pp) < 0))
59                 return rc;
60         return 0;
61 }
62
63 /* main priority routine */
64 int prio_path_weight(struct path *pp, char *prio_args)
65 {
66         STRBUF_ON_STACK(path);
67         char *arg __attribute__((cleanup(cleanup_charp))) = NULL;
68         char *temp, *regex, *prio;
69         char split_char[] = " \t";
70         int priority = DEFAULT_PRIORITY, path_found = 0;
71         regex_t pathe;
72
73         /* Return default priority if there is no argument */
74         if (!prio_args)
75                 return priority;
76
77         arg = strdup(prio_args);
78         temp = arg;
79
80         regex = get_next_string(&temp, split_char);
81
82         /* Return default priority if the argument is not parseable */
83         if (!regex) {
84                 return priority;
85         }
86
87         if (!strcmp(regex, HBTL)) {
88                 if (print_strbuf(&path, "%d:%d:%d:%" PRIu64, pp->sg_id.host_no,
89                                  pp->sg_id.channel, pp->sg_id.scsi_id,
90                                  pp->sg_id.lun) < 0)
91                         return priority;
92         } else if (!strcmp(regex, DEV_NAME)) {
93                 if (append_strbuf_str(&path, pp->dev) < 0)
94                         return priority;
95         } else if (!strcmp(regex, SERIAL)) {
96                 if (build_serial_path(pp, &path) != 0)
97                         return priority;
98         } else if (!strcmp(regex, WWN)) {
99                 if (build_wwn_path(pp, &path) != 0)
100                         return priority;
101         } else {
102                 condlog(0, "%s: %s - Invalid arguments", pp->dev,
103                         pp->prio.name);
104                 return priority;
105         }
106
107         while (!path_found) {
108                 if (!temp)
109                         break;
110                 if (!(regex = get_next_string(&temp, split_char)))
111                         break;
112                 if (!(prio = get_next_string(&temp, split_char)))
113                         break;
114
115                 if (!regcomp(&pathe, regex, REG_EXTENDED|REG_NOSUB)) {
116                         if (!regexec(&pathe, get_strbuf_str(&path), 0,
117                                      NULL, 0)) {
118                                 path_found = 1;
119                                 priority = atoi(prio);
120                         }
121                         regfree(&pathe);
122                 }
123         }
124
125         return priority;
126 }
127
128 int getprio(struct path *pp, char *args)
129 {
130         return prio_path_weight(pp, args);
131 }