Date: Thu, 24 Sep 2009 01:58:30 +0000 (UTC) From: Lawrence Stewart <lstewart@FreeBSD.org> To: src-committers@freebsd.org, svn-src-projects@freebsd.org Subject: svn commit: r197447 - in projects/tcp_ffcaia2008_8.x/sys: kern sys Message-ID: <200909240158.n8O1wUgh080272@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
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 */
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200909240158.n8O1wUgh080272>