svn commit: r197447 - in projects/tcp_ffcaia2008_8.x/sys: kern sys
Lawrence Stewart
lstewart at FreeBSD.org
Thu Sep 24 01:58:30 UTC 2009
Author: lstewart
Date: Thu Sep 24 01:58:29 2009
New Revision: 197447
URL: http://svn.freebsd.org/changeset/base/197447
Log:
Fix alq_getn such that it no longer uses malloc, which ensures the KPI is safe
to use in all contexts. This change allows the buffer to develop a "hole" at the
end when a wrap occurs, which should significantly improve performance in
situations where the buffer is wrapping frequently. Testing is required.
Sponsored by: FreeBSD Foundation
Modified:
projects/tcp_ffcaia2008_8.x/sys/kern/kern_alq.c
projects/tcp_ffcaia2008_8.x/sys/sys/alq.h
Modified: projects/tcp_ffcaia2008_8.x/sys/kern/kern_alq.c
==============================================================================
--- projects/tcp_ffcaia2008_8.x/sys/kern/kern_alq.c Thu Sep 24 00:22:33 2009 (r197446)
+++ projects/tcp_ffcaia2008_8.x/sys/kern/kern_alq.c Thu Sep 24 01:58:29 2009 (r197447)
@@ -59,7 +59,9 @@ struct alq {
char *aq_entbuf; /* Buffer for stored entries */
int aq_writehead;
int aq_writetail;
+ int aq_wrapearly; /* # bytes left blank at end of buf */
int aq_flags; /* Queue flags */
+ struct ale aq_getpost; /* ALE for use by get/post */
struct mtx aq_mtx; /* Queue lock */
struct vnode *aq_vp; /* Open vnode handle */
struct ucred *aq_cred; /* Credentials of the opening thread */
@@ -303,6 +305,7 @@ alq_doio(struct alq *alq)
int totlen;
int iov;
int vfslocked;
+ int wrapearly;
KASSERT((ALQ_HAS_PENDING_DATA(alq)),
("%s: queue emtpy!", __func__)
@@ -331,13 +334,15 @@ alq_doio(struct alq *alq)
* - first is from writetail to end of buffer
* - second is from start of buffer to writehead
*/
- aiov[0].iov_len = alq->aq_buflen - alq->aq_writetail;
+ aiov[0].iov_len = alq->aq_buflen - alq->aq_writetail -
+ alq->aq_wrapearly;
iov++;
aiov[1].iov_base = alq->aq_entbuf;
aiov[1].iov_len = alq->aq_writehead;
totlen = aiov[0].iov_len + aiov[1].iov_len;
}
+ wrapearly = alq->aq_wrapearly;
alq->aq_flags |= AQ_FLUSHING;
ALQ_UNLOCK(alq);
@@ -379,8 +384,16 @@ alq_doio(struct alq *alq)
alq->aq_flags &= ~AQ_FLUSHING;
/* Adjust writetail as required, taking into account wrapping. */
- alq->aq_writetail = (alq->aq_writetail + totlen) % alq->aq_buflen;
- alq->aq_freebytes += totlen;
+ alq->aq_writetail = (alq->aq_writetail + totlen + wrapearly) %
+ alq->aq_buflen;
+ alq->aq_freebytes += totlen + wrapearly;
+
+ /*
+ * If we just flushed part of the buffer which wrapped, reset the
+ * wrapearly indicator.
+ */
+ if (wrapearly)
+ alq->aq_wrapearly = 0;
/*
* If we just flushed the buffer completely,
@@ -613,21 +626,12 @@ alq_get(struct alq *alq, int flags)
struct ale *
alq_getn(struct alq *alq, int len, int flags)
{
- struct ale *ale;
int contigbytes;
KASSERT((len > 0 && len <= alq->aq_buflen),
("%s: len <= 0 || len > alq->aq_buflen", __func__)
);
- ale = malloc( sizeof(struct ale),
- M_ALD,
- (flags & ALQ_NOWAIT) ? M_NOWAIT : M_WAITOK
- );
-
- if (ale == NULL)
- return (NULL);
-
ALQ_LOCK(alq);
/*
@@ -640,9 +644,28 @@ alq_getn(struct alq *alq, int len, int f
*/
if (alq->aq_writehead <= alq->aq_writetail)
contigbytes = alq->aq_freebytes;
- else
+ else {
contigbytes = alq->aq_buflen - alq->aq_writehead;
+ if (contigbytes < len) {
+ /*
+ * Insufficient space at end of buffer to handle a
+ * contiguous write. Wrap early if there's space at
+ * the beginning. This will leave a hole at the end
+ * of the buffer which we will have to skip over when
+ * flushing the buffer to disk.
+ */
+ if (alq->aq_writetail >= len || flags & ALQ_WAITOK) {
+ /* Keep track of # bytes left blank. */
+ alq->aq_wrapearly = contigbytes;
+ /* Do the wrap and adjust counters. */
+ contigbytes = alq->aq_freebytes =
+ alq->aq_writetail;
+ alq->aq_writehead = 0;
+ }
+ }
+ }
+
/*
* If the message is larger than our underlying buffer or
* there is not enough free contiguous space in our underlying buffer
@@ -651,7 +674,6 @@ alq_getn(struct alq *alq, int len, int f
if ((len > alq->aq_buflen) ||
((flags & ALQ_NOWAIT) && (contigbytes < len))) {
ALQ_UNLOCK(alq);
- free(ale, M_ALD);
return (NULL);
}
@@ -678,10 +700,9 @@ alq_getn(struct alq *alq, int len, int f
*/
wakeup_one(alq);
- /* Bail if we're shutting down */
+ /* Bail if we're shutting down. */
if (alq->aq_flags & AQ_SHUTDOWN) {
ALQ_UNLOCK(alq);
- free(ale, M_ALD);
return (NULL);
}
@@ -689,8 +710,7 @@ alq_getn(struct alq *alq, int len, int f
* If we are here, we have a contiguous number of bytes >= len
* available in our buffer starting at aq_writehead.
*/
- ale->ae_data = alq->aq_entbuf + alq->aq_writehead;
- ale->ae_datalen = len;
+ alq->aq_getpost.ae_data = alq->aq_entbuf + alq->aq_writehead;
alq->aq_writehead += len;
alq->aq_freebytes -= len;
@@ -702,7 +722,7 @@ alq_getn(struct alq *alq, int len, int f
("%s: aq_writehead < 0 || aq_writehead >= aq_buflen", __func__)
);
- return (ale);
+ return (&alq->aq_getpost);
}
void
@@ -724,8 +744,6 @@ alq_post(struct alq *alq, struct ale *al
ald_activate(alq);
ALD_UNLOCK();
}
-
- free(ale, M_ALD);
}
void
Modified: projects/tcp_ffcaia2008_8.x/sys/sys/alq.h
==============================================================================
--- projects/tcp_ffcaia2008_8.x/sys/sys/alq.h Thu Sep 24 00:22:33 2009 (r197446)
+++ projects/tcp_ffcaia2008_8.x/sys/sys/alq.h Thu Sep 24 01:58:29 2009 (r197447)
@@ -42,8 +42,9 @@ extern struct thread *ald_thread;
* Async. Logging Entry
*/
struct ale {
- char *ae_data; /* Entry buffer */
- int ae_datalen; /* Length of buffer */
+ struct ale *ae_next; /* Unused, compat. */
+ char *ae_data; /* Write ptr. */
+ int ae_flags; /* Unused, compat. */
};
/* flags options */
More information about the svn-src-projects
mailing list