This patch is generated from the store_check branch of HEAD in squid
Mon Jan 26 12:50:24 2004 GMT
See http://devel.squid-cache.org/

Index: squid/src/cf.data.pre
diff -u squid/src/cf.data.pre:1.4 squid/src/cf.data.pre:1.4.8.2
--- squid/src/cf.data.pre:1.4	Fri Nov  3 00:39:20 2000
+++ squid/src/cf.data.pre	Sat Nov 25 16:25:43 2000
@@ -3271,6 +3271,44 @@
 	Set this to 'round-robin' as an alternative.
 DOC_END
 
+NAME: store_background_permit
+TYPE: acl_access
+LOC: Config.accessList.storebackgroundcheck
+DEFAULT: none
+DEFAULT_IF_NONE: deny all
+DOC_START
+        Allow the store background consistency check to run. Only use
+        time ACL's!
+
+        store_background_permit allow [!]aclname
+
+        NOTE on default values:
+
+        If there are no "background_permit" lines present, the default is to
+        run 24x7. 
+
+        If none of the "background_permit" lines cause a match, the check will
+        never run. 
+
+NOCOMMENT_START
+#Recommended configuration:
+#
+acl eleventotwo time 23:00-23:59
+acl eleventotwo time 00:00-02:00
+store_background_permit allow eleventotwo
+NOCOMMENT_END
+DOC_END
+
+
+NAME: store_background_check_rate
+TYPE: int
+LOC: Config.store_background_check_rate
+DEFAULT: 50
+DOC_START
+	The number of entries to check on each store background check. Low 
+	numbers (<100) are good.
+DOC_END
+
 NAME: forward_log
 IFDEF: WIP_FWD_LOG
 TYPE: string
Index: squid/src/main.c
diff -u squid/src/main.c:1.5 squid/src/main.c:1.5.6.1
--- squid/src/main.c:1.5	Fri Nov 10 08:36:45 2000
+++ squid/src/main.c	Sat Nov 25 14:34:43 2000
@@ -101,8 +101,7 @@
 	"       -F        Don't serve any requests until store is rebuilt.\n"
 	"       -N        No daemon mode.\n"
 	"       -R        Do not set REUSEADDR on port.\n"
-	"       -S force  Force double-check swap during rebuild.\n"
-        "       -S reportonly Force double-check but do not attempt repair.\n"
+	"       -S        Force debug double-check swap during rebuild. [stops on errors]\n"
 	"       -V        Virtual host httpd-accelerator.\n"
 	"       -X        Force full debugging.\n"
 	"       -Y        Only return UDP_HIT or UDP_MISS_NOFETCH during fast reload.\n",
@@ -116,7 +115,7 @@
     extern char *optarg;
     int c;
 
