mirror of
https://github.com/postgres/postgres.git
synced 2025-08-31 17:02:12 +03:00
Add code to apply some simple sanity checks to the header fields of a
page when it's read in, per pghackers discussion around 17-Feb. Add a GUC variable zero_damaged_pages that causes the response to be a WARNING followed by zeroing the page, rather than the normal ERROR; this is per Hiroshi's suggestion that there needs to be a way to get at the data in the rest of the table.
This commit is contained in:
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/storage/buffer/bufmgr.c,v 1.134 2003/02/13 05:35:11 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/storage/buffer/bufmgr.c,v 1.135 2003/03/28 20:17:13 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)
|
||||
|
@@ -8,14 +8,12 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/storage/page/bufpage.c,v 1.51 2003/01/11 05:01:03 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/storage/page/bufpage.c,v 1.52 2003/03/28 20:17:13 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
|
||||
*
|
||||
|
Reference in New Issue
Block a user