Checker name is not displayed on failure
[multipath-tools/.git] / libmultipath / prio.c
1 #include <stdio.h>
2 #include <string.h>
3 #include <stddef.h>
4 #include <dlfcn.h>
5 #include <sys/stat.h>
6
7 #include "debug.h"
8 #include "prio.h"
9 #include "config.h"
10
11 static LIST_HEAD(prioritizers);
12
13 int init_prio (void)
14 {
15         if (!add_prio(DEFAULT_PRIO))
16                 return 1;
17         return 0;
18 }
19
20 static struct prio * alloc_prio (void)
21 {
22         struct prio *p;
23
24         p = MALLOC(sizeof(struct prio));
25         if (p)
26                 INIT_LIST_HEAD(&p->node);
27         return p;
28 }
29
30 void free_prio (struct prio * p)
31 {
32         condlog(3, "unloading %s prioritizer", p->name);
33         list_del(&p->node);
34         if (p->handle) {
35                 if (dlclose(p->handle) != 0) {
36                         condlog(0, "Cannot unload prioritizer %s: %s",
37                                 p->name, dlerror());
38                 }
39         }
40         FREE(p);
41 }
42
43 void cleanup_prio(void)
44 {
45         struct prio * prio_loop;
46         struct prio * prio_temp;
47
48         list_for_each_entry_safe(prio_loop, prio_temp, &prioritizers, node) {
49                 free_prio(prio_loop);
50         }
51 }
52
53 struct prio * prio_lookup (char * name)
54 {
55         struct prio * p;
56
57         list_for_each_entry(p, &prioritizers, node) {
58                 if (!strncmp(name, p->name, PRIO_NAME_LEN))
59                         return p;
60         }
61         return add_prio(name);
62 }
63
64 int prio_set_args (struct prio * p, char * args)
65 {
66         return snprintf(p->args, PRIO_ARGS_LEN, "%s", args);
67 }
68
69 struct prio * add_prio (char * name)
70 {
71         char libname[LIB_PRIO_NAMELEN];
72         struct stat stbuf;
73         struct prio * p;
74         char *errstr;
75
76         p = alloc_prio();
77         if (!p)
78                 return NULL;
79         snprintf(libname, LIB_PRIO_NAMELEN, "%s/libprio%s.so",
80                  conf->multipath_dir, name);
81         if (stat(libname,&stbuf) < 0) {
82                 condlog(0,"Prioritizer '%s' not found in %s",
83                         name, conf->multipath_dir);
84                 goto out;
85         }
86         condlog(3, "loading %s prioritizer", libname);
87         p->handle = dlopen(libname, RTLD_NOW);
88         if (!p->handle) {
89                 if ((errstr = dlerror()) != NULL)
90                         condlog(0, "A dynamic linking error occurred: (%s)",
91                                 errstr);
92                 goto out;
93         }
94         p->getprio = (int (*)(struct path *, char *)) dlsym(p->handle, "getprio");
95         errstr = dlerror();
96         if (errstr != NULL)
97                 condlog(0, "A dynamic linking error occurred: (%s)", errstr);
98         if (!p->getprio)
99                 goto out;
100         snprintf(p->name, PRIO_NAME_LEN, "%s", name);
101         list_add(&p->node, &prioritizers);
102         return p;
103 out:
104         free_prio(p);
105         return NULL;
106 }
107
108 int prio_getprio (struct prio * p, struct path * pp)
109 {
110         return p->getprio(pp, p->args);
111 }
112
113 char * prio_name (struct prio * p)
114 {
115         return p->name;
116 }
117
118 char * prio_args (struct prio * p)
119 {
120         return p->args;
121 }