📄 log_work.c
字号:
/* * Copyright (C) International Business Machines Corp., 2000-2005 * * 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-1307 USA */#include <config.h>#include <time.h>#include <stdio.h>#include <stdlib.h>#include <fcntl.h>#include <memory.h>#include <string.h>#include <errno.h>#include "jfs_types.h"#include "jfs_filsys.h"#include "jfs_superblock.h"#include "jfs_dinode.h"#include "jfs_dtree.h"#include "jfs_xtree.h"#include "jfs_logmgr.h"#include "jfs_dmap.h"#include "jfs_imap.h"#include "jfs_endian.h"#include "logredo.h"#include "devices.h"#include "debug.h"#include "fsck_message.h" /* for fsck message logging facility *//* + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + * * R E M E M B E R M E M O R Y A L L O C F A I L U R E * */extern int32_t Insuff_memory_for_maps;extern char *available_stg_addr;extern int32_t available_stg_bytes;extern char *bmap_stg_addr;extern int32_t bmap_stg_bytes;extern int end_of_transaction;/* + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + * * L O C A L M A C R O D E F I N I T I O N S * */#define UZBIT_8 ((uint8_t) (1 << 7))#define UZBIT_16 ((uint16_t) (1 << 15 ))#define UZBIT_32 ((uint32_t) (1 << 31 ))#define DTPGWORD 32#define L2DTPGWORD 5#define DATAPGWORD 32#define L2DATAPGWORD 5/* convert disk block number to bmap file page number */#define BLKTODMAPN(b)\ (((b) >> 13) + ((b) >> 23) + ((b) >> 33) + 3 + 1)/* The following MACRO update bmap for extents that have * XAD_NEW | XAD_EXTENDED flag in Xadlist. Then reset * the XAD_NEW | XAD_EXTENDED bits in the flag */#define MARKXADNEW(PXD, XADP, BMAPT, VOL)\{\ PXDlength((&PXD), lengthXAD(XADP));\ PXDaddress((&PXD), addressXAD((XADP)));\ markBmap((struct dmap*)(BMAPT), (PXD), 1, (VOL));\ (XADP)->flag &= ~(XAD_NEW|XAD_EXTENDED);\}/* * * T R A N S A C T I O N H A S H T A B L E * * each entry represents a committed transaction in recovery-in-progress * * An entry stays in the commit table until the first (in time, last seen * by logredo) record of a transaction is seen. (It is recognized because * its backchain == 0) */#define COMSIZE 512int comfree; /* index of a free com structure */int comhmask = 63; /* hash mask for comhash */int comhash[64]; /* head of hash chains */struct com { int tid; /* 4: committed tid. */ int next; /* 4: next on free list or hash chain */} com[COMSIZE]; /* (8) *//* * * R E D O P A G E H A S H T A B L E * * each entry represents a disk page that have been updated * by LOG_REDOPAGE records. * * When replay the LOG_REDOPAGE log rec, we should track which portion of the * disk page has been updated by the LOG_REDOPAGE log records. * When log is read in backwards direction, a LOG_REDOPAGE log record is * only applied to disk page image that has not been updated by any earlier * log records. So that only the last update to a portion is applied. * * There are many types of data for LOG_REDOPAGE log rec. Fields * ino_base, ino_ea, ino_data, summary1 and summary2 use different * way to do the track according to log.redopage.type: * * 1) Xtree page -- since the log record carries at most 2 segments, * the first one is header, if any, the second one is the * updated contigous xtree entries starting from offset. * The number of entries specified in the length. * If there is only one segment, it must be header. * * For xtree, the new entry either inserts or appends. * If it appends, then the log rec contains only the * new entry data. If it is inserted, all the entries * after the insertion need to shift. Then the log rec * contains all entries starting from the new insertion. * So only low water mark (lwm) offset needs to be recorded * in summary2. At logredo time, only the log rec having * offset lower than lwm will apply to page and only apply * the difference between offset and lwm. * Header of the xtree page should be only applied once * in logredo. So another field in summzry2 track header. * 2) Dtree page -- A dtree page has 128 slots including header. the slot size * is 32 byte. A 4 words(32 byte) array is used as a bit * vector to track the 128 slots. * 3) inode page -- There are 3 slot sizes and 5 sub-types for inode page. * Each type is in a separate log record. * * a) type == INODE * Section I (128 byte) of the dinode is logged. Offset is * counted from the beginning of the inode page. * A 8-bit vector tracks 8 inodes in inode page. * the slot size for this type is 128 byte. * Note: Each inode has 512 bytes, the INODE type only refers * to the first 128 section. so the offset should * be always a multiply of 4, i.e. 0, 4, 8, 12, etc.. * b) type == EA ( extended attribute ) * it is the top 16 bytes of section II of the dinode. * offset should be always ???. * A 8-bit vector tracks 8 inodes in inode page. * the slot size is 16 bytes. * c) type == DATA ( in-line data for symlink ) * A real xt data file starts from the 16 bytes above * section III of the dinode. * offset should be always ???. * A 8-bit vector tracks 8 inodes in inode page. * the slot size is 16 bytes. * d) type == BTROOT + DTREE * It starts from the 32 bytes above section III of the dinode. * Offset is counted from the beginning of BTROOT. * An array of 8 uint16_t, each is used as a bit vector to track * one dtroot. * the slot size for this type is 32 byte. * e) type == BTROOT + XTREE * It starts from the 32 bytes above section III of the dinode. * Offset is counted from the beginning of BTROOT. * an array of 8 structrues, each tracks one xtroot for lwm and * header of xtroot. * the slot size for this type is 16 byte. * * Note1: The slot size is stored in lrd.redopage.l2linesize field. * * Note2: The hash key for doblk is aggregate+pxd. * The same pxd can be used for an INODE log record, * a BTROOT+DTREE log rec, a BTROOT+XTREE log rec, * a EA log rec, and a in-line DATA log rec. So for these * five types, we cannot overlay them each other. * But the same pxd can be used for either a BTROOT+DTREE log rec * or a DTREE page log rec, not both. The same pxd can be used * for either a BTROOT+XTREE log rec or a XTREE page log rec, * not both. * Note3: xtpage_lwm and i_xtroot[] have a different initialization value * from rest of the types. They have to be inited to the * highest value. */#define BHASHSIZE 1024 /* must be a power of two */struct doblk { int32_t aggregate; /* file system aggregate/lv number */ pxd_t pxd; /* on-disk page pxd */ uint16_t type; /* doblk type (inode, xtree, dtree, data) */#define LOG_NONE 0X1000 /* Invalid doblk type to guarantee noredo */ uint16_t reserved; union { struct { uint8_t ino_base; /* each bit tracks one dinode * for section I of the dinode * (128 bytes.) Each inode has * 4 128-byte slots, with one * base slot. A total of 8 * bits that need to be marked * for 8 dinodes in one inode * page */ uint8_t ino_ea; /* extended attribute */ uint8_t ino_data; /* in-line data */ uint8_t xtrt_hd; /* xtroot header */ uint8_t xtrt_lwm[8]; /* xtroot lwm value. */ uint16_t ino_dtroot[8]; /* dtree root. each dinode has * 9 dtree-root slots, including * 1 slot header. Each slot is * 32-byte. Each element of * i_dtroot[] monitors one dtree * root of the dinode. For each * 16-bit, only 9-bit is used. */ uint8_t ino_link; /* in-line symlink */ uint8_t dtree; /* flag per ino whether dtree * has been logged */ uint8_t reserved[2]; } inode; uint32_t dtpage_word[4]; /* dtree page. a total of 128 * slots including header */ struct { uint8_t xtpage_hd; /* xtree page header */ uint8_t xtpage_lwm; /* xtree page. the lowest offset * among non-header segments */ } xtpg; uint32_t data_word[8]; /* data page has 256 16-byte slots */ } summary; struct doblk *next; /* next entry on hash chain */};#define db_ibase summary.inode.ino_base#define db_iea summary.inode.ino_ea#define db_idata summary.inode.ino_data#define db_dtroot summary.inode.ino_dtroot#define db_xtrt_hd summary.inode.xtrt_hd#define db_xtrt_lwm summary.inode.xtrt_lwm#define db_idtree summary.inode.dtree#define db_ilink summary.inode.ino_link#define db_dtpagewd summary.dtpage_word#define db_xtpagelwm summary.xtpg.xtpage_lwm#define db_xtpghd summary.xtpg.xtpage_hd#define db_datawd summary.data_wordextern int32_t numdoblk; /* number of do blocks used */int32_t blkhmask = (BHASHSIZE - 1); /* hash mask for blkhash */struct doblk *blkhash[BHASHSIZE]; /* head of doblk hash chains */int32_t Freedoblk; /* number of unused doblk struct */struct doblk *Blkpage; /* beginning address of doblk hash table page *//* * * N O R E D O F I L E H A S H T A B L E * * each entry represents a file system object which has been deleted * (entry is added when the log record describing the delete is processed) */#define NODOFILEHASHSIZE 512struct nodofile { int32_t aggregate; /* 4: file system aggregate/lv number */ uint32_t inode; /* 4: inode number */ struct nodofile *next; /* 4: next entry on nodo hash chain */}; /* (16) */extern int32_t numnodofile; /* number of nodo file blocks used */int32_t nodofilehmask = (NODOFILEHASHSIZE - 1); /* hash mask for nodohash */struct nodofile *nodofilehash[NODOFILEHASHSIZE]; /* head of nodo hash chains */int32_t Freenodofile; /* number of unused nodofile struct */struct nodofile *Nodofilep; /* the beginning address of nodo hash table page */struct ExtDtPg { int32_t pg_vol; /* 4: volume containing the dtpage */ int64_t pg_off; /* 8: dtpage offset, in fsblocks */ struct ExtDtPg *next; /* 4: next entry on list */}; /* (16) */extern int32_t numExtDtPg; /* number of extended dtpage blocks used */int32_t FreeExtDtPg = 0; /* number of unused extended dtpage blocks */struct ExtDtPg *DtPgPage = NULL; /* storage available for new blocks */struct ExtDtPg *DtPgList = NULL; /* list of extended dtpages *//* + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + * * S T U F F F O R T H E L O G * * externals defined in logredo.c *//* * * O P E N F I L E S Y S T E M A G G R E G A T E / L V A R R A Y * * Defined in logredo.c */extern struct vopen vopen[]; /* (88) *//* * * B U F F E R H E A D E R T A B L E * */extern struct bufhdr { int16_t next; /* 2: next on free/lru list */ int16_t prev; /* 2: previous on free/lru list */ int16_t hnext; /* 2: next on hash chain */ int16_t hprev; /* 2: previous on hash chain */ char modify; /* 1: buffer was modified */ char inuse; /* 1: buffer on hash chain */ int16_t reserve; /* 2 */ int32_t vol; /* 4: minor of agrregate/lv number */ pxd_t pxd; /* 8: on-disk page pxd */} bufhdr[]; /* (24) *//* * * L O G P A G E B U F F E R C A C H E * * log has its own 4 page buffer pool. * --> afterdata defined in logredo.c <-- */extern uint8_t afterdata[LOGPSIZE]; /* buffer to read in redopage data */extern struct logsuper logsup; /* log super block *//* * * E X T E R N A L A N D F O R W A R D R E F E R E N C E S * *//* * external references */extern int bread(int32_t, pxd_t, void **, int32_t);extern int fsError(int, int, int64_t);extern int openVol(int32_t);extern int alloc_storage(int32_t, void **, int32_t *);extern int dMapGet(int, int);extern int iagGet(int, int32_t);/* * forward references */int deleteCommit(int32_t);int doAfter(struct lrd *, int32_t);int doCommit(struct lrd *);int doExtDtPg(void);int doNoRedoFile(struct lrd *, uint32_t);int doNoRedoInoExt(struct lrd *);int doNoRedoPage(struct lrd *);int doUpdateMap(struct lrd *);int dtpg_resetFreeList(int32_t, int *);int dtrt_resetFreeList(int32_t, struct doblk *, struct lrd *, caddr_t);int findCommit(int32_t);int findPageRedo(int32_t, pxd_t, struct doblk **);int logredoInit(void);int markBmap(struct dmap *, pxd_t, int, int);int markImap(struct fsimap_lst *, uint32_t, pxd_t, int, int);int updatePage(struct lrd *, int32_t);int saveExtDtPg(int32_t, int64_t);/* ===================================================================*//* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * * NAME: deleteCommit(tid) * * FUNCTION: Search in the commit array for a commit record with * transaction id (tid) matching the given tid. If a * match is found, delete the array entry containing it. */int deleteCommit(int32_t tid){ /* transaction id to be deleted */ int k, n, hash; hash = tid & comhmask; /* hash class */ n = 0; /* previous entry on hash chain */ for (k = comhash[hash]; com[k].tid != tid; k = com[k].next) n = k; /* remove k from hash chain and put it on free list * Special case when 1st on the hash list */ if (n == 0) comhash[hash] = com[k].next; else com[n].next = com[k].next; com[k].next = comfree; comfree = k; /* note that the end of the transaction has been seen so * that the log records it contains will be written to the * device. */ end_of_transaction = -1; return (0);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -