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