📄 store_dir_ufs.c
字号:
/* * $Id: store_dir_ufs.c,v 1.61 2006/08/03 02:31:13 adrian Exp $ * * DEBUG: section 47 Store Directory Routines * AUTHOR: Duane Wessels * * SQUID Web Proxy Cache http://www.squid-cache.org/ * ---------------------------------------------------------- * * Squid is the result of efforts by numerous individuals from * the Internet community; see the CONTRIBUTORS file for full * details. Many organizations have provided support for Squid's * development; see the SPONSORS file for full details. Squid is * Copyrighted (C) 2001 by the Regents of the University of * California; see the COPYRIGHT file for full details. Squid * incorporates software developed and/or copyrighted by other * sources; see the CREDITS file for full details. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. * */#include "squid.h"#include "store_ufs.h"#define DefaultLevelOneDirs 16#define DefaultLevelTwoDirs 256#define STORE_META_BUFSZ 4096typedef struct _RebuildState RebuildState;struct _RebuildState { SwapDir *sd; int n_read; FILE *log; int speed; int curlvl1; int curlvl2; struct { unsigned int need_to_validate:1; unsigned int clean:1; unsigned int init:1; } flags; int done; int in_dir; int fn; struct dirent *entry; DIR *td; char fullpath[SQUID_MAXPATHLEN]; char fullfilename[SQUID_MAXPATHLEN]; struct _store_rebuild_data counts;};static int n_ufs_dirs = 0;static int *ufs_dir_index = NULL;MemPool *ufs_state_pool = NULL;static int ufs_initialised = 0;static char *storeUfsDirSwapSubDir(SwapDir *, int subdirn);static int storeUfsDirCreateDirectory(const char *path, int);static int storeUfsDirVerifyCacheDirs(SwapDir *);static int storeUfsDirVerifyDirectory(const char *path);static void storeUfsDirCreateSwapSubDirs(SwapDir *);static char *storeUfsDirSwapLogFile(SwapDir *, const char *);static EVH storeUfsDirRebuildFromDirectory;static EVH storeUfsDirRebuildFromSwapLog;static int storeUfsDirGetNextFile(RebuildState *, sfileno *, int *size);static StoreEntry *storeUfsDirAddDiskRestore(SwapDir * SD, const cache_key * key, int file_number, squid_file_sz swap_file_sz, time_t expires, time_t timestamp, time_t lastref, time_t lastmod, u_num32 refcount, u_short flags, int clean);static void storeUfsDirRebuild(SwapDir * sd);static void storeUfsDirCloseTmpSwapLog(SwapDir * sd);static FILE *storeUfsDirOpenTmpSwapLog(SwapDir *, int *, int *);static STLOGOPEN storeUfsDirOpenSwapLog;static STINIT storeUfsDirInit;static STFREE storeUfsDirFree;static STLOGCLEANSTART storeUfsDirWriteCleanStart;static STLOGCLEANNEXTENTRY storeUfsDirCleanLogNextEntry;static STLOGCLEANWRITE storeUfsDirWriteCleanEntry;static STLOGCLEANDONE storeUfsDirWriteCleanDone;static STLOGCLOSE storeUfsDirCloseSwapLog;static STLOGWRITE storeUfsDirSwapLog;static STNEWFS storeUfsDirNewfs;static STDUMP storeUfsDirDump;static STMAINTAINFS storeUfsDirMaintain;static STCHECKOBJ storeUfsDirCheckObj;static STCHECKLOADAV storeUfsDirCheckLoadAv;static STREFOBJ storeUfsDirRefObj;static STUNREFOBJ storeUfsDirUnrefObj;static QS rev_int_sort;static int storeUfsDirClean(int swap_index);static EVH storeUfsDirCleanEvent;static int storeUfsDirIs(SwapDir * sd);static int storeUfsFilenoBelongsHere(int fn, int F0, int F1, int F2);static int storeUfsCleanupDoubleCheck(SwapDir *, StoreEntry *);static void storeUfsDirStats(SwapDir *, StoreEntry *);static void storeUfsDirInitBitmap(SwapDir *);static int storeUfsDirValidFileno(SwapDir *, sfileno, int);STSETUP storeFsSetup_ufs;/* * These functions were ripped straight out of the heart of store_dir.c. * They assume that the given filenum is on a ufs partiton, which may or * may not be true.. * XXX this evilness should be tidied up at a later date! */static intstoreUfsDirMapBitTest(SwapDir * SD, sfileno filn){ ufsinfo_t *ufsinfo; ufsinfo = (ufsinfo_t *) SD->fsdata; return file_map_bit_test(ufsinfo->map, filn);}static voidstoreUfsDirMapBitSet(SwapDir * SD, int fn){ sfileno filn = fn; ufsinfo_t *ufsinfo; ufsinfo = (ufsinfo_t *) SD->fsdata; file_map_bit_set(ufsinfo->map, filn);}voidstoreUfsDirMapBitReset(SwapDir * SD, int fn){ sfileno filn = fn; ufsinfo_t *ufsinfo; ufsinfo = (ufsinfo_t *) SD->fsdata; /* * We have to test the bit before calling file_map_bit_reset. * file_map_bit_reset doesn't do bounds checking. It assumes * filn is a valid file number, but it might not be because * the map is dynamic in size. Also clearing an already clear * bit puts the map counter of-of-whack. */ if (file_map_bit_test(ufsinfo->map, filn)) file_map_bit_reset(ufsinfo->map, filn);}intstoreUfsDirMapBitAllocate(SwapDir * SD){ ufsinfo_t *ufsinfo = (ufsinfo_t *) SD->fsdata; int fn; fn = file_map_allocate(ufsinfo->map, ufsinfo->suggest); file_map_bit_set(ufsinfo->map, fn); ufsinfo->suggest = fn + 1; return fn;}/* * Initialise the ufs bitmap * * If there already is a bitmap, and the numobjects is larger than currently * configured, we allocate a new bitmap and 'grow' the old one into it. */static voidstoreUfsDirInitBitmap(SwapDir * sd){ ufsinfo_t *ufsinfo = (ufsinfo_t *) sd->fsdata; if (ufsinfo->map == NULL) { /* First time */ ufsinfo->map = file_map_create(); } else if (ufsinfo->map->max_n_files) { /* it grew, need to expand */ /* XXX We don't need it anymore .. */ } /* else it shrunk, and we leave the old one in place */}static char *storeUfsDirSwapSubDir(SwapDir * sd, int subdirn){ ufsinfo_t *ufsinfo = (ufsinfo_t *) sd->fsdata; LOCAL_ARRAY(char, fullfilename, SQUID_MAXPATHLEN); assert(0 <= subdirn && subdirn < ufsinfo->l1); snprintf(fullfilename, SQUID_MAXPATHLEN, "%s/%02X", sd->path, subdirn); return fullfilename;}static intstoreUfsDirCreateDirectory(const char *path, int should_exist){ int created = 0; struct stat st; getCurrentTime(); if (0 == stat(path, &st)) { if (S_ISDIR(st.st_mode)) { debug(47, should_exist ? 3 : 1) ("%s exists\n", path); } else { fatalf("Swap directory %s is not a directory.", path); }#ifdef _SQUID_MSWIN_ } else if (0 == mkdir(path)) {#else } else if (0 == mkdir(path, 0755)) {#endif debug(47, should_exist ? 1 : 3) ("%s created\n", path); created = 1; } else { fatalf("Failed to make swap directory %s: %s", path, xstrerror()); } return created;}static intstoreUfsDirVerifyDirectory(const char *path){ struct stat sb; if (stat(path, &sb) < 0) { debug(47, 0) ("%s: %s\n", path, xstrerror()); return -1; } if (S_ISDIR(sb.st_mode) == 0) { debug(47, 0) ("%s is not a directory\n", path); return -1; } return 0;}/* * This function is called by storeUfsDirInit(). If this returns < 0, * then Squid exits, complains about swap directories not * existing, and instructs the admin to run 'squid -z' */static intstoreUfsDirVerifyCacheDirs(SwapDir * sd){ ufsinfo_t *ufsinfo = (ufsinfo_t *) sd->fsdata; int j; const char *path = sd->path; if (storeUfsDirVerifyDirectory(path) < 0) return -1; for (j = 0; j < ufsinfo->l1; j++) { path = storeUfsDirSwapSubDir(sd, j); if (storeUfsDirVerifyDirectory(path) < 0) return -1; } return 0;}static voidstoreUfsDirCreateSwapSubDirs(SwapDir * sd){ ufsinfo_t *ufsinfo = (ufsinfo_t *) sd->fsdata; int i, k; int should_exist; LOCAL_ARRAY(char, name, MAXPATHLEN); for (i = 0; i < ufsinfo->l1; i++) { snprintf(name, MAXPATHLEN, "%s/%02X", sd->path, i); if (storeUfsDirCreateDirectory(name, 0)) should_exist = 0; else should_exist = 1; debug(47, 1) ("Making directories in %s\n", name); for (k = 0; k < ufsinfo->l2; k++) { snprintf(name, MAXPATHLEN, "%s/%02X/%02X", sd->path, i, k); storeUfsDirCreateDirectory(name, should_exist); } }}static char *storeUfsDirSwapLogFile(SwapDir * sd, const char *ext){ LOCAL_ARRAY(char, path, SQUID_MAXPATHLEN); LOCAL_ARRAY(char, pathtmp, SQUID_MAXPATHLEN); LOCAL_ARRAY(char, digit, 32); char *pathtmp2; if (Config.Log.swap) { xstrncpy(pathtmp, sd->path, SQUID_MAXPATHLEN - 64); pathtmp2 = pathtmp; while ((pathtmp2 = strchr(pathtmp2, '/')) != NULL) *pathtmp2 = '.'; while (strlen(pathtmp) && pathtmp[strlen(pathtmp) - 1] == '.') pathtmp[strlen(pathtmp) - 1] = '\0'; for (pathtmp2 = pathtmp; *pathtmp2 == '.'; pathtmp2++); snprintf(path, SQUID_MAXPATHLEN - 64, Config.Log.swap, pathtmp2); if (strncmp(path, Config.Log.swap, SQUID_MAXPATHLEN - 64) == 0) { strcat(path, "."); snprintf(digit, 32, "%02d", sd->index); strncat(path, digit, 3); } } else { xstrncpy(path, sd->path, SQUID_MAXPATHLEN - 64); strcat(path, "/swap.state"); } if (ext) strncat(path, ext, 16); return path;}static voidstoreUfsDirOpenSwapLog(SwapDir * sd){ ufsinfo_t *ufsinfo = (ufsinfo_t *) sd->fsdata; char *path; int fd; path = storeUfsDirSwapLogFile(sd, NULL); if (ufsinfo->swaplog_fd >= 0) { debug(50, 1) ("storeUfsDirOpenSwapLog: %s already open\n", path); return; } fd = file_open(path, O_WRONLY | O_CREAT | O_BINARY); if (fd < 0) { debug(50, 1) ("%s: %s\n", path, xstrerror()); fatal("storeUfsDirOpenSwapLog: Failed to open swap log."); } debug(50, 3) ("Cache Dir #%d log opened on FD %d\n", sd->index, fd); ufsinfo->swaplog_fd = fd; if (0 == n_ufs_dirs) assert(NULL == ufs_dir_index); n_ufs_dirs++; assert(n_ufs_dirs <= Config.cacheSwap.n_configured);}static voidstoreUfsDirCloseSwapLog(SwapDir * sd){ ufsinfo_t *ufsinfo = (ufsinfo_t *) sd->fsdata; if (ufsinfo->swaplog_fd < 0) /* not open */ return; file_close(ufsinfo->swaplog_fd); debug(47, 3) ("Cache Dir #%d log closed on FD %d\n", sd->index, ufsinfo->swaplog_fd); ufsinfo->swaplog_fd = -1; n_ufs_dirs--; assert(n_ufs_dirs >= 0); if (0 == n_ufs_dirs) safe_free(ufs_dir_index);}static voidstoreUfsCheckConfig(SwapDir * sd){ if (!opt_create_swap_dirs) requirePathnameExists("cache_dir", sd->path);}static voidstoreUfsDirInit(SwapDir * sd){ static int started_clean_event = 0; static const char *errmsg = "\tFailed to verify one of the swap directories, Check cache.log\n" "\tfor details. Run 'squid -z' to create swap directories\n" "\tif needed, or if running Squid for the first time."; storeUfsDirInitBitmap(sd); if (storeUfsDirVerifyCacheDirs(sd) < 0) fatal(errmsg); storeUfsDirOpenSwapLog(sd); storeUfsDirRebuild(sd); if (!started_clean_event) { eventAdd("storeDirClean", storeUfsDirCleanEvent, NULL, 15.0, 1); started_clean_event = 1; } (void) storeDirGetBlkSize(sd->path, &sd->fs.blksize);}static voidstoreUfsDirRebuildComplete(RebuildState * rb){ if (rb->log) { debug(47, 1) ("Done reading %s swaplog (%d entries)\n", rb->sd->path, rb->n_read); fclose(rb->log); rb->log = NULL; } else { debug(47, 1) ("Done scanning %s (%d entries)\n", rb->sd->path, rb->counts.scancount); } store_dirs_rebuilding--; storeUfsDirCloseTmpSwapLog(rb->sd); storeRebuildComplete(&rb->counts); cbdataFree(rb);}static voidstoreUfsDirRebuildFromDirectory(void *data){ RebuildState *rb = data; SwapDir *SD = rb->sd; LOCAL_ARRAY(char, hdr_buf, SM_PAGE_SIZE); StoreEntry *e = NULL; StoreEntry tmpe; cache_key key[MD5_DIGEST_CHARS]; sfileno filn = 0; int count; int size; struct stat sb; int swap_hdr_len; int fd = -1; tlv *tlv_list; tlv *t; assert(rb != NULL); debug(47, 3) ("storeUfsDirRebuildFromDirectory: DIR #%d\n", rb->sd->index); for (count = 0; count < rb->speed; count++) { assert(fd == -1); fd = storeUfsDirGetNextFile(rb, &filn, &size); if (fd == -2) { storeUfsDirRebuildComplete(rb); return; } else if (fd < 0) { continue; } assert(fd > -1); /* lets get file stats here */ if (fstat(fd, &sb) < 0) { debug(47, 1) ("storeUfsDirRebuildFromDirectory: fstat(FD %d): %s\n", fd, xstrerror()); file_close(fd); store_open_disk_fd--; fd = -1; continue; } if ((++rb->counts.scancount & 0xFFFF) == 0) debug(47, 3) (" %s %7d files opened so far.\n", rb->sd->path, rb->counts.scancount); debug(47, 9) ("file_in: fd=%d %08X\n", fd, filn); statCounter.syscalls.disk.reads++; if (FD_READ_METHOD(fd, hdr_buf, SM_PAGE_SIZE) < 0) { debug(47, 1) ("storeUfsDirRebuildFromDirectory: read(FD %d): %s\n", fd, xstrerror()); file_close(fd); store_open_disk_fd--; fd = -1; continue; } file_close(fd); store_open_disk_fd--; fd = -1; swap_hdr_len = 0;#if USE_TRUNCATE if (sb.st_size == 0) continue;#endif tlv_list = storeSwapMetaUnpack(hdr_buf, &swap_hdr_len); if (tlv_list == NULL) { debug(47, 1) ("storeUfsDirRebuildFromDirectory: failed to get meta data\n"); /* XXX shouldn't this be a call to storeUfsUnlink ? */ storeUfsDirUnlinkFile(SD, filn); continue; } debug(47, 3) ("storeUfsDirRebuildFromDirectory: successful swap meta unpacking\n"); memset(key, '\0', MD5_DIGEST_CHARS); memset(&tmpe, '\0', sizeof(StoreEntry)); for (t = tlv_list; t; t = t->next) { switch (t->type) { case STORE_META_KEY: assert(t->length == MD5_DIGEST_CHARS); xmemcpy(key, t->value, MD5_DIGEST_CHARS); break;#if SIZEOF_SQUID_FILE_SZ == SIZEOF_SIZE_T case STORE_META_STD: assert(t->length == STORE_HDR_METASIZE); xmemcpy(&tmpe.timestamp, t->value, STORE_HDR_METASIZE); break;#else case STORE_META_STD_LFS: assert(t->length == STORE_HDR_METASIZE); xmemcpy(&tmpe.timestamp, t->value, STORE_HDR_METASIZE); break; case STORE_META_STD: assert(t->length == STORE_HDR_METASIZE_OLD); { struct {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -