Imported Upstream version 0.8.7
[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, see <https://www.gnu.org/licenses/>.
16 */
17 #ifndef _FOREIGN_H
18 #define _FOREIGN_H
19 #include <stdbool.h>
20 #include <libudev.h>
21 #define LIBMP_FOREIGN_API ((1 << 8) | 1)
22
23 struct strbuf;
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  * @param enable: regex to match foreign library name ("*" above) against
199  * @returns: 0 on success, negative value on failure.
200  */
201 int init_foreign(const char *multipath_dir, const char *enable);
202
203 /**
204  * cleanup_foreign(dir)
205  * cleanup and free all data structures owned by foreign libraries
206  */
207 void cleanup_foreign(void);
208
209 /**
210  * add_foreign(udev)
211  * check if a device belongs to any foreign library.
212  * calls add() for all known foreign libs, in the order registered,
213  * until the first one returns FOREIGN_CLAIMED or FOREIGN_OK.
214  * @param udev: udev device to check
215  * @returns: status code
216  * @retval FOREIGN_CLAIMED: newly claimed by a foreign lib
217  * @retval FOREIGN_OK: already claimed by a foreign lib
218  * @retval FOREIGN_IGNORED: ignored by all foreign libs
219  * @retval FOREIGN_ERR: an error occurred
220  */
221 int add_foreign(struct udev_device *);
222
223 /**
224  * change_foreign(udev)
225  * Notify foreign libraries of an udev CHANGE event
226  * @param udev: udev device to check
227  * @returns: status code (see change() method above).
228  */
229 int change_foreign(struct udev_device *);
230
231 /**
232  * delete_foreign(udev)
233  * @param udev: udev device being removed
234  * @returns: status code (see remove() above)
235  */
236 int delete_foreign(struct udev_device *);
237
238 /**
239  * delete_all_foreign()
240  * call delete_all() for all foreign libraries
241  * @returns: status code (see delete_all() above)
242  */
243 int delete_all_foreign(void);
244
245 /**
246  * check_foreign()
247  * call check() (see above) for all foreign libraries
248  */
249 void check_foreign(void);
250
251 /**
252  * foreign_path_layout()
253  * call this before printing paths, after get_path_layout(), to determine
254  * output field width.
255  */
256 void foreign_path_layout(void);
257
258 /**
259  * foreign_multipath_layout()
260  * call this before printing maps, after get_multipath_layout(), to determine
261  * output field width.
262  */
263 void foreign_multipath_layout(void);
264
265 /**
266  * snprint_foreign_topology(buf, len, verbosity);
267  * prints topology information from foreign libraries into buffer,
268  * '\0' - terminated.
269  * @param buf: output buffer
270  * @param verbosity: verbosity level
271  * @returns: number of printed characters excluding trailing '\0'.
272  */
273 int snprint_foreign_topology(struct strbuf *buf, 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 style: format string
281  * @param pad: whether to pad field width
282  * @returns: number of printed characters excluding trailing '\0'.
283  */
284 int snprint_foreign_paths(struct strbuf *buf, const char *style, int pad);
285
286 /**
287  * snprint_foreign_multipaths(buf, len, style, pad);
288  * prints formatted map information from foreign libraries into buffer,
289  * '\0' - terminated.
290  * @param buf: output buffer
291  * @param style: format string
292  * @param pad: whether to pad field width
293  * @returns: number of printed characters excluding trailing '\0'.
294  */
295 int snprint_foreign_multipaths(struct strbuf *buf,
296                                const char *style, int pretty);
297
298 /**
299  * print_foreign_topology(v)
300  * print foreign topology to stdout
301  * @param verbosity: verbosity level
302  */
303 void print_foreign_topology(int verbosity);
304
305 /**
306  * is_claimed_by_foreign(ud)
307  * @param udev: udev device
308  * @returns: true if device is (newly or already) claimed by a foreign lib
309  */
310 static inline bool
311 is_claimed_by_foreign(struct udev_device *ud)
312 {
313         int rc = add_foreign(ud);
314
315         return (rc == FOREIGN_CLAIMED || rc == FOREIGN_OK);
316 }
317
318 #endif /*  _FOREIGN_H */