Initial git import.
[multipath-tools/.git] / libmultipath / pgpolicies.c
1 /*
2  * Here we define the path grouping policies
3  */
4 #include <stdio.h>
5 #include <stdlib.h>
6 #include <string.h>
7
8 #include "util.h"
9 #include "memory.h"
10 #include "vector.h"
11 #include "structs.h"
12 #include "pgpolicies.h"
13
14 #include "../libcheckers/path_state.h"
15
16 extern int
17 get_pgpolicy_id (char * str)
18 {
19         if (0 == strncmp(str, "failover", 8))
20                 return FAILOVER;
21         if (0 == strncmp(str, "multibus", 8))
22                 return MULTIBUS;
23         if (0 == strncmp(str, "group_by_serial", 15))
24                 return GROUP_BY_SERIAL;
25         if (0 == strncmp(str, "group_by_prio", 13))
26                 return GROUP_BY_PRIO;
27         if (0 == strncmp(str, "group_by_node_name", 18))
28                 return GROUP_BY_NODE_NAME;
29
30         return -1;
31 }
32
33 extern void
34 get_pgpolicy_name (char * buff, int id)
35 {
36         char * s;
37
38         switch (id) {
39         case FAILOVER:
40                 s = "failover";
41                 break;
42         case MULTIBUS:
43                 s = "multibus";
44                 break;
45         case GROUP_BY_SERIAL:
46                 s = "group_by_serial";
47                 break;
48         case GROUP_BY_PRIO:
49                 s = "group_by_prio";
50                 break;
51         case GROUP_BY_NODE_NAME:
52                 s = "group_by_node_name";
53                 break;
54         default:
55                 s = "undefined";
56                 break;
57         }
58         if(safe_snprintf(buff, POLICY_NAME_SIZE, "%s", s)) {
59                 fprintf(stderr, "get_pgpolicy_name: buff too small\n");
60                 exit(1);
61         }
62 }
63
64 /*
65  * One path group per unique tgt_node_name present in the path vector
66  */
67 extern int
68 group_by_node_name (struct multipath * mp) {
69         int i, j;
70         int * bitmap;
71         struct path * pp;
72         struct pathgroup * pgp;
73         struct path * pp2;
74         
75         if (!mp->pg)
76                 mp->pg = vector_alloc();
77
78         if (!mp->pg)
79                 return 1;
80
81         /* init the bitmap */
82         bitmap = (int *)MALLOC(VECTOR_SIZE(mp->paths) * sizeof (int));
83
84         if (!bitmap)
85                 goto out;
86
87         for (i = 0; i < VECTOR_SIZE(mp->paths); i++) {
88
89                 if (bitmap[i])
90                         continue;
91
92                 pp = VECTOR_SLOT(mp->paths, i);
93
94                 /* here, we really got a new pg */
95                 pgp = alloc_pathgroup();
96
97                 if (!pgp)
98                         goto out1;
99
100                 if (store_pathgroup(mp->pg, pgp))
101                         goto out1;
102
103                 /* feed the first path */
104                 if (store_path(pgp->paths, pp))
105                         goto out1;
106
107                 bitmap[i] = 1;
108
109                 for (j = i + 1; j < VECTOR_SIZE(mp->paths); j++) {
110                         
111                         if (bitmap[j])
112                                 continue;
113
114                         pp2 = VECTOR_SLOT(mp->paths, j);
115                         
116                         if (!strncmp(pp->tgt_node_name, pp2->tgt_node_name,
117                                         NODE_NAME_SIZE)) {
118                                 if (store_path(pgp->paths, pp2))
119                                         goto out1;
120
121                                 bitmap[j] = 1;
122                         }
123                 }
124         }
125         FREE(bitmap);
126         free_pathvec(mp->paths, KEEP_PATHS);
127         mp->paths = NULL;
128         return 0;
129 out1:
130         FREE(bitmap);
131 out:
132         free_pgvec(mp->pg, KEEP_PATHS);
133         return 1;
134 }
135
136 /*
137  * One path group per unique serial number present in the path vector
138  */
139 extern int
140 group_by_serial (struct multipath * mp) {
141         int i, j;
142         int * bitmap;
143         struct path * pp;
144         struct pathgroup * pgp;
145         struct path * pp2;
146         
147         if (!mp->pg)
148                 mp->pg = vector_alloc();
149
150         if (!mp->pg)
151                 return 1;
152
153         /* init the bitmap */
154         bitmap = (int *)MALLOC(VECTOR_SIZE(mp->paths) * sizeof (int));
155
156         if (!bitmap)
157                 goto out;
158
159         for (i = 0; i < VECTOR_SIZE(mp->paths); i++) {
160
161                 if (bitmap[i])
162                         continue;
163
164                 pp = VECTOR_SLOT(mp->paths, i);
165
166                 /* here, we really got a new pg */
167                 pgp = alloc_pathgroup();
168
169                 if (!pgp)
170                         goto out1;
171
172                 if (store_pathgroup(mp->pg, pgp))
173                         goto out1;
174
175                 /* feed the first path */
176                 if (store_path(pgp->paths, pp))
177                         goto out1;
178                                 
179                 bitmap[i] = 1;
180
181                 for (j = i + 1; j < VECTOR_SIZE(mp->paths); j++) {
182                         
183                         if (bitmap[j])
184                                 continue;
185
186                         pp2 = VECTOR_SLOT(mp->paths, j);
187                         
188                         if (0 == strcmp(pp->serial, pp2->serial)) {
189                                 if (store_path(pgp->paths, pp2))
190                                         goto out1;
191
192                                 bitmap[j] = 1;
193                         }
194                 }
195         }
196         FREE(bitmap);
197         free_pathvec(mp->paths, KEEP_PATHS);
198         mp->paths = NULL;
199         return 0;
200 out1:
201         FREE(bitmap);
202 out:
203         free_pgvec(mp->pg, KEEP_PATHS);
204         return 1;
205 }
206
207 extern int
208 one_path_per_group (struct multipath * mp)
209 {
210         int i;
211         struct path * pp;
212         struct pathgroup * pgp;
213
214         if (!mp->pg)
215                 mp->pg = vector_alloc();
216         
217         if (!mp->pg)
218                 return 1;
219
220         for (i = 0; i < VECTOR_SIZE(mp->paths); i++) {
221                 pp = VECTOR_SLOT(mp->paths, i);
222                 pgp = alloc_pathgroup();
223
224                 if (!pgp)
225                         goto out;
226
227                 if (store_pathgroup(mp->pg, pgp))
228                         goto out;
229                 
230                 if (store_path(pgp->paths, pp))
231                         goto out;
232         }
233         free_pathvec(mp->paths, KEEP_PATHS);
234         mp->paths = NULL;
235         return 0;
236 out:
237         free_pgvec(mp->pg, KEEP_PATHS);
238         return 1;
239 }
240
241 extern int
242 one_group (struct multipath * mp)       /* aka multibus */
243 {
244         struct pathgroup * pgp;
245
246         if (VECTOR_SIZE(pgp->paths) < 0)
247                 return 0;
248
249         if (!mp->pg)
250                 mp->pg = vector_alloc();
251
252         if (!mp->pg)
253                 return 1;
254
255         pgp = alloc_pathgroup();
256         
257         if (!pgp)
258                 goto out;
259         
260         vector_free(pgp->paths);
261         pgp->paths = mp->paths;
262         mp->paths = NULL;
263
264         if (store_pathgroup(mp->pg, pgp))
265                 goto out;
266
267         return 0;
268 out:
269         free_pgvec(mp->pg, KEEP_PATHS);
270         return 1;
271 }
272
273 extern int
274 group_by_prio (struct multipath * mp)
275 {
276         int i;
277         unsigned int prio;
278         struct path * pp;
279         struct pathgroup * pgp;
280
281         if (!mp->pg)
282                 mp->pg = vector_alloc();
283
284         if (!mp->pg)
285                 return 1;
286
287         while (VECTOR_SIZE(mp->paths) > 0) {
288                 pp = VECTOR_SLOT(mp->paths, 0);
289                 prio = pp->priority;
290
291                 /*
292                  * Find the position to insert the new path group. All groups
293                  * are ordered by the priority value (higher value first).
294                  */
295                 vector_foreach_slot(mp->pg, pgp, i) {
296                         pp  = VECTOR_SLOT(pgp->paths, 0);
297
298                         if (prio > pp->priority)
299                                 break;
300                 }
301
302                 /*
303                  * Initialize the new path group.
304                  */
305                 pgp = alloc_pathgroup();
306
307                 if (!pgp)
308                         goto out;
309                 
310                 if (store_path(pgp->paths, VECTOR_SLOT(mp->paths, 0)))
311                                 goto out;
312
313                 vector_del_slot(mp->paths, 0);
314
315                 /*
316                  * Store the new path group into the vector.
317                  */
318                 if (i < VECTOR_SIZE(mp->pg)) {
319                         if (!vector_insert_slot(mp->pg, i, pgp))
320                                 goto out;
321                 } else {
322                         if (store_pathgroup(mp->pg, pgp))
323                                 goto out;
324                 }
325
326                 /*
327                  * add the other paths with the same prio
328                  */
329                 vector_foreach_slot(mp->paths, pp, i) {
330                         if (pp->priority == prio) {
331                                 if (store_path(pgp->paths, pp))
332                                         goto out;
333
334                                 vector_del_slot(mp->paths, i);
335                                 i--;
336                         }
337                 }
338         }
339         free_pathvec(mp->paths, KEEP_PATHS);
340         mp->paths = NULL;
341         return 0;
342 out:
343         free_pgvec(mp->pg, KEEP_PATHS);
344         return 1;
345
346 }