svn commit: r322614 - in head: share/man/man9 sys/kern sys/sys
Lawrence Stewart
lstewart at FreeBSD.org
Thu Aug 17 07:20:10 UTC 2017
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
More information about the svn-src-all
mailing list