git: c8cc568961df - main - Provide an interface that allows GEOM modules to return multiple messages.
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Sun, 20 Feb 2022 05:33:11 UTC
The branch main has been updated by mckusick: URL: https://cgit.FreeBSD.org/src/commit/?id=c8cc568961dfccf3d91821f06f7072437b04edf5 commit c8cc568961dfccf3d91821f06f7072437b04edf5 Author: Kirk McKusick <mckusick@FreeBSD.org> AuthorDate: 2022-02-20 05:30:37 +0000 Commit: Kirk McKusick <mckusick@FreeBSD.org> CommitDate: 2022-02-20 05:33:02 +0000 Provide an interface that allows GEOM modules to return multiple messages. The gctl_error() function provides GEOM modules with the ability to report only a single message. When running with the verbose flag, commands that handle multiple devices may want to report a message for each of the devices on which it operates. This commit adds the gctl_msg() function that can be called multiple times to post messages. When finished issuing messages, the application must either call gctl_post_messages() or call gctl_error() to cause the messages to be reported to the calling process. Tested by: Peter Holm --- sys/geom/geom.h | 2 ++ sys/geom/geom_ctl.c | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 57 insertions(+), 2 deletions(-) diff --git a/sys/geom/geom.h b/sys/geom/geom.h index d48deb0e0ae4..fbd9336b2e50 100644 --- a/sys/geom/geom.h +++ b/sys/geom/geom.h @@ -435,6 +435,8 @@ char const *gctl_get_asciiparam(struct gctl_req *req, const char *param); void *gctl_get_paraml(struct gctl_req *req, const char *param, int len); void *gctl_get_paraml_opt(struct gctl_req *req, const char *param, int len); int gctl_error(struct gctl_req *req, const char *fmt, ...) __printflike(2, 3); +void gctl_msg(struct gctl_req *req, const char *fmt, ...) __printflike(2, 3); +void gctl_post_messages(struct gctl_req *req); struct g_class *gctl_get_class(struct gctl_req *req, char const *arg); struct g_geom *gctl_get_geom(struct gctl_req *req, struct g_class *mp, char const *arg); struct g_provider *gctl_get_provider(struct gctl_req *req, char const *arg); diff --git a/sys/geom/geom_ctl.c b/sys/geom/geom_ctl.c index b0e2673bdc42..c387b9e5102c 100644 --- a/sys/geom/geom_ctl.c +++ b/sys/geom/geom_ctl.c @@ -91,18 +91,71 @@ gctl_error(struct gctl_req *req, const char *fmt, ...) if (sbuf_done(req->serror)) { if (!req->nerror) req->nerror = EEXIST; +#ifdef DIAGNOSTIC + printf("gctl_error: buffer closed, message discarded.\n"); +#endif return (req->nerror); } if (!req->nerror) req->nerror = EINVAL; + /* If this is the last of several messages, indent it on a new line */ + if (sbuf_len(req->serror) > 0) + sbuf_cat(req->serror, "\n\t"); va_start(ap, fmt); sbuf_vprintf(req->serror, fmt, ap); va_end(ap); + gctl_post_messages(req); + return (req->nerror); +} + +/* + * The gctl_error() function will only report a single message. + * Commands that handle multiple devices may want to report a + * message for each of the devices. The gctl_msg() function + * can be called multiple times to post messages. When done + * the application must either call gctl_post_messages() or + * call gctl_error() to cause the messages to be reported to + * the calling process. + */ +void +gctl_msg(struct gctl_req *req, const char *fmt, ...) +{ + va_list ap; + + if (req == NULL) + return; + if (sbuf_done(req->serror)) { +#ifdef DIAGNOSTIC + printf("gctl_msg: buffer closed, message discarded.\n"); +#endif + return; + } + /* Put second and later messages indented on a new line */ + if (sbuf_len(req->serror) > 0) + sbuf_cat(req->serror, "\n\t"); + va_start(ap, fmt); + sbuf_vprintf(req->serror, fmt, ap); + va_end(ap); +} + +/* + * Post the messages to the user. + */ +void +gctl_post_messages(struct gctl_req *req) +{ + + if (sbuf_done(req->serror)) { +#ifdef DIAGNOSTIC + printf("gctl_post_messages: message buffer already closed.\n"); +#endif + return; + } sbuf_finish(req->serror); if (g_debugflags & G_F_CTLDUMP) - printf("gctl %p error \"%s\"\n", req, sbuf_data(req->serror)); - return (req->nerror); + printf("gctl %p message(s) \"%s\"\n", req, + sbuf_data(req->serror)); } /*