Index: backend/storage/buffer/bufmgr.c =================================================================== RCS file: /respaldo/alvherre/cvs/pgsql-server/src/backend/storage/buffer/bufmgr.c,v retrieving revision 1.134 retrieving revision 1.135 diff -c -r1.134 -r1.135 *** backend/storage/buffer/bufmgr.c 13 Feb 2003 05:35:11 -0000 1.134 --- backend/storage/buffer/bufmgr.c 28 Mar 2003 20:17:13 -0000 1.135 *************** *** 8,14 **** * * * IDENTIFICATION ! * $Header: /respaldo/alvherre/cvs/pgsql-server/src/backend/storage/buffer/bufmgr.c,v 1.134 2003/02/13 05:35:11 momjian Exp $ * *------------------------------------------------------------------------- */ --- 8,14 ---- * * * IDENTIFICATION ! * $Header: /respaldo/alvherre/cvs/pgsql-server/src/backend/storage/buffer/bufmgr.c,v 1.135 2003/03/28 20:17:13 tgl Exp $ * *------------------------------------------------------------------------- */ *************** *** 49,54 **** --- 49,55 ---- #include "miscadmin.h" #include "storage/buf_internals.h" #include "storage/bufmgr.h" + #include "storage/bufpage.h" #include "storage/proc.h" #include "storage/smgr.h" #include "utils/relcache.h" *************** *** 59,64 **** --- 60,69 ---- (*((XLogRecPtr*) MAKE_PTR((bufHdr)->data))) + /* GUC variable */ + bool zero_damaged_pages = false; + + static void WaitIO(BufferDesc *buf); static void StartBufferIO(BufferDesc *buf, bool forInput); static void TerminateBufferIO(BufferDesc *buf); *************** *** 217,222 **** --- 222,241 ---- { status = smgrread(DEFAULT_SMGR, reln, blockNum, (char *) MAKE_PTR(bufHdr->data)); + /* check for garbage data */ + if (status == SM_SUCCESS && + !PageHeaderIsValid((PageHeader) MAKE_PTR(bufHdr->data))) + { + if (zero_damaged_pages) + { + elog(WARNING, "Invalid page header in block %u of %s; zeroing out page", + blockNum, RelationGetRelationName(reln)); + MemSet((char *) MAKE_PTR(bufHdr->data), 0, BLCKSZ); + } + else + elog(ERROR, "Invalid page header in block %u of %s", + blockNum, RelationGetRelationName(reln)); + } } if (isLocalBuf) Index: backend/storage/page/bufpage.c =================================================================== RCS file: /respaldo/alvherre/cvs/pgsql-server/src/backend/storage/page/bufpage.c,v retrieving revision 1.51 retrieving revision 1.52 diff -c -r1.51 -r1.52 *** backend/storage/page/bufpage.c 11 Jan 2003 05:01:03 -0000 1.51 --- backend/storage/page/bufpage.c 28 Mar 2003 20:17:13 -0000 1.52 *************** *** 8,21 **** * * * IDENTIFICATION ! * $Header: /respaldo/alvherre/cvs/pgsql-server/src/backend/storage/page/bufpage.c,v 1.51 2003/01/11 05:01:03 momjian Exp $ * *------------------------------------------------------------------------- */ #include "postgres.h" - #include - #include "storage/bufpage.h" --- 8,19 ---- * * * IDENTIFICATION ! * $Header: /respaldo/alvherre/cvs/pgsql-server/src/backend/storage/page/bufpage.c,v 1.52 2003/03/28 20:17:13 tgl Exp $ * *------------------------------------------------------------------------- */ #include "postgres.h" #include "storage/bufpage.h" *************** *** 45,50 **** --- 43,93 ---- p->pd_upper = pageSize - specialSize; p->pd_special = pageSize - specialSize; PageSetPageSizeAndVersion(page, pageSize, PG_PAGE_LAYOUT_VERSION); + } + + + /* + * PageHeaderIsValid + * Check that the header fields of a page appear valid. + * + * This is called when a page has just been read in from disk. The idea is + * to cheaply detect trashed pages before we go nuts following bogus item + * pointers, testing invalid transaction identifiers, etc. + * + * It turns out to be necessary to allow zeroed pages here too. Even though + * this routine is *not* called when deliberately adding a page to a relation, + * there are scenarios in which a zeroed page might be found in a table. + * (Example: a backend extends a relation, then crashes before it can write + * any WAL entry about the new page. The kernel will already have the + * zeroed page in the file, and it will stay that way after restart.) So we + * allow zeroed pages here, and are careful that the page access macros + * treat such a page as empty and without free space. Eventually, VACUUM + * will clean up such a page and make it usable. + */ + bool + PageHeaderIsValid(PageHeader page) + { + char *pagebytes; + int i; + + /* Check normal case */ + if (PageGetPageSize(page) == BLCKSZ && + PageGetPageLayoutVersion(page) == PG_PAGE_LAYOUT_VERSION && + page->pd_lower >= SizeOfPageHeaderData && + page->pd_lower <= page->pd_upper && + page->pd_upper <= page->pd_special && + page->pd_special <= BLCKSZ && + page->pd_special == MAXALIGN(page->pd_special)) + return true; + + /* Check all-zeroes case */ + pagebytes = (char *) page; + for (i = 0; i < BLCKSZ; i++) + { + if (pagebytes[i] != 0) + return false; + } + return true; } Index: backend/utils/misc/guc.c =================================================================== RCS file: /respaldo/alvherre/cvs/pgsql-server/src/backend/utils/misc/guc.c,v retrieving revision 1.117 retrieving revision 1.118 diff -c -r1.117 -r1.118 *** backend/utils/misc/guc.c 20 Mar 2003 04:51:44 -0000 1.117 --- backend/utils/misc/guc.c 28 Mar 2003 20:17:13 -0000 1.118 *************** *** 5,11 **** * command, configuration file, and command line options. * See src/backend/utils/misc/README for more information. * ! * $Header: /respaldo/alvherre/cvs/pgsql-server/src/backend/utils/misc/guc.c,v 1.117 2003/03/20 04:51:44 momjian Exp $ * * Copyright 2000 by PostgreSQL Global Development Group * Written by Peter Eisentraut . --- 5,11 ---- * command, configuration file, and command line options. * See src/backend/utils/misc/README for more information. * ! * $Header: /respaldo/alvherre/cvs/pgsql-server/src/backend/utils/misc/guc.c,v 1.118 2003/03/28 20:17:13 tgl Exp $ * * Copyright 2000 by PostgreSQL Global Development Group * Written by Peter Eisentraut . *************** *** 356,361 **** --- 356,365 ---- { {"fsync", PGC_SIGHUP}, &enableFsync, true, NULL, NULL + }, + { + {"zero_damaged_pages", PGC_SUSET}, &zero_damaged_pages, + false, NULL, NULL }, { {"silent_mode", PGC_POSTMASTER}, &SilentMode, Index: backend/utils/misc/postgresql.conf.sample =================================================================== RCS file: /respaldo/alvherre/cvs/pgsql-server/src/backend/utils/misc/postgresql.conf.sample,v retrieving revision 1.73 retrieving revision 1.74 diff -c -r1.73 -r1.74 *** backend/utils/misc/postgresql.conf.sample 24 Mar 2003 20:39:10 -0000 1.73 --- backend/utils/misc/postgresql.conf.sample 28 Mar 2003 20:17:13 -0000 1.74 *************** *** 213,218 **** #sql_inheritance = true #transform_null_equals = false #statement_timeout = 0 # 0 is disabled, in milliseconds #db_user_namespace = false #preload_libraries = '' - --- 213,218 ---- #sql_inheritance = true #transform_null_equals = false #statement_timeout = 0 # 0 is disabled, in milliseconds + #zero_damaged_pages = false # set this true only for disaster recovery #db_user_namespace = false #preload_libraries = '' Index: include/storage/bufmgr.h =================================================================== RCS file: /respaldo/alvherre/cvs/pgsql-server/src/include/storage/bufmgr.h,v retrieving revision 1.66 retrieving revision 1.67 diff -c -r1.66 -r1.67 *** include/storage/bufmgr.h 22 Oct 2002 20:00:48 -0000 1.66 --- include/storage/bufmgr.h 28 Mar 2003 20:17:13 -0000 1.67 *************** *** 7,13 **** * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * ! * $Id: bufmgr.h,v 1.66 2002/10/22 20:00:48 petere Exp $ * *------------------------------------------------------------------------- */ --- 7,13 ---- * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * ! * $Id: bufmgr.h,v 1.67 2003/03/28 20:17:13 tgl Exp $ * *------------------------------------------------------------------------- */ *************** *** 24,29 **** --- 24,32 ---- /* in globals.c ... this duplicates miscadmin.h */ extern DLLIMPORT int NBuffers; + + /* in bufmgr.c */ + extern bool zero_damaged_pages; /* in buf_init.c */ extern DLLIMPORT Block *BufferBlockPointers; Index: include/storage/bufpage.h =================================================================== RCS file: /respaldo/alvherre/cvs/pgsql-server/src/include/storage/bufpage.h,v retrieving revision 1.53 retrieving revision 1.54 diff -c -r1.53 -r1.54 *** include/storage/bufpage.h 4 Sep 2002 20:31:45 -0000 1.53 --- include/storage/bufpage.h 28 Mar 2003 20:17:13 -0000 1.54 *************** *** 7,13 **** * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * ! * $Id: bufpage.h,v 1.53 2002/09/04 20:31:45 momjian Exp $ * *------------------------------------------------------------------------- */ --- 7,13 ---- * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * ! * $Id: bufpage.h,v 1.54 2003/03/28 20:17:13 tgl Exp $ * *------------------------------------------------------------------------- */ *************** *** 19,25 **** #include "storage/item.h" #include "storage/itemid.h" #include "storage/off.h" - #include "storage/page.h" #include "access/xlog.h" /* --- 19,24 ---- *************** *** 74,84 **** * fields. */ ! /* ! * PageIsValid ! * True iff page is valid. ! */ ! #define PageIsValid(page) PointerIsValid(page) /* --- 73,79 ---- * fields. */ ! typedef Pointer Page; /* *************** *** 141,162 **** * page support macros * ---------------------------------------------------------------- */ - /* - * PageIsValid -- This is defined in page.h. - */ /* ! * PageIsUsed ! * True iff the page size is used. ! * ! * Note: ! * Assumes page is valid. */ ! #define PageIsUsed(page) \ ! ( \ ! AssertMacro(PageIsValid(page)), \ ! ((bool) (((PageHeader) (page))->pd_lower != 0)) \ ! ) /* * line pointer does not count as part of header --- 136,147 ---- * page support macros * ---------------------------------------------------------------- */ /* ! * PageIsValid ! * True iff page is valid. */ ! #define PageIsValid(page) PointerIsValid(page) /* * line pointer does not count as part of header *************** *** 172,180 **** /* * PageIsNew ! * returns true iff page is not initialized (by PageInit) */ - #define PageIsNew(page) (((PageHeader) (page))->pd_upper == 0) /* --- 157,164 ---- /* * PageIsNew ! * returns true iff page has not been initialized (by PageInit) */ #define PageIsNew(page) (((PageHeader) (page))->pd_upper == 0) /* *************** *** 199,210 **** /* * PageSizeIsValid * True iff the page size is valid. - * - * XXX currently all page sizes are "valid" but we only actually - * use BLCKSZ. - * - * 01/06/98 Now does something useful. darrenk - * */ #define PageSizeIsValid(pageSize) ((pageSize) == BLCKSZ) --- 183,188 ---- *************** *** 214,220 **** * * this can only be called on a formatted page (unlike * BufferGetPageSize, which can be called on an unformatted page). ! * however, it can be called on a page for which there is no buffer. */ #define PageGetPageSize(page) \ ((Size) (((PageHeader) (page))->pd_pagesize_version & (uint16) 0xFF00)) --- 192,198 ---- * * this can only be called on a formatted page (unlike * BufferGetPageSize, which can be called on an unformatted page). ! * however, it can be called on a page that is not stored in a buffer. */ #define PageGetPageSize(page) \ ((Size) (((PageHeader) (page))->pd_pagesize_version & (uint16) 0xFF00)) *************** *** 222,231 **** /* * PageGetPageLayoutVersion * Returns the page layout version of a page. - * - * this can only be called on a formatted page (unlike - * BufferGetPageSize, which can be called on an unformatted page). - * however, it can be called on a page for which there is no buffer. */ #define PageGetPageLayoutVersion(page) \ (((PageHeader) (page))->pd_pagesize_version & 0x00FF) --- 200,205 ---- *************** *** 251,259 **** /* * PageGetSpecialSize * Returns size of special space on a page. - * - * Note: - * Assumes page is locked. */ #define PageGetSpecialSize(page) \ ((uint16) (PageGetPageSize(page) - ((PageHeader)(page))->pd_special)) --- 225,230 ---- *************** *** 261,269 **** /* * PageGetSpecialPointer * Returns pointer to special space on a page. - * - * Note: - * Assumes page is locked. */ #define PageGetSpecialPointer(page) \ ( \ --- 232,237 ---- *************** *** 339,344 **** --- 307,313 ---- */ extern void PageInit(Page page, Size pageSize, Size specialSize); + extern bool PageHeaderIsValid(PageHeader page); extern OffsetNumber PageAddItem(Page page, Item item, Size size, OffsetNumber offsetNumber, ItemIdFlags flags); extern Page PageGetTempPage(Page page, Size specialSize);