From 5a99de79ab45c9d5278d4a32f473cf84b04350bf Mon Sep 17 00:00:00 2001 From: scottl Date: Thu, 26 Jan 2017 20:08:58 +0000 Subject: [PATCH] Refactor xpt_print_path, xpt_print, and xpt_path_string. Implement all of them in terms of an sbuf-based back-end, xpt_path_sbuf. This unifies the implementation, but more importantly it stops the output fropm being split between 4 or more invocations of printf. The multiple invocations cause interleaving of the messages on the console during boot, making the output of disk discovery often unintelligible. This change helps a lot, but more work is needed. Reviewed by: ken, mav Sponsored by: Netflix --- sys/cam/cam_xpt.c | 76 +++++++++++++++++++++++------------------------ sys/cam/cam_xpt.h | 14 +++++++++ 2 files changed, 51 insertions(+), 39 deletions(-) diff --git a/sys/cam/cam_xpt.c b/sys/cam/cam_xpt.c index ee760b1fc7a9..4f4532354e86 100644 --- a/sys/cam/cam_xpt.c +++ b/sys/cam/cam_xpt.c @@ -3697,33 +3697,14 @@ xpt_path_comp_dev(struct cam_path *path, struct cam_ed *dev) void xpt_print_path(struct cam_path *path) { + struct sbuf sb; + char buffer[XPT_PRINT_LEN]; - if (path == NULL) - printf("(nopath): "); - else { - if (path->periph != NULL) - printf("(%s%d:", path->periph->periph_name, - path->periph->unit_number); - else - printf("(noperiph:"); - - if (path->bus != NULL) - printf("%s%d:%d:", path->bus->sim->sim_name, - path->bus->sim->unit_number, - path->bus->sim->bus_id); - else - printf("nobus:"); - - if (path->target != NULL) - printf("%d:", path->target->target_id); - else - printf("X:"); - - if (path->device != NULL) - printf("%jx): ", (uintmax_t)path->device->lun_id); - else - printf("X): "); - } + sbuf_new(&sb, buffer, XPT_PRINT_LEN, SBUF_FIXEDLEN); + xpt_path_sbuf(path, &sb); + sbuf_finish(&sb); + printf("%s", sbuf_data(&sb)); + sbuf_delete(&sb); } void @@ -3745,49 +3726,66 @@ void xpt_print(struct cam_path *path, const char *fmt, ...) { va_list ap; - xpt_print_path(path); + struct sbuf sb; + char buffer[XPT_PRINT_MAXLEN]; + + sbuf_new(&sb, buffer, XPT_PRINT_MAXLEN, SBUF_FIXEDLEN); + + xpt_path_sbuf(path, &sb); va_start(ap, fmt); - vprintf(fmt, ap); + sbuf_vprintf(&sb, fmt, ap); va_end(ap); + + sbuf_finish(&sb); + printf("%s", sbuf_data(&sb)); + sbuf_delete(&sb); } int xpt_path_string(struct cam_path *path, char *str, size_t str_len) { struct sbuf sb; + int len; sbuf_new(&sb, str, str_len, 0); + len = xpt_path_sbuf(path, &sb); + sbuf_finish(&sb); + return (len); +} + +int +xpt_path_sbuf(struct cam_path *path, struct sbuf *sb) +{ if (path == NULL) - sbuf_printf(&sb, "(nopath): "); + sbuf_printf(sb, "(nopath): "); else { if (path->periph != NULL) - sbuf_printf(&sb, "(%s%d:", path->periph->periph_name, + sbuf_printf(sb, "(%s%d:", path->periph->periph_name, path->periph->unit_number); else - sbuf_printf(&sb, "(noperiph:"); + sbuf_printf(sb, "(noperiph:"); if (path->bus != NULL) - sbuf_printf(&sb, "%s%d:%d:", path->bus->sim->sim_name, + sbuf_printf(sb, "%s%d:%d:", path->bus->sim->sim_name, path->bus->sim->unit_number, path->bus->sim->bus_id); else - sbuf_printf(&sb, "nobus:"); + sbuf_printf(sb, "nobus:"); if (path->target != NULL) - sbuf_printf(&sb, "%d:", path->target->target_id); + sbuf_printf(sb, "%d:", path->target->target_id); else - sbuf_printf(&sb, "X:"); + sbuf_printf(sb, "X:"); if (path->device != NULL) - sbuf_printf(&sb, "%jx): ", + sbuf_printf(sb, "%jx): ", (uintmax_t)path->device->lun_id); else - sbuf_printf(&sb, "X): "); + sbuf_printf(sb, "X): "); } - sbuf_finish(&sb); - return(sbuf_len(&sb)); + return(sbuf_len(sb)); } path_id_t diff --git a/sys/cam/cam_xpt.h b/sys/cam/cam_xpt.h index ba5c924ab1ad..2f3f22e713cd 100644 --- a/sys/cam/cam_xpt.h +++ b/sys/cam/cam_xpt.h @@ -32,11 +32,15 @@ #ifndef _CAM_CAM_XPT_H #define _CAM_CAM_XPT_H 1 +#include +#include "opt_printf.h" + /* Forward Declarations */ union ccb; struct cam_periph; struct cam_ed; struct cam_sim; +struct sbuf; /* * Definition of a CAM path. Paths are created from bus, target, and lun ids @@ -49,6 +53,15 @@ struct cam_path; #ifdef _KERNEL +/* Wild guess based on not wanting to grow the stack too much */ +#define XPT_PRINT_MAXLEN 512 +#ifdef PRINTF_BUFR_SIZE +#define XPT_PRINT_LEN PRINTF_BUFR_SIZE +#else +#define XPT_PRINT_LEN 128 +#endif +_Static_assert(XPT_PRINT_LEN <= XPT_PRINT_MAXLEN, "XPT_PRINT_LEN is too large"); + /* * Definition of an async handler callback block. These are used to add * SIMs and peripherals to the async callback lists. @@ -102,6 +115,7 @@ void xpt_print_device(struct cam_ed *device); void xpt_print(struct cam_path *path, const char *fmt, ...); int xpt_path_string(struct cam_path *path, char *str, size_t str_len); +int xpt_path_sbuf(struct cam_path *path, struct sbuf *sb); path_id_t xpt_path_path_id(struct cam_path *path); target_id_t xpt_path_target_id(struct cam_path *path); lun_id_t xpt_path_lun_id(struct cam_path *path);