From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 2178) id 37C203858414; Tue, 29 Aug 2023 07:32:04 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 37C203858414 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1693294324; bh=KZAIln1p2DzlMegjS4NVsAYmXS+me1kTeJ0XshLL5+c=; h=From:To:Subject:Date:From; b=o8w0aa+YaggmgWLJgcK6Sh34ERHeZdLyVymribvX0GfF6VlwrGF9BnxNFZ900CG4A sT1A2Lkd376af+7t5/8mQiCy6E+DljrgoUrfBjckviQuNNsCNA+A7HVpeCigvm3JDp tsDKkw3Bdi2nW9rZ5v5IZ6OigwI2Lnw3ENpFpOxU= Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: Florian Weimer To: glibc-cvs@sourceware.org Subject: [glibc] nscd: Skip unusable entries in first pass in prune_cache (bug 30800) X-Act-Checkin: glibc X-Git-Author: Florian Weimer X-Git-Refname: refs/heads/master X-Git-Oldrev: 693918b6dd13ce2bd8dd3c5734de99f67d5818db X-Git-Newrev: c00b984fcd53f679ca2dafcd1aee2c89836e6e73 Message-Id: <20230829073204.37C203858414@sourceware.org> Date: Tue, 29 Aug 2023 07:32:04 +0000 (GMT) List-Id: https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=c00b984fcd53f679ca2dafcd1aee2c89836e6e73 commit c00b984fcd53f679ca2dafcd1aee2c89836e6e73 Author: Florian Weimer Date: Tue Aug 29 08:28:31 2023 +0200 nscd: Skip unusable entries in first pass in prune_cache (bug 30800) Previously, if an entry was marked unusable for any reason, but had not timed out yet, the assert would trigger. One way to get into such state is if a data change is detected during re-validation of an entry. This causes the entry to be marked as not usable. If exits nscd soon after that, then the clock jumps backwards, and nscd restarted, the cache re-validation run after startup triggers the removed assert. The change is more complicated than just the removal of the assert because entries marked as not usable should be garbage-collected in the second pass. To make this happen, it is necessary to update some book-keeping data. Reviewed-by: DJ Delorie Diff: --- nscd/cache.c | 25 +++++++++++-------------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/nscd/cache.c b/nscd/cache.c index b4b54d82bb..336ff548cb 100644 --- a/nscd/cache.c +++ b/nscd/cache.c @@ -370,8 +370,11 @@ prune_cache (struct database_dyn *table, time_t now, int fd) serv2str[runp->type], str, dh->timeout); } - /* Check whether the entry timed out. */ - if (dh->timeout < now) + /* Check whether the entry timed out. Timed out entries + will be revalidated. For unusable records, it is still + necessary to record that the bucket needs to be scanned + again below. */ + if (dh->timeout < now || !dh->usable) { /* This hash bucket could contain entries which need to be looked at. */ @@ -383,7 +386,7 @@ prune_cache (struct database_dyn *table, time_t now, int fd) /* We only have to look at the data of the first entries since the count information is kept in the data part which is shared. */ - if (runp->first) + if (runp->first && dh->usable) { /* At this point there are two choices: we reload the @@ -399,9 +402,6 @@ prune_cache (struct database_dyn *table, time_t now, int fd) { /* Remove the value. */ dh->usable = false; - - /* We definitely have some garbage entries now. */ - any = true; } else { @@ -413,18 +413,15 @@ prune_cache (struct database_dyn *table, time_t now, int fd) time_t timeout = readdfcts[runp->type] (table, runp, dh); next_timeout = MIN (next_timeout, timeout); - - /* If the entry has been replaced, we might need - cleanup. */ - any |= !dh->usable; } } + + /* If the entry has been replaced, we might need cleanup. */ + any |= !dh->usable; } else - { - assert (dh->usable); - next_timeout = MIN (next_timeout, dh->timeout); - } + /* Entry has not timed out and is usable. */ + next_timeout = MIN (next_timeout, dh->timeout); run = runp->next; }