1
0
mirror of https://github.com/postgres/postgres.git synced 2025-11-28 11:44:57 +03:00

Back-patch changes to validate page header fields immediately after

reading in any page.  Also back-port the zero_damaged_pages boolean
that determines what to do about it.
This commit is contained in:
Tom Lane
2003-04-04 00:32:57 +00:00
parent a880697f09
commit 8fe728b009
6 changed files with 101 additions and 11 deletions

View File

@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/storage/buffer/bufmgr.c,v 1.133 2002/09/14 19:59:20 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/storage/buffer/bufmgr.c,v 1.133.2.1 2003/04/04 00:32:57 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -49,6 +49,7 @@
#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,6 +60,10 @@
(*((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,6 +222,20 @@ ReadBufferInternal(Relation reln, BlockNumber blockNum,
{
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)

View File

@@ -8,14 +8,12 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/storage/page/bufpage.c,v 1.50 2002/09/04 20:31:26 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/storage/page/bufpage.c,v 1.50.2.1 2003/04/04 00:32:57 tgl Exp $
*
*-------------------------------------------------------------------------
*/
#include "postgres.h"
#include <sys/file.h>
#include "storage/bufpage.h"
@@ -48,6 +46,51 @@ PageInit(Page page, Size pageSize, Size specialSize)
}
/*
* 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;
}
/* ----------------
* PageAddItem
*