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