aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorConrad Meyer <cem@FreeBSD.org>2019-05-07 17:47:20 +0000
committerConrad Meyer <cem@FreeBSD.org>2019-05-07 17:47:20 +0000
commit7d7db5298d505495426c2f0790707757fd7c6acb (patch)
tree6168ea2d5cc5ae447ebe8c6c3fdd7fe381bb879a /lib
parent5350e15d0d85c3ffb021adab9304b7e4b1ab7f08 (diff)
downloadsrc-7d7db5298d505495426c2f0790707757fd7c6acb.tar.gz
src-7d7db5298d505495426c2f0790707757fd7c6acb.zip
device_printf: Use sbuf for more coherent prints on SMP
device_printf does multiple calls to printf allowing other console messages to be inserted between the device name, and the rest of the message. This change uses sbuf to compose to two into a single buffer, and prints it all at once. It exposes an sbuf drain function (drain-to-printf) for common use. Update documentation to match; some unit tests included. Submitted by: jmg Sponsored by: Dell EMC Isilon Differential Revision: https://reviews.freebsd.org/D16690
Notes
Notes: svn path=/head/; revision=347229
Diffstat (limited to 'lib')
-rw-r--r--lib/libsbuf/Symbol.map1
-rw-r--r--lib/libsbuf/tests/sbuf_core_test.c61
-rw-r--r--lib/libsbuf/tests/sbuf_stdio_test.c57
3 files changed, 119 insertions, 0 deletions
diff --git a/lib/libsbuf/Symbol.map b/lib/libsbuf/Symbol.map
index 7bbc4bf9f8f1..44839d19456a 100644
--- a/lib/libsbuf/Symbol.map
+++ b/lib/libsbuf/Symbol.map
@@ -37,5 +37,6 @@ FBSD_1.4 {
FBSD_1.5 {
sbuf_putbuf;
+ sbuf_printf_drain;
};
diff --git a/lib/libsbuf/tests/sbuf_core_test.c b/lib/libsbuf/tests/sbuf_core_test.c
index 8ac4984e6804..13a27933c20d 100644
--- a/lib/libsbuf/tests/sbuf_core_test.c
+++ b/lib/libsbuf/tests/sbuf_core_test.c
@@ -63,6 +63,9 @@ ATF_TC_BODY(sbuf_clear_test, tc)
*/
child_proc = atf_utils_fork();
if (child_proc == 0) {
+ ATF_REQUIRE_EQ_MSG(0, sbuf_finish(sb), "sbuf_finish failed: %s",
+ strerror(errno));
+
sbuf_putbuf(sb);
exit(0);
}
@@ -100,6 +103,34 @@ ATF_TC_BODY(sbuf_done_and_sbuf_finish_test, tc)
sbuf_delete(sb);
}
+static int
+drain_ret0(void *arg, const char *data, int len)
+{
+
+ (void)arg;
+ (void)data;
+ (void)len;
+
+ return (0);
+}
+
+ATF_TC_WITHOUT_HEAD(sbuf_drain_ret0_test);
+ATF_TC_BODY(sbuf_drain_ret0_test, tc)
+{
+ struct sbuf *sb;
+
+ sb = sbuf_new_auto();
+
+ sbuf_set_drain(sb, drain_ret0, NULL);
+
+ sbuf_cat(sb, test_string);
+
+ ATF_CHECK_EQ_MSG(-1, sbuf_finish(sb),
+ "required to return error when drain func returns 0");
+ ATF_CHECK_EQ_MSG(EDEADLK, errno,
+ "errno required to be EDEADLK when drain func returns 0");
+}
+
ATF_TC_WITHOUT_HEAD(sbuf_len_test);
ATF_TC_BODY(sbuf_len_test, tc)
{
@@ -131,6 +162,34 @@ ATF_TC_BODY(sbuf_len_test, tc)
sbuf_delete(sb);
}
+ATF_TC_WITHOUT_HEAD(sbuf_new_fixedlen);
+ATF_TC_BODY(sbuf_new_fixedlen, tc)
+{
+ char buf[strlen(test_string) + 1];
+ struct sbuf sb;
+ pid_t child_proc;
+
+ sbuf_new(&sb, buf, sizeof(buf), SBUF_FIXEDLEN);
+
+ sbuf_cat(&sb, test_string);
+
+ child_proc = atf_utils_fork();
+ if (child_proc == 0) {
+ ATF_REQUIRE_EQ_MSG(0, sbuf_finish(&sb), "sbuf_finish failed: %s",
+ strerror(errno));
+
+ sbuf_putbuf(&sb);
+ exit(0);
+ }
+ atf_utils_wait(child_proc, 0, test_string, "");
+
+ sbuf_putc(&sb, ' ');
+
+ ATF_CHECK_EQ_MSG(-1, sbuf_finish(&sb), "failed to return error on overflow");
+
+ sbuf_delete(&sb);
+}
+
ATF_TC_WITHOUT_HEAD(sbuf_setpos_test);
ATF_TC_BODY(sbuf_setpos_test, tc)
{
@@ -190,7 +249,9 @@ ATF_TP_ADD_TCS(tp)
ATF_TP_ADD_TC(tp, sbuf_clear_test);
ATF_TP_ADD_TC(tp, sbuf_done_and_sbuf_finish_test);
+ ATF_TP_ADD_TC(tp, sbuf_drain_ret0_test);
ATF_TP_ADD_TC(tp, sbuf_len_test);
+ ATF_TP_ADD_TC(tp, sbuf_new_fixedlen);
#if 0
/* TODO */
#ifdef HAVE_SBUF_CLEAR_FLAGS
diff --git a/lib/libsbuf/tests/sbuf_stdio_test.c b/lib/libsbuf/tests/sbuf_stdio_test.c
index 681b870a3434..74928d9d09ea 100644
--- a/lib/libsbuf/tests/sbuf_stdio_test.c
+++ b/lib/libsbuf/tests/sbuf_stdio_test.c
@@ -59,6 +59,60 @@ sbuf_vprintf_helper(struct sbuf *sb, const char * restrict format, ...)
return (rc);
}
+ATF_TC_WITHOUT_HEAD(sbuf_printf_drain_null_test);
+ATF_TC_BODY(sbuf_printf_drain_null_test, tc)
+{
+ struct sbuf *sb;
+ char buf[2];
+ pid_t child_proc;
+
+ sb = sbuf_new(NULL, buf, sizeof(buf), SBUF_FIXEDLEN);
+ ATF_REQUIRE_MSG(sb != NULL, "sbuf_new_auto failed: %s",
+ strerror(errno));
+
+ child_proc = atf_utils_fork();
+ if (child_proc == 0) {
+ sbuf_set_drain(sb, sbuf_printf_drain, NULL);
+
+ ATF_REQUIRE_EQ_MSG(0, sbuf_cat(sb, test_string),
+ "sbuf_cat failed");
+
+ ATF_CHECK_EQ(0, sbuf_finish(sb));
+ exit(0);
+ }
+ atf_utils_wait(child_proc, 0, test_string, "");
+
+ sbuf_delete(sb);
+}
+
+ATF_TC_WITHOUT_HEAD(sbuf_printf_drain_test);
+ATF_TC_BODY(sbuf_printf_drain_test, tc)
+{
+ struct sbuf *sb;
+ char buf[2];
+ pid_t child_proc;
+ size_t cnt = 0;
+
+ sb = sbuf_new(NULL, buf, sizeof(buf), SBUF_FIXEDLEN);
+ ATF_REQUIRE_MSG(sb != NULL, "sbuf_new_auto failed: %s",
+ strerror(errno));
+
+ child_proc = atf_utils_fork();
+ if (child_proc == 0) {
+ sbuf_set_drain(sb, sbuf_printf_drain, &cnt);
+
+ ATF_REQUIRE_EQ_MSG(0, sbuf_cat(sb, test_string),
+ "sbuf_cat failed");
+
+ ATF_CHECK_EQ(0, sbuf_finish(sb));
+ ATF_CHECK_EQ(strlen(test_string), cnt);
+ exit(0);
+ }
+ atf_utils_wait(child_proc, 0, test_string, "");
+
+ sbuf_delete(sb);
+}
+
ATF_TC_WITHOUT_HEAD(sbuf_printf_test);
ATF_TC_BODY(sbuf_printf_test, tc)
{
@@ -106,6 +160,7 @@ ATF_TC_BODY(sbuf_putbuf_test, tc)
child_proc = atf_utils_fork();
if (child_proc == 0) {
+ ATF_CHECK_EQ(0, sbuf_finish(sb));
sbuf_putbuf(sb);
exit(0);
}
@@ -152,6 +207,8 @@ ATF_TC_BODY(sbuf_vprintf_test, tc)
ATF_TP_ADD_TCS(tp)
{
+ ATF_TP_ADD_TC(tp, sbuf_printf_drain_null_test);
+ ATF_TP_ADD_TC(tp, sbuf_printf_drain_test);
ATF_TP_ADD_TC(tp, sbuf_printf_test);
ATF_TP_ADD_TC(tp, sbuf_putbuf_test);
ATF_TP_ADD_TC(tp, sbuf_vprintf_test);