public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/4] stringbuf: A string buffer implementation
@ 2007-10-23 21:12 Matthew Wilcox
  2007-10-23 21:12 ` [PATCH 2/4] isdn: Use stringbuf Matthew Wilcox
                   ` (7 more replies)
  0 siblings, 8 replies; 39+ messages in thread
From: Matthew Wilcox @ 2007-10-23 21:12 UTC (permalink / raw)
  To: torvalds, akpm, linux-kernel; +Cc: Matthew Wilcox, Matthew Wilcox

Consecutive calls to printk are non-atomic, which leads to various
implementations for accumulating strings which can be printed in one call.
This is a generic string buffer which can also be used for non-printk
purposes.  There is no sb_scanf implementation yet as I haven't identified
a user for it.

Signed-off-by: Matthew Wilcox <willy@linux.intel.com>
---
 include/linux/stringbuf.h |   85 +++++++++++++++++++++++++++++++++++++++++++++
 lib/Makefile              |    2 +-
 lib/stringbuf.c           |   79 +++++++++++++++++++++++++++++++++++++++++
 3 files changed, 165 insertions(+), 1 deletions(-)
 create mode 100644 include/linux/stringbuf.h
 create mode 100644 lib/stringbuf.c

diff --git a/include/linux/stringbuf.h b/include/linux/stringbuf.h
new file mode 100644
index 0000000..f9200fe
--- /dev/null
+++ b/include/linux/stringbuf.h
@@ -0,0 +1,85 @@
+/*
+ * An auto-expanding string buffer.  There's no sb_alloc because you really
+ * want to allocate it on the stack or embed it in another structure.
+ *
+ * Please don't access the elements directly; that will give us the chance
+ * to change the implementation later if necessary.
+ *
+ * No locking is performed, although memory allocation is done with
+ * GFP_ATOMIC to allow it to be called when you're holding a lock.
+ */
+
+#include <stdarg.h>
+#include <linux/string.h>
+
+struct stringbuf {
+	char *s;
+	int alloc;
+	int len;
+};
+
+/*
+ * Returns the current length of the string.  Note that more memory
+ * may have been allocated for the string than this.
+ */
+static inline int sb_len(struct stringbuf *sb)
+{
+	return sb->len;
+}
+
+/*
+ * Returns a negative errno if an error has been found with this stringbuf,
+ * or 0 if no error has occurred.  If an error has occurred, sb_string()
+ * returns a suitable description of the error
+ */
+static inline int sb_error(struct stringbuf *sb)
+{
+	return sb->alloc < 0 ? sb->alloc : 0;
+}
+
+/*
+ * Initialise a newly-allocated stringbuf
+ */
+static inline void sb_init(struct stringbuf *sb)
+{
+	memset(sb, 0, sizeof(*sb));
+}
+
+/*
+ * Free the contents of a stringbuf, not the stringbuf itself.  The
+ * stringbuf is then reinitialised so it can be reused, or sb_free can
+ * be called on it multiple times.
+ */
+static inline void sb_free(struct stringbuf *sb)
+{
+	if (sb->alloc > 0)
+		kfree(sb->s);
+	sb_init(sb);
+}
+
+extern void sb_printf(struct stringbuf *sb, const char *fmt, ...)
+	__attribute__((format(printf, 2, 3)));
+#if 0
+/* Waiting for a user to show up */
+extern void sb_vprintf(struct stringbuf *sb, const char *fmt, va_list args)
+	__attribute__((format(printf, 2, 0)));
+#endif
+
+/* Get a pointer to the string. */
+static inline char *sb_string(struct stringbuf *sb)
+{
+	return sb->s;
+}
+
+/*
+ * Convert the stringbuf to a string.  It is the caller's responsibility
+ * to free the string.  The stringbuf is then ready to be reused.
+ */
+static inline char *sb_to_string(struct stringbuf *sb)
+{
+	char *s = sb->s;
+	if (sb_error(sb))
+		s = kstrdup(s, GFP_ATOMIC);
+	sb_init(sb);
+	return s;
+}
diff --git a/lib/Makefile b/lib/Makefile
index 3a0983b..0c33ff6 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -2,7 +2,7 @@
 # Makefile for some libs needed in the kernel.
 #
 
-lib-y := ctype.o string.o vsprintf.o cmdline.o \
+lib-y := ctype.o string.o stringbuf.o vsprintf.o cmdline.o \
 	 rbtree.o radix-tree.o dump_stack.o \
 	 idr.o int_sqrt.o bitmap.o extable.o prio_tree.o \
 	 sha1.o irq_regs.o reciprocal_div.o argv_split.o \