-    while ((c = getopt(argc, argv, "CDFNRS:VYXa:d:f:hk:m::su:vz?")) != -1) {
+    while ((c = getopt(argc, argv, "CDFNRSVYXa:d:f:hk:m::su:vz?")) != -1) {
 	switch (c) {
 	case 'C':
 	    opt_catch_signals = 0;
@@ -134,14 +133,8 @@
 	    opt_reuseaddr = 0;
 	    break;
 	case 'S':
-            if ((int) strlen(optarg) < 1) 
-                usage();
-            else if (!strncmp(optarg, "force", strlen(optarg)))
-                opt_store_doublecheck = DBLCHECK_FORCE; /* trigger a doublecheck on startup */
-            else if (!strncmp(optarg, "reportonly", strlen(optarg)))
-                opt_store_doublecheck = DBLCHECK_REPORTONLY; /* trigger a doublecheck that doesn't repair */ 
-            else
-                usage();
+            /* trigger a doublecheck that doesn't repair */
+            opt_store_doublecheck = DBLCHECK_REPORTONLY; 
 	    break;
 	case 'V':
 	    vhost_mode = 1;
Index: squid/src/protos.h
diff -u squid/src/protos.h:1.5 squid/src/protos.h:1.5.4.1
--- squid/src/protos.h:1.5	Tue Nov 14 05:03:47 2000
+++ squid/src/protos.h	Sat Nov 25 14:34:43 2000
@@ -822,6 +822,7 @@
 extern int storeUnlockObject(StoreEntry *);
 extern int storePendingNClients(const StoreEntry *);
 extern EVH storeMaintainSwapSpace;
+extern EVH storeBackgroundCheck;
 extern void storeExpireNow(StoreEntry *);
 extern void storeReleaseRequest(StoreEntry *);
 extern off_t storeLowestMemReaderOffset(const StoreEntry *);
Index: squid/src/store.c
diff -u squid/src/store.c:1.5 squid/src/store.c:1.5.4.3
--- squid/src/store.c:1.5	Sat Nov 18 03:01:27 2000
+++ squid/src/store.c	Sat Nov 25 16:25:44 2000
@@ -770,6 +770,94 @@
 }
 
 
+/*
+ * This routine is kicked off from main.c. It routinely checks the files by 
+ * swap entry to ensure they are still valid. This will catch failing disks, 
+ * half written entries and the like.
+ *
+ * This version works from store entry down to the files. An alternative would
+ * be to work from files up to the matching storeentry.
+ */
+
+static int
+storeBackgroundCheckEntry(StoreEntry * e)
+{
+    SwapDir *SD = &Config.cacheSwap.swapDirs[e->swap_dirn];
+    if (SD->bkgcheck)
+        return (SD->bkgcheck(SD, e));
+    else
+        return 0;
+}
+
+void
+storeBackgroundCheck(void *datanotused)
+{
+    static int bucketnum = -1;
+    static int validnum = 0;
+    static int store_errors = 0;
+    static unsigned int checkedonce = 0;
+    int runnow = 1;
+    int validnum_start;
+    aclCheck_t *cl;
+    StoreEntry *e;
+    hash_link *link_ptr = NULL;
+    hash_link *link_next = NULL;
+    validnum_start = validnum;
+    if (checkedonce!=0) {
+        if (Config.accessList.storebackgroundcheck != NULL) {
+            cl = aclChecklistCreate(Config.accessList.storebackgroundcheck,
+                NULL, NULL);
+            runnow = aclCheckFast(Config.accessList.storebackgroundcheck, cl);
+            aclChecklistFree(cl);    
+        }
+    }
+    if (!runnow) {
+        /* we don't calculate when next to run, because a reconfigure might
+         * occur in the middle.
+         * TODO: calculate when to run, and on reconfigure remove and reinsert
+         * the event
+         */
+        debug (20,9) ("storeBackgroundCheck: deferring check\n");
+        eventAdd("storeBackground", storeBackgroundCheck, NULL, 1.0, 1);
+        return;
+    }
+    if (validnum==0)
+        debug(20,2) (" Beginning store background check at rate %d\n", Config.store_background_check_rate);
+    while (validnum - validnum_start < Config.store_background_check_rate) {
+        if (++bucketnum >= store_hash_buckets) {
+            debug(20, 2) ("  Completed Background Check Loop\n");
+            debug(20, 2) ("  Rechecked %d Entries\n", validnum);
+            debug(20, 2) ("  store_swap_size = %dk\n", store_swap_size);
+            bucketnum = -1;
+            validnum = 0;
+            checkedonce=1;
+            eventAdd("storeBackground", storeBackgroundCheck, NULL, 1.0, 1);
+            return;
+        }
+        link_next = hash_get_bucket(store_table, bucketnum);
+        while (NULL != (link_ptr = link_next)) {
+            link_next = link_ptr->next;
+            e = (StoreEntry *) link_ptr;
+            /* skip unvalidated entries */
+            if (!EBIT_TEST(e->flags, ENTRY_VALIDATED))
+                continue;
+            if (e->swap_filen < 0)
+                continue;
+            if (!(e->swap_status == SWAPOUT_DONE))
+                continue;
+            if (storeBackgroundCheckEntry(e)){
+                    store_errors++;
+                }
+#if 0
+            storeDirUpdateSwapSize(&Config.cacheSwap.swapDirs[e->swap_dirn], e->swap_file_sz, 1);
+#endif
+            if ((++validnum & 0x3FFFF) == 0)
+                debug(20, 2) ("  %7d Entries Validated so far.\n", validnum);
+        }
+    }
+    eventAdd("storeBackground", storeBackgroundCheck, NULL, 1.0, 1);
+}
+
 /* release an object from a cache */
 void
 storeRelease(StoreEntry * e)
Index: squid/src/store_rebuild.c
diff -u squid/src/store_rebuild.c:1.5 squid/src/store_rebuild.c:1.5.6.2
--- squid/src/store_rebuild.c:1.5	Fri Nov 10 08:36:45 2000
+++ squid/src/store_rebuild.c	Sat Nov 25 14:58:02 2000
@@ -74,10 +74,12 @@
 	    store_dirs_rebuilding--;
 	    assert(0 == store_dirs_rebuilding);
 	    if (opt_store_doublecheck != DBLCHECK_NONE)
-            /* we want to assert here because the storeFScode should auto-clean the entries */
+            /* we want to assert here because the doublecheck is for debugging
+             * storeFScode only. */
 		assert(store_errors == 0);
 	    if (store_digest)
 		storeDigestNoteStoreReady();
+            eventAdd("storeBackground", storeBackgroundCheck, NULL, 1.0, 1);
 	    return;
 	}
 	link_next = hash_get_bucket(store_table, bucketnum);
@@ -124,8 +126,8 @@
     counts.invalid += dc->invalid;
     counts.badflags += dc->badflags;
     counts.bad_log_op += dc->bad_log_op;
-    counts.missingcount += dc->missingcount;
-    counts.filesizemismatchcount += dc->filesizemismatchcount;
+/*    counts.missingcount += dc->missingcount;
+    counts.filesizemismatchcount += dc->filesizemismatchcount; */
     counts.zero_object_sz += dc->zero_object_sz;
     /*
      * When store_dirs_rebuilding == 1, it means we are done reading
@@ -144,7 +146,7 @@
     debug(20, 1) ("  %7d Objects cancelled.\n", counts.cancelcount);
     debug(20, 1) ("  %7d Duplicate URLs purged.\n", counts.dupcount);
     debug(20, 1) ("  %7d Swapfile clashes avoided.\n", counts.clashcount);
-    debug(20, 1) ("  %7d Missing files ignored.\n", counts.missingcount);
+/*    debug(20, 1) ("  %7d Missing files ignored.\n", counts.missingcount); */
     debug(20, 1) ("  %7d Incorrect length swapfiles %s.\n",
       counts.filesizemismatchcount,
       (opt_store_doublecheck == DBLCHECK_REPORTONLY) ? "ignored" : "unlinked");
Index: squid/src/structs.h
diff -u squid/src/structs.h:1.7 squid/src/structs.h:1.7.4.2
--- squid/src/structs.h:1.7	Tue Nov 14 05:03:47 2000
+++ squid/src/structs.h	Sat Nov 25 16:25:44 2000
@@ -447,6 +447,7 @@
 	acl_access *identLookup;
 #endif
 	acl_access *redirector;
+        acl_access *storebackgroundcheck;
     } accessList;
     acl_deny_info_list *denyInfoList;
     char *proxyAuthRealm;
