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