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 "memory.h"
11 #include "vector.h"
12 #include "util.h"
13 #include "structs.h"
14 #include "config.h"
15 #include "debug.h"
16 #include "structs_vec.h"
17 #include "blacklist.h"
18 #include "waiter.h"
19 #include "prio.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                 pgp = NULL;
85         }
86
87         return pgp;
88 }
89
90 void
91 free_pathgroup (struct pathgroup * pgp, int free_paths)
92 {
93         if (!pgp)
94                 return;
95
96         free_pathvec(pgp->paths, free_paths);
97         FREE(pgp);
98 }
99
100 void
101 free_pgvec (vector pgvec, int free_paths)
102 {
103         int i;
104         struct pathgroup * pgp;
105
106         if (!pgvec)
107                 return;
108
109         vector_foreach_slot(pgvec, pgp, i)
110                 free_pathgroup(pgp, free_paths);
111
112         vector_free(pgvec);
113 }
114
115 struct multipath *
116 alloc_multipath (void)
117 {
118         struct multipath * mpp;
119
120         mpp = (struct multipath *)MALLOC(sizeof(struct multipath));
121
122         if (mpp) {
123                 mpp->bestpg = 1;
124                 mpp->mpcontext = NULL;
125         }
126         return mpp;
127 }
128
129 extern void
130 free_multipath_attributes (struct multipath * mpp)
131 {
132         if (!mpp)
133                 return;
134
135         if (mpp->selector &&
136             mpp->selector != conf->selector &&
137             (!mpp->mpe || (mpp->mpe && mpp->selector != mpp->mpe->selector)) &&
138             (!mpp->hwe || (mpp->hwe && mpp->selector != mpp->hwe->selector))) {
139                 FREE(mpp->selector);
140                 mpp->selector = NULL;
141         }
142
143         if (mpp->features &&
144             mpp->features != conf->features &&
145             (!mpp->hwe || (mpp->hwe && mpp->features != mpp->hwe->features))) {
146                 FREE(mpp->features);
147                 mpp->features = NULL;
148         }
149
150         if (mpp->hwhandler &&
151             mpp->hwhandler != conf->hwhandler &&
152             (!mpp->hwe || (mpp->hwe && mpp->hwhandler != mpp->hwe->hwhandler))) {
153                 FREE(mpp->hwhandler);
154                 mpp->hwhandler = NULL;
155         }
156 }
157
158 void
159 free_multipath (struct multipath * mpp, int free_paths)
160 {
161         if (!mpp)
162                 return;
163
164         free_multipath_attributes(mpp);
165
166         if (mpp->alias) {
167                 FREE(mpp->alias);
168                 mpp->alias = NULL;
169         }
170
171         if (mpp->dmi) {
172                 FREE(mpp->dmi);
173                 mpp->dmi = NULL;
174         }
175
176         /*
177          * better own vecs->lock here
178          */
179         if (mpp->waiter)
180                 ((struct event_thread *)mpp->waiter)->mpp = NULL;
181
182         free_pathvec(mpp->paths, free_paths);
183         free_pgvec(mpp->pg, free_paths);
184         FREE_PTR(mpp->mpcontext);
185         FREE(mpp);
186 }
187
188 void
189 drop_multipath (vector mpvec, char * wwid, int free_paths)
190 {
191         int i;
192         struct multipath * mpp;
193
194         if (!mpvec)
195                 return;
196
197         vector_foreach_slot (mpvec, mpp, i) {
198                 if (!strncmp(mpp->wwid, wwid, WWID_SIZE)) {
199                         free_multipath(mpp, free_paths);
200                         vector_del_slot(mpvec, i);
201                         return;
202                 }
203         }
204 }
205
206 void
207 free_multipathvec (vector mpvec, int free_paths)
208 {
209         int i;
210         struct multipath * mpp;
211
212         if (!mpvec)
213                 return;
214
215         vector_foreach_slot (mpvec, mpp, i)
216                 free_multipath(mpp, free_paths);
217
218         vector_free(mpvec);
219 }
220
221 int
222 store_path (vector pathvec, struct path * pp)
223 {
224         if (!vector_alloc_slot(pathvec))
225                 return 1;
226
227         vector_set_slot(pathvec, pp);
228
229         return 0;
230 }
231
232 int
233 store_pathgroup (vector pgvec, struct pathgroup * pgp)
234 {
235         if (!vector_alloc_slot(pgvec))
236                 return 1;
237
238         vector_set_slot(pgvec, pgp);
239
240         return 0;
241 }
242
243 struct multipath *
244 find_mp_by_minor (vector mpvec, int minor)
245 {
246         int i;
247         struct multipath * mpp;
248
249         if (!mpvec)
250                 return NULL;
251
252         vector_foreach_slot (mpvec, mpp, i) {
253                 if (!mpp->dmi)
254                         continue;
255
256                 if (mpp->dmi->minor == minor)
257                         return mpp;
258         }
259         return NULL;
260 }
261
262 struct multipath *
263 find_mp_by_wwid (vector mpvec, char * wwid)
264 {
265         int i;
266         struct multipath * mpp;
267
268         if (!mpvec)
269                 return NULL;
270
271         vector_foreach_slot (mpvec, mpp, i)
272                 if (!strncmp(mpp->wwid, wwid, WWID_SIZE))
273                         return mpp;
274
275         return NULL;
276 }
277
278 struct multipath *
279 find_mp_by_alias (vector mpvec, char * alias)
280 {
281         int i;
282         int len;
283         struct multipath * mpp;
284
285         if (!mpvec)
286                 return NULL;
287
288         len = strlen(alias);
289
290         if (!len)
291                 return NULL;
292
293         vector_foreach_slot (mpvec, mpp, i) {
294                 if (strlen(mpp->alias) == len &&
295                     !strncmp(mpp->alias, alias, len))
296                         return mpp;
297         }
298         return NULL;
299 }
300
301 struct multipath *
302 find_mp_by_str (vector mpvec, char * str)
303 {
304         int minor;
305
306         if (sscanf(str, "dm-%d", &minor) == 1)
307                 return find_mp_by_minor(mpvec, minor);
308         else
309                 return find_mp_by_alias(mpvec, str);
310 }
311
312 struct path *
313 find_path_by_dev (vector pathvec, char * dev)
314 {
315         int i;
316         struct path * pp;
317
318         if (!pathvec)
319                 return NULL;
320
321         vector_foreach_slot (pathvec, pp, i)
322                 if (!strcmp_chomp(pp->dev, dev))
323                         return pp;
324
325         condlog(3, "%s: not found in pathvec", dev);
326         return NULL;
327 }
328
329 struct path *
330 find_path_by_devt (vector pathvec, char * dev_t)
331 {
332         int i;
333         struct path * pp;
334
335         if (!pathvec)
336                 return NULL;
337
338         vector_foreach_slot (pathvec, pp, i)
339                 if (!strcmp_chomp(pp->dev_t, dev_t))
340                         return pp;
341
342         condlog(3, "%s: not found in pathvec", dev_t);
343         return NULL;
344 }
345
346 extern int
347 pathcountgr (struct pathgroup * pgp, int state)
348 {
349         struct path *pp;
350         int count = 0;
351         int i;
352
353         vector_foreach_slot (pgp->paths, pp, i)
354                 if ((pp->state == state) || (state == PATH_WILD))
355                         count++;
356
357         return count;
358 }
359
360 extern int
361 pathcount (struct multipath * mpp, int state)
362 {
363         struct pathgroup *pgp;
364         int count = 0;
365         int i;
366
367         if (mpp->pg) {
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;
378         if (!mpp->pg)
379                 return NULL;
380         pgp = VECTOR_SLOT(mpp->pg, 0);
381
382         return pgp?VECTOR_SLOT(pgp->paths, 0):NULL;
383 }
384
385 extern void
386 setup_feature(struct multipath * mpp, char *feature)
387 {
388         if (!strncmp(feature, "queue_if_no_path", 16))
389                 mpp->no_path_retry = NO_PATH_RETRY_QUEUE;
390 }