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));
}
/*