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() */
_______________________________________________
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to