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