11 char *checker_state_names[] = {
24 static LIST_HEAD(checkers);
26 char * checker_state_name (int i)
28 return checker_state_names[i];
31 int init_checkers (char *multipath_dir)
33 if (!add_checker(multipath_dir, DEFAULT_CHECKER))
38 struct checker * alloc_checker (void)
42 c = MALLOC(sizeof(struct checker));
44 INIT_LIST_HEAD(&c->node);
51 void free_checker (struct checker * c)
57 condlog(3, "%s checker refcount %d",
58 c->name, c->refcount);
61 condlog(3, "unloading %s checker", c->name);
64 if (dlclose(c->handle) != 0) {
65 condlog(0, "Cannot unload checker %s: %s",
72 void cleanup_checkers (void)
74 struct checker * checker_loop;
75 struct checker * checker_temp;
77 list_for_each_entry_safe(checker_loop, checker_temp, &checkers, node) {
78 free_checker(checker_loop);
82 struct checker * checker_lookup (char * name)
86 if (!name || !strlen(name))
88 list_for_each_entry(c, &checkers, node) {
89 if (!strncmp(name, c->name, CHECKER_NAME_LEN))
95 struct checker * add_checker (char *multipath_dir, char * name)
97 char libname[LIB_CHECKER_NAMELEN];
105 snprintf(c->name, CHECKER_NAME_LEN, "%s", name);
106 if (!strncmp(c->name, NONE, 4))
108 snprintf(libname, LIB_CHECKER_NAMELEN, "%s/libcheck%s.so",
109 multipath_dir, name);
110 if (stat(libname,&stbuf) < 0) {
111 condlog(0,"Checker '%s' not found in %s",
112 name, multipath_dir);
115 condlog(3, "loading %s checker", libname);
116 c->handle = dlopen(libname, RTLD_NOW);
118 if ((errstr = dlerror()) != NULL)
119 condlog(0, "A dynamic linking error occurred: (%s)",
123 c->check = (int (*)(struct checker *)) dlsym(c->handle, "libcheck_check");
126 condlog(0, "A dynamic linking error occurred: (%s)", errstr);
130 c->init = (int (*)(struct checker *)) dlsym(c->handle, "libcheck_init");
133 condlog(0, "A dynamic linking error occurred: (%s)", errstr);
137 c->free = (void (*)(struct checker *)) dlsym(c->handle, "libcheck_free");
140 condlog(0, "A dynamic linking error occurred: (%s)", errstr);
144 c->msgtable_size = 0;
145 c->msgtable = dlsym(c->handle, "libcheck_msgtable");
147 if (c->msgtable != NULL) {
150 for (p = c->msgtable;
151 *p && (p - c->msgtable) < CHECKER_MSGTABLE_SIZE; p++)
154 c->msgtable_size = p - c->msgtable;
156 c->msgtable_size = 0;
157 condlog(3, "checker %s: message table size = %d",
158 c->name, c->msgtable_size);
163 list_add(&c->node, &checkers);
170 void checker_set_fd (struct checker * c, int fd)
177 void checker_set_sync (struct checker * c)
184 void checker_set_async (struct checker * c)
191 void checker_enable (struct checker * c)
198 void checker_disable (struct checker * c)
205 int checker_init (struct checker * c, void ** mpctxt_addr)
209 c->mpcontext = mpctxt_addr;
215 void checker_clear (struct checker *c)
217 memset(c, 0x0, sizeof(struct checker));
221 void checker_put (struct checker * dst)
223 struct checker * src;
225 if (!dst || !strlen(dst->name))
227 src = checker_lookup(dst->name);
234 int checker_check (struct checker * c, int path_state)
241 c->msgid = CHECKER_MSGID_NONE;
243 c->msgid = CHECKER_MSGID_DISABLED;
244 return PATH_UNCHECKED;
246 if (!strncmp(c->name, NONE, 4))
250 c->msgid = CHECKER_MSGID_NO_FD;
258 int checker_selected (struct checker * c)
262 if (!strncmp(c->name, NONE, 4))
264 return (c->check) ? 1 : 0;
267 const char *checker_name(const struct checker *c)
274 static const char *generic_msg[CHECKER_GENERIC_MSGTABLE_SIZE] = {
275 [CHECKER_MSGID_NONE] = "",
276 [CHECKER_MSGID_DISABLED] = " is disabled",
277 [CHECKER_MSGID_NO_FD] = " has no usable fd",
278 [CHECKER_MSGID_INVALID] = " provided invalid message id",
279 [CHECKER_MSGID_UP] = " reports path is up",
280 [CHECKER_MSGID_DOWN] = " reports path is down",
281 [CHECKER_MSGID_GHOST] = " reports path is ghost",
284 const char *checker_message(const struct checker *c)
288 if (!c || c->msgid < 0 ||
289 (c->msgid >= CHECKER_GENERIC_MSGTABLE_SIZE &&
290 c->msgid < CHECKER_FIRST_MSGID))
293 if (c->msgid < CHECKER_GENERIC_MSGTABLE_SIZE)
294 return generic_msg[c->msgid];
296 id = c->msgid - CHECKER_FIRST_MSGID;
297 if (id < c->cls->msgtable_size)
298 return c->cls->msgtable[id];
301 return generic_msg[CHECKER_MSGID_NONE];
304 void checker_clear_message (struct checker *c)
308 c->msgid = CHECKER_MSGID_NONE;
311 void checker_get (char *multipath_dir, struct checker * dst, char * name)
313 struct checker * src = NULL;
318 if (name && strlen(name)) {
319 src = checker_lookup(name);
321 src = add_checker(multipath_dir, name);
328 dst->sync = src->sync;
329 strncpy(dst->name, src->name, CHECKER_NAME_LEN);
330 dst->msgid = CHECKER_MSGID_NONE;
331 dst->check = src->check;
332 dst->init = src->init;
333 dst->free = src->free;
334 dst->msgtable = src->msgtable;
335 dst->msgtable_size = src->msgtable_size;