tipc: Elimination of print buffer chaining

This patch revamps TIPC's print buffer subsystem to eliminate
support for arbitrary chains of print buffers, which were
rarely needed and difficult to use safely.

In its place, print buffers can now be configured to echo their
output to the system console.  This provides an equivalent for
the only chaining currently utilized by TIPC, in a faster and
more compact manner.

Signed-off-by: Allan Stephens <allan.stephens@windriver.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Allan Stephens 2008-05-05 01:22:30 -07:00 committed by David S. Miller
parent 40dbfae440
commit c89039850b
3 changed files with 82 additions and 96 deletions

View file

@ -66,7 +66,6 @@
struct tipc_msg; struct tipc_msg;
extern struct print_buf *TIPC_NULL, *TIPC_CONS, *TIPC_LOG; extern struct print_buf *TIPC_NULL, *TIPC_CONS, *TIPC_LOG;
extern struct print_buf *TIPC_TEE(struct print_buf *, struct print_buf *);
void tipc_msg_print(struct print_buf*,struct tipc_msg *,const char*); void tipc_msg_print(struct print_buf*,struct tipc_msg *,const char*);
void tipc_printf(struct print_buf *, const char *fmt, ...); void tipc_printf(struct print_buf *, const char *fmt, ...);
void tipc_dump(struct print_buf*,const char *fmt, ...); void tipc_dump(struct print_buf*,const char *fmt, ...);
@ -98,11 +97,13 @@ void tipc_dump(struct print_buf*,const char *fmt, ...);
* TIPC_CONS : system console * TIPC_CONS : system console
* TIPC_LOG : TIPC log buffer * TIPC_LOG : TIPC log buffer
* &buf : user-defined buffer (struct print_buf *) * &buf : user-defined buffer (struct print_buf *)
* TIPC_TEE(&buf_a,&buf_b) : list of buffers (eg. TIPC_TEE(TIPC_CONS,TIPC_LOG)) *
* Note: TIPC_LOG is configured to echo its output to the system console;
* user-defined buffers can be configured to do the same thing.
*/ */
#ifndef TIPC_OUTPUT #ifndef TIPC_OUTPUT
#define TIPC_OUTPUT TIPC_TEE(TIPC_CONS,TIPC_LOG) #define TIPC_OUTPUT TIPC_LOG
#endif #endif
#ifndef DBG_OUTPUT #ifndef DBG_OUTPUT

View file

