[multipathd]
[platform/upstream/multipath-tools.git] / libmultipath / devmapper.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <libdevmapper.h>
5 #include <ctype.h>
6 #include <linux/kdev_t.h>
7
8 #include "vector.h"
9 #include "structs.h"
10 #include "debug.h"
11 #include "memory.h"
12
13 extern int
14 dm_prereq (char * str, int x, int y, int z)
15 {
16         int r = 1;
17         struct dm_task *dmt;
18         struct dm_versions *target;
19         struct dm_versions *last_target;
20
21         if (!(dmt = dm_task_create(DM_DEVICE_LIST_VERSIONS)))
22                 return 1;
23
24         dm_task_no_open_count(dmt);
25
26         if (!dm_task_run(dmt))
27                 goto out;
28
29         target = dm_task_get_versions(dmt);
30
31         /* Fetch targets and print 'em */
32         do {
33                 last_target = target;
34
35                 if (!strncmp(str, target->name, strlen(str)) &&
36                     /* dummy prereq on multipath version */
37                     target->version[0] >= x &&
38                     target->version[1] >= y &&
39                     target->version[2] >= z
40                    )
41                         r = 0;
42
43                 target = (void *) target + target->next;
44         } while (last_target != target);
45
46         out:
47         dm_task_destroy(dmt);
48         return r;
49 }
50
51 extern int
52 dm_simplecmd (int task, const char *name) {
53         int r = 0;
54         struct dm_task *dmt;
55
56         if (!(dmt = dm_task_create (task)))
57                 return 0;
58
59         if (!dm_task_set_name (dmt, name))
60                 goto out;
61
62         dm_task_no_open_count(dmt);
63
64         r = dm_task_run (dmt);
65
66         out:
67         dm_task_destroy (dmt);
68         return r;
69 }
70
71 extern int
72 dm_addmap (int task, const char *name, const char *target,
73            const char *params, unsigned long size) {
74         int r = 0;
75         struct dm_task *dmt;
76
77         if (!(dmt = dm_task_create (task)))
78                 return 0;
79
80         if (!dm_task_set_name (dmt, name))
81                 goto addout;
82
83         if (!dm_task_add_target (dmt, 0, size, target, params))
84                 goto addout;
85
86         dm_task_no_open_count(dmt);
87
88         r = dm_task_run (dmt);
89
90         addout:
91         dm_task_destroy (dmt);
92         return r;
93 }
94
95 extern int
96 dm_map_present (char * str)
97 {
98         int r = 0;
99         struct dm_task *dmt;
100         struct dm_info info;
101
102         if (!(dmt = dm_task_create(DM_DEVICE_INFO)))
103                 return 0;
104
105         if (!dm_task_set_name(dmt, str))
106                 goto out;
107
108         dm_task_no_open_count(dmt);
109
110         if (!dm_task_run(dmt))
111                 goto out;
112
113         if (!dm_task_get_info(dmt, &info))
114                 goto out;
115
116         if (info.exists)
117                 r = 1;
118 out:
119         dm_task_destroy(dmt);
120         return r;
121 }
122
123 extern int
124 dm_get_map(char * name, unsigned long * size, char * outparams)
125 {
126         int r = 1;
127         struct dm_task *dmt;
128         void *next = NULL;
129         uint64_t start, length;
130         char *target_type = NULL;
131         char *params = NULL;
132
133         if (!(dmt = dm_task_create(DM_DEVICE_TABLE)))
134                 return 1;
135
136         if (!dm_task_set_name(dmt, name))
137                 goto out;
138
139         dm_task_no_open_count(dmt);
140
141         if (!dm_task_run(dmt))
142                 goto out;
143
144         /* Fetch 1st target */
145         next = dm_get_next_target(dmt, next, &start, &length,
146                                   &target_type, &params);
147
148         if (size)
149                 *size = length;
150
151         if (snprintf(outparams, PARAMS_SIZE, "%s", params) <= PARAMS_SIZE)
152                 r = 0;
153 out:
154         dm_task_destroy(dmt);
155         return r;
156 }
157
158 extern int
159 dm_get_status(char * name, char * outstatus)
160 {
161         int r = 1;
162         struct dm_task *dmt;
163         void *next = NULL;
164         uint64_t start, length;
165         char *target_type;
166         char *status;
167
168         if (!(dmt = dm_task_create(DM_DEVICE_STATUS)))
169                 return 1;
170
171         if (!dm_task_set_name(dmt, name))
172                 goto out;
173
174         dm_task_no_open_count(dmt);
175
176         if (!dm_task_run(dmt))
177                 goto out;
178
179         /* Fetch 1st target */
180         next = dm_get_next_target(dmt, next, &start, &length,
181                                   &target_type, &status);
182
183         if (snprintf(outstatus, PARAMS_SIZE, "%s", status) <= PARAMS_SIZE)
184                 r = 0;
185 out:
186         dm_task_destroy(dmt);
187         return r;
188 }
189
190 extern int
191 dm_type(char * name, char * type)
192 {
193         int r = 0;
194         struct dm_task *dmt;
195         void *next = NULL;
196         uint64_t start, length;
197         char *target_type = NULL;
198         char *params;
199
200         if (!(dmt = dm_task_create(DM_DEVICE_TABLE)))
201                 return 0;
202
203         if (!dm_task_set_name(dmt, name))
204                 goto out;
205
206         dm_task_no_open_count(dmt);
207
208         if (!dm_task_run(dmt))
209                 goto out;
210
211         /* Fetch 1st target */
212         next = dm_get_next_target(dmt, next, &start, &length,
213                                   &target_type, &params);
214
215         if (0 == strcmp(target_type, type))
216                 r = 1;
217
218 out:
219         dm_task_destroy(dmt);
220         return r;
221 }
222
223 int
224 dm_get_opencount (char * mapname)
225 {
226         int r = -1;
227         struct dm_task *dmt;
228         struct dm_info info;
229
230         if (!(dmt = dm_task_create(DM_DEVICE_INFO)))
231                 return 0;
232
233         if (!dm_task_set_name(dmt, mapname))
234                 goto out;
235
236         if (!dm_task_run(dmt))
237                 goto out;
238
239         if (!dm_task_get_info(dmt, &info))
240                 goto out;
241
242         r = info.open_count;
243 out:
244         dm_task_destroy(dmt);
245         return r;
246 }
247         
248 extern int
249 dm_flush_maps (char * type)
250 {
251         int r = 0;
252         struct dm_task *dmt;
253         struct dm_names *names;
254         unsigned next = 0;
255
256         if (!(dmt = dm_task_create (DM_DEVICE_LIST)))
257                 return 0;
258
259         dm_task_no_open_count(dmt);
260
261         if (!dm_task_run (dmt))
262                 goto out;
263
264         if (!(names = dm_task_get_names (dmt)))
265                 goto out;
266
267         if (!names->dev)
268                 goto out;
269
270         do {
271                 if (dm_type(names->name, type) &&
272                     dm_get_opencount(names->name) == 0 &&
273                     !dm_simplecmd(DM_DEVICE_REMOVE, names->name))
274                         r++;
275
276                 next = names->next;
277                 names = (void *) names + next;
278         } while (next);
279
280         out:
281         dm_task_destroy (dmt);
282         return r;
283 }
284
285 int
286 dm_fail_path(char * mapname, char * path)
287 {
288         int r = 1;
289         struct dm_task *dmt;
290         char str[32];
291
292         if (!(dmt = dm_task_create(DM_DEVICE_TARGET_MSG)))
293                 return 1;
294
295         if (!dm_task_set_name(dmt, mapname))
296                 goto out;
297
298         if (!dm_task_set_sector(dmt, 0))
299                 goto out;
300
301         if (snprintf(str, 32, "fail_path %s\n", path) > 32)
302                 goto out;
303
304         if (!dm_task_set_message(dmt, str))
305                 goto out;
306
307         dm_task_no_open_count(dmt);
308
309         if (!dm_task_run(dmt))
310                 goto out;
311
312         r = 0;
313 out:
314         dm_task_destroy(dmt);
315         return r;
316 }
317
318 int
319 dm_reinstate(char * mapname, char * path)
320 {
321         int r = 1;
322         struct dm_task *dmt;
323         char str[32];
324
325         if (!(dmt = dm_task_create(DM_DEVICE_TARGET_MSG)))
326                 return 1;
327
328         if (!dm_task_set_name(dmt, mapname))
329                 goto out;
330
331         if (!dm_task_set_sector(dmt, 0))
332                 goto out;
333
334         if (snprintf(str, 32, "reinstate_path %s\n", path) > 32)
335                 goto out;
336
337         if (!dm_task_set_message(dmt, str))
338                 goto out;
339
340         dm_task_no_open_count(dmt);
341
342         if (!dm_task_run(dmt))
343                 goto out;
344
345         r = 0;
346 out:
347         dm_task_destroy(dmt);
348         return r;
349 }
350
351 int
352 dm_switchgroup(char * mapname, int index)
353 {
354         int r = 0;
355         struct dm_task *dmt;
356         char str[24];
357
358         if (!(dmt = dm_task_create(DM_DEVICE_TARGET_MSG)))
359                 return 0;
360
361         if (!dm_task_set_name(dmt, mapname))
362                 goto out;
363
364         if (!dm_task_set_sector(dmt, 0))
365                 goto out;
366
367         snprintf(str, 24, "switch_group %i\n", index);
368         condlog(3, "message %s 0 %s", mapname, str);
369
370         if (!dm_task_set_message(dmt, str))
371                 goto out;
372
373         dm_task_no_open_count(dmt);
374
375         if (!dm_task_run(dmt))
376                 goto out;
377
378         r = 1;
379
380         out:
381         dm_task_destroy(dmt);
382
383         return r;
384 }
385
386 int
387 dm_get_maps (vector mp, char * type)
388 {
389         struct multipath * mpp;
390         int r = 1;
391         struct dm_task *dmt;
392         struct dm_names *names;
393         unsigned next = 0;
394
395         if (!type || !mp)
396                 return 1;
397
398         if (!(dmt = dm_task_create(DM_DEVICE_LIST)))
399                 return 1;
400
401         dm_task_no_open_count(dmt);
402
403         if (!dm_task_run(dmt))
404                 goto out;
405
406         if (!(names = dm_task_get_names(dmt)))
407                 goto out;
408
409         if (!names->dev) {
410                 r = 0; /* this is perfectly valid */
411                 goto out;
412         }
413
414         do {
415                 if (dm_type(names->name, type)) {
416                         mpp = alloc_multipath();
417
418                         if (!mpp)
419                                 goto out;
420
421                         if (dm_get_map(names->name, &mpp->size, mpp->params))
422                                 goto out1;
423
424                         if (dm_get_status(names->name, mpp->status))
425                                 goto out1;
426
427                         mpp->alias = MALLOC(strlen(names->name) + 1);
428
429                         if (!mpp->alias)
430                                 goto out1;
431
432                         strncat(mpp->alias, names->name, strlen(names->name));
433
434                         if (!vector_alloc_slot(mp))
435                                 goto out1;
436                         
437                         vector_set_slot(mp, mpp);
438                         mpp = NULL;
439                 }
440                 next = names->next;
441                 names = (void *) names + next;
442         } while (next);
443
444         r = 0;
445         goto out;
446 out1:
447         free_multipath(mpp, KEEP_PATHS);
448 out:
449         dm_task_destroy (dmt);
450         return r;
451 }
452
453 int
454 dm_geteventnr (char *name)
455 {
456         struct dm_task *dmt;
457         struct dm_info info;
458
459         if (!(dmt = dm_task_create(DM_DEVICE_INFO)))
460                 return 0;
461
462         if (!dm_task_set_name(dmt, name))
463                 goto out;
464
465         dm_task_no_open_count(dmt);
466
467         if (!dm_task_run(dmt))
468                 goto out;
469
470         if (!dm_task_get_info(dmt, &info)) {
471                 info.event_nr = 0;
472                 goto out;
473         }
474
475         if (!info.exists) {
476                 info.event_nr = 0;
477                 goto out;
478         }
479
480 out:
481         dm_task_destroy(dmt);
482
483         return info.event_nr;
484 }