2 Copyright (c) 2018 Martin Wilck, SUSE Linux GmbH
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.
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.
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,
24 #define LIBMP_FOREIGN_API ((1 << 8) | 0)
28 /* return codes of functions below returning "int" */
29 enum foreign_retcode {
36 __LAST_FOREIGN_RETCODE,
40 * Foreign multipath library API
41 * Foreign libraries must implement the following methods.
45 * method: init(api, name)
46 * Initialize foreign library, and check API compatibility
47 * return pointer to opaque internal data strucure if successful,
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.
55 struct context* (*init)(unsigned int api, const char *name);
58 * method: cleanup(context)
59 * Free data structures used by foreign library, including
62 * @param[in] context foreign library context. This shouldn't be
63 * referenced any more after calling cleanup().
65 void (*cleanup)(struct context *);
68 * method: add(context, udev)
69 * This is called during path detection, and for udev ADD events.
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 occured (e.g. out-of-memory)
79 int (*add)(struct context *, struct udev_device *);
83 * This is called on udev CHANGE events.
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 occured (e.g. out-of-memory)
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.
98 int (*change)(struct context *, struct udev_device *);
102 * This is called on udev DELETE events.
104 * @param[in] context foreign library context
105 * @param[in] udev udev device that has generated the event and
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 occured.
112 int (*delete)(struct context *, struct udev_device *);
116 * This is called if multipathd reconfigures itself.
117 * Deletes all registered devices (maps and paths)
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 occured
125 int (*delete_all)(struct context*);
129 * This is called from multipathd's checker loop.
131 * Check status of managed devices, update internal status, and print
132 * log messages if appropriate.
133 * @param[in] context foreign library context
135 void (*check)(struct context *);
138 * lock internal data stuctures.
139 * @param[in] ctx: foreign context
141 void (*lock)(struct context *ctx);
144 * unlock internal data stuctures.
145 * @param[in] ctx: foreign context (void* in order to use the function
146 * as argument to pthread_cleanup_push())
148 void (*unlock)(void *ctx);
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.
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).
159 const struct _vector* (*get_multipaths)(const struct context *);
162 * method: release_multipaths(context, mpvec)
163 * release data structures obtained with get_multipaths (if any)
165 * @param[in] ctx the foreign context
166 * @param[in] mpvec the vector allocated with get_multipaths()
168 void (*release_multipaths)(const struct context *ctx,
169 const struct _vector* mpvec);
173 * Returned vector must be freed by calling release_paths().
174 * Lock must be held until release_paths() is called.
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)
180 const struct _vector* (*get_paths)(const struct context *);
183 * release data structures obtained with get_multipaths (if any)
185 * @param[in] ctx the foreign context
186 * @param[in] ppvec the vector allocated with get_paths()
188 void (*release_paths)(const struct context *ctx,
189 const struct _vector* ppvec);
192 struct context *context;
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.
202 int init_foreign(const char *multipath_dir);
205 * cleanup_foreign(dir)
206 * cleanup and free all data structures owned by foreign libraries
208 void cleanup_foreign(void);
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 occured
222 int add_foreign(struct udev_device *);
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).
230 int change_foreign(struct udev_device *);
233 * delete_foreign(udev)
234 * @param udev: udev device being removed
235 * @returns: status code (see remove() above)
237 int delete_foreign(struct udev_device *);
240 * delete_all_foreign()
241 * call delete_all() for all foreign libraries
242 * @returns: status code (see delete_all() above)
244 int delete_all_foreign(void);
248 * call check() (see above) for all foreign libraries
250 void check_foreign(void);
253 * foreign_path_layout()
254 * call this before printing paths, after get_path_layout(), to determine
255 * output field width.
257 void foreign_path_layout(void);
260 * foreign_multipath_layout()
261 * call this before printing maps, after get_multipath_layout(), to determine
262 * output field width.
264 void foreign_multipath_layout(void);
267 * snprint_foreign_topology(buf, len, verbosity);
268 * prints topology information from foreign libraries into buffer,
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'.
275 int snprint_foreign_topology(char *buf, int len, int verbosity);
278 * snprint_foreign_paths(buf, len, style, pad);
279 * prints formatted path information from foreign libraries into buffer,
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'.
287 int snprint_foreign_paths(char *buf, int len, const char *style, int pad);
290 * snprint_foreign_multipaths(buf, len, style, pad);
291 * prints formatted map information from foreign libraries into buffer,
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'.
299 int snprint_foreign_multipaths(char *buf, int len,
300 const char *style, int pretty);
303 * print_foreign_topology(v)
304 * print foreign topology to stdout
305 * @param verbosity: verbosity level
307 void print_foreign_topology(int verbosity);
310 * is_claimed_by_foreign(ud)
311 * @param udev: udev device
312 * @returns: true iff device is (newly or already) claimed by a foreign lib
315 is_claimed_by_foreign(struct udev_device *ud)
317 int rc = add_foreign(ud);
319 return (rc == FOREIGN_CLAIMED || rc == FOREIGN_OK);
322 #endif /* _FOREIGN_H */