summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authorglebius <glebius@FreeBSD.org>2013-10-09 11:57:53 +0000
committerglebius <glebius@FreeBSD.org>2013-10-09 11:57:53 +0000
commit0216035e665dc869f340e168960a39630e822232 (patch)
treef5a49eb40794fc5d8fcfb3ade6caa5b627ca38e1 /sys
parentee2fafc6a903bcdb2569fc1d6c3ffce0f14c3ebd (diff)
downloadFreeBSD-src-0216035e665dc869f340e168960a39630e822232.zip
FreeBSD-src-0216035e665dc869f340e168960a39630e822232.tar.gz
- Substitute sbdrop_internal() with sbcut_internal(). The latter doesn't free
mbufs, but return chain of free mbufs to a caller. Caller can either reuse them or return to allocator in a batch manner. - Implement sbdrop()/sbdrop_locked() as a wrapper around sbcut_internal(). - Expose sbcut_locked() for outside usage. Sponsored by: Netflix Sponsored by: Nginx, Inc. Approved by: re (marius)
Diffstat (limited to 'sys')
-rw-r--r--sys/kern/uipc_sockbuf.c45
-rw-r--r--sys/sys/sockbuf.h2
2 files changed, 36 insertions, 11 deletions
diff --git a/sys/kern/uipc_sockbuf.c b/sys/kern/uipc_sockbuf.c
index 9fa8ae0..c23995f 100644
--- a/sys/kern/uipc_sockbuf.c
+++ b/sys/kern/uipc_sockbuf.c
@@ -65,7 +65,7 @@ u_long sb_max_adj =
static u_long sb_efficiency = 8; /* parameter for sbreserve() */
-static void sbdrop_internal(struct sockbuf *sb, int len);
+static struct mbuf *sbcut_internal(struct sockbuf *sb, int len);
static void sbflush_internal(struct sockbuf *sb);
/*
@@ -818,7 +818,7 @@ sbflush_internal(struct sockbuf *sb)
*/
if (!sb->sb_cc && (sb->sb_mb == NULL || sb->sb_mb->m_len))
break;
- sbdrop_internal(sb, (int)sb->sb_cc);
+ m_freem(sbcut_internal(sb, (int)sb->sb_cc));
}
if (sb->sb_cc || sb->sb_mb || sb->sb_mbcnt)
panic("sbflush_internal: cc %u || mb %p || mbcnt %u",
@@ -843,15 +843,16 @@ sbflush(struct sockbuf *sb)
}
/*
- * Drop data from (the front of) a sockbuf.
+ * Cut data from (the front of) a sockbuf.
*/
-static void
-sbdrop_internal(struct sockbuf *sb, int len)
+static struct mbuf *
+sbcut_internal(struct sockbuf *sb, int len)
{
- struct mbuf *m;
- struct mbuf *next;
+ struct mbuf *m, *n, *next, *mfree;
next = (m = sb->sb_mb) ? m->m_nextpkt : 0;
+ mfree = NULL;
+
while (len > 0) {
if (m == 0) {
if (next == 0)
@@ -872,11 +873,17 @@ sbdrop_internal(struct sockbuf *sb, int len)
}
len -= m->m_len;
sbfree(sb, m);
- m = m_free(m);
+ n = m->m_next;
+ m->m_next = mfree;
+ mfree = m;
+ m = n;
}
while (m && m->m_len == 0) {
sbfree(sb, m);
- m = m_free(m);
+ n = m->m_next;
+ m->m_next = mfree;
+ mfree = m;
+ m = n;
}
if (m) {
sb->sb_mb = m;
@@ -894,6 +901,8 @@ sbdrop_internal(struct sockbuf *sb, int len)
} else if (m->m_nextpkt == NULL) {
sb->sb_lastrecord = m;
}
+
+ return (mfree);
}
/*
@@ -904,17 +913,31 @@ sbdrop_locked(struct sockbuf *sb, int len)
{
SOCKBUF_LOCK_ASSERT(sb);
+ m_freem(sbcut_internal(sb, len));
+}
- sbdrop_internal(sb, len);
+/*
+ * Drop data from (the front of) a sockbuf,
+ * and return it to caller.
+ */
+struct mbuf *
+sbcut_locked(struct sockbuf *sb, int len)
+{
+
+ SOCKBUF_LOCK_ASSERT(sb);
+ return (sbcut_internal(sb, len));
}
void
sbdrop(struct sockbuf *sb, int len)
{
+ struct mbuf *mfree;
SOCKBUF_LOCK(sb);
- sbdrop_locked(sb, len);
+ mfree = sbcut_internal(sb, len);
SOCKBUF_UNLOCK(sb);
+
+ m_freem(mfree);
}
/*
diff --git a/sys/sys/sockbuf.h b/sys/sys/sockbuf.h
index 402a8f0..e716241 100644
--- a/sys/sys/sockbuf.h
+++ b/sys/sys/sockbuf.h
@@ -140,6 +140,8 @@ struct mbuf *
void sbdestroy(struct sockbuf *sb, struct socket *so);
void sbdrop(struct sockbuf *sb, int len);
void sbdrop_locked(struct sockbuf *sb, int len);
+struct mbuf *
+ sbcut_locked(struct sockbuf *sb, int len);
void sbdroprecord(struct sockbuf *sb);
void sbdroprecord_locked(struct sockbuf *sb);
void sbflush(struct sockbuf *sb);
OpenPOWER on IntegriCloud