The branch stable/12 has been updated by imp:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=81999965113107eb9cecc217a4f496dd78c1ca3a

commit 81999965113107eb9cecc217a4f496dd78c1ca3a
Author:     Conrad Meyer <[email protected]>
AuthorDate: 2019-08-07 19:23:07 +0000
Commit:     Warner Losh <[email protected]>
CommitDate: 2021-07-16 17:43:55 +0000

    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
    
    (cherry picked from commit 71db411eb627601a5f9a3464f88d75741927ce60)
---
 share/man/man9/sbuf.9 | 11 +++++++++--
 sys/kern/subr_sbuf.c  | 16 +++++++++-------
 sys/sys/sbuf.h        |  1 +
 3 files changed, 19 insertions(+), 9 deletions(-)

diff --git a/share/man/man9/sbuf.9 b/share/man/man9/sbuf.9
index 519e801e4868..4184f77631a7 100644
--- a/share/man/man9/sbuf.9
+++ b/share/man/man9/sbuf.9
@@ -25,7 +25,7 @@
 .\"
 .\" $FreeBSD$
 .\"
-.Dd August 26, 2020
+.Dd July 12, 2021
 .Dt SBUF 9
 .Os
 .Sh NAME
@@ -278,7 +278,14 @@ as a record boundary marker that will be used during drain 
operations to avoid
 records being split.
 If a record grows sufficiently large such that it fills the
 .Fa sbuf
-and therefore cannot be drained without being split, an error of EDEADLK is 
set.
+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
diff --git a/sys/kern/subr_sbuf.c b/sys/kern/subr_sbuf.c
index 03f7b1e94c51..4a046cc41787 100644
--- a/sys/kern/subr_sbuf.c
+++ b/sys/kern/subr_sbuf.c
@@ -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 
flags)
        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 
flags)
        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 flags)
        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) {
diff --git a/sys/sys/sbuf.h b/sys/sys/sbuf.h
index 1927996c8f38..9ef9bad7d9be 100644
--- a/sys/sys/sbuf.h
+++ b/sys/sys/sbuf.h
@@ -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() */
_______________________________________________
[email protected] mailing list
https://lists.freebsd.org/mailman/listinfo/dev-commits-src-all
To unsubscribe, send any mail to "[email protected]"

Reply via email to