diff --git a/lib/stringbuf.c b/lib/stringbuf.c
new file mode 100644
index 0000000..0853062
--- /dev/null
+++ b/lib/stringbuf.c
@@ -0,0 +1,79 @@
+/*
+ * stringbuf.c
+ *
+ * Copyright (c) 2007 Intel Corporation
+ * By Matthew Wilcox <willy@linux.intel.com>
+ *
+ * Released under the terms of the GNU GPL, version 2.
+ *
+ * A simple automatically expanding string.  I'm not opposed to adding
+ * more functions to this (eg sb_scanf, sb_insert, sb_delete, sb_strchr, etc),
+ * but I have no need for them right now, so I haven't added them.
+ */
+
+#include <stdarg.h>
+#include <linux/compiler.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/stringbuf.h>
+
+#define INITIAL_SIZE 32
+#define ERR_STRING "out of memory"
+
+/*
+ * Not currently used outside this file, but separated from sb_printf
+ * for when someone needs it.
+ */
+static void sb_vprintf(struct stringbuf *sb, const char *format, va_list args)
+{
+	char *s;
+	int size;
+
+	if (sb->alloc == -ENOMEM)
+		return;
+	if (sb->alloc == 0) {
+		sb->s = kmalloc(INITIAL_SIZE, GFP_ATOMIC);
+		if (!sb->s) 
+			goto nomem;
+		sb->alloc = INITIAL_SIZE;
+	}
+
+	s = sb->s + sb->len;
+	size = vsnprintf(s, sb->alloc - sb->len, format, args);
+
+	sb->len += size;
+	if (likely(sb->len < sb->alloc))
+		return;
+
+	s = krealloc(sb->s, sb->len + 1, GFP_ATOMIC);
+	if (!s)
+		goto nomem;
+	sb->s = s;
+	sb->alloc = ksize(s);
+
+	/* Point to the end of the old string since we already updated ->len */
+	s += sb->len - size;
+	vsprintf(s, format, args);
+	return;
+
+ nomem:
+	kfree(sb->s);
+	sb->s = ERR_STRING;
+	sb->len = sizeof(ERR_STRING);
+	sb->alloc = -ENOMEM;
+}
+/* When we get our first modular user, delete this comment
+EXPORT_SYMBOL(sb_vprintf);
+*/
+
+void sb_printf(struct stringbuf *sb, const char *format, ...)
+{
+	va_list args;
+
+	va_start(args, format);
+	sb_vprintf(sb, format, args);
+	va_end(args);
+}
+EXPORT_SYMBOL(sb_printf);
-- 
1.5.3.4


^ permalink raw reply related	[flat|nested] 39+ messages in thread
* Stringbuf, v2
@ 2007-10-24 19:58 Matthew Wilcox
  2007-10-24 19:59 ` [PATCH 1/4] stringbuf: A string buffer implementation Matthew Wilcox
  0 siblings, 1 reply; 39+ messages in thread
From: Matthew Wilcox @ 2007-10-24 19:58 UTC (permalink / raw)
  To: Linus Torvalds, Andrew Morton, linux-kernel


Incorporated all feedback received:

 - Explicitly allow people to dereference sb->buf and sb->len, and include
   comments about the potential problems with doing so.  Document that alloc
   is probably better left unreferenced.  Remove sb_len() and sb_string().
 - Ensure that we grow by at least 1.5x, even if we're using slob.
 - Start by allocating 128 bytes
 - Pass a gfp_t to sb_printk
 - Drop the bogus change to snd_ac97_proc_regs_write
 - Add stringbuf.o to obj-y instead of lib-y, otherwise a fully modular kernel
   might not pull in sb_printf

-- 
Intel are signing my paycheques ... these opinions are still mine
"Bill, look, we understand that you're interested in selling us this
operating system, but compare it to ours.  We can't possibly take such
a retrograde step."

^ permalink raw reply	[flat|nested] 39+ messages in thread

end of thread, other threads:[~2007-10-30 15:26 UTC | newest]

Thread overview: 39+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-10-23 21:12 [PATCH 1/4] stringbuf: A string buffer implementation Matthew Wilcox
2007-10-23 21:12 ` [PATCH 2/4] isdn: Use stringbuf Matthew Wilcox
2007-10-23 21:12   ` [PATCH 3/4] sound: " Matthew Wilcox
2007-10-23 21:12     ` [PATCH 4/4] partitions: Fix non-atomic printk Matthew Wilcox
2007-10-24 14:18     ` [PATCH 3/4] sound: Use stringbuf Takashi Iwai
2007-10-24 16:01       ` Matthew Wilcox
2007-10-24 14:50         ` Takashi Iwai
2007-10-23 22:11 ` [PATCH 1/4] stringbuf: A string buffer implementation Matt Mackall
2007-10-24  1:49   ` Matthew Wilcox
2007-10-24 15:20     ` Matt Mackall
2007-10-24 15:30       ` Matthew Wilcox
2007-10-23 23:43 ` Linus Torvalds
2007-10-24  2:30   ` Matthew Wilcox
2007-10-24  2:45     ` Andrew Morton
2007-10-24  2:19 ` Eric St-Laurent
2007-10-24  2:35   ` Matthew Wilcox
2007-10-24  2:48     ` Eric St-Laurent
2007-10-24 13:21 ` Florian Weimer
2007-10-24 14:02   ` Matthew Wilcox
2007-10-26 12:05 ` Pekka Enberg
2007-10-27  7:31 ` Pavel Machek
2007-10-30 15:26 ` Denys Vlasenko
  -- strict thread matches above, loose matches on Subject: below --
2007-10-24 19:58 Stringbuf, v2 Matthew Wilcox
2007-10-24 19:59 ` [PATCH 1/4] stringbuf: A string buffer implementation Matthew Wilcox
2007-10-24 20:59   ` Kyle Moffett
2007-10-24 21:21     ` Matthew Wilcox
2007-10-25  0:07       ` Kyle Moffett
2007-10-25  3:23         ` Matthew Wilcox
2007-10-26  2:11   ` Rusty Russell
2007-10-26  3:41     ` Joe Perches
2007-10-26  5:05       ` Joe Perches
2007-10-26 11:57     ` Matthew Wilcox
2007-10-26 20:57       ` Matt Mackall
2007-10-27 10:09         ` Rusty Russell
2007-10-29  3:03           ` Matt Mackall
2007-10-29  5:38             ` Rusty Russell
2007-10-27 11:47     ` Pekka Enberg
2007-10-27 12:50       ` Rusty Russell
2007-10-27 16:34         ` Pekka Enberg
2007-10-27 16:48           ` Matthew Wilcox

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox