netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Allan Stephens <allan.stephens@windriver.com>
To: David Miller <davem@davemloft.net>
Cc: netdev@vger.kernel.org, allan.stephens@windriver.com
Subject: [PATCH 5/9 net-next-2.6] [TIPC]: Elimination of print buffer chaining
Date: Mon, 28 Apr 2008 15:48:42 -0400	[thread overview]
Message-ID: <1209412126-2109-6-git-send-email-allan.stephens@windriver.com> (raw)
In-Reply-To: <1209412126-2109-1-git-send-email-allan.stephens@windriver.com>

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>
---
 net/tipc/core.h |    7 ++-
 net/tipc/dbg.c  |  163 +++++++++++++++++++++++++------------------------------
 net/tipc/dbg.h  |    4 +-
 3 files changed, 80 insertions(+), 94 deletions(-)

diff --git a/net/tipc/core.h b/net/tipc/core.h
index 325404f..7042ef3 100644
--- a/net/tipc/core.h
+++ b/net/tipc/core.h
@@ -66,7 +66,6 @@
 
 struct tipc_msg;
 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_printf(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_LOG		   : TIPC log buffer
  * &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
-#define TIPC_OUTPUT TIPC_TEE(TIPC_CONS,TIPC_LOG)
+#define TIPC_OUTPUT TIPC_LOG
 #endif
 
 #ifndef DBG_OUTPUT
diff --git a/net/tipc/dbg.c b/net/tipc/dbg.c
index 834319e..8ca9457 100644
--- a/net/tipc/dbg.c
+++ b/net/tipc/dbg.c
@@ -38,18 +38,44 @@
 #include "config.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;
 
-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;
 
-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;
 
+/*
+ * 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) \
 {\
@@ -60,27 +86,14 @@ struct print_buf *TIPC_LOG = &log_buf;
        *(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
  * @pb: pointer to print buffer structure
  * @raw: pointer to character array used by print buffer
  * @size: size of character array
  *
- * Makes the print buffer a null device that discards anything written to it
- * if the character array is too small (or absent).
+ * Note: If the character array is too small (or absent), the print buffer
+ * becomes a null device that discards anything written to it.
  */
 
 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->crs = raw;
 	pb->size = size;
-	pb->next = NULL;
+	pb->echo = 0;
 
 	if (size < TIPC_PB_MIN_SIZE) {
 		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)
 {
-	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 ***");
 		pb_to->buf[pb_to->size - 1] = ~0;
 		pb_to->crs = strchr(pb_to->buf, 0);
-		pb_to->next = NULL;
 		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
- * @pb: pointer to chain of print buffers (may be NULL)
+ * tipc_printf - append formatted output to print buffer
+ * @pb: pointer to print buffer
  * @fmt: formatted info to be printed
  */
 
@@ -215,66 +231,36 @@ void tipc_printf(struct print_buf *pb, const char *fmt, ...)
 	int chars_to_add;
 	int chars_left;
 	char save_char;
-	struct print_buf *pb_next;
 
 	spin_lock_bh(&print_lock);
+
 	FORMAT(print_string, chars_to_add, fmt);
 	if (chars_to_add >= TIPC_PB_MAX_STR)
 		strcpy(print_string, "*** PRINT BUFFER STRING TOO LONG ***");
 
-	while (pb) {
-		if (pb == TIPC_CONS)
-			printk(print_string);
-		else if (pb->buf) {
-			chars_left = pb->buf + pb->size - pb->crs - 1;
-			if (chars_to_add <= chars_left) {
-				strcpy(pb->crs, print_string);
-				pb->crs += chars_to_add;
-			} else if (chars_to_add >= (pb->size - 1)) {
-				strcpy(pb->buf, print_string + chars_to_add + 1
-				       - pb->size);
-				pb->crs = pb->buf + pb->size - 1;
-			} else {
-				strcpy(pb->buf, print_string + chars_left);
-				save_char = print_string[chars_left];
-				print_string[chars_left] = 0;
-				strcpy(pb->crs, print_string);
-				print_string[chars_left] = save_char;
-				pb->crs = pb->buf + chars_to_add - chars_left;
-			}
+	if (pb->buf) {
+		chars_left = pb->buf + pb->size - pb->crs - 1;
+		if (chars_to_add <= chars_left) {
+			strcpy(pb->crs, print_string);
+			pb->crs += chars_to_add;
+		} else if (chars_to_add >= (pb->size - 1)) {
+			strcpy(pb->buf, print_string + chars_to_add + 1
+			       - pb->size);
+			pb->crs = pb->buf + pb->size - 1;
+		} else {
+			strcpy(pb->buf, print_string + chars_left);
+			save_char = print_string[chars_left];
+			print_string[chars_left] = 0;
+			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;
 	}
-	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 (pb->echo)
+		printk(print_string);
 
-	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;
 }
 
 /**
@@ -323,31 +309,28 @@ static void printbuf_dump(struct print_buf *pb)
 }
 
 /**
- * tipc_dump - dump non-console print buffer(s) to console
- * @pb: pointer to chain of print buffers
+ * tipc_dump - dump (non-console) print buffer to console
+ * @pb: pointer to print buffer
  */
 
 void tipc_dump(struct print_buf *pb, const char *fmt, ...)
 {
-	struct print_buf *pb_next;
 	int len;
 
+	if (pb == TIPC_CONS)
+		return;
+
 	spin_lock_bh(&print_lock);
+
 	FORMAT(print_string, len, fmt);
 	printk(print_string);
 
-	for (; pb; pb = pb->next) {
-		if (pb != TIPC_CONS) {
-			printk("\n---- Start of %s log dump ----\n\n",
-			       (pb == TIPC_LOG) ? "global" : "local");
-			printbuf_dump(pb);
-			tipc_printbuf_reset(pb);
-			printk("\n---- End of dump ----\n");
-		}
-		pb_next = pb->next;
-		pb->next = NULL;
-		pb = pb_next;
-	}
+	printk("\n---- Start of %s log dump ----\n\n",
+	       (pb == TIPC_LOG) ? "global" : "local");
+	printbuf_dump(pb);
+	tipc_printbuf_reset(pb);
+	printk("\n---- End of dump ----\n");
+
 	spin_unlock_bh(&print_lock);
 }
 
@@ -368,8 +351,10 @@ int tipc_log_resize(int log_size)
 	if (log_size) {
 		if (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),
 				   log_size);
+		TIPC_LOG->echo = res;
 		res = !TIPC_LOG->buf;
 	}
 	spin_unlock_bh(&print_lock);
diff --git a/net/tipc/dbg.h b/net/tipc/dbg.h
index 6b00062..5ef1bc8 100644
--- a/net/tipc/dbg.h
+++ b/net/tipc/dbg.h
@@ -42,14 +42,14 @@
  * @buf: pointer to character array containing print buffer contents
  * @size: size of character array
  * @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 {
 	char *buf;
 	u32 size;
 	char *crs;
-	struct print_buf *next;
+	int echo;
 };
 
 #define TIPC_PB_MIN_SIZE 64	/* minimum size for a print buffer's array */
-- 
1.5.3.2


  parent reply	other threads:[~2008-04-28 19:52 UTC|newest]

Thread overview: 19+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-04-28 19:48 [PATCH 0/9 net-next-2.6] [TIPC]: System & debug output modifications Allan Stephens
2008-04-28 19:48 ` [PATCH 1/9 net-next-2.6] [TIPC]: Simplify log buffer resizing Allan Stephens
2008-05-05  8:20   ` David Miller
2008-04-28 19:48 ` [PATCH 2/9 net-next-2.6] [TIPC]: Provide feedback when log buffer resizing fails Allan Stephens
2008-05-05  8:20   ` David Miller
2008-04-28 19:48 ` [PATCH 3/9 net-next-2.6] [TIPC]: Fix recursive spinlock invocation in print buffer code Allan Stephens
2008-05-05  8:21   ` David Miller
2008-04-28 19:48 ` [PATCH 4/9 net-next-2.6] [TIPC]: Fix null pointer dereference in debug code Allan Stephens
2008-05-05  8:22   ` David Miller
2008-04-28 19:48 ` Allan Stephens [this message]
2008-05-05  8:22   ` [PATCH 5/9 net-next-2.6] [TIPC]: Elimination of print buffer chaining David Miller
2008-04-28 19:48 ` [PATCH 6/9 net-next-2.6] [TIPC]: Cosmetic cleanup of print buffer code Allan Stephens
2008-05-05  8:23   ` David Miller
2008-04-28 19:48 ` [PATCH 7/9 net-next-2.6] [TIPC]: Cosmetic cleanup of system & debug output declarations Allan Stephens
2008-05-05  8:23   ` David Miller
2008-04-28 19:48 ` [PATCH 8/9 net-next-2.6] [TIPC]: Exclude debug-only print buffer code when not debugging Allan Stephens
2008-05-05  8:24   ` David Miller
2008-04-28 19:48 ` [PATCH 9/9 net-next-2.6] [TIPC]: Update version number to TIPC 1.6.4 Allan Stephens
2008-05-05  8:24   ` David Miller

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1209412126-2109-6-git-send-email-allan.stephens@windriver.com \
    --to=allan.stephens@windriver.com \
    --cc=davem@davemloft.net \
    --cc=netdev@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).