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