697f12f87b21987cc5b4a1d8dae6d54301217f20
[multipath-tools/.git] / libmultipath / foreign.h
1 /*
2   Copyright (c) 2018 Martin Wilck, SUSE Linux GmbH
3
4   This program is free software; you can redistribute it and/or
5   modify it under the terms of the GNU General Public License
6   as published by the Free Software Foundation; either version 2
7   of the License, or (at your option) any later version.
8
9   This program is distributed in the hope that it will be useful,
10   but WITHOUT ANY WARRANTY; without even the implied warranty of
11   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12   GNU General Public License for more details.
13
14   You should have received a copy of the GNU General Public License
15   along with this program.  If not, see <https://www.gnu.org/licenses/>.
16 */
17 #ifndef _FOREIGN_H
18 #define _FOREIGN_H
19 #include <stdbool.h>
20 #include <libudev.h>
21
22 #define LIBMP_FOREIGN_API ((1 << 8) | 0)
23
24 struct context;
25
26 /* return codes of functions below returning "int" */
27 enum foreign_retcode {
28         FOREIGN_OK,
29         FOREIGN_CLAIMED,
30         FOREIGN_IGNORED,
31         FOREIGN_UNCLAIMED,
32         FOREIGN_NODEV,
33         FOREIGN_ERR,
34         __LAST_FOREIGN_RETCODE,
35 };
36
37 /**
38  * Foreign multipath library API
39  * Foreign libraries must implement the following methods.
40  */
41 struct foreign {
42         /**
43          * method: init(api, name)
44          * Initialize foreign library, and check API compatibility
45          * return pointer to opaque internal data strucure if successful,
46          * NULL otherwise.
47          *
48          * @param[in] api: API version
49          * @param[in] name: name to use for references to self in log messages,
50          *     doesn't need to be strdup'd
51          * @returns context pointer to use in future method calls.
52          */
53         struct context* (*init)(unsigned int api, const char *name);
54
55         /**
56          * method: cleanup(context)
57          * Free data structures used by foreign library, including
58          * context itself.
59          *
60          * @param[in] context foreign library context. This shouldn't be
61          * referenced any more after calling cleanup().
62          */
63         void (*cleanup)(struct context *);
64
65         /**
66          * method: add(context, udev)
67          * This is called during path detection, and for udev ADD events.
68          *
69          * @param[in] context foreign library context
70          * @param[in] udev udev device to add
71          * @returns status code
72          * @retval FOREIGN_CLAIMED: device newly claimed
73          * @retval FOREIGN_OK: device already registered, no action taken
74          * @retval FOREIGN_IGNORED: device is ignored, no action taken
75          * @retval FOREIGN_ERR: an error occurred (e.g. out-of-memory)
76          */
77         int (*add)(struct context *, struct udev_device *);
78
79         /**
80          * method: change
81          * This is called on udev CHANGE events.
82          *
83          * @param[in] context foreign library context
84          * @param[in] udev udev device that has generated the event
85          * @returns status code
86          * @retval FOREIGN_OK: event processed
87          * @retval FOREIGN_IGNORED: the device is ignored
88          * @retval FOREIGN_ERR: an error occurred (e.g. out-of-memory)
89          *
90          * Note: theoretically it can happen that the status of a foreign device
91          * (claimed vs. not claimed) changes in a change event.
92          * Supporting this correctly would require big efforts. For now, we
93          * don't support it. "multipathd reconfigure" starts foreign device
94          * detection from scratch and should be able to handle this situation.
95          */
96         int (*change)(struct context *, struct udev_device *);
97
98         /**
99          * method: delete
100          * This is called on udev DELETE events.
101          *
102          * @param[in] context foreign library context
103          * @param[in] udev udev device that has generated the event and
104          *      should be deleted
105          * @returns status code
106          * @retval FOREIGN_OK: processed correctly (device deleted)
107          * @retval FOREIGN_IGNORED: device wasn't registered internally
108          * @retval FOREIGN_ERR: error occurred.
109          */
110         int (*delete)(struct context *, struct udev_device *);
111
112         /**
113          * method: delete_all
114          * This is called if multipathd reconfigures itself.
115          * Deletes all registered devices (maps and paths)
116          *
117          * @param[in] context foreign library context
118          * @returns status code
119          * @retval FOREIGN_OK: processed correctly
120          * @retval FOREIGN_IGNORED: nothing to delete
121          * @retval FOREIGN_ERR: error occurred
122          */
123         int (*delete_all)(struct context*);
124
125         /**
126          * method: check
127          * This is called from multipathd's checker loop.
128          *
129          * Check status of managed devices, update internal status, and print
130          * log messages if appropriate.
131          * @param[in] context foreign library context
132          */
133         void (*check)(struct context *);
134
135         /**
136          * lock internal data structures.
137          * @param[in] ctx: foreign context
138          */
139         void (*lock)(struct context *ctx);
140
141         /**
142          * unlock internal data structures.
143          * @param[in] ctx: foreign context (void* in order to use the function
144          *      as argument to pthread_cleanup_push())
145          */
146         void (*unlock)(void *ctx);
147
148         /**
149          * method: get_multipaths(context)
150          * Returned vector must be freed by calling release_multipaths().
151          * Lock must be held until release_multipaths() is called.
152          *
153          * @param[in] context foreign library context
154          * @returns a vector of "struct gen_multipath*" with the map devices
155          * belonging to this library (see generic.h).
156          */
157         const struct _vector* (*get_multipaths)(const struct context *);
158
159         /**
160          * method: release_multipaths(context, mpvec)
161          * release data structures obtained with get_multipaths (if any)
162          *
163          * @param[in] ctx the foreign context
164          * @param[in] mpvec the vector allocated with get_multipaths()
165          */
166         void (*release_multipaths)(const struct context *ctx,
167                                    const struct _vector* mpvec);
168
169         /**
170          * method: get_paths
171          * Returned vector must be freed by calling release_paths().
172          * Lock must be held until release_paths() is called.
173          *
174          * @param[in] context foreign library context
175          * @returns a vector of "struct gen_path*" with the path devices
176          * belonging to this library (see generic.h)
177          */
178         const struct _vector* (*get_paths)(const struct context *);
179
180         /**
181          * release data structures obtained with get_multipaths (if any)
182          *
183          * @param[in] ctx the foreign context
184          * @param[in] ppvec the vector allocated with get_paths()
185          */
186         void (*release_paths)(const struct context *ctx,
187                               const struct _vector* ppvec);
188
189         void *handle;
190         struct context *context;
191         const char name[0];
192 };
193
194 /**
195  * init_foreign(dir)
196  * load and initialize foreign multipath libraries in dir (libforeign-*.so).
197  * @param dir: directory to search
198  * @returns: 0 on success, negative value on failure.
199  */
200 int init_foreign(const char *multipath_dir);
201
202 /**
203  * cleanup_foreign(dir)
204  * cleanup and free all data structures owned by foreign libraries
205  */
206 void cleanup_foreign(void);
207
208 /**
209  * add_foreign(udev)
210  * check if a device belongs to any foreign library.
211  * calls add() for all known foreign libs, in the order registered,
212  * until the first one returns FOREIGN_CLAIMED or FOREIGN_OK.
213  * @param udev: udev device to check
214  * @returns: status code
215  * @retval FOREIGN_CLAIMED: newly claimed by a foreign lib
216  * @retval FOREIGN_OK: already claimed by a foreign lib
217  * @retval FOREIGN_IGNORED: ignored by all foreign libs
218  * @retval FOREIGN_ERR: an error occurred
219  */
220 int add_foreign(struct udev_device *);
221
222 /**
223  * change_foreign(udev)
224  * Notify foreign libraries of an udev CHANGE event
225  * @param udev: udev device to check
226  * @returns: status code (see change() method above).
227  */
228 int change_foreign(struct udev_device *);
229
230 /**
231  * delete_foreign(udev)
232  * @param udev: udev device being removed
233  * @returns: status code (see remove() above)
234  */
235 int delete_foreign(struct udev_device *);
236
237 /**
238  * delete_all_foreign()
239  * call delete_all() for all foreign libraries
240  * @returns: status code (see delete_all() above)
241  */
242 int delete_all_foreign(void);
243
244 /**
245  * check_foreign()
246  * call check() (see above) for all foreign libraries
247  */
248 void check_foreign(void);
249
250 /**
251  * foreign_path_layout()
252  * call this before printing paths, after get_path_layout(), to determine
253  * output field width.
254  */
255 void foreign_path_layout(void);
256
257 /**
258  * foreign_multipath_layout()
259  * call this before printing maps, after get_multipath_layout(), to determine
260  * output field width.
261  */
262 void foreign_multipath_layout(void);
263
264 /**
265  * snprint_foreign_topology(buf, len, verbosity);
266  * prints topology information from foreign libraries into buffer,
267  * '\0' - terminated.
268  * @param buf: output buffer
269  * @param len: size of output buffer
270  * @param verbosity: verbosity level
271  * @returns: number of printed characters excluding trailing '\0'.
272  */
273 int snprint_foreign_topology(char *buf, int len, int verbosity);
274
275 /**
276  * snprint_foreign_paths(buf, len, style, pad);
277  * prints formatted path information from foreign libraries into buffer,
278  * '\0' - terminated.
279  * @param buf: output buffer
280  * @param len: size of output buffer
281  * @param style: format string
282  * @param pad: whether to pad field width
283  * @returns: number of printed characters excluding trailing '\0'.
284  */
285 int snprint_foreign_paths(char *buf, int len, const char *style, int pad);
286
287 /**
288  * snprint_foreign_multipaths(buf, len, style, pad);
289  * prints formatted map information from foreign libraries into buffer,
290  * '\0' - terminated.
291  * @param buf: output buffer
292  * @param len: size of output buffer
293  * @param style: format string
294  * @param pad: whether to pad field width
295  * @returns: number of printed characters excluding trailing '\0'.
296  */
297 int snprint_foreign_multipaths(char *buf, int len,
298                                const char *style, int pretty);
299
300 /**
301  * print_foreign_topology(v)
302  * print foreign topology to stdout
303  * @param verbosity: verbosity level
304  */
305 void print_foreign_topology(int verbosity);
306
307 /**
308  * is_claimed_by_foreign(ud)
309  * @param udev: udev device
310  * @returns: true if device is (newly or already) claimed by a foreign lib
311  */
312 static inline bool
313 is_claimed_by_foreign(struct udev_device *ud)
314 {
315         int rc = add_foreign(ud);
316
317         return (rc == FOREIGN_CLAIMED || rc == FOREIGN_OK);
318 }
319
320 #endif /*  _FOREIGN_H */