Stop annoying prio_lookup warning messages
[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                 p->refcount = 1;
28         }
29         return p;
30 }
31
32 void free_prio (struct prio * p)
33 {
34         if (!p)
35                 return;
36         p->refcount--;
37         if (p->refcount) {
38                 condlog(3, "%s prioritizer refcount %d",
39                         p->name, p->refcount);
40                 return;
41         }
42         condlog(3, "unloading %s prioritizer", p->name);
43         list_del(&p->node);
44         if (p->handle) {
45                 if (dlclose(p->handle) != 0) {
46                         condlog(0, "Cannot unload prioritizer %s: %s",
47                                 p->name, dlerror());
48                 }
49         }
50         FREE(p);
51 }
52
53 void cleanup_prio(void)
54 {
55         struct prio * prio_loop;
56         struct prio * prio_temp;
57
58         list_for_each_entry_safe(prio_loop, prio_temp, &prioritizers, node) {
59                 free_prio(prio_loop);
60         }
61 }
62
63 struct prio * prio_lookup (char * name)
64 {
65         struct prio * p;
66
67         list_for_each_entry(p, &prioritizers, node) {
68                 if (!strncmp(name, p->name, PRIO_NAME_LEN))
69                         return p;
70         }
71         return add_prio(name);
72 }
73
74 int prio_set_args (struct prio * p, char * args)
75 {
76         return snprintf(p->args, PRIO_ARGS_LEN, "%s", args);
77 }
78
79 struct prio * add_prio (char * name)
80 {
81         char libname[LIB_PRIO_NAMELEN];
82         struct stat stbuf;
83         struct prio * p;
84         char *errstr;
85
86         p = alloc_prio();
87         if (!p)
88                 return NULL;
89         snprintf(p->name, PRIO_NAME_LEN, "%s", name);
90         snprintf(libname, LIB_PRIO_NAMELEN, "%s/libprio%s.so",
91                  conf->multipath_dir, name);
92         if (stat(libname,&stbuf) < 0) {
93                 condlog(0,"Prioritizer '%s' not found in %s",
94                         name, conf->multipath_dir);
95                 goto out;
96         }
97         condlog(3, "loading %s prioritizer", libname);
98         p->handle = dlopen(libname, RTLD_NOW);
99         if (!p->handle) {
100                 if ((errstr = dlerror()) != NULL)
101                         condlog(0, "A dynamic linking error occurred: (%s)",
102                                 errstr);
103                 goto out;
104         }
105         p->getprio = (int (*)(struct path *, char *)) dlsym(p->handle, "getprio");
106         errstr = dlerror();
107         if (errstr != NULL)
108                 condlog(0, "A dynamic linking error occurred: (%s)", errstr);
109         if (!p->getprio)
110                 goto out;
111         list_add(&p->node, &prioritizers);
112         return p;
113 out:
114         free_prio(p);
115         return NULL;
116 }
117
118 int prio_getprio (struct prio * p, struct path * pp)
119 {
120         return p->getprio(pp, p->args);
121 }
122
123 int prio_selected (struct prio * p)
124 {
125         if (!p || !p->getprio)
126                 return 0;
127         return (p->getprio) ? 1 : 0;
128 }
129
130 char * prio_name (struct prio * p)
131 {
132         return p->name;
133 }
134
135 char * prio_args (struct prio * p)
136 {
137         return p->args;
138 }
139
140 void prio_get (struct prio * dst, char * name, char * args)
141 {
142         struct prio * src = prio_lookup(name);
143
144         if (!src) {
145                 dst->getprio = NULL;
146                 return;
147         }
148
149         strncpy(dst->name, src->name, PRIO_NAME_LEN);
150         if (args)
151                 strncpy(dst->args, args, PRIO_ARGS_LEN);
152         dst->getprio = src->getprio;
153         dst->handle = NULL;
154
155         src->refcount++;
156 }
157
158 void prio_put (struct prio * dst)
159 {
160         struct prio * src;
161
162         if (!dst)
163                 return;
164
165         if (!strlen(dst->name))
166                 src = NULL;
167         else
168                 src = prio_lookup(dst->name);
169         memset(dst, 0x0, sizeof(struct prio));
170         free_prio(src);
171 }