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