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, see <https://www.gnu.org/licenses/>.
21 #define LIBMP_FOREIGN_API ((1 << 8) | 2)
26 /* return codes of functions below returning "int" */
27 enum foreign_retcode {
34 __LAST_FOREIGN_RETCODE,
38 * Foreign multipath library API
39 * Foreign libraries must implement the following methods.
43 * method: init(api, name)
44 * Initialize foreign library, and check API compatibility
45 * return pointer to opaque internal data structure if successful,
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.
53 struct context* (*init)(unsigned int api, const char *name);
56 * method: cleanup(context)
57 * Free data structures used by foreign library, including
60 * @param[in] context foreign library context. This shouldn't be
61 * referenced any more after calling cleanup().
63 void (*cleanup)(struct context *);
66 * method: add(context, udev)
67 * This is called during path detection, and for udev ADD events.
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)
77 int (*add)(struct context *, struct udev_device *);
81 * This is called on udev CHANGE events.
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)
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.
96 int (*change)(struct context *, struct udev_device *);
100 * This is called on udev DELETE events.
102 * @param[in] context foreign library context
103 * @param[in] udev udev device that has generated the event and
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.
110 int (*delete)(struct context *, struct udev_device *);
114 * This is called if multipathd reconfigures itself.
115 * Deletes all registered devices (maps and paths)
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
123 int (*delete_all)(struct context*);
127 * This is called from multipathd's checker loop.
129 * Check status of managed devices, update internal status, and print
130 * log messages if appropriate.
131 * @param[in] context foreign library context
133 void (*check)(struct context *);
136 * lock internal data structures.
137 * @param[in] ctx: foreign context
139 void (*lock)(struct context *ctx);
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())
146 void (*unlock)(void *ctx);
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.
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).
157 const struct _vector* (*get_multipaths)(const struct context *);
160 * method: release_multipaths(context, mpvec)
161 * release data structures obtained with get_multipaths (if any)
163 * @param[in] ctx the foreign context
164 * @param[in] mpvec the vector allocated with get_multipaths()
166 void (*release_multipaths)(const struct context *ctx,
167 const struct _vector* mpvec);
171 * Returned vector must be freed by calling release_paths().
172 * Lock must be held until release_paths() is called.
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)
178 const struct _vector* (*get_paths)(const struct context *);
181 * release data structures obtained with get_multipaths (if any)
183 * @param[in] ctx the foreign context
184 * @param[in] ppvec the vector allocated with get_paths()
186 void (*release_paths)(const struct context *ctx,
187 const struct _vector* ppvec);
190 struct context *context;
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.
201 int init_foreign(const char *multipath_dir, const char *enable);
204 * cleanup_foreign(dir)
205 * cleanup and free all data structures owned by foreign libraries
207 void cleanup_foreign(void);
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
221 int add_foreign(struct udev_device *);
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).
229 int change_foreign(struct udev_device *);
232 * delete_foreign(udev)
233 * @param udev: udev device being removed
234 * @returns: status code (see remove() above)
236 int delete_foreign(struct udev_device *);
239 * delete_all_foreign()
240 * call delete_all() for all foreign libraries
241 * @returns: status code (see delete_all() above)
243 int delete_all_foreign(void);
247 * call check() (see above) for all foreign libraries
249 void check_foreign(void);
252 * foreign_path_layout()
253 * call this before printing paths, after get_path_layout(), to determine
254 * output field width.
255 * @param width: an array allocated by alloc_path_layout()
257 void foreign_path_layout(fieldwidth_t *width);
260 * foreign_multipath_layout()
261 * call this before printing maps, after get_multipath_layout(), to determine
262 * output field width.
263 * @param width: an array allocated by alloc_multipath_layout()
265 void foreign_multipath_layout(fieldwidth_t *width);
268 * snprint_foreign_topology(buf, len, verbosity);
269 * prints topology information from foreign libraries into buffer,
271 * @param buf: output buffer
272 * @param verbosity: verbosity level
273 * @param width: an array of field widths, initialized by _get_path_layout()
274 * @returns: number of printed characters excluding trailing '\0'.
276 int snprint_foreign_topology(struct strbuf *buf, int verbosity,
277 const fieldwidth_t *width);
280 * snprint_foreign_paths(buf, len, style, pad);
281 * prints formatted path information from foreign libraries into buffer,
283 * @param buf: output buffer
284 * @param style: format string
285 * @param width: array initialized with get_path_layout(), or NULL for no padding
286 * @returns: number of printed characters excluding trailing '\0'.
288 int snprint_foreign_paths(struct strbuf *buf, const char *style,
289 const fieldwidth_t *width);
292 * snprint_foreign_multipaths(buf, len, style, pad);
293 * prints formatted map information from foreign libraries into buffer,
295 * @param buf: output buffer
296 * @param style: format string
297 * @param width: array initialized with get_path_layout(), or NULL for no padding
298 * @returns: number of printed characters excluding trailing '\0'.
300 int snprint_foreign_multipaths(struct strbuf *buf, const char *style,
301 const fieldwidth_t *width);
304 * print_foreign_topology(v)
305 * print foreign topology to stdout
306 * @param verbosity: verbosity level
308 void print_foreign_topology(int verbosity);
311 * is_claimed_by_foreign(ud)
312 * @param udev: udev device
313 * @returns: true if device is (newly or already) claimed by a foreign lib
316 is_claimed_by_foreign(struct udev_device *ud)
318 int rc = add_foreign(ud);
320 return (rc == FOREIGN_CLAIMED || rc == FOREIGN_OK);
323 #endif /* _FOREIGN_H */