aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAllan Stephens <allan.stephens@windriver.com>2008-05-05 04:22:30 -0400
committerDavid S. Miller <davem@davemloft.net>2008-05-05 04:22:30 -0400
commitc89039850bdf8047472b4ee6132048dacef2cf5a (patch)
tree6541bb6adb8d899e2e9bb3f570cd0a1759df1a55
parent40dbfae440abe6860167f12e0296bd7a1a599839 (diff)
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>
-rw-r--r--net/tipc/core.h7
-rw-r--r--net/tipc/dbg.c163
-rw-r--r--net/tipc/dbg.h4
3 files changed, 80 insertions, 94 deletions
diff --git a/net/tipc/core.h b/net/tipc/core.h
index 325404fd4eb5..7042ef377262 100644
--- a/net/tipc/core.h
+++ b/net/tipc/core.h
@@ -66,7 +66,6 @@
66 66
67struct tipc_msg; 67struct tipc_msg;
68extern struct print_buf *TIPC_NULL, *TIPC_CONS, *TIPC_LOG; 68extern struct print_buf *TIPC_NULL, *TIPC_CONS, *TIPC_LOG;
69extern struct print_buf *TIPC_TEE(struct print_buf *, struct print_buf *);
70void tipc_msg_print(struct print_buf*,struct tipc_msg *,const char*); 69void tipc_msg_print(struct print_buf*,struct tipc_msg *,const char*);
71void tipc_printf(struct print_buf *, const char *fmt, ...); 70void tipc_printf(struct print_buf *, const char *fmt, ...);
72void tipc_dump(struct print_buf*,const char *fmt, ...); 71void tipc_dump(struct print_buf*,const char *fmt, ...);
@@ -98,11 +97,13 @@ void tipc_dump(struct print_buf*,const char *fmt, ...);
98 * TIPC_CONS : system console 97 * TIPC_CONS : system console
99 * TIPC_LOG : TIPC log buffer 98 * TIPC_LOG : TIPC log buffer
100 * &buf : user-defined buffer (struct print_buf *) 99 * &buf : user-defined buffer (struct print_buf *)
101 * TIPC_TEE(&buf_a,&buf_b) : list of buffers (eg. TIPC_TEE(TIPC_CONS,TIPC_LOG)) 100 *
101 * Note: TIPC_LOG is configured to echo its output to the system console;
102 * user-defined buffers can be configured to do the same thing.
102 */ 103 */
103 104
104#ifndef TIPC_OUTPUT 105#ifndef TIPC_OUTPUT
105#define TIPC_OUTPUT TIPC_TEE(TIPC_CONS,TIPC_LOG) 106#define TIPC_OUTPUT TIPC_LOG
106#endif 107#endif
107 108
108#ifndef DBG_OUTPUT 109#ifndef DBG_OUTPUT
diff --git a/net/tipc/dbg.c b/net/tipc/dbg.c
index 834319e3b7e7..8ca9457250be 100644
--- a/net/tipc/dbg.c
+++ b/net/tipc/dbg.c
@@ -38,18 +38,44 @@
38#include "config.h" 38#include "config.h"
39#include "dbg.h" 39#include "dbg.h"
40 40
41static char print_string[TIPC_PB_MAX_STR]; 41/*
42static DEFINE_SPINLOCK(print_lock); 42 * TIPC pre-defines the following print buffers:
43 *
44 * TIPC_NULL : null buffer (i.e. print nowhere)
45 * TIPC_CONS : system console
46 * TIPC_LOG : TIPC log buffer
47 *
48 * Additional user-defined print buffers are also permitted.
49 */
43 50
44static struct print_buf null_buf = { NULL, 0, NULL, NULL }; 51static struct print_buf null_buf = { NULL, 0, NULL, 0 };
45struct print_buf *TIPC_NULL = &null_buf; 52struct print_buf *TIPC_NULL = &null_buf;
46 53
47static struct print_buf cons_buf = { NULL, 0, NULL, NULL }; 54static struct print_buf cons_buf = { NULL, 0, NULL, 1 };
48struct print_buf *TIPC_CONS = &cons_buf; 55struct print_buf *TIPC_CONS = &cons_buf;
49 56
50static struct print_buf log_buf = { NULL, 0, NULL, NULL }; 57static struct print_buf log_buf = { NULL, 0, NULL, 1 };
51struct print_buf *TIPC_LOG = &log_buf; 58struct print_buf *TIPC_LOG = &log_buf;
52 59
60/*
61 * Locking policy when using print buffers.
62 *
63 * 1) tipc_printf() uses 'print_lock' to protect against concurrent access to
64 * 'print_string' when writing to a print buffer. This also protects against
65 * concurrent writes to the print buffer being written to.
66 *
67 * 2) tipc_dump() and tipc_log_XXX() leverage the aforementioned
68 * use of 'print_lock' to protect against all types of concurrent operations
69 * on their associated print buffer (not just write operations).
70 *
71 * Note: All routines of the form tipc_printbuf_XXX() are lock-free, and rely
72 * on the caller to prevent simultaneous use of the print buffer(s) being
73 * manipulated.
74 */
75
76static char print_string[TIPC_PB_MAX_STR];
77static DEFINE_SPINLOCK(print_lock);
78
53 79
54#define FORMAT(PTR,LEN,FMT) \ 80#define FORMAT(PTR,LEN,FMT) \
55{\ 81{\
@@ -60,27 +86,14 @@ struct print_buf *TIPC_LOG = &log_buf;
60 *(PTR + LEN) = '\0';\ 86 *(PTR + LEN) = '\0';\
61} 87}
62 88
63/*
64 * Locking policy when using print buffers.
65 *
66 * The following routines use 'print_lock' for protection:
67 * 1) tipc_printf() - to protect its print buffer(s) and 'print_string'
68 * 2) TIPC_TEE() - to protect its print buffer(s)
69 * 3) tipc_dump() - to protect its print buffer(s) and 'print_string'
70 * 4) tipc_log_XXX() - to protect TIPC_LOG
71 *
72 * All routines of the form tipc_printbuf_XXX() rely on the caller to prevent
73 * simultaneous use of the print buffer(s) being manipulated.
74 */
75
76/** 89/**
77 * tipc_printbuf_init - initialize print buffer to empty 90 * tipc_printbuf_init - initialize print buffer to empty
78 * @pb: pointer to print buffer structure 91 * @pb: pointer to print buffer structure
79 * @raw: pointer to character array used by print buffer 92 * @raw: pointer to character array used by print buffer
80 * @size: size of character array 93 * @size: size of character array
81 * 94 *
82 * Makes the print buffer a null device that discards anything written to it 95 * Note: If the character array is too small (or absent), the print buffer
83 * if the character array is too small (or absent). 96 * becomes a null device that discards anything written to it.
84 */ 97 */
85 98
86void tipc_printbuf_init(struct print_buf *pb, char *raw, u32 size) 99void 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)
88 pb->buf = raw; 101 pb->buf = raw;
89 pb->crs = raw; 102 pb->crs = raw;
90 pb->size = size; 103 pb->size = size;
91 pb->next = NULL; 104 pb->echo = 0;
92 105
93 if (size < TIPC_PB_MIN_SIZE) { 106 if (size < TIPC_PB_MIN_SIZE) {
94 pb->buf = NULL; 107 pb->buf = NULL;
@@ -105,7 +118,11 @@ void tipc_printbuf_init(struct print_buf *pb, char *raw, u32 size)
105 118
106void tipc_printbuf_reset(struct print_buf *pb) 119void tipc_printbuf_reset(struct print_buf *pb)
107{ 120{
108 tipc_printbuf_init(pb, pb->buf, pb->size); 121 if (pb->buf != NULL) {
122 pb->crs = pb->buf;
123 pb->buf[0] = 0;
124 pb->buf[pb->size - 1] = ~0;
125 }
109} 126}
110 127
111/** 128/**
@@ -182,7 +199,6 @@ void tipc_printbuf_move(struct print_buf *pb_to, struct print_buf *pb_from)
182 strcpy(pb_to->buf, "*** PRINT BUFFER MOVE ERROR ***"); 199 strcpy(pb_to->buf, "*** PRINT BUFFER MOVE ERROR ***");
183 pb_to->buf[pb_to->size - 1] = ~0; 200 pb_to->buf[pb_to->size - 1] = ~0;
184 pb_to->crs = strchr(pb_to->buf, 0); 201 pb_to->crs = strchr(pb_to->buf, 0);
185 pb_to->next = NULL;
186 return; 202 return;
187 } 203 }
188 204
@@ -205,8 +221,8 @@ void tipc_printbuf_move(struct print_buf *pb_to, struct print_buf *pb_from)
205} 221}
206 222
207/** 223/**
208 * tipc_printf - append formatted output to print buffer chain 224 * tipc_printf - append formatted output to print buffer
209 * @pb: pointer to chain of print buffers (may be NULL) 225 * @pb: pointer to print buffer
210 * @fmt: formatted info to be printed 226 * @fmt: formatted info to be printed
211 */ 227 */
212 228
@@ -215,66 +231,36 @@ void tipc_printf(struct print_buf *pb, const char *fmt, ...)
215 int chars_to_add; 231 int chars_to_add;
216 int chars_left; 232 int chars_left;
217 char save_char; 233 char save_char;
218 struct print_buf *pb_next;
219 234
220 spin_lock_bh(&print_lock); 235 spin_lock_bh(&print_lock);
236
221 FORMAT(print_string, chars_to_add, fmt); 237 FORMAT(print_string, chars_to_add, fmt);
222 if (chars_to_add >= TIPC_PB_MAX_STR) 238 if (chars_to_add >= TIPC_PB_MAX_STR)
223 strcpy(print_string, "*** PRINT BUFFER STRING TOO LONG ***"); 239 strcpy(print_string, "*** PRINT BUFFER STRING TOO LONG ***");
224 240
225 while (pb) { 241 if (pb->buf) {
226 if (pb == TIPC_CONS) 242 chars_left = pb->buf + pb->size - pb->crs - 1;
227 printk(print_string); 243 if (chars_to_add <= chars_left) {
228 else if (pb->buf) { 244 strcpy(pb->crs, print_string);
229 chars_left = pb->buf + pb->size - pb->crs - 1; 245 pb->crs += chars_to_add;
230 if (chars_to_add <= chars_left) { 246 } else if (chars_to_add >= (pb->size - 1)) {
231 strcpy(pb->crs, print_string); 247 strcpy(pb->buf, print_string + chars_to_add + 1
232 pb->crs += chars_to_add; 248 - pb->size);
233 } else if (chars_to_add >= (pb->size - 1)) { 249 pb->crs = pb->buf + pb->size - 1;
234 strcpy(pb->buf, print_string + chars_to_add + 1 250 } else {
235 - pb->size); 251 strcpy(pb->buf, print_string + chars_left);
236 pb->crs = pb->buf + pb->size - 1; 252 save_char = print_string[chars_left];
237 } else { 253 print_string[chars_left] = 0;
238 strcpy(pb->buf, print_string + chars_left); 254 strcpy(pb->crs, print_string);
239 save_char = print_string[chars_left]; 255 print_string[chars_left] = save_char;
240 print_string[chars_left] = 0; 256 pb->crs = pb->buf + chars_to_add - chars_left;
241 strcpy(pb->crs, print_string);
242 print_string[chars_left] = save_char;
243 pb->crs = pb->buf + chars_to_add - chars_left;
244 }
245 } 257 }
246 pb_next = pb->next;
247 pb->next = NULL;
248 pb = pb_next;
249 } 258 }
250 spin_unlock_bh(&print_lock);
251}
252 259
253/** 260 if (pb->echo)
254 * TIPC_TEE - perform next output operation on both print buffers 261 printk(print_string);
255 * @b0: pointer to chain of print buffers (may be NULL)
256 * @b1: pointer to print buffer to add to chain
257 *
258 * Returns pointer to print buffer chain.
259 */
260
261struct print_buf *TIPC_TEE(struct print_buf *b0, struct print_buf *b1)
262{
263 struct print_buf *pb = b0;
264 262
265 if (!b0 || (b0 == b1))
266 return b1;
267
268 spin_lock_bh(&print_lock);
269 while (pb->next) {
270 if ((pb->next == b1) || (pb->next == b0))
271 pb->next = pb->next->next;
272 else
273 pb = pb->next;
274 }
275 pb->next = b1;
276 spin_unlock_bh(&print_lock); 263 spin_unlock_bh(&print_lock);
277 return b0;
278} 264}
279 265
280/** 266/**
@@ -323,31 +309,28 @@ static void printbuf_dump(struct print_buf *pb)
323} 309}
324 310
325/** 311/**
326 * tipc_dump - dump non-console print buffer(s) to console 312 * tipc_dump - dump (non-console) print buffer to console
327 * @pb: pointer to chain of print buffers 313 * @pb: pointer to print buffer
328 */ 314 */
329 315
330void tipc_dump(struct print_buf *pb, const char *fmt, ...) 316void tipc_dump(struct print_buf *pb, const char *fmt, ...)
331{ 317{
332 struct print_buf *pb_next;
333 int len; 318 int len;
334 319
320 if (pb == TIPC_CONS)
321 return;
322
335 spin_lock_bh(&print_lock); 323 spin_lock_bh(&print_lock);
324
336 FORMAT(print_string, len, fmt); 325 FORMAT(print_string, len, fmt);
337 printk(print_string); 326 printk(print_string);
338 327
339 for (; pb; pb = pb->next) { 328 printk("\n---- Start of %s log dump ----\n\n",
340 if (pb != TIPC_CONS) { 329 (pb == TIPC_LOG) ? "global" : "local");
341 printk("\n---- Start of %s log dump ----\n\n", 330 printbuf_dump(pb);
342 (pb == TIPC_LOG) ? "global" : "local"); 331 tipc_printbuf_reset(pb);
343 printbuf_dump(pb); 332 printk("\n---- End of dump ----\n");
344 tipc_printbuf_reset(pb); 333
345 printk("\n---- End of dump ----\n");
346 }
347 pb_next = pb->next;
348 pb->next = NULL;
349 pb = pb_next;
350 }
351 spin_unlock_bh(&print_lock); 334 spin_unlock_bh(&print_lock);
352} 335}
353 336
@@ -368,8 +351,10 @@ int tipc_log_resize(int log_size)
368 if (log_size) { 351 if (log_size) {
369 if (log_size < TIPC_PB_MIN_SIZE) 352 if (log_size < TIPC_PB_MIN_SIZE)
370 log_size = TIPC_PB_MIN_SIZE; 353 log_size = TIPC_PB_MIN_SIZE;
354 res = TIPC_LOG->echo;
371 tipc_printbuf_init(TIPC_LOG, kmalloc(log_size, GFP_ATOMIC), 355 tipc_printbuf_init(TIPC_LOG, kmalloc(log_size, GFP_ATOMIC),
372 log_size); 356 log_size);
357 TIPC_LOG->echo = res;
373 res = !TIPC_LOG->buf; 358 res = !TIPC_LOG->buf;
374 } 359 }
375 spin_unlock_bh(&print_lock); 360 spin_unlock_bh(&print_lock);
diff --git a/net/tipc/dbg.h b/net/tipc/dbg.h
index 6b00062bf040..5ef1bc8f64ef 100644
--- a/net/tipc/dbg.h
+++ b/net/tipc/dbg.h
@@ -42,14 +42,14 @@
42 * @buf: pointer to character array containing print buffer contents 42 * @buf: pointer to character array containing print buffer contents
43 * @size: size of character array 43 * @size: size of character array
44 * @crs: pointer to first unused space in character array (i.e. final NUL) 44 * @crs: pointer to first unused space in character array (i.e. final NUL)
45 * @next: used to link print buffers when printing to more than one at a time 45 * @echo: echo output to system console if non-zero
46 */ 46 */
47 47
48struct print_buf { 48struct print_buf {
49 char *buf; 49 char *buf;
50 u32 size; 50 u32 size;
51 char *crs; 51 char *crs;
52 struct print_buf *next; 52 int echo;
53}; 53};
54 54
55#define TIPC_PB_MIN_SIZE 64 /* minimum size for a print buffer's array */ 55#define TIPC_PB_MIN_SIZE 64 /* minimum size for a print buffer's array */