From patchwork Sun Mar 1 17:55:33 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Florian Weimer X-Patchwork-Id: 444999 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4A77714009B for ; Mon, 2 Mar 2015 20:43:29 +1100 (AEDT) Authentication-Results: ozlabs.org; dkim=pass reason="1024-bit key; unprotected key" header.d=sourceware.org header.i=@sourceware.org header.b=PDLJrTDU; dkim-adsp=none (unprotected policy); dkim-atps=neutral DomainKey-Signature: a=rsa-sha1; c=nofws; d=sourceware.org; h=list-id :list-unsubscribe:list-subscribe:list-archive:list-post :list-help:sender:message-id:in-reply-to:references:from:date :subject:to; q=dns; s=default; b=QGl+4Lwamoyd/8DfF8AHk+MBdv7LqCF Bb23WNsxSeygwFVs8WZcGQT31MzMApUDo78u00tYUxa2N5VtZmJFVp6a0/zWNfyf iFBB+WRA2J7CQFzJuH+5HJ0iPJkeMaSfxNcJjgY2wFjKpQWzR9B6SZfEWa5S08sU 19ZWOpkwjay0= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=sourceware.org; h=list-id :list-unsubscribe:list-subscribe:list-archive:list-post :list-help:sender:message-id:in-reply-to:references:from:date :subject:to; s=default; bh=EsN17E9GlXkyZXkZH/LcPp5y7gU=; b=PDLJr TDUxXu6xL5qTeMmPq4BwPgvPQqBpmG6WRNmQHSMeEvvXpy6Xel2Wq48dFyIO7EYK XjOtbwSrX7/RKC7md0PYT3MHC90+uFS3fY/3hap7xfx4JBBVYadrBOq2OiDUMosA SxX/SSTwPkJnH2YKNjIprr1E+ostXwQyPqZX8U= Received: (qmail 26281 invoked by alias); 2 Mar 2015 09:43:07 -0000 Mailing-List: contact libc-alpha-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: libc-alpha-owner@sourceware.org Delivered-To: mailing list libc-alpha@sourceware.org Received: (qmail 26215 invoked by uid 89); 2 Mar 2015 09:43:06 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-1.0 required=5.0 tests=AWL, BAYES_50, DATE_IN_PAST_12_24, SPF_HELO_PASS, SPF_PASS, T_RP_MATCHES_RCVD autolearn=no version=3.3.2 X-HELO: mx1.redhat.com Message-Id: In-Reply-To: References: From: Florian Weimer Date: Sun, 1 Mar 2015 18:55:33 +0100 Subject: [PATCH 14/25] nscd: Use struct scratch_buffer instead of extend_alloca in most caches To: libc-alpha@sourceware.org This replaces the ERANGE retry loops with loops which have heap fallback. Heap allocation might actually be required for extremely large NSS results. --- nscd/grpcache.c | 57 +++++++++++++++++---------------------------------- nscd/hstcache.c | 58 ++++++++++++++++++---------------------------------- nscd/pwdcache.c | 56 ++++++++++++++++---------------------------------- nscd/servicescache.c | 56 ++++++++++++++++---------------------------------- 4 files changed, 75 insertions(+), 152 deletions(-) diff --git a/nscd/grpcache.c b/nscd/grpcache.c index eed0e3d..e32011d 100644 --- a/nscd/grpcache.c +++ b/nscd/grpcache.c @@ -16,7 +16,6 @@ You should have received a copy of the GNU General Public License along with this program; if not, see . */ -#include #include #include #include @@ -32,6 +31,7 @@ #include #include #include +#include #include "nscd.h" #include "dbg_log.h" @@ -437,12 +437,12 @@ addgrbyX (struct database_dyn *db, int fd, request_header *req, look again in the table whether the dataset is now available. We simply insert it. It does not matter if it is in there twice. The pruning function only will look at the timestamp. */ - size_t buflen = 1024; - char *buffer = (char *) alloca (buflen); + struct group resultbuf; struct group *grp; - bool use_malloc = false; int errval = 0; + struct scratch_buffer tmpbuf; + scratch_buffer_init (&tmpbuf); if (__glibc_unlikely (debug_level > 0)) { @@ -452,43 +452,24 @@ addgrbyX (struct database_dyn *db, int fd, request_header *req, dbg_log (_("Reloading \"%s\" in group cache!"), keystr); } - while (lookup (req->type, key, &resultbuf, buffer, buflen, &grp) != 0 + while (lookup (req->type, key, &resultbuf, + tmpbuf.data, tmpbuf.length, &grp) != 0 && (errval = errno) == ERANGE) - { - errno = 0; - - if (__glibc_unlikely (buflen > 32768)) - { - char *old_buffer = buffer; - buflen *= 2; - buffer = (char *) realloc (use_malloc ? buffer : NULL, buflen); - if (buffer == NULL) - { - /* We ran out of memory. We cannot do anything but - sending a negative response. In reality this should - never happen. */ - grp = NULL; - buffer = old_buffer; - - /* We set the error to indicate this is (possibly) a - temporary error and that it does not mean the entry - is not available at all. */ - errval = EAGAIN; - break; - } - use_malloc = true; - } - else - /* Allocate a new buffer on the stack. If possible combine it - with the previously allocated buffer. */ - buffer = (char *) extend_alloca (buffer, buflen, 2 * buflen); - } + if (!scratch_buffer_grow (&tmpbuf)) + { + /* We ran out of memory. We cannot do anything but sending a + negative response. In reality this should never + happen. */ + grp = NULL; + /* We set the error to indicate this is (possibly) a temporary + error and that it does not mean the entry is not available + at all. */ + errval = EAGAIN; + break; + } time_t timeout = cache_addgr (db, fd, req, keystr, grp, uid, he, dh, errval); - - if (use_malloc) - free (buffer); - + scratch_buffer_free (&tmpbuf); return timeout; } diff --git a/nscd/hstcache.c b/nscd/hstcache.c index e6db064..1b76ca1 100644 --- a/nscd/hstcache.c +++ b/nscd/hstcache.c @@ -34,6 +34,7 @@ #include #include #include +#include #include "nscd.h" #include "dbg_log.h" @@ -463,11 +464,8 @@ addhstbyX (struct database_dyn *db, int fd, request_header *req, look again in the table whether the dataset is now available. We simply insert it. It does not matter if it is in there twice. The pruning function only will look at the timestamp. */ - int buflen = 1024; - char *buffer = (char *) alloca (buflen); struct hostent resultbuf; struct hostent *hst; - bool use_malloc = false; int errval = 0; int32_t ttl = INT32_MAX; @@ -487,46 +485,30 @@ addhstbyX (struct database_dyn *db, int fd, request_header *req, dbg_log (_("Reloading \"%s\" in hosts cache!"), (char *) str); } - while (lookup (req->type, key, &resultbuf, buffer, buflen, &hst, &ttl) != 0 + struct scratch_buffer tmpbuf; + scratch_buffer_init (&tmpbuf); + + while (lookup (req->type, key, &resultbuf, + tmpbuf.data, tmpbuf.length, &hst, &ttl) != 0 && h_errno == NETDB_INTERNAL && (errval = errno) == ERANGE) - { - errno = 0; - - if (__glibc_unlikely (buflen > 32768)) - { - char *old_buffer = buffer; - buflen *= 2; - buffer = (char *) realloc (use_malloc ? buffer : NULL, buflen); - if (buffer == NULL) - { - /* We ran out of memory. We cannot do anything but - sending a negative response. In reality this should - never happen. */ - hst = NULL; - buffer = old_buffer; - - /* We set the error to indicate this is (possibly) a - temporary error and that it does not mean the entry - is not available at all. */ - h_errno = TRY_AGAIN; - errval = EAGAIN; - break; - } - use_malloc = true; - } - else - /* Allocate a new buffer on the stack. If possible combine it - with the previously allocated buffer. */ - buffer = (char *) extend_alloca (buffer, buflen, 2 * buflen); - } + if (!scratch_buffer_grow (&tmpbuf)) + { + /* We ran out of memory. We cannot do anything but sending a + negative response. In reality this should never + happen. */ + hst = NULL; + /* We set the error to indicate this is (possibly) a temporary + error and that it does not mean the entry is not + available at all. */ + h_errno = TRY_AGAIN; + errval = EAGAIN; + break; + } time_t timeout = cache_addhst (db, fd, req, key, hst, uid, he, dh, h_errno == TRY_AGAIN ? errval : 0, ttl); - - if (use_malloc) - free (buffer); - + scratch_buffer_free (&tmpbuf); return timeout; } diff --git a/nscd/pwdcache.c b/nscd/pwdcache.c index b12a13d..07b9e48 100644 --- a/nscd/pwdcache.c +++ b/nscd/pwdcache.c @@ -16,7 +16,6 @@ You should have received a copy of the GNU General Public License along with this program; if not, see . */ -#include #include #include #include @@ -32,6 +31,7 @@ #include #include #include +#include #include "nscd.h" #include "dbg_log.h" @@ -415,12 +415,11 @@ addpwbyX (struct database_dyn *db, int fd, request_header *req, look again in the table whether the dataset is now available. We simply insert it. It does not matter if it is in there twice. The pruning function only will look at the timestamp. */ - size_t buflen = 1024; - char *buffer = (char *) alloca (buflen); struct passwd resultbuf; struct passwd *pwd; - bool use_malloc = false; int errval = 0; + struct scratch_buffer tmpbuf; + scratch_buffer_init (&tmpbuf); if (__glibc_unlikely (debug_level > 0)) { @@ -430,45 +429,26 @@ addpwbyX (struct database_dyn *db, int fd, request_header *req, dbg_log (_("Reloading \"%s\" in password cache!"), keystr); } - while (lookup (req->type, key, &resultbuf, buffer, buflen, &pwd) != 0 + while (lookup (req->type, key, &resultbuf, + tmpbuf.data, tmpbuf.length, &pwd) != 0 && (errval = errno) == ERANGE) - { - errno = 0; - - if (__glibc_unlikely (buflen > 32768)) - { - char *old_buffer = buffer; - buflen *= 2; - buffer = (char *) realloc (use_malloc ? buffer : NULL, buflen); - if (buffer == NULL) - { - /* We ran out of memory. We cannot do anything but - sending a negative response. In reality this should - never happen. */ - pwd = NULL; - buffer = old_buffer; - - /* We set the error to indicate this is (possibly) a - temporary error and that it does not mean the entry - is not available at all. */ - errval = EAGAIN; - break; - } - use_malloc = true; - } - else - /* Allocate a new buffer on the stack. If possible combine it - with the previously allocated buffer. */ - buffer = (char *) extend_alloca (buffer, buflen, 2 * buflen); - } + if (!scratch_buffer_grow (&tmpbuf)) + { + /* We ran out of memory. We cannot do anything but sending a + negative response. In reality this should never + happen. */ + pwd = NULL; + /* We set the error to indicate this is (possibly) a temporary + error and that it does not mean the entry is not available + at all. */ + errval = EAGAIN; + break; + } /* Add the entry to the cache. */ time_t timeout = cache_addpw (db, fd, req, keystr, pwd, c_uid, he, dh, errval); - - if (use_malloc) - free (buffer); - + scratch_buffer_free (&tmpbuf); return timeout; } diff --git a/nscd/servicescache.c b/nscd/servicescache.c index 4e8ee4c..fc29d25 100644 --- a/nscd/servicescache.c +++ b/nscd/servicescache.c @@ -16,7 +16,6 @@ You should have received a copy of the GNU General Public License along with this program; if not, see . */ -#include #include #include #include @@ -25,6 +24,7 @@ #include #include #include +#include #include "nscd.h" #include "dbg_log.h" @@ -374,12 +374,11 @@ addservbyX (struct database_dyn *db, int fd, request_header *req, look again in the table whether the dataset is now available. We simply insert it. It does not matter if it is in there twice. The pruning function only will look at the timestamp. */ - size_t buflen = 1024; - char *buffer = (char *) alloca (buflen); struct servent resultbuf; struct servent *serv; - bool use_malloc = false; int errval = 0; + struct scratch_buffer tmpbuf; + scratch_buffer_init (&tmpbuf); if (__glibc_unlikely (debug_level > 0)) { @@ -389,43 +388,24 @@ addservbyX (struct database_dyn *db, int fd, request_header *req, dbg_log (_("Reloading \"%s\" in services cache!"), key); } - while (lookup (req->type, key, &resultbuf, buffer, buflen, &serv) != 0 + while (lookup (req->type, key, &resultbuf, + tmpbuf.data, tmpbuf.length, &serv) != 0 && (errval = errno) == ERANGE) - { - errno = 0; - - if (__glibc_unlikely (buflen > 32768)) - { - char *old_buffer = buffer; - buflen *= 2; - buffer = (char *) realloc (use_malloc ? buffer : NULL, buflen); - if (buffer == NULL) - { - /* We ran out of memory. We cannot do anything but - sending a negative response. In reality this should - never happen. */ - serv = NULL; - buffer = old_buffer; - - /* We set the error to indicate this is (possibly) a - temporary error and that it does not mean the entry - is not available at all. */ - errval = EAGAIN; - break; - } - use_malloc = true; - } - else - /* Allocate a new buffer on the stack. If possible combine it - with the previously allocated buffer. */ - buffer = (char *) extend_alloca (buffer, buflen, 2 * buflen); - } + if (!scratch_buffer_grow (&tmpbuf)) + { + /* We ran out of memory. We cannot do anything but sending a + negative response. In reality this should never + happen. */ + serv = NULL; + /* We set the error to indicate this is (possibly) a temporary + error and that it does not mean the entry is not available + at all. */ + errval = EAGAIN; + break; + } time_t timeout = cache_addserv (db, fd, req, key, serv, uid, he, dh, errval); - - if (use_malloc) - free (buffer); - + scratch_buffer_free (&tmpbuf); return timeout; }