[libmultipath] print the multipath strings in "show topo"
[platform/upstream/multipath-tools.git] / libmultipath / structs.c
1 /*
2  * Copyright (c) 2004, 2005 Christophe Varoqui
3  * Copyright (c) 2004 Stefan Bader, IBM
4  */
5 #include <stdio.h>
6 #include <unistd.h>
7 #include <libdevmapper.h>
8
9 #include <checkers.h>
10
11 #include "memory.h"
12 #include "vector.h"
13 #include "util.h"
14 #include "structs.h"
15 #include "config.h"
16 #include "debug.h"
17 #include "structs_vec.h"
18 #include "blacklist.h"
19 #include "waiter.h"
20
21 struct path *
22 alloc_path (void)
23 {
24         struct path * pp;
25         
26         pp = (struct path *)MALLOC(sizeof(struct path));
27
28         if (pp) {
29                 pp->sg_id.host_no = -1;
30                 pp->sg_id.channel = -1;
31                 pp->sg_id.scsi_id = -1;
32                 pp->sg_id.lun = -1;
33                 pp->fd = -1;
34         }
35         return pp;
36 }
37
38 void
39 free_path (struct path * pp)
40 {
41         if (!pp)
42                 return;
43
44         if (checker_selected(&pp->checker))
45                 checker_put(&pp->checker);
46
47         if (pp->fd >= 0)
48                 close(pp->fd);
49
50         FREE(pp);
51 }
52
53 void
54 free_pathvec (vector vec, int free_paths)
55 {
56         int i;
57         struct path * pp;
58
59         if (!vec)
60                 return;
61
62         if (free_paths)
63                 vector_foreach_slot(vec, pp, i)
64                         free_path(pp);
65
66         vector_free(vec);
67 }
68
69 struct pathgroup *
70 alloc_pathgroup (void)
71 {
72         struct pathgroup * pgp;
73
74         pgp = (struct pathgroup *)MALLOC(sizeof(struct pathgroup));
75
76         if (!pgp)
77                 return NULL;
78
79         pgp->paths = vector_alloc();
80
81         if (!pgp->paths)
82                 FREE(pgp);
83
84         return pgp;
85 }
86
87 void
88 free_pathgroup (struct pathgroup * pgp, int free_paths)
89 {
90         if (!pgp)
91                 return;
92
93         free_pathvec(pgp->paths, free_paths);
94         FREE(pgp);
95 }
96
97 void
98 free_pgvec (vector pgvec, int free_paths)
99 {
100         int i;
101         struct pathgroup * pgp;
102
103         if (!pgvec)
104                 return;
105
106         vector_foreach_slot(pgvec, pgp, i)
107                 free_pathgroup(pgp, free_paths);
108
109         vector_free(pgvec);
110 }
111
112 struct multipath *
113 alloc_multipath (void)
114 {
115         struct multipath * mpp;
116
117         mpp = (struct multipath *)MALLOC(sizeof(struct multipath));
118
119         if (mpp)
120                 mpp->bestpg = 1;
121
122         return mpp;
123 }
124
125 extern void
126 free_multipath_attributes (struct multipath * mpp)
127 {
128         if (!mpp)
129                 return;
130
131         if (mpp->selector &&
132             mpp->selector != conf->selector &&
133             (!mpp->mpe || (mpp->mpe && mpp->selector != mpp->mpe->selector)) &&
134             (!mpp->hwe || (mpp->hwe && mpp->selector != mpp->hwe->selector))) {
135                 FREE(mpp->selector);
136                 mpp->selector = NULL;
137         }
138
139         if (mpp->features &&
140             mpp->features != conf->features &&
141             (!mpp->hwe || (mpp->hwe && mpp->features != mpp->hwe->features))) {
142                 FREE(mpp->features);
143                 mpp->features = NULL;
144         }
145
146         if (mpp->hwhandler &&
147             mpp->hwhandler != conf->hwhandler &&
148             (!mpp->hwe || (mpp->hwe && mpp->hwhandler != mpp->hwe->hwhandler))) {
149                 FREE(mpp->hwhandler);
150                 mpp->hwhandler = NULL;
151         }
152 }
153
154 void
155 free_multipath (struct multipath * mpp, int free_paths)
156 {
157         if (!mpp)
158                 return;
159
160         free_multipath_attributes(mpp);
161
162         if (mpp->alias &&
163             (!mpp->mpe || (mpp->mpe && mpp->alias != mpp->mpe->alias)) &&
164             (mpp->wwid && mpp->alias != mpp->wwid)) {
165                 FREE(mpp->alias);
166                 mpp->alias = NULL;
167         }
168
169         if (mpp->dmi)
170                 FREE(mpp->dmi);
171         
172 #if DAEMON
173         /*
174          * better own vecs->lock here
175          */
176         if (mpp->waiter)
177                 ((struct event_thread *)mpp->waiter)->mpp = NULL;
178 #endif
179
180         free_pathvec(mpp->paths, free_paths);
181         free_pgvec(mpp->pg, free_paths);
182         FREE(mpp);
183 }
184
185 void
186 drop_multipath (vector mpvec, char * wwid, int free_paths)
187 {
188         int i;
189         struct multipath * mpp;
190
191         if (!mpvec)
192                 return;
193
194         vector_foreach_slot (mpvec, mpp, i) {
195                 if (!strncmp(mpp->wwid, wwid, WWID_SIZE)) {
196                         free_multipath(mpp, free_paths);
197                         vector_del_slot(mpvec, i);
198                         return;
199                 }
200         }
201 }
202
203 void
204 free_multipathvec (vector mpvec, int free_paths)
205 {
206         int i;
207         struct multipath * mpp;
208
209         if (!mpvec)
210                 return;
211
212         vector_foreach_slot (mpvec, mpp, i)
213                 free_multipath(mpp, free_paths);
214
215         vector_free(mpvec);
216 }
217
218 int
219 store_path (vector pathvec, struct path * pp)
220 {
221         if (!vector_alloc_slot(pathvec))
222                 return 1;
223
224         vector_set_slot(pathvec, pp);
225
226         return 0;
227 }
228
229 int
230 store_pathgroup (vector pgvec, struct pathgroup * pgp)
231 {
232         if (!vector_alloc_slot(pgvec))
233                 return 1;
234
235         vector_set_slot(pgvec, pgp);
236
237         return 0;
238 }
239
240 struct multipath *
241 find_mp_by_minor (vector mpvec, int minor)
242 {
243         int i;
244         struct multipath * mpp;
245         
246         if (!mpvec)
247                 return NULL;
248
249         vector_foreach_slot (mpvec, mpp, i) {
250                 if (!mpp->dmi)
251                         continue;
252
253                 if (mpp->dmi->minor == minor)
254                         return mpp;
255         }
256         return NULL;
257 }
258
259 struct multipath *
260 find_mp_by_wwid (vector mpvec, char * wwid)
261 {
262         int i;
263         struct multipath * mpp;
264         
265         if (!mpvec)
266                 return NULL;
267
268         vector_foreach_slot (mpvec, mpp, i)
269                 if (!strncmp(mpp->wwid, wwid, WWID_SIZE))
270                         return mpp;
271
272         return NULL;
273 }
274
275 struct multipath *
276 find_mp_by_alias (vector mpvec, char * alias)
277 {
278         int i;
279         int len;
280         struct multipath * mpp;
281         
282         if (!mpvec)
283                 return NULL;
284
285         len = strlen(alias);
286
287         if (!len)
288                 return NULL;
289         
290         vector_foreach_slot (mpvec, mpp, i) {
291                 if (strlen(mpp->alias) == len &&
292                     !strncmp(mpp->alias, alias, len))
293                         return mpp;
294         }
295         return NULL;
296 }
297
298 struct multipath *
299 find_mp_by_str (vector mpvec, char * str)
300 {
301         int minor;
302
303         if (sscanf(str, "dm-%d", &minor) == 1)
304                 return find_mp_by_minor(mpvec, minor);
305         else
306                 return find_mp_by_alias(mpvec, str);
307 }
308
309 struct path *
310 find_path_by_dev (vector pathvec, char * dev)
311 {
312         int i;
313         struct path * pp;
314
315         if (!pathvec)
316                 return NULL;
317         
318         vector_foreach_slot (pathvec, pp, i)
319                 if (!strcmp_chomp(pp->dev, dev))
320                         return pp;
321
322         condlog(3, "%s: not found in pathvec", dev);
323         return NULL;
324 }
325
326 struct path *
327 find_path_by_devt (vector pathvec, char * dev_t)
328 {
329         int i;
330         struct path * pp;
331
332         if (!pathvec)
333                 return NULL;
334
335         vector_foreach_slot (pathvec, pp, i)
336                 if (!strcmp_chomp(pp->dev_t, dev_t))
337                         return pp;
338
339         condlog(3, "%s: not found in pathvec", dev_t);
340         return NULL;
341 }
342
343 extern int
344 pathcountgr (struct pathgroup * pgp, int state)
345 {
346         struct path *pp;
347         int count = 0;
348         int i;
349
350         vector_foreach_slot (pgp->paths, pp, i)
351                 if ((pp->state == state) || (state < 0))
352                         count++;
353
354         return count;
355 }
356
357 extern int
358 pathcount (struct multipath * mpp, int state)
359 {
360         struct pathgroup *pgp;
361         int count = 0;
362         int i;
363
364         vector_foreach_slot (mpp->pg, pgp, i)
365                 count += pathcountgr(pgp, state);
366
367         return count;
368 }
369
370 struct path *
371 first_path (struct multipath * mpp)
372 {
373         struct pathgroup * pgp = VECTOR_SLOT(mpp->pg, 0);
374         return VECTOR_SLOT(pgp->paths, 0);
375 }