Date: Thu, 17 Aug 2017 07:20:09 +0000 (UTC) From: Lawrence Stewart <lstewart@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r322614 - in head: share/man/man9 sys/kern sys/sys Message-ID: <201708170720.v7H7K9BO085131@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: lstewart Date: Thu Aug 17 07:20:09 2017 New Revision: 322614 URL: https://svnweb.freebsd.org/changeset/base/322614 Log: Implement simple record boundary tracking in sbuf(9) to avoid record splitting during drain operations. When an sbuf is configured to use this feature by way of the SBUF_DRAINTOEOR sbuf_new() flag, top-level sections started with sbuf_start_section() create a record boundary marker that is used to avoid flushing partial records. Reviewed by: cem,imp,wblock MFC after: 2 weeks Sponsored by: Netflix, Inc. Differential Revision: https://reviews.freebsd.org/D8536 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 Thu Aug 17 06:36:21 2017 (r322613) +++ head/share/man/man9/sbuf.9 Thu Aug 17 07:20:09 2017 (r322614) @@ -25,7 +25,7 @@ .\" .\" $FreeBSD$ .\" -.Dd April 5, 2017 +.Dd August 17, 2017 .Dt SBUF 9 .Os .Sh NAME @@ -271,6 +271,14 @@ This indicates that the storage buffer may be extended as resources allow, to hold additional data. .It Dv SBUF_INCLUDENUL This causes the final nulterm byte to be counted in the length of the data. +.It Dv SBUF_DRAINTOEOR +Treat top-level sections started with +.Fn sbuf_start_section +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. .El .Pp Note that if Modified: head/sys/kern/subr_sbuf.c ============================================================================== --- head/sys/kern/subr_sbuf.c Thu Aug 17 06:36:21 2017 (r322613) +++ head/sys/kern/subr_sbuf.c Thu Aug 17 07:20:09 2017 (r322614) @@ -73,6 +73,8 @@ static MALLOC_DEFINE(M_SBUF, "sbuf", "string buffers") #define SBUF_CANEXTEND(s) ((s)->s_flags & SBUF_AUTOEXTEND) #define SBUF_ISSECTION(s) ((s)->s_flags & SBUF_INSECTION) #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)) /* * Set / clear flags @@ -308,6 +310,7 @@ sbuf_clear(struct sbuf *s) SBUF_CLEARFLAG(s, SBUF_FINISHED); s->s_error = 0; s->s_len = 0; + s->s_rec_off = 0; s->s_sect_len = 0; } @@ -362,7 +365,10 @@ sbuf_drain(struct sbuf *s) KASSERT(s->s_len > 0, ("Shouldn't drain empty sbuf %p", s)); KASSERT(s->s_error == 0, ("Called %s with error on %p", __func__, s)); - len = s->s_drain_func(s->s_drain_arg, s->s_buf, s->s_len); + if (SBUF_DODRAINTOEOR(s) && s->s_rec_off == 0) + return (s->s_error = EDEADLK); + len = s->s_drain_func(s->s_drain_arg, s->s_buf, + SBUF_DODRAINTOEOR(s) ? s->s_rec_off : s->s_len); if (len < 0) { s->s_error = -len; return (s->s_error); @@ -370,6 +376,7 @@ sbuf_drain(struct sbuf *s) KASSERT(len > 0 && len <= s->s_len, ("Bad drain amount %d for sbuf %p", len, s)); s->s_len -= len; + s->s_rec_off -= len; /* * Fast path for the expected case where all the data was * drained. @@ -835,6 +842,7 @@ sbuf_start_section(struct sbuf *s, ssize_t *old_lenp) ("s_sect_len != 0 when starting a section")); if (old_lenp != NULL) *old_lenp = -1; + s->s_rec_off = s->s_len; SBUF_SETFLAG(s, SBUF_INSECTION); } else { KASSERT(old_lenp != NULL, @@ -865,7 +873,7 @@ sbuf_end_section(struct sbuf *s, ssize_t old_len, size } len = s->s_sect_len; if (old_len == -1) { - s->s_sect_len = 0; + s->s_rec_off = s->s_sect_len = 0; SBUF_CLEARFLAG(s, SBUF_INSECTION); } else { s->s_sect_len += old_len; Modified: head/sys/sys/sbuf.h ============================================================================== --- head/sys/sys/sbuf.h Thu Aug 17 06:36:21 2017 (r322613) +++ head/sys/sys/sbuf.h Thu Aug 17 07:20:09 2017 (r322614) @@ -49,6 +49,7 @@ struct sbuf { #define SBUF_FIXEDLEN 0x00000000 /* fixed length buffer (default) */ #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_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() */ @@ -56,6 +57,7 @@ struct sbuf { #define SBUF_INSECTION 0x00100000 /* set by sbuf_start_section() */ int s_flags; /* flags */ ssize_t s_sect_len; /* current length of section */ + ssize_t s_rec_off; /* current record start offset */ }; #ifndef HD_COLUMN_MASK
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201708170720.v7H7K9BO085131>