From owner-svn-src-projects@FreeBSD.ORG Thu Sep 24 01:58:30 2009 Return-Path: Delivered-To: svn-src-projects@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 41C98106566B; Thu, 24 Sep 2009 01:58:30 +0000 (UTC) (envelope-from lstewart@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 313248FC1E; Thu, 24 Sep 2009 01:58:30 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id n8O1wU5D080275; Thu, 24 Sep 2009 01:58:30 GMT (envelope-from lstewart@svn.freebsd.org) Received: (from lstewart@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id n8O1wUgh080272; Thu, 24 Sep 2009 01:58:30 GMT (envelope-from lstewart@svn.freebsd.org) Message-Id: <200909240158.n8O1wUgh080272@svn.freebsd.org> From: Lawrence Stewart Date: Thu, 24 Sep 2009 01:58:30 +0000 (UTC) To: src-committers@freebsd.org, svn-src-projects@freebsd.org X-SVN-Group: projects MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r197447 - in projects/tcp_ffcaia2008_8.x/sys: kern sys X-BeenThere: svn-src-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the src " projects" tree" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 24 Sep 2009 01:58:30 -0000 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 */