svn commit: r350691 - in head: share/man/man9 sys/kern sys/sys
Conrad Meyer
cem at FreeBSD.org
Wed Aug 7 19:23:08 UTC 2019
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() */
More information about the svn-src-head
mailing list