From: "Benjamin Marzinski" <bmarzins@redhat.com>
To: Martin Wilck <mwilck@suse.com>
Cc: dm-devel@redhat.com
Subject: Re: [RFC PATCH 15/20] libmultipath: API for foreign multipath handling
Date: Wed, 28 Feb 2018 21:01:55 -0600 [thread overview]
Message-ID: <20180301030155.GL14513@octiron.msp.redhat.com> (raw)
In-Reply-To: <20180220132658.22295-16-mwilck@suse.com>
On Tue, Feb 20, 2018 at 02:26:53PM +0100, Martin Wilck wrote:
> Add an API for "foreign" multipaths. Foreign libraries are loaded
> from ${multipath_dir}/libforeign-*.so, as we do for checkers.
>
> Refer to "foreign.h" for details about the API itself. Like we do for
> checkers, high-level multipath code isn't supposed to call the API directly,
> but rather the wrapper functions declared in "foreign.h".
>
> This API is used only for displaying information and for logging. An extension to
> other functionality (such as monitoring or administration) might be feasible,
> but is not planned.
>
> Foreign libraries communicate with libmultipath through the API defined in
> "foreign.h". The foreign library can implement multipath maps, pathgroups,
> and paths as it likes, they just need to provide the simple interfaces
> defined in "generic.h" to libmultipath. These interfaces are used in libmultipath's
> "print" implementation to convey various bits of information to users. By
> using the same interfaces for printing that libmultipath uses internally,
> foreign library implementations can focus on the technical side without
> worrying about output formatting compatibility.
ACK, with one minor nit
>
> Signed-off-by: Martin Wilck <mwilck@suse.com>
> ---
> libmultipath/Makefile | 2 +-
> libmultipath/foreign.c | 471 +++++++++++++++++++++++++++++++++++++++++++++++++
> libmultipath/foreign.h | 322 +++++++++++++++++++++++++++++++++
> 3 files changed, 794 insertions(+), 1 deletion(-)
> create mode 100644 libmultipath/foreign.c
> create mode 100644 libmultipath/foreign.h
<snip>
> +struct foreign {
> + /**
> + * method: init(api, name)
> + * Initialize foreign library, and check API compatibility
> + * return pointer to opaque internal data strucure if successful,
> + * NULL otherwise.
> + *
> + * @param[in] api: API version
> + * @param[in] name: name to use for references to self in log messages,
> + * doesn't need to be strdup'd
> + * @returns context pointer to use in future method calls.
> + */
> + struct context* (*init)(unsigned int api, const char *name);
> +
> + /**
> + * method: cleanup(context)
> + * Free data structures used by foreign library, including
> + * context itself.
> + *
> + * @param[in] context foreign library context. This shouldn't be
> + * referenced any more after calling cleanup().
> + */
> + void (*cleanup)(struct context *);
> +
> + /**
> + * method: add(context, udev)
> + * This is called during path detection, and for udev ADD events.
> + *
> + * @param[in] context foreign library context
> + * @param[in] udev udev device to add
> + * @returns status code
> + * @retval FOREIGN_CLAIMED: device newly claimed
> + * @retval FOREIGN_OK: device already registered, no action taken
> + * @retval FOREIGN_IGNORED: device is ignored, no action taken
> + * @retval FOREIGN_ERR: an error occured (e.g. out-of-memory)
> + */
> + int (*add)(struct context *, struct udev_device *);
> +
> + /**
> + * method: change
> + * This is called on udev CHANGE events.
> + *
> + * @param[in] context foreign library context
> + * @param[in] udev udev device that has generated the event
> + * @returns status code
> + * @retval FOREIGN_OK: event processed
> + * @retval FOREIGN_IGNORED: the device is ignored
> + * @retval FOREIGN_ERR: an error occured (e.g. out-of-memory)
> + *
> + * Note: theoretically it can happen that the status of a foreign device
> + * (claimed vs. not claimed) changes in a change event.
> + * Supporting this correctly would require big efforts. For now, we
> + * don't support it. "multipathd reconfigure" starts foreign device
> + * detection from scratch and should be able to handle this situation.
> + */
> + int (*change)(struct context *, struct udev_device *);
> +
> + /**
> + * method: delete
> + * This is called on udev DELETE events.
> + *
> + * @param[in] context foreign library context
> + * @param[in] udev udev device that has generated the event and
> + * should be deleted
> + * @returns status code
> + * @retval FOREIGN_OK: processed correctly (device deleted)
> + * @retval FOREIGN_IGNORED: device wasn't registered internally
> + * @retval FOREIGN_ERR: error occured.
> + */
> + int (*delete)(struct context *, struct udev_device *);
> +
> + /**
> + * method: delete_all
> + * This is called if multipathd reconfigures itself.
> + * Deletes all registered devices (maps and paths)
> + *
> + * @param[in] context foreign library context
> + * @returns status code
> + * @retval FOREIGN_OK: processed correctly
> + * @retval FOREIGN_IGNORED: nothing to delete
> + * @retval FOREIGN_ERR: error occured
> + */
> + int (*delete_all)(struct context*);
> +
> + /**
> + * method: check
> + * This is called from multipathd's checker loop.
> + *
> + * Check status of managed devices, update internal status, and print
> + * log messages if appropriate.
> + * @param[in] context foreign library context
> + */
> + void (*check)(struct context *);
> +
> + /**
> + * lock internal data stuctures.
> + * @param[in] ctx: foreign context
> + */
> + void (*lock)(struct context *ctx);
> +
> + /**
> + * unlock internal data stuctures.
> + * @param[in] ctx: foreign context (void* in order to use the function
> + * as argument to pthread_cleanup_push())
> + */
> + void (*unlock)(void *ctx);
> +
> + /**
> + * method: get_multipaths(context)
> + * Returned vector must be freed by calling release_multipaths().
> + * Lock must be held until release_multipaths() is called.
> + *
> + * @param[in] context foreign library context
> + * @returns a vector of "struct gen_multipath*" with the map devices
> + * belonging to this library (see generic.h).
> + */
> + const struct _vector* (*get_multipaths)(const struct context *);
> +
> + /**
> + * method: release_multipaths(context, mpvec)
> + * release data structures obtained with get_multipaths (if any)
> + *
> + * @param[in] ctx the foreign context
> + * @param[in] mpvec the vector allocated with get_multipaths()
> + */
> + void (*release_multipaths)(const struct context *ctx,
> + const struct _vector* mpvec);
> +
> + /**
> + * method: get_paths
> + * Returned vector must be freed by calling release_paths().
> + * Lock must be held until release_paths() is called.
> + *
> + * @param[in] context foreign library context
> + * @returns a vector of "struct gen_path*" with the path devices
> + * belonging to this library (see generic.h)
> + */
> + const struct _vector* (*get_paths)(const struct context *);
> +
> + /**
> + * release data structures obtained with get_multipaths (if any)
> + *
> + * @param[in] ctx the foreign context
> + * @param[in] ppvec the vector allocated with get_paths()
> + */
> + void (*release_paths)(const struct context *ctx,
> + const struct _vector* ppvec);
> +
> + const char *name;
> + void *handle;
> + struct context *context;
> +};
Instead of having a separate pointer "name", would you mind using
const char name[0];
at the end of the structure, like struct logmsg does? I believe this
should work with const.
-Ben
> +
> +/**
> + * init_foreign(dir)
> + * load and initialize foreign multipath libraries in dir (libforeign-*.so).
> + * @param dir: directory to search
> + * @returns: 0 on success, negative value on failure.
> + */
> +int init_foreign(const char *multipath_dir);
> +
> +/**
> + * cleanup_foreign(dir)
> + * cleanup and free all data structures owned by foreign libraries
> + */
> +void cleanup_foreign(void);
> +
> +/**
> + * add_foreign(udev)
> + * check if a device belongs to any foreign library.
> + * calls add() for all known foreign libs, in the order registered,
> + * until the first one returns FOREIGN_CLAIMED or FOREIGN_OK.
> + * @param udev: udev device to check
> + * @returns: status code
> + * @retval FOREIGN_CLAIMED: newly claimed by a foreign lib
> + * @retval FOREIGN_OK: already claimed by a foreign lib
> + * @retval FOREIGN_IGNORED: ignored by all foreign libs
> + * @retval FOREIGN_ERR: an error occured
> + */
> +int add_foreign(struct udev_device *);
> +
> +/**
> + * change_foreign(udev)
> + * Notify foreign libraries of an udev CHANGE event
> + * @param udev: udev device to check
> + * @returns: status code (see change() method above).
> + */
> +int change_foreign(struct udev_device *);
> +
> +/**
> + * delete_foreign(udev)
> + * @param udev: udev device being removed
> + * @returns: status code (see remove() above)
> + */
> +int delete_foreign(struct udev_device *);
> +
> +/**
> + * delete_all_foreign()
> + * call delete_all() for all foreign libraries
> + * @returns: status code (see delete_all() above)
> + */
> +int delete_all_foreign(void);
> +
> +/**
> + * check_foreign()
> + * call check() (see above) for all foreign libraries
> + */
> +void check_foreign(void);
> +
> +/**
> + * foreign_path_layout()
> + * call this before printing paths, after get_path_layout(), to determine
> + * output field width.
> + */
> +void foreign_path_layout(void);
> +
> +/**
> + * foreign_multipath_layout()
> + * call this before printing maps, after get_multipath_layout(), to determine
> + * output field width.
> + */
> +void foreign_multipath_layout(void);
> +
> +/**
> + * snprint_foreign_topology(buf, len, verbosity);
> + * prints topology information from foreign libraries into buffer,
> + * '\0' - terminated.
> + * @param buf: output buffer
> + * @param len: size of output buffer
> + * @param verbosity: verbosity level
> + * @returns: number of printed characters excluding trailing '\0'.
> + */
> +int snprint_foreign_topology(char *buf, int len, int verbosity);
> +
> +/**
> + * snprint_foreign_paths(buf, len, style, pad);
> + * prints formatted path information from foreign libraries into buffer,
> + * '\0' - terminated.
> + * @param buf: output buffer
> + * @param len: size of output buffer
> + * @param style: format string
> + * @param pad: whether to pad field width
> + * @returns: number of printed characters excluding trailing '\0'.
> + */
> +int snprint_foreign_paths(char *buf, int len, const char *style, int pad);
> +
> +/**
> + * snprint_foreign_multipaths(buf, len, style, pad);
> + * prints formatted map information from foreign libraries into buffer,
> + * '\0' - terminated.
> + * @param buf: output buffer
> + * @param len: size of output buffer
> + * @param style: format string
> + * @param pad: whether to pad field width
> + * @returns: number of printed characters excluding trailing '\0'.
> + */
> +int snprint_foreign_multipaths(char *buf, int len,
> + const char *style, int pretty);
> +
> +/**
> + * print_foreign_topology(v)
> + * print foreign topology to stdout
> + * @param verbosity: verbosity level
> + */
> +void print_foreign_topology(int verbosity);
> +
> +/**
> + * is_claimed_by_foreign(ud)
> + * @param udev: udev device
> + * @returns: true iff device is (newly or already) claimed by a foreign lib
> + */
> +static inline bool
> +is_claimed_by_foreign(struct udev_device *ud)
> +{
> + int rc = add_foreign(ud);
> +
> + return (rc == FOREIGN_CLAIMED || rc == FOREIGN_OK);
> +}
> +
> +#endif /* _FOREIGN_H */
> --
> 2.16.1
next prev parent reply other threads:[~2018-03-01 3:01 UTC|newest]
Thread overview: 63+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-02-20 13:26 [RFC PATCH 00/20] "Foreign" NVMe support for multipath-tools Martin Wilck
2018-02-20 13:26 ` [RFC PATCH 01/20] multipath(d)/Makefile: add explicit dependency on libraries Martin Wilck
2018-03-01 5:35 ` Benjamin Marzinski
2018-02-20 13:26 ` [RFC PATCH 02/20] libmultipath: remove unused "stdout helpers" Martin Wilck
2018-03-01 5:36 ` Benjamin Marzinski
2018-02-20 13:26 ` [RFC PATCH 03/20] libmultipath: get rid of selector "hack" in print.c Martin Wilck
2018-03-01 5:36 ` Benjamin Marzinski
2018-02-20 13:26 ` [RFC PATCH 04/20] libmultipath: parser: use call-by-value for "snprint" methods Martin Wilck
2018-03-01 5:37 ` Benjamin Marzinski
2018-02-20 13:26 ` [RFC PATCH 05/20] libmultipath: don't update path groups when printing Martin Wilck
2018-02-28 23:40 ` Benjamin Marzinski
2018-03-02 13:59 ` Martin Wilck
2018-03-02 15:31 ` Benjamin Marzinski
2018-02-20 13:26 ` [RFC PATCH 06/20] libmultipath/print: use "const" where appropriate Martin Wilck
2018-03-01 5:37 ` Benjamin Marzinski
2018-02-20 13:26 ` [RFC PATCH 07/20] libmultipath: use "const" in devmapper code Martin Wilck
2018-03-01 5:39 ` Benjamin Marzinski
2018-02-20 13:26 ` [RFC PATCH 08/20] libmultipath: fix compiler warnings for -Wcast-qual Martin Wilck
2018-03-01 5:39 ` Benjamin Marzinski
2018-02-20 13:26 ` [RFC PATCH 09/20] multipath-tools: Makefile.inc: use -Werror=cast-qual Martin Wilck
2018-03-01 5:59 ` Benjamin Marzinski
2018-02-20 13:26 ` [RFC PATCH 10/20] libmultipath: add vector_free_const() Martin Wilck
2018-03-01 6:00 ` Benjamin Marzinski
2018-02-20 13:26 ` [RFC PATCH 11/20] libmultipath: add vector_convert() Martin Wilck
2018-03-01 6:02 ` Benjamin Marzinski
2018-02-20 13:26 ` [RFC PATCH 12/20] libmultipath: "generic multipath" interface Martin Wilck
2018-02-28 23:47 ` Benjamin Marzinski
2018-03-01 8:51 ` Martin Wilck
2018-02-20 13:26 ` [RFC PATCH 13/20] libmultipath: print: convert API to generic data type Martin Wilck
2018-02-28 23:55 ` Benjamin Marzinski
2018-02-20 13:26 ` [RFC PATCH 14/20] libmultipath: print: use generic API for get_x_layout() Martin Wilck
2018-03-01 6:03 ` Benjamin Marzinski
2018-02-20 13:26 ` [RFC PATCH 15/20] libmultipath: API for foreign multipath handling Martin Wilck
2018-03-01 3:01 ` Benjamin Marzinski [this message]
2018-02-20 13:26 ` [RFC PATCH 16/20] libmultipath/print: add "%G - foreign" wildcard Martin Wilck
2018-03-01 6:04 ` Benjamin Marzinski
2018-02-20 13:26 ` [RFC PATCH 17/20] libmultipath/foreign: nvme foreign library Martin Wilck
2018-03-01 3:14 ` Benjamin Marzinski
2018-03-02 16:04 ` Martin Wilck
2018-03-02 18:30 ` Benjamin Marzinski
2018-02-20 13:26 ` [RFC PATCH 18/20] multipath: use foreign API Martin Wilck
2018-03-01 3:55 ` Benjamin Marzinski
2018-03-02 16:36 ` Martin Wilck
2018-02-20 13:26 ` [RFC PATCH 19/20] multipathd: " Martin Wilck
2018-03-01 5:13 ` Benjamin Marzinski
2018-03-02 17:04 ` Martin Wilck
2018-03-02 18:42 ` Benjamin Marzinski
2018-03-02 19:19 ` Martin Wilck
2018-03-02 20:00 ` Benjamin Marzinski
2018-03-02 21:18 ` [PATCH] multipathd: fix inverted signal blocking logic Martin Wilck
2018-03-02 21:35 ` Bart Van Assche
2018-03-02 22:15 ` Martin Wilck
2018-03-02 22:23 ` Bart Van Assche
2018-03-02 23:16 ` Martin Wilck
2018-03-02 23:27 ` Bart Van Assche
2018-03-03 0:31 ` Martin Wilck
2018-03-05 16:27 ` Bart Van Assche
2018-03-05 17:28 ` Martin Wilck
2018-03-06 0:46 ` Benjamin Marzinski
2018-03-06 8:48 ` Martin Wilck
2018-03-02 21:00 ` [RFC PATCH 19/20] multipathd: use foreign API Bart Van Assche
2018-02-20 13:26 ` [RFC PATCH 20/20] libmultipath: foreign/nvme: implement path display Martin Wilck
2018-03-01 5:19 ` Benjamin Marzinski
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20180301030155.GL14513@octiron.msp.redhat.com \
--to=bmarzins@redhat.com \
--cc=dm-devel@redhat.com \
--cc=mwilck@suse.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox