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