[multipathd] remove the retry login in uev_remove_path()
[platform/upstream/multipath-tools.git] / libmultipath / dmparser.c
1 /*
2  * Copyright (c) 2004, 2005 Christophe Varoqui
3  * Copyright (c) 2005 Stefan Bader, IBM
4  * Copyright (c) 2005 Edward Goggin, EMC
5  */
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <string.h>
9
10 #include "vector.h"
11 #include "memory.h"
12 #include "structs.h"
13 #include "util.h"
14 #include "debug.h"
15
16 #define WORD_SIZE 64
17
18 static int
19 merge_words (char ** dst, char * word, int space)
20 {
21         char * p;
22         int len;
23
24         len = strlen(*dst) + strlen(word) + space;
25         *dst = REALLOC(*dst, len + 1);
26
27         if (!*dst)
28                 return 1;
29
30         p = *dst;
31
32         while (*p != '\0')
33                 p++;
34
35         while (space) {
36                 *p = ' ';
37                 p++;
38                 space--;
39         }
40         strncpy(p, word, strlen(word) + 1);
41
42         return 0;
43 }
44
45 /*
46  * Transforms the path group vector into a proper device map string
47  */
48 int
49 assemble_map (struct multipath * mp)
50 {
51         int i, j;
52         int shift, freechar;
53         int minio;
54         char * p;
55         struct pathgroup * pgp;
56         struct path * pp;
57
58         minio = mp->minio;
59         p = mp->params;
60         freechar = sizeof(mp->params);
61         
62         shift = snprintf(p, freechar, "%s %s %i %i",
63                          mp->features, mp->hwhandler,
64                          VECTOR_SIZE(mp->pg), mp->bestpg);
65
66         if (shift >= freechar) {
67                 fprintf(stderr, "mp->params too small\n");
68                 return 1;
69         }
70         p += shift;
71         freechar -= shift;
72         
73         vector_foreach_slot (mp->pg, pgp, i) {
74                 pgp = VECTOR_SLOT(mp->pg, i);
75                 shift = snprintf(p, freechar, " %s %i 1", mp->selector,
76                                  VECTOR_SIZE(pgp->paths));
77                 if (shift >= freechar) {
78                         fprintf(stderr, "mp->params too small\n");
79                         return 1;
80                 }
81                 p += shift;
82                 freechar -= shift;
83
84                 vector_foreach_slot (pgp->paths, pp, j) {
85                         if (mp->rr_weight == RR_WEIGHT_PRIO && pp->priority)
86                                 minio *= pp->priority;
87
88                         shift = snprintf(p, freechar, " %s %d",
89                                          pp->dev_t, minio);
90                         if (shift >= freechar) {
91                                 fprintf(stderr, "mp->params too small\n");
92                                 return 1;
93                         }
94                         p += shift;
95                         freechar -= shift;
96                 }
97         }
98         if (freechar < 1) {
99                 fprintf(stderr, "mp->params too small\n");
100                 return 1;
101         }
102         snprintf(p, 1, "\n");
103         return 0;
104 }
105
106 extern int
107 disassemble_map (vector pathvec, char * params, struct multipath * mpp)
108 {
109         char * word;
110         char * p;
111         int i, j, k;
112         int num_features = 0;
113         int num_hwhandler = 0;
114         int num_pg = 0;
115         int num_pg_args = 0;
116         int num_paths = 0;
117         int num_paths_args = 0;
118         struct path * pp;
119         struct pathgroup * pgp;
120
121         p = params;
122
123         /*
124          * features
125          */
126         p += get_word(p, &mpp->features);
127
128         if (!mpp->features)
129                 return 1;
130
131         num_features = atoi(mpp->features);
132
133         for (i = 0; i < num_features; i++) {
134                 p += get_word(p, &word);
135
136                 if (!word)
137                         return 1;
138
139                 if (merge_words(&mpp->features, word, 1)) {
140                         FREE(word);
141                         return 1;
142                 }
143                 FREE(word);
144         }
145
146         /*
147          * hwhandler
148          */
149         p += get_word(p, &mpp->hwhandler);
150
151         if (!mpp->hwhandler)
152                 return 1;
153
154         num_hwhandler = atoi(mpp->hwhandler);
155
156         for (i = 0; i < num_hwhandler; i++) {
157                 p += get_word(p, &word);
158
159                 if (!word)
160                         return 1;
161
162                 if (merge_words(&mpp->hwhandler, word, 1)) {
163                         FREE(word);
164                         return 1;
165                 }
166                 FREE(word);
167         }
168
169         /*
170          * nb of path groups
171          */
172         p += get_word(p, &word);
173
174         if (!word)
175                 return 1;
176
177         num_pg = atoi(word);
178         FREE(word);
179
180         if (num_pg > 0 && !mpp->pg)
181                 mpp->pg = vector_alloc();
182         
183         if (!mpp->pg)
184                 return 1;
185         /*
186          * first pg to try
187          */
188         p += get_word(p, &word);
189
190         if (!word)
191                 goto out;
192
193         mpp->nextpg = atoi(word);
194         FREE(word);
195
196         for (i = 0; i < num_pg; i++) {
197                 /*
198                  * selector
199                  */
200
201                 if (!mpp->selector) {
202                         p += get_word(p, &mpp->selector);
203
204                         if (!mpp->selector)
205                                 goto out;
206
207                         /*
208                          * selector args
209                          */
210                         p += get_word(p, &word);
211
212                         if (!word)
213                                 goto out;
214
215                         num_pg_args = atoi(word);
216                         
217                         if (merge_words(&mpp->selector, word, 1)) {
218                                 FREE(word);
219                                 goto out1;
220                         }
221                         FREE(word);
222                 } else {
223                         p += get_word(p, NULL);
224                         p += get_word(p, NULL);
225                 }
226
227                 for (j = 0; j < num_pg_args; j++)
228                         p += get_word(p, NULL);
229
230                 /*
231                  * paths
232                  */
233                 pgp = alloc_pathgroup();
234                 
235                 if (!pgp)
236                         goto out;
237
238                 if (store_pathgroup(mpp->pg, pgp))
239                         goto out;
240
241                 p += get_word(p, &word);
242
243                 if (!word)
244                         goto out;
245
246                 num_paths = atoi(word);
247                 FREE(word);
248
249                 p += get_word(p, &word);
250
251                 if (!word)
252                         goto out;
253
254                 num_paths_args = atoi(word);
255                 FREE(word);
256
257                 for (j = 0; j < num_paths; j++) {
258                         pp = NULL;
259                         p += get_word(p, &word);
260
261                         if (!word)
262                                 goto out;
263
264                         if (pathvec)
265                                 pp = find_path_by_devt(pathvec, word);
266
267                         if (!pp) {
268                                 pp = alloc_path();
269
270                                 if (!pp)
271                                         goto out1;
272
273                                 strncpy(pp->dev_t, word, BLK_DEV_SIZE);
274
275 #ifndef DAEMON
276                                 if (store_path(pathvec, pp))
277                                         goto out;
278 #endif
279                         }
280                         FREE(word);
281
282                         if (store_path(pgp->paths, pp))
283                                 goto out;
284
285                         /*
286                          * Update wwid for multipaths which are not setup
287                          * in the get_dm_mpvec() code path
288                          */
289                         if (!strlen(mpp->wwid))
290                                 strncpy(mpp->wwid, pp->wwid, WWID_SIZE);
291
292                         /*
293                          * Update wwid for paths which may not have been
294                          * active at the time the getuid callout was run
295                          */
296                         else if (!strlen(pp->wwid))
297                                 strncpy(pp->wwid, mpp->wwid, WWID_SIZE);
298
299                         pgp->id ^= (long)pp;
300                         pp->pgindex = i + 1;
301
302                         for (k = 0; k < num_paths_args; k++)
303                                 if (k == 0 && !strncmp(mpp->selector,
304                                                        "round-robin", 11)) {
305                                         p += get_word(p, &word);
306                                         mpp->minio = atoi(word);
307
308                                         if (mpp->rr_weight)
309                                                 mpp->minio /= mpp->rr_weight;
310
311                                         FREE(word);
312                                 }
313                                 else
314                                         p += get_word(p, NULL);
315
316                 }
317         }
318         return 0;
319 out1:
320         FREE(word);
321 out:
322         free_pgvec(mpp->pg, KEEP_PATHS);
323         return 1;
324 }
325
326 extern int
327 disassemble_status (char * params, struct multipath * mpp)
328 {
329         char * word;
330         char * p;
331         int i, j, k;
332         int num_feature_args;
333         int num_hwhandler_args;
334         int num_pg;
335         int num_pg_args;
336         int num_paths;
337         struct path * pp;
338         struct pathgroup * pgp;
339
340         p = params;
341
342         /*
343          * features
344          */
345         p += get_word(p, &word);
346
347         if (!word)
348                 return 1;
349
350         num_feature_args = atoi(word);
351         FREE(word);
352
353         for (i = 0; i < num_feature_args; i++) {
354                 if (i == 1) {
355                         p += get_word(p, &word);
356
357                         if (!word)
358                                 return 1;
359
360                         mpp->queuedio = atoi(word);
361                         FREE(word);
362                         continue;
363                 }
364                 /* unknown */
365                 p += get_word(p, NULL);
366         }
367         /*
368          * hwhandler
369          */
370         p += get_word(p, &word);
371
372         if (!word)
373                 return 1;
374
375         num_hwhandler_args = atoi(word);
376         FREE(word);
377
378         for (i = 0; i < num_hwhandler_args; i++)
379                 p += get_word(p, NULL);
380
381         /*
382          * nb of path groups
383          */
384         p += get_word(p, &word);
385
386         if (!word)
387                 return 1;
388
389         num_pg = atoi(word);
390         FREE(word);
391
392         /*
393          * next pg to try
394          */
395         p += get_word(p, NULL);
396
397         if (VECTOR_SIZE(mpp->pg) < num_pg)
398                 return 1;
399
400         for (i = 0; i < num_pg; i++) {
401                 pgp = VECTOR_SLOT(mpp->pg, i);
402                 /*
403                  * PG status
404                  */
405                 p += get_word(p, &word);
406
407                 if (!word)
408                         return 1;
409
410                 switch (*word) {
411                 case 'D':
412                         pgp->status = PGSTATE_DISABLED;
413                         break;
414                 case 'A':
415                         pgp->status = PGSTATE_ACTIVE;
416                         break;
417                 case 'E':
418                         pgp->status = PGSTATE_ENABLED;
419                         break;
420                 default:
421                         pgp->status = PGSTATE_UNDEF;
422                         break;
423                 }
424                 FREE(word);
425
426                 /*
427                  * undef ?
428                  */
429                 p += get_word(p, NULL);
430
431                 p += get_word(p, &word);
432
433                 if (!word)
434                         return 1;
435
436                 num_paths = atoi(word);
437                 FREE(word);
438
439                 p += get_word(p, &word);
440
441                 if (!word)
442                         return 1;
443
444                 num_pg_args = atoi(word);
445                 FREE(word);
446
447                 if (VECTOR_SIZE(pgp->paths) < num_paths)
448                         return 1;
449
450                 for (j = 0; j < num_paths; j++) {
451                         pp = VECTOR_SLOT(pgp->paths, j);
452                         /*
453                          * path
454                          */
455                         p += get_word(p, NULL);
456
457                         /*
458                          * path status
459                          */
460                         p += get_word(p, &word);
461
462                         if (!word)
463                                 return 1;
464
465                         switch (*word) {
466                         case 'F':
467                                 pp->dmstate = PSTATE_FAILED;
468                                 break;
469                         case 'A':
470                                 pp->dmstate = PSTATE_ACTIVE;
471                                 break;
472                         default:
473                                 break;
474                         }
475                         FREE(word);
476                         /*
477                          * fail count
478                          */
479                         p += get_word(p, &word);
480
481                         if (!word)
482                                 return 1;
483
484                         pp->failcount = atoi(word);
485                         FREE(word);
486
487                         /*
488                          * selector args
489                          */
490                         for (k = 0; k < num_pg_args; k++)
491                                 p += get_word(p, NULL);
492                 }
493         }
494         return 0;
495 }