@@ -515,6 +516,7 @@
 	size_t high_memory;
     } warnings;
     char *store_dir_select_algorithm;
+    int store_background_check_rate;
 };
 
 struct _SquidConfig2 {
@@ -1353,6 +1355,7 @@
     STDUMP *dump;		/* Dump fs config snippet */
     STFREE *freefs;		/* Free the fs data */
     STDBLCHECK *dblcheck;	/* Double check the obj integrity */
+    STDBLCHECK *bkgcheck;       /* Background check the obj integrity */
     STSTATFS *statfs;		/* Dump fs statistics */
     STMAINTAINFS *maintainfs;	/* Replacement maintainence */
     STCHECKOBJ *checkobj;	/* Check if the fs will store an object */
Index: squid/src/fs/aufs/store_dir_aufs.c
diff -u squid/src/fs/aufs/store_dir_aufs.c:1.5 squid/src/fs/aufs/store_dir_aufs.c:1.5.6.2
--- squid/src/fs/aufs/store_dir_aufs.c:1.5	Sat Nov 11 01:40:02 2000
+++ squid/src/fs/aufs/store_dir_aufs.c	Mon Nov 27 01:50:42 2000
@@ -119,7 +119,8 @@
 static int storeAufsDirIs(SwapDir * sd);
 static int storeAufsFilenoBelongsHere(int fn, int F0, int F1, int F2);
 static int storeAufsCleanupDoubleCheck(SwapDir *, StoreEntry *);
-static int storeAufsCheckFile(SwapDir * sd, sfileno filn, size_t swap_file_sz );
+static int storeAufsBackgroundCheck(SwapDir * sd, StoreEntry * e);
+static int storeAufsCheckFile(SwapDir * sd, sfileno filn, size_t swap_file_sz, int debuglevel );
 static void storeAufsDirStats(SwapDir *, StoreEntry *);
 static void storeAufsDirInitBitmap(SwapDir *);
 static int storeAufsDirValidFileno(SwapDir *, sfileno, int);
@@ -526,7 +527,6 @@
     int count;
     int used;			/* is swapfile already in use? */
     int disk_entry_newer;	/* is the log entry newer than current entry? */
-    int file_bad;
     double x;
     assert(rb != NULL);
     /* load a number of objects per invocation */
@@ -612,21 +612,7 @@
 	 * appear to have a newer entry?  Compare 'lastref' from the
 	 * swap log to e->lastref. */
 	disk_entry_newer = e ? (s.lastref > e->lastref ? 1 : 0) : 0;
-        if (!used && (rb->flags.need_to_validate ||
-            (opt_store_doublecheck != DBLCHECK_NONE))){
-            file_bad = storeAufsCheckFile(SD, s.swap_filen, s.swap_file_sz);
-        } else
-            file_bad = 0;
-        if (file_bad){
-            if (file_bad==-2){
-                  if (opt_store_doublecheck == DBLCHECK_FORCE)
-                      storeAufsDirUnlinkFile(SD, s.swap_filen);
-                  rb->counts.filesizemismatchcount++;
-                  continue;
-            }
-            rb->counts.missingcount++;
-            continue;
-	} else if (used && !disk_entry_newer) {
+	if (used && !disk_entry_newer) {
 	    /* log entry is old, ignore it */
 	    rb->counts.clashcount++;
 	    continue;
@@ -1603,33 +1589,56 @@
 static int
 storeAufsCleanupDoubleCheck(SwapDir * sd, StoreEntry * e)
 {
-    int rv= storeAufsCheckFile(sd, e->swap_filen, e->swap_file_sz);
+    int rv= storeAufsCheckFile(sd, e->swap_filen, e->swap_file_sz, 1);
     if (rv) storeEntryDump(e, 0);
     return rv;
 }
 
 /*
+ * storeAufsBackgroundCheck 
+ * 
+ * This is called by storeBackgroundCheck() to perform background consistency 
+ * checking. 
+ */ 
+static int  
+storeAufsBackgroundCheck(SwapDir  * sd, StoreEntry * e) 
+{ 
+    int rv; 
+    /* we shouldn't be called until the rebuild finishes... but who knows? */ 
+    if (store_dirs_rebuilding)  
+        return 0; 
+    rv = storeAufsCheckFile(sd, e->swap_filen, e->swap_file_sz, 3); 
+    
+    if (rv) { 
+        /* the file is faulty - missing or has a size mismatch from the  
+         * in-memory swap.state */ 
+        storeRelease(e); 
+    } 
+    return rv; 
+} 
+
+/*
  * storeAufsCheckFile
  *
  * This is called by storerebuildFromSwapLog if -S was given on the command 
  * line. or a Dirty state is found
  */
 static int
-storeAufsCheckFile(SwapDir * sd, sfileno filen, size_t swap_file_sz )
+storeAufsCheckFile(SwapDir * sd, sfileno filen, size_t swap_file_sz, int debuglevel)
 {
     struct stat sb;
 
     if (stat(storeAufsDirFullPath(sd, filen, NULL), &sb) < 0) {
-        debug(20, 1) ("storeAufsCheckFile: MISSING SWAP FILE\n");
-        debug(20, 1) ("storeAufsCheckFile: FILENO %08X\n", filen);
-        debug(20, 1) ("storeAufsCheckFile: PATH %s\n", storeAufsDirFullPath(sd, filen, NULL));
+        debug(20, debuglevel) ("storeAufsCheckFile: MISSING SWAP FILE\n");
+        debug(20, debuglevel) ("storeAufsCheckFile: FILENO %08X\n", filen);
+        debug(20, debuglevel) ("storeAufsCheckFile: PATH %s\n", storeAufsDirFullPath(sd, filen, NULL));
         return -1;
     }
     if (swap_file_sz != sb.st_size) {
-        debug(20, 1) ("storeAufsCheckFile: SIZE MISMATCH\n");
-        debug(20, 1) ("storeAufsCheckFile: FILENO %08X\n", filen);
-        debug(20, 1) ("storeAufsCheckFile: PATH %s\n", storeAufsDirFullPath(sd, filen, NULL));
-        debug(20, 1) ("storeAufsCheckFile: ENTRY SIZE: %d, FILE SIZE: %d\n", swap_file_sz, (int) sb.st_size);
+        debug(20, debuglevel) ("storeAufsCheckFile: SIZE MISMATCH\n");
+        debug(20, debuglevel) ("storeAufsCheckFile: FILENO %08X\n", filen);
+        debug(20, debuglevel) ("storeAufsCheckFile: PATH %s\n", storeAufsDirFullPath(sd, filen, NULL));
+        debug(20, debuglevel) ("storeAufsCheckFile: ENTRY SIZE: %d, FILE SIZE: %d\n", swap_file_sz, (int) sb.st_size);
         return -2;
     }
     return 0;
@@ -1686,6 +1695,7 @@
     sd->dump = storeAufsDirDump;
     sd->freefs = storeAufsDirFree;
     sd->dblcheck = storeAufsCleanupDoubleCheck;
+    sd->bkgcheck = storeAufsBackgroundCheck;
     sd->statfs = storeAufsDirStats;
     sd->maintainfs = storeAufsDirMaintain;
     sd->checkobj = storeAufsDirCheckObj;
Index: squid/src/fs/coss/store_dir_coss.c
diff -u squid/src/fs/coss/store_dir_coss.c:1.3 squid/src/fs/coss/store_dir_coss.c:1.3.8.1
--- squid/src/fs/coss/store_dir_coss.c:1.3	Fri Nov  3 00:39:21 2000
+++ squid/src/fs/coss/store_dir_coss.c	Sat Nov 25 14:34:44 2000
@@ -732,6 +732,7 @@
     sd->dump = storeCossDirDump;
     sd->freefs = storeCossDirShutdown;
     sd->dblcheck = NULL;
+    sd->bkgcheck = NULL;
     sd->statfs = storeCossDirStats;
     sd->maintainfs = NULL;
     sd->checkobj = storeCossDirCheckObj;
Index: squid/src/fs/diskd/store_dir_diskd.c
diff -u squid/src/fs/diskd/store_dir_diskd.c:1.4 squid/src/fs/diskd/store_dir_diskd.c:1.4.6.3
--- squid/src/fs/diskd/store_dir_diskd.c:1.4	Fri Nov 10 08:36:46 2000
+++ squid/src/fs/diskd/store_dir_diskd.c	Mon Nov 27 02:22:02 2000
@@ -127,7 +127,8 @@
 static int storeDiskdDirIs(SwapDir * sd);
 static int storeDiskdFilenoBelongsHere(int fn, int F0, int F1, int F2);
 static int storeDiskdCleanupDoubleCheck(SwapDir *, StoreEntry *);
-static int storeDiskdCheckFile(SwapDir * sd, sfileno filn, size_t swap_file_sz);
+static int storeDiskdCheckFile(SwapDir * sd, sfileno filn, size_t swap_file_sz, int debuglevel);
+static int storeDiskdBackgroundCheck(SwapDir * sd, StoreEntry * e);
 static void storeDiskdDirStats(SwapDir *, StoreEntry *);
 static void storeDiskdDirInitBitmap(SwapDir *);
 static int storeDiskdDirValidFileno(SwapDir *, sfileno, int);
@@ -692,7 +693,6 @@
     int count;
     int used;			/* is swapfile already in use? */
     int disk_entry_newer;	/* is the log entry newer than current entry? */
-    int file_bad;
     double x;
     assert(rb != NULL);
     /* load a number of objects per invocation */
@@ -803,21 +803,7 @@
 	 * appear to have a newer entry?  Compare 'lastref' from the
 	 * swap log to e->lastref. */
 	disk_entry_newer = e ? (s.lastref > e->lastref ? 1 : 0) : 0;
-        if (!used && (rb->flags.need_to_validate ||
-            (opt_store_doublecheck != DBLCHECK_NONE))){
-            file_bad = storeDiskdCheckFile(SD, s.swap_filen, s.swap_file_sz);
-        } else
-            file_bad = 0;
-        if (file_bad){
-            if (file_bad==-2){
-                  if (opt_store_doublecheck == DBLCHECK_FORCE)
-                      storeDiskdDirUnlinkFile(SD, s.swap_filen);
-                  rb->counts.filesizemismatchcount++;
-                  continue;
-            }
-            rb->counts.missingcount++;
-            continue;
-       } else if (used && !disk_entry_newer) {
+       if (used && !disk_entry_newer) {
 	    /* log entry is old, ignore it */
 	    rb->counts.clashcount++;
 	    continue;
@@ -1845,33 +1831,58 @@
 static int
 storeDiskdCleanupDoubleCheck(SwapDir * sd, StoreEntry * e)
 {
-    int rv= storeDiskdCheckFile(sd, e->swap_filen, e->swap_file_sz);
+    int rv= storeDiskdCheckFile(sd, e->swap_filen, e->swap_file_sz, 1);
     if (rv) storeEntryDump(e, 0);
     return rv;
 }
 
+
+/*
+ * storeDiskdBackgroundCheck
+ *
+ * This is called by storeBackgroundCheck() to perform background consistency
+ * checking.
+ */
+static int
+storeDiskdBackgroundCheck(SwapDir  * sd, StoreEntry * e)
+{
+    int rv;
+    /* we shouldn't be called until the rebuild finishes... but who knows? */
+    if (store_dirs_rebuilding)
+        return 0;
+    rv = storeDiskdCheckFile(sd, e->swap_filen, e->swap_file_sz, 3);
+
+    if (rv) {
+        /* the file is faulty - missing or has a size mismatch from the
+         * in-memory swap.state */
+        storeRelease(e);
+    }
+    return rv;
+}
+
+
 /*
  * storeDiskdCheckFile
  *
  * This is called by storerebuildFromSwapLog if -S was given on the command line * or a Dirty state is found
  */
 static int
-storeDiskdCheckFile(SwapDir * sd, sfileno filen, size_t swap_file_sz )
+storeDiskdCheckFile(SwapDir * sd, sfileno filen, size_t swap_file_sz, int debuglevel)
 {
      struct stat sb;
 
     if (stat(storeDiskdDirFullPath(sd, filen, NULL), &sb) < 0) {
-        debug(20, 1) ("storeDiskdCheckFile: MISSING SWAP FILE\n");
-        debug(20, 1) ("storeDiskdCheckFile: FILENO %08X\n", filen);
-        debug(20, 1) ("storeDiskdCheckFile: PATH %s\n", storeDiskdDirFullPath(sd, filen, NULL));
+        debug(20, debuglevel) ("storeDiskdCheckFile: MISSING SWAP FILE\n");
+        debug(20, debuglevel) ("storeDiskdCheckFile: FILENO %08X\n", filen);
+        debug(20, debuglevel) ("storeDiskdCheckFile: PATH %s\n", storeDiskdDirFullPath(sd, filen, NULL));
 
         return -1;
     }
     if (swap_file_sz != sb.st_size) {
-        debug(20, 1) ("storeDiskdCheckFile: SIZE MISMATCH\n");
-        debug(20, 1) ("storeDiskdCheckFile: FILENO %08X\n", filen);
-        debug(20, 1) ("storeDiskdCheckFile: PATH %s\n", storeDiskdDirFullPath(sd, filen, NULL));
-        debug(20, 1) ("storeDiskdCheckFile: ENTRY SIZE: %d, FILE SIZE: %d\n", swap_file_sz, (int) sb.st_size);
+        debug(20, debuglevel) ("storeDiskdCheckFile: SIZE MISMATCH\n");
+        debug(20, debuglevel) ("storeDiskdCheckFile: FILENO %08X\n", filen);
+        debug(20, debuglevel) ("storeDiskdCheckFile: PATH %s\n", storeDiskdDirFullPath(sd, filen, NULL));
+        debug(20, debuglevel) ("storeDiskdCheckFile: ENTRY SIZE: %d, FILE SIZE: %d\n", swap_file_sz, (int) sb.st_size);
         return -2;
      }
     return 0;
@@ -1937,6 +1948,7 @@
     sd->dump = storeDiskdDirDump;
     sd->freefs = storeDiskdDirFree;
     sd->dblcheck = storeDiskdCleanupDoubleCheck;
+    sd->bkgcheck = storeDiskdBackgroundCheck;
     sd->statfs = storeDiskdDirStats;
     sd->maintainfs = storeDiskdDirMaintain;
     sd->checkobj = storeDiskdDirCheckObj;
Index: squid/src/fs/ufs/store_dir_ufs.c
diff -u squid/src/fs/ufs/store_dir_ufs.c:1.4 squid/src/fs/ufs/store_dir_ufs.c:1.4.6.2
--- squid/src/fs/ufs/store_dir_ufs.c:1.4	Fri Nov 10 08:36:47 2000
+++ squid/src/fs/ufs/store_dir_ufs.c	Sat Nov 25 16:25:44 2000
@@ -117,7 +117,8 @@
 static int storeUfsDirIs(SwapDir * sd);
 static int storeUfsFilenoBelongsHere(int fn, int F0, int F1, int F2);
 static int storeUfsCleanupDoubleCheck(SwapDir *, StoreEntry *);
-static int storeUfsCheckFile(SwapDir * sd, sfileno filn, size_t swap_file_sz );
+static int storeUfsBackgroundCheck(SwapDir  * sd, StoreEntry * e);
+static int storeUfsCheckFile(SwapDir * sd, sfileno filn, size_t swap_file_sz, int debuglevel );
 static void storeUfsDirStats(SwapDir *, StoreEntry *);
 static void storeUfsDirInitBitmap(SwapDir *);
 static int storeUfsDirValidFileno(SwapDir *, sfileno, int);
@@ -524,7 +525,6 @@
     int count;
     int used;			/* is swapfile already in use? */
     int disk_entry_newer;	/* is the log entry newer than current entry? */
-    int file_bad;
     double x;
     assert(rb != NULL);
     /* load a number of objects per invocation */
@@ -610,21 +610,7 @@
 	 * appear to have a newer entry?  Compare 'lastref' from the
 	 * swap log to e->lastref. */
 	disk_entry_newer = e ? (s.lastref > e->lastref ? 1 : 0) : 0;
-        if (!used && (rb->flags.need_to_validate ||
-            (opt_store_doublecheck != DBLCHECK_NONE))){
-            file_bad = storeUfsCheckFile(SD, s.swap_filen, s.swap_file_sz);
-        } else 
-            file_bad = 0;
-        if (file_bad){
-            if (file_bad==-2){
-                  if (opt_store_doublecheck == DBLCHECK_FORCE) 
-                      storeUfsDirUnlinkFile(SD, s.swap_filen);
-                  rb->counts.filesizemismatchcount++; 
-                  continue;
-            }
-            rb->counts.missingcount++;
-            continue;
-	}else if (used && !disk_entry_newer) {
+	if (used && !disk_entry_newer) {
 	    /* log entry is old, ignore it */
 	    rb->counts.clashcount++;
 	    continue;
@@ -1591,33 +1577,58 @@
 static int
 storeUfsCleanupDoubleCheck(SwapDir * sd, StoreEntry * e)
 {
-    int rv= storeUfsCheckFile(sd, e->swap_filen, e->swap_file_sz);
+    int rv= storeUfsCheckFile(sd, e->swap_filen, e->swap_file_sz, 1);
     if (rv) storeEntryDump(e, 0);
     return rv;
 }
 
+/* 
+ * storeUfsBackgroundCheck
+ *
+ * This is called by storeBackgroundCheck() to perform background consistency
+ * checking.
+ */
+static int 
+storeUfsBackgroundCheck(SwapDir  * sd, StoreEntry * e)
+{
+    int rv;
+    /* we shouldn't be called until the rebuild finishes... but who knows? */
+    if (store_dirs_rebuilding) 
+        return 0;
+    rv = storeUfsCheckFile(sd, e->swap_filen, e->swap_file_sz, 3);
+    
+    if (rv) {
+        /* the file is faulty - missing or has a size mismatch from the 
+         * in-memory swap.state */
+        storeRelease(e);
+    }
+    return rv;
+}
+
+
+
 /*
  * storeUfsCheckFile
  *
  * This is called by storerebuildFromSwapLog if -S was given on the command line. or a Dirty state is found
  */
 static int
-storeUfsCheckFile(SwapDir * sd, sfileno filen, size_t swap_file_sz )
+storeUfsCheckFile(SwapDir * sd, sfileno filen, size_t swap_file_sz , int debuglevel)
 {
     struct stat sb;
 
     if (stat(storeUfsDirFullPath(sd, filen, NULL), &sb) < 0) {
-        debug(20, 1) ("storeUfsCheckFile: MISSING SWAP FILE\n");
-        debug(20, 1) ("storeUfsCheckFile: FILENO %08X\n", filen);
-        debug(20, 1) ("storeUfsCheckFile: PATH %s\n", storeUfsDirFullPath(sd, filen, NULL));
+        debug(20, debuglevel) ("storeUfsCheckFile: MISSING SWAP FILE\n");
+        debug(20, debuglevel) ("storeUfsCheckFile: FILENO %08X\n", filen);
+        debug(20, debuglevel) ("storeUfsCheckFile: PATH %s\n", storeUfsDirFullPath(sd, filen, NULL));
 
         return -1;
     }
     if (swap_file_sz != sb.st_size) {
-        debug(20, 1) ("storeUfsCheckFile: SIZE MISMATCH\n");
-        debug(20, 1) ("storeUfsCheckFile: FILENO %08X\n", filen);
-        debug(20, 1) ("storeUfsCheckFile: PATH %s\n", storeUfsDirFullPath(sd, filen, NULL));
-        debug(20, 1) ("storeUfsCheckFile: ENTRY SIZE: %d, FILE SIZE: %d\n", swap_file_sz, (int) sb.st_size);
+        debug(20, debuglevel) ("storeUfsCheckFile: SIZE MISMATCH\n");
+        debug(20, debuglevel) ("storeUfsCheckFile: FILENO %08X\n", filen);
+        debug(20, debuglevel) ("storeUfsCheckFile: PATH %s\n", storeUfsDirFullPath(sd, filen, NULL));
+        debug(20, debuglevel) ("storeUfsCheckFile: ENTRY SIZE: %d, FILE SIZE: %d\n", swap_file_sz, (int) sb.st_size);
         return -2;
     }
     return 0;
@@ -1676,6 +1687,7 @@
     sd->dump = storeUfsDirDump;
     sd->freefs = storeUfsDirFree;
     sd->dblcheck = storeUfsCleanupDoubleCheck;
+    sd->bkgcheck = storeUfsBackgroundCheck;
     sd->statfs = storeUfsDirStats;
     sd->maintainfs = storeUfsDirMaintain;
     sd->checkobj = storeUfsDirCheckObj;
squid-store_check-HEAD.new squid-store_check-HEAD differ: char 70, line 2