Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 7 Aug 2019 19:23:07 +0000 (UTC)
From:      Conrad Meyer <cem@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r350691 - in head: share/man/man9 sys/kern sys/sys
Message-ID:  <201908071923.x77JN7Ci083696@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: cem
Date: Wed Aug  7 19:23:07 2019
New Revision: 350691
URL: https://svnweb.freebsd.org/changeset/base/350691

Log:
  sbuf(9): Add NOWAIT dynamic buffer extension mode
  
  The goal is to avoid some kinds of low-memory deadlock when formatting
  heap-allocated buffers.
  
  Reviewed by:	vangyzen
  Sponsored by:	Dell EMC Isilon
  Differential Revision:	https://reviews.freebsd.org/D21015

Modified:
  head/share/man/man9/sbuf.9
  head/sys/kern/subr_sbuf.c
  head/sys/sys/sbuf.h

Modified: head/share/man/man9/sbuf.9
==============================================================================
--- head/share/man/man9/sbuf.9	Wed Aug  7 19:18:32 2019	(r350690)
+++ head/share/man/man9/sbuf.9	Wed Aug  7 19:23:07 2019	(r350691)
@@ -25,7 +25,7 @@
 .\"
 .\" $FreeBSD$
 .\"
-.Dd May 7, 2019
+.Dd August 7, 2019
 .Dt SBUF 9
 .Os
 .Sh NAME
@@ -288,6 +288,11 @@ If a record grows sufficiently large such that it fill
 and therefore cannot be drained without being split, an error of
 .Er EDEADLK
 is set.
+.It Dv SBUF_NOWAIT
+Indicates that attempts to extend the storage buffer should fail in low memory
+conditions, like
+.Xr malloc 9
+.Dv M_NOWAIT .
 .El
 .Pp
 Note that if

Modified: head/sys/kern/subr_sbuf.c
==============================================================================
--- head/sys/kern/subr_sbuf.c	Wed Aug  7 19:18:32 2019	(r350690)
+++ head/sys/kern/subr_sbuf.c	Wed Aug  7 19:23:07 2019	(r350691)
@@ -56,11 +56,11 @@ __FBSDID("$FreeBSD$");
 
 #ifdef _KERNEL
 static MALLOC_DEFINE(M_SBUF, "sbuf", "string buffers");
-#define	SBMALLOC(size)		malloc(size, M_SBUF, M_WAITOK|M_ZERO)
+#define	SBMALLOC(size, flags)	malloc(size, M_SBUF, (flags) | M_ZERO)
 #define	SBFREE(buf)		free(buf, M_SBUF)
 #else /* _KERNEL */
 #define	KASSERT(e, m)
-#define	SBMALLOC(size)		calloc(1, size)
+#define	SBMALLOC(size, flags)	calloc(1, size)
 #define	SBFREE(buf)		free(buf)
 #endif /* _KERNEL */
 
@@ -77,6 +77,8 @@ static MALLOC_DEFINE(M_SBUF, "sbuf", "string buffers")
 #define	SBUF_NULINCLUDED(s)	((s)->s_flags & SBUF_INCLUDENUL)
 #define	SBUF_ISDRAINTOEOR(s)	((s)->s_flags & SBUF_DRAINTOEOR)
 #define	SBUF_DODRAINTOEOR(s)	(SBUF_ISSECTION(s) && SBUF_ISDRAINTOEOR(s))
+#define	SBUF_MALLOCFLAG(s)	\
+	(((s)->s_flags & SBUF_NOWAIT) ? M_NOWAIT : M_WAITOK)
 
 /*
  * Set / clear flags
@@ -171,7 +173,7 @@ sbuf_extend(struct sbuf *s, int addlen)
 	if (!SBUF_CANEXTEND(s))
 		return (-1);
 	newsize = sbuf_extendsize(s->s_size + addlen);
-	newbuf = SBMALLOC(newsize);
+	newbuf = SBMALLOC(newsize, SBUF_MALLOCFLAG(s));
 	if (newbuf == NULL)
 		return (-1);
 	memcpy(newbuf, s->s_buf, s->s_size);
@@ -198,7 +200,7 @@ sbuf_newbuf(struct sbuf *s, char *buf, int length, int
 	s->s_size = length;
 	s->s_buf = buf;
 
-	if ((s->s_flags & SBUF_AUTOEXTEND) == 0) {
+	if (!SBUF_CANEXTEND(s)) {
 		KASSERT(s->s_size >= SBUF_MINSIZE,
 		    ("attempt to create an sbuf smaller than %d bytes",
 		    SBUF_MINSIZE));
@@ -207,10 +209,10 @@ sbuf_newbuf(struct sbuf *s, char *buf, int length, int
 	if (s->s_buf != NULL)
 		return (s);
 
-	if ((flags & SBUF_AUTOEXTEND) != 0)
+	if (SBUF_CANEXTEND(s))
 		s->s_size = sbuf_extendsize(s->s_size);
 
-	s->s_buf = SBMALLOC(s->s_size);
+	s->s_buf = SBMALLOC(s->s_size, SBUF_MALLOCFLAG(s));
 	if (s->s_buf == NULL)
 		return (NULL);
 	SBUF_SETFLAG(s, SBUF_DYNAMIC);
@@ -235,7 +237,7 @@ sbuf_new(struct sbuf *s, char *buf, int length, int fl
 	if (s != NULL)
 		return (sbuf_newbuf(s, buf, length, flags));
 
-	s = SBMALLOC(sizeof(*s));
+	s = SBMALLOC(sizeof(*s), (flags & SBUF_NOWAIT) ? M_NOWAIT : M_WAITOK);
 	if (s == NULL)
 		return (NULL);
 	if (sbuf_newbuf(s, buf, length, flags) == NULL) {

Modified: head/sys/sys/sbuf.h
==============================================================================
--- head/sys/sys/sbuf.h	Wed Aug  7 19:18:32 2019	(r350690)
+++ head/sys/sys/sbuf.h	Wed Aug  7 19:23:07 2019	(r350691)
@@ -52,6 +52,7 @@ struct sbuf {
 #define	SBUF_AUTOEXTEND	0x00000001	/* automatically extend buffer */
 #define	SBUF_INCLUDENUL	0x00000002	/* nulterm byte is counted in len */
 #define	SBUF_DRAINTOEOR	0x00000004	/* use section 0 as drain EOR marker */
+#define	SBUF_NOWAIT	0x00000008	/* Extend with non-blocking malloc */
 #define	SBUF_USRFLAGMSK	0x0000ffff	/* mask of flags the user may specify */
 #define	SBUF_DYNAMIC	0x00010000	/* s_buf must be freed */
 #define	SBUF_FINISHED	0x00020000	/* set by sbuf_finish() */



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201908071923.x77JN7Ci083696>