@ -38,18 +38,44 @@
#include "config.h" #include "config.h"
#include "dbg.h" #include "dbg.h"
static char print_string[TIPC_PB_MAX_STR]; /*
static DEFINE_SPINLOCK(print_lock); * TIPC pre-defines the following print buffers:
*
* TIPC_NULL : null buffer (i.e. print nowhere)
* TIPC_CONS : system console
* TIPC_LOG : TIPC log buffer
*
* Additional user-defined print buffers are also permitted.
*/
static struct print_buf null_buf = { NULL, 0, NULL, NULL }; static struct print_buf null_buf = { NULL, 0, NULL, 0 };
struct print_buf *TIPC_NULL = &null_buf; struct print_buf *TIPC_NULL = &null_buf;
static struct print_buf cons_buf = { NULL, 0, NULL, NULL }; static struct print_buf cons_buf = { NULL, 0, NULL, 1 };
struct print_buf *TIPC_CONS = &cons_buf; struct print_buf *TIPC_CONS = &cons_buf;
static struct print_buf log_buf = { NULL, 0, NULL, NULL }; static struct print_buf log_buf = { NULL, 0, NULL, 1 };
struct print_buf *TIPC_LOG = &log_buf; struct print_buf *TIPC_LOG = &log_buf;
/*
* Locking policy when using print buffers.
*
* 1) tipc_printf() uses 'print_lock' to protect against concurrent access to
* 'print_string' when writing to a print buffer. This also protects against
* concurrent writes to the print buffer being written to.
*
* 2) tipc_dump() and tipc_log_XXX() leverage the aforementioned
* use of 'print_lock' to protect against all types of concurrent operations
* on their associated print buffer (not just write operations).
*
* Note: All routines of the form tipc_printbuf_XXX() are lock-free, and rely
* on the caller to prevent simultaneous use of the print buffer(s) being
* manipulated.
*/
static char print_string[TIPC_PB_MAX_STR];
static DEFINE_SPINLOCK(print_lock);
#define FORMAT(PTR,LEN,FMT) \ #define FORMAT(PTR,LEN,FMT) \
{\ {\
@ -60,27 +86,14 @@ struct print_buf *TIPC_LOG = &log_buf;
*(PTR + LEN) = '\0';\ *(PTR + LEN) = '\0';\
} }
/*
* Locking policy when using print buffers.
*
* The following routines use 'print_lock' for protection:
* 1) tipc_printf() - to protect its print buffer(s) and 'print_string'
* 2) TIPC_TEE() - to protect its print buffer(s)
* 3) tipc_dump() - to protect its print buffer(s) and 'print_string'
* 4) tipc_log_XXX() - to protect TIPC_LOG
*
* All routines of the form tipc_printbuf_XXX() rely on the caller to prevent
* simultaneous use of the print buffer(s) being manipulated.
*/
/** /**
* tipc_printbuf_init - initialize print buffer to empty * tipc_printbuf_init - initialize print buffer to empty
* @pb: pointer to print buffer structure * @pb: pointer to print buffer structure
* @raw: pointer to character array used by print buffer * @raw: pointer to character array used by print buffer
* @size: size of character array * @size: size of character array
* *
* Makes the print buffer a null device that discards anything written to it * Note: If the character array is too small (or absent), the print buffer
* if the character array is too small (or absent). * becomes a null device that discards anything written to it.
*/ */
void tipc_printbuf_init(struct print_buf *pb, char *raw, u32 size) void tipc_printbuf_init(struct print_buf *pb, char *raw, u32 size)
@ -88,7 +101,7 @@ void tipc_printbuf_init(struct print_buf *pb, char *raw, u32 size)
pb->buf = raw; pb->buf = raw;
pb->crs = raw; pb->crs = raw;
pb->size = size; pb->size = size;
pb->next = NULL; pb->echo = 0;
if (size < TIPC_PB_MIN_SIZE) { if (size < TIPC_PB_MIN_SIZE) {
pb->buf = NULL; pb->buf = NULL;
@ -105,7 +118,11 @@ void tipc_printbuf_init(struct print_buf *pb, char *raw, u32 size)
void tipc_printbuf_reset(struct print_buf *pb) void tipc_printbuf_reset(struct print_buf *pb)
{ {
tipc_printbuf_init(pb, pb->buf, pb->size); if (pb->buf != NULL) {
pb->crs = pb->buf;
pb->buf[0] = 0;
pb->buf[pb->size - 1] = ~0;
}
} }
/** /**
@ -182,7 +199,6 @@ void tipc_printbuf_move(struct print_buf *pb_to, struct print_buf *pb_from)
strcpy(pb_to->buf, "*** PRINT BUFFER MOVE ERROR ***"); strcpy(pb_to->buf, "*** PRINT BUFFER MOVE ERROR ***");
pb_to->buf[pb_to->size - 1] = ~0; pb_to->buf[pb_to->size - 1] = ~0;
pb_to->crs = strchr(pb_to->buf, 0); pb_to->crs = strchr(pb_to->buf, 0);
pb_to->next = NULL;
return; return;
} }
@ -205,8 +221,8 @@ void tipc_printbuf_move(struct print_buf *pb_to, struct print_buf *pb_from)
} }
/** /**
* tipc_printf - append formatted output to print buffer chain * tipc_printf - append formatted output to print buffer
* @pb: pointer to chain of print buffers (may be NULL) * @pb: pointer to print buffer
* @fmt: formatted info to be printed * @fmt: formatted info to be printed
*/ */
@ -215,68 +231,38 @@ void tipc_printf(struct print_buf *pb, const char *fmt, ...)
int chars_to_add; int chars_to_add;
int chars_left; int chars_left;
char save_char; char save_char;
struct print_buf *pb_next;
spin_lock_bh(&print_lock); spin_lock_bh(&print_lock);
FORMAT(print_string, chars_to_add, fmt); FORMAT(print_string, chars_to_add, fmt);
if (chars_to_add >= TIPC_PB_MAX_STR) if (chars_to_add >= TIPC_PB_MAX_STR)
strcpy(print_string, "*** PRINT BUFFER STRING TOO LONG ***"); strcpy(print_string, "*** PRINT BUFFER STRING TOO LONG ***");
while (pb) { if (pb->buf) {
if (pb == TIPC_CONS) chars_left = pb->buf + pb->size - pb->crs - 1;
printk(print_string); if (chars_to_add <= chars_left) {
else if (pb->buf) { strcpy(pb->crs, print_string);
chars_left = pb->buf + pb->size - pb->crs - 1; pb->crs += chars_to_add;
if (chars_to_add <= chars_left) { } else if (chars_to_add >= (pb->size - 1)) {
strcpy(pb->crs, print_string); strcpy(pb->buf, print_string + chars_to_add + 1
pb->crs += chars_to_add; - pb->size);
} else if (chars_to_add >= (pb->size - 1)) { pb->crs = pb->buf + pb->size - 1;
strcpy(pb->buf, print_string + chars_to_add + 1 } else {
- pb->size); strcpy(pb->buf, print_string + chars_left);
pb->crs = pb->buf + pb->size - 1; save_char = print_string[chars_left];
} else { print_string[chars_left] = 0;
strcpy(pb->buf, print_string + chars_left); strcpy(pb->crs, print_string);
save_char = print_string[chars_left]; print_string[chars_left] = save_char;
print_string[chars_left] = 0; pb->crs = pb->buf + chars_to_add - chars_left;
strcpy(pb->crs, print_string);
print_string[chars_left] = save_char;
pb->crs = pb->buf + chars_to_add - chars_left;
}
} }
pb_next = pb->next;
pb->next = NULL;
pb = pb_next;
} }
if (pb->echo)
printk(print_string);
spin_unlock_bh(&print_lock); spin_unlock_bh(&print_lock);
} }
/**
* TIPC_TEE - perform next output operation on both print buffers
* @b0: pointer to chain of print buffers (may be NULL)
* @b1: pointer to print buffer to add to chain
*
* Returns pointer to print buffer chain.
*/
struct print_buf *TIPC_TEE(struct print_buf *b0, struct print_buf *b1)
{
struct print_buf *pb = b0;
if (!b0 || (b0 == b1))
return b1;
spin_lock_bh(&print_lock);
while (pb->next) {
if ((pb->next == b1) || (pb->next == b0))
pb->next = pb->next->next;
else
pb = pb->next;
}
pb->next = b1;
spin_unlock_bh(&print_lock);
return b0;
}
/** /**
* print_to_console - write string of bytes to console in multiple chunks * print_to_console - write string of bytes to console in multiple chunks
*/ */
@ -323,31 +309,28 @@ static void printbuf_dump(struct print_buf *pb)
} }
/** /**
* tipc_dump - dump non-console print buffer(s) to console * tipc_dump - dump (non-console) print buffer to console
* @pb: pointer to chain of print buffers * @pb: pointer to print buffer
*/ */
void tipc_dump(struct print_buf *pb, const char *fmt, ...) void tipc_dump(struct print_buf *pb, const char *fmt, ...)
{ {
struct print_buf *pb_next;
int len; int len;
if (pb == TIPC_CONS)
return;
spin_lock_bh(&print_lock); spin_lock_bh(&print_lock);
FORMAT(print_string, len, fmt); FORMAT(print_string, len, fmt);
printk(print_string); printk(print_string);
for (; pb; pb = pb->next) { printk("\n---- Start of %s log dump ----\n\n",
if (pb != TIPC_CONS) { (pb == TIPC_LOG) ? "global" : "local");
printk("\n---- Start of %s log dump ----\n\n", printbuf_dump(pb);
(pb == TIPC_LOG) ? "global" : "local"); tipc_printbuf_reset(pb);
printbuf_dump(pb); printk("\n---- End of dump ----\n");
tipc_printbuf_reset(pb);
printk("\n---- End of dump ----\n");
}
pb_next = pb->next;
pb->next = NULL;
pb = pb_next;
}
spin_unlock_bh(&print_lock); spin_unlock_bh(&print_lock);
} }
@ -368,8 +351,10 @@ int tipc_log_resize(int log_size)
if (log_size) { if (log_size) {
if (log_size < TIPC_PB_MIN_SIZE) if (log_size < TIPC_PB_MIN_SIZE)
log_size = TIPC_PB_MIN_SIZE; log_size = TIPC_PB_MIN_SIZE;
res = TIPC_LOG->echo;
tipc_printbuf_init(TIPC_LOG, kmalloc(log_size, GFP_ATOMIC), tipc_printbuf_init(TIPC_LOG, kmalloc(log_size, GFP_ATOMIC),
log_size); log_size);
TIPC_LOG->echo = res;
res = !TIPC_LOG->buf; res = !TIPC_LOG->buf;
} }
spin_unlock_bh(&print_lock); spin_unlock_bh(&print_lock);

View file

@ -42,14 +42,14 @@
* @buf: pointer to character array containing print buffer contents * @buf: pointer to character array containing print buffer contents
* @size: size of character array * @size: size of character array
* @crs: pointer to first unused space in character array (i.e. final NUL) * @crs: pointer to first unused space in character array (i.e. final NUL)
* @next: used to link print buffers when printing to more than one at a time * @echo: echo output to system console if non-zero
*/ */
struct print_buf { struct print_buf {
char *buf; char *buf;
u32 size; u32 size;
char *crs; char *crs;
struct print_buf *next; int echo;
}; };
#define TIPC_PB_MIN_SIZE 64 /* minimum size for a print buffer's array */ #define TIPC_PB_MIN_SIZE 64 /* minimum size for a print buffer's array */