Merge branch 'master' of git://git.kernel.org/pub/scm/linux/storage/multipath-tools/
[platform/upstream/multipath-tools.git] / libmultipath / checkers.c
1 #include <stdio.h>
2 #include <string.h>
3 #include <stddef.h>
4 #include <dlfcn.h>
5
6 #include "debug.h"
7 #include "checkers.h"
8 #include "vector.h"
9 #include "config.h"
10
11 static LIST_HEAD(checkers);
12
13 int init_checkers (void)
14 {
15         INIT_LIST_HEAD(&checkers);
16         if (!add_checker(DEFAULT_CHECKER))
17                 return 1;
18         return 0;
19 }
20
21 struct checker * alloc_checker (void)
22 {
23         return zalloc(sizeof(struct checker));
24 }
25
26 void free_checker (struct checker * c)
27 {
28         free(c);
29 }
30
31 void cleanup_checkers (void)
32 {
33         struct checker * checker_loop;
34         struct checker * checker_temp;
35
36         list_for_each_entry_safe(checker_loop, checker_temp, &checkers, node) {
37                 list_del(&checker_loop->node);
38                 free(checker_loop);
39         }
40 }
41
42 struct checker * checker_lookup (char * name)
43 {
44         struct checker * c;
45
46         list_for_each_entry(c, &checkers, node) {
47                 if (!strncmp(name, c->name, CHECKER_NAME_LEN))
48                         return c;
49         }
50         c = add_checker(name);
51         if (c)
52                 return c;
53         return checker_default();
54 }
55
56 struct checker * add_checker (char * name)
57 {
58         char libname[LIB_CHECKER_NAMELEN];
59         void * handle;
60         struct checker * c;
61         char *errstr;
62
63         c = alloc_checker();
64         if (!c)
65                 return NULL;
66         snprintf(libname, LIB_CHECKER_NAMELEN, "%s/libcheck%s.so",
67                  conf->multipath_dir, name);
68         condlog(3, "loading %s checker", libname);
69         handle = dlopen(libname, RTLD_NOW);
70         errstr = dlerror();
71         if (errstr != NULL)
72         condlog(0, "A dynamic linking error occurred: (%s)", errstr);
73         if (!handle)
74                 goto out;
75
76         c->check = (int (*)(struct checker *)) dlsym(handle, "libcheck_check");
77         errstr = dlerror();
78         if (errstr != NULL)
79         condlog(0, "A dynamic linking error occurred: (%s)", errstr);
80         if (!c->check)
81                 goto out;
82
83         c->init = (int (*)(struct checker *)) dlsym(handle, "libcheck_init");
84         errstr = dlerror();
85         if (errstr != NULL)
86         condlog(0, "A dynamic linking error occurred: (%s)", errstr);
87         if (!c->init)
88                 goto out;
89
90         c->free = (void (*)(struct checker *)) dlsym(handle, "libcheck_free");
91         errstr = dlerror();
92         if (errstr != NULL)
93         condlog(0, "A dynamic linking error occurred: (%s)", errstr);
94         if (!c->free)
95                 goto out;
96
97         snprintf(c->name, CHECKER_NAME_LEN, "%s", name);
98         c->fd = 0;
99         c->sync = 1;
100         list_add(&c->node, &checkers);
101         return c;
102 out:
103         free_checker(c);
104         return NULL;
105 }
106
107 void checker_set_fd (struct checker * c, int fd)
108 {
109         c->fd = fd;
110 }
111
112 void checker_set_sync (struct checker * c)
113 {
114         c->sync = 1;
115 }
116
117 void checker_set_async (struct checker * c)
118 {
119         c->sync = 0;
120 }
121
122 void checker_enable (struct checker * c)
123 {
124         c->disable = 0;
125 }
126
127 void checker_disable (struct checker * c)
128 {
129         c->disable = 1;
130 }
131
132 int checker_init (struct checker * c, void ** mpctxt_addr)
133 {
134         c->mpcontext = mpctxt_addr;
135         return c->init(c);
136 }
137
138 void checker_put (struct checker * c)
139 {
140         if (c->free)
141                 c->free(c);
142         memset(c, 0x0, sizeof(struct checker));
143 }
144
145 int checker_check (struct checker * c)
146 {
147         int r;
148
149         if (c->disable)
150                 return PATH_UNCHECKED;
151         if (c->fd <= 0) {
152                 MSG(c, "no usable fd");
153                 return PATH_WILD;
154         }
155         r = c->check(c);
156
157         return r;
158 }
159
160 int checker_selected (struct checker * c)
161 {
162         return (c->check) ? 1 : 0;
163 }
164
165 char * checker_name (struct checker * c)
166 {
167         return c->name;
168 }
169
170 char * checker_message (struct checker * c)
171 {
172         return c->message;
173 }
174
175 struct checker * checker_default (void)
176 {
177         return checker_lookup(DEFAULT_CHECKER);
178 }
179
180 void checker_get (struct checker * dst, struct checker * src)
181 {
182         dst->fd = src->fd;
183         dst->sync = src->sync;
184         strncpy(dst->name, src->name, CHECKER_NAME_LEN);
185         strncpy(dst->message, src->message, CHECKER_MSG_LEN);
186         dst->check = src->check;
187         dst->init = src->init;
188         dst->free = src->free;
189 }