📄 store_dir_diskd.c
字号:
/* * $Id: store_dir_diskd.c,v 1.85 2006/09/22 00:51:43 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 <sys/ipc.h>#include <sys/msg.h>#include <sys/shm.h>#include "store_diskd.h"#define DefaultLevelOneDirs 16#define DefaultLevelTwoDirs 256#define STORE_META_BDISKDZ 4096diskd_stats_t diskd_stats;typedef 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_diskd_dirs = 0;static int *diskd_dir_index = NULL;MemPool *diskd_state_pool = NULL;static int diskd_initialised = 0;static char *storeDiskdDirSwapSubDir(SwapDir *, int subdirn);static int storeDiskdDirCreateDirectory(const char *path, int);static int storeDiskdDirVerifyCacheDirs(SwapDir *);static int storeDiskdDirVerifyDirectory(const char *path);static void storeDiskdDirCreateSwapSubDirs(SwapDir *);static char *storeDiskdDirSwapLogFile(SwapDir *, const char *);static EVH storeDiskdDirRebuildFromDirectory;static EVH storeDiskdDirRebuildFromSwapLog;static int storeDiskdDirGetNextFile(RebuildState *, sfileno *, int *size);static StoreEntry *storeDiskdDirAddDiskRestore(SwapDir * SD, const cache_key * key, sfileno 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 storeDiskdDirRebuild(SwapDir * sd);static void storeDiskdDirCloseTmpSwapLog(SwapDir * sd);static FILE *storeDiskdDirOpenTmpSwapLog(SwapDir *, int *, int *);static STLOGOPEN storeDiskdDirOpenSwapLog;static STINIT storeDiskdDirInit;static STCHECKCONFIG storeDiskdCheckConfig;static STFREE storeDiskdDirFree;static STLOGCLEANSTART storeDiskdDirWriteCleanStart;static STLOGCLEANNEXTENTRY storeDiskdDirCleanLogNextEntry;static STLOGCLEANWRITE storeDiskdDirWriteCleanEntry;static STLOGCLEANDONE storeDiskdDirWriteCleanDone;static STLOGCLOSE storeDiskdDirCloseSwapLog;static STLOGWRITE storeDiskdDirSwapLog;static STNEWFS storeDiskdDirNewfs;static STDUMP storeDiskdDirDump;static STMAINTAINFS storeDiskdDirMaintain;static STCHECKOBJ storeDiskdDirCheckObj;static STCHECKLOADAV storeDiskdDirCheckLoadAv;static STREFOBJ storeDiskdDirRefObj;static STUNREFOBJ storeDiskdDirUnrefObj;static QS rev_int_sort;static int storeDiskdDirClean(int swap_index);static EVH storeDiskdDirCleanEvent;static int storeDiskdDirIs(SwapDir * sd);static int storeDiskdFilenoBelongsHere(int fn, int F0, int F1, int F2);static int storeDiskdCleanupDoubleCheck(SwapDir *, StoreEntry *);static void storeDiskdDirStats(SwapDir *, StoreEntry *);static void storeDiskdDirInitBitmap(SwapDir *);static int storeDiskdDirValidFileno(SwapDir *, sfileno, int);static void storeDiskdStats(StoreEntry * sentry);static void storeDiskdDirSync(SwapDir *);/* The only externally visible interface */STSETUP storeFsSetup_diskd;/* * These functions were ripped straight out of the heart of store_dir.c. * They assume that the given filenum is on a diskd partiton, which may or * may not be true.. * XXX this evilness should be tidied up at a later date! */static intstoreDiskdDirMapBitTest(SwapDir * SD, sfileno filn){ diskdinfo_t *diskdinfo; diskdinfo = SD->fsdata; return file_map_bit_test(diskdinfo->map, filn);}static voidstoreDiskdDirMapBitSet(SwapDir * SD, sfileno filn){ diskdinfo_t *diskdinfo; diskdinfo = SD->fsdata; file_map_bit_set(diskdinfo->map, filn);}voidstoreDiskdDirMapBitReset(SwapDir * SD, sfileno filn){ diskdinfo_t *diskdinfo; diskdinfo = 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(diskdinfo->map, filn)) file_map_bit_reset(diskdinfo->map, filn);}intstoreDiskdDirMapBitAllocate(SwapDir * SD){ diskdinfo_t *diskdinfo = SD->fsdata; int fn; fn = file_map_allocate(diskdinfo->map, diskdinfo->suggest); file_map_bit_set(diskdinfo->map, fn); diskdinfo->suggest = fn + 1; return fn;}/* * Initialise the diskd 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 voidstoreDiskdDirInitBitmap(SwapDir * sd){ diskdinfo_t *diskdinfo = sd->fsdata; if (diskdinfo->map == NULL) { /* First time */ diskdinfo->map = file_map_create(); } else if (diskdinfo->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 *storeDiskdDirSwapSubDir(SwapDir * sd, int subdirn){ diskdinfo_t *diskdinfo = sd->fsdata; LOCAL_ARRAY(char, fullfilename, SQUID_MAXPATHLEN); assert(0 <= subdirn && subdirn < diskdinfo->l1); snprintf(fullfilename, SQUID_MAXPATHLEN, "%s/%02X", sd->path, subdirn); return fullfilename;}static intstoreDiskdDirCreateDirectory(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(20, should_exist ? 3 : 1) ("%s exists\n", path); } else { fatalf("Swap directory %s is not a directory.", path); } } else if (0 == mkdir(path, 0755)) { debug(20, should_exist ? 1 : 3) ("%s created\n", path); created = 1; } else { fatalf("Failed to make swap directory %s: %s", path, xstrerror()); } return created;}static intstoreDiskdDirVerifyDirectory(const char *path){ struct stat sb; if (stat(path, &sb) < 0) { debug(20, 0) ("%s: %s\n", path, xstrerror()); return -1; } if (S_ISDIR(sb.st_mode) == 0) { debug(20, 0) ("%s is not a directory\n", path); return -1; } return 0;}/* * This function is called by storeDiskdDirInit(). If this returns < 0, * then Squid exits, complains about swap directories not * existing, and instructs the admin to run 'squid -z' */static intstoreDiskdDirVerifyCacheDirs(SwapDir * sd){ diskdinfo_t *diskdinfo = sd->fsdata; int j; const char *path = sd->path; if (storeDiskdDirVerifyDirectory(path) < 0) return -1; for (j = 0; j < diskdinfo->l1; j++) { path = storeDiskdDirSwapSubDir(sd, j); if (storeDiskdDirVerifyDirectory(path) < 0) return -1; } return 0;}static voidstoreDiskdDirCreateSwapSubDirs(SwapDir * sd){ diskdinfo_t *diskdinfo = sd->fsdata; int i, k; int should_exist; LOCAL_ARRAY(char, name, MAXPATHLEN); for (i = 0; i < diskdinfo->l1; i++) { snprintf(name, MAXPATHLEN, "%s/%02X", sd->path, i); if (storeDiskdDirCreateDirectory(name, 0)) should_exist = 0; else should_exist = 1; debug(47, 1) ("Making directories in %s\n", name); for (k = 0; k < diskdinfo->l2; k++) { snprintf(name, MAXPATHLEN, "%s/%02X/%02X", sd->path, i, k); storeDiskdDirCreateDirectory(name, should_exist); } }}static char *storeDiskdDirSwapLogFile(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 voidstoreDiskdDirOpenSwapLog(SwapDir * sd){ diskdinfo_t *diskdinfo = sd->fsdata; char *path; int fd; path = storeDiskdDirSwapLogFile(sd, NULL); fd = file_open(path, O_WRONLY | O_CREAT | O_BINARY); if (fd < 0) { debug(50, 1) ("%s: %s\n", path, xstrerror()); fatal("storeDiskdDirOpenSwapLog: Failed to open swap log."); } debug(47, 3) ("Cache Dir #%d log opened on FD %d\n", sd->index, fd); diskdinfo->swaplog_fd = fd; if (0 == n_diskd_dirs) assert(NULL == diskd_dir_index); n_diskd_dirs++; assert(n_diskd_dirs <= Config.cacheSwap.n_configured);}static voidstoreDiskdDirCloseSwapLog(SwapDir * sd){ diskdinfo_t *diskdinfo = sd->fsdata; if (diskdinfo->swaplog_fd < 0) /* not open */ return; file_close(diskdinfo->swaplog_fd); debug(47, 3) ("Cache Dir #%d log closed on FD %d\n", sd->index, diskdinfo->swaplog_fd); diskdinfo->swaplog_fd = -1; n_diskd_dirs--; assert(n_diskd_dirs >= 0); if (0 == n_diskd_dirs) safe_free(diskd_dir_index);}static voidstoreDiskdCheckConfig(SwapDir * sd){ requirePathnameExists("diskd_program", Config.Program.diskd); if (!opt_create_swap_dirs) requirePathnameExists("cache_dir", sd->path);}static voiddiskdExited(int fd, void *unused){ fatal("diskd exited unexpectedly");}static voidstoreDiskdDirInit(SwapDir * sd){ static int started_clean_event = 0; pid_t pid; int i; int ikey; const char *args[5]; char skey1[32]; char skey2[32]; char skey3[32]; diskdinfo_t *diskdinfo = sd->fsdata; 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."; ikey = (getpid() << 10) + (sd->index << 2); ikey &= 0x7fffffff; diskdinfo->smsgid = msgget((key_t) ikey, 0700 | IPC_CREAT); if (diskdinfo->smsgid < 0) { debug(50, 0) ("storeDiskdInit: msgget: %s\n", xstrerror()); fatal("msgget failed"); } diskdinfo->rmsgid = msgget((key_t) (ikey + 1), 0700 | IPC_CREAT); if (diskdinfo->rmsgid < 0) { debug(50, 0) ("storeDiskdInit: msgget: %s\n", xstrerror()); fatal("msgget failed"); } diskdinfo->shm.nbufs = diskdinfo->magic2 * 1.3; diskdinfo->shm.id = shmget((key_t) (ikey + 2), diskdinfo->shm.nbufs * SHMBUF_BLKSZ, 0600 | IPC_CREAT); if (diskdinfo->shm.id < 0) { debug(50, 0) ("storeDiskdInit: shmget: %s\n", xstrerror()); fatal("shmget failed"); } diskdinfo->shm.buf = shmat(diskdinfo->shm.id, NULL, 0); if (diskdinfo->shm.buf == (void *) -1) { debug(50, 0) ("storeDiskdInit: shmat: %s\n", xstrerror()); fatal("shmat failed"); } diskdinfo->shm.inuse_map = xcalloc((diskdinfo->shm.nbufs + 7) / 8, 1); diskd_stats.shmbuf_count += diskdinfo->shm.nbufs; for (i = 0; i < diskdinfo->shm.nbufs; i++) { CBIT_SET(diskdinfo->shm.inuse_map, i); storeDiskdShmPut(sd, i * SHMBUF_BLKSZ); } snprintf(skey1, 32, "%d", ikey); snprintf(skey2, 32, "%d", ikey + 1); snprintf(skey3, 32, "%d", ikey + 2); args[0] = "diskd"; args[1] = skey1; args[2] = skey2; args[3] = skey3; args[4] = NULL; pid = ipcCreate(IPC_STREAM, Config.Program.diskd, args, "diskd", &diskdinfo->rfd, &diskdinfo->wfd,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -