Add support for verifying block checksums
Patch by Jeff Davis, rebased by Fabrízio de Royes Mello.
This commit is contained in:
parent
e3b9612db0
commit
81982fa168
@ -59,7 +59,7 @@ not require any manual adjustments of the Makefile.
|
|||||||
------------------------------------------------------------------------
|
------------------------------------------------------------------------
|
||||||
Invocation:
|
Invocation:
|
||||||
|
|
||||||
pg_filedump [-abcdfhixy] [-R startblock [endblock]] [-S blocksize] file
|
pg_filedump [-abcdfhikxy] [-R startblock [endblock]] [-S blocksize] file
|
||||||
|
|
||||||
Defaults are: relative addressing, range of the entire file, block size
|
Defaults are: relative addressing, range of the entire file, block size
|
||||||
as listed on block 0 in the file
|
as listed on block 0 in the file
|
||||||
@ -74,6 +74,7 @@ The following options are valid for heap and index files:
|
|||||||
-f Display formatted block content dump along with interpretation
|
-f Display formatted block content dump along with interpretation
|
||||||
-h Display this information
|
-h Display this information
|
||||||
-i Display interpreted item details
|
-i Display interpreted item details
|
||||||
|
-k Verify block checksums
|
||||||
-R Display specific block ranges within the file (Blocks are
|
-R Display specific block ranges within the file (Blocks are
|
||||||
indexed from 0)
|
indexed from 0)
|
||||||
[startblock]: block to start at
|
[startblock]: block to start at
|
||||||
|
@ -26,6 +26,13 @@
|
|||||||
|
|
||||||
#include "utils/pg_crc_tables.h"
|
#include "utils/pg_crc_tables.h"
|
||||||
|
|
||||||
|
// checksum_impl.h uses Assert, which doesn't work outside the server
|
||||||
|
#undef Assert
|
||||||
|
#define Assert(X)
|
||||||
|
|
||||||
|
#include "storage/checksum.h"
|
||||||
|
#include "storage/checksum_impl.h"
|
||||||
|
|
||||||
// Global variables for ease of use mostly
|
// Global variables for ease of use mostly
|
||||||
static FILE *fp = NULL; // File to dump or format
|
static FILE *fp = NULL; // File to dump or format
|
||||||
static char *fileName = NULL; // File name for display
|
static char *fileName = NULL; // File name for display
|
||||||
@ -40,12 +47,12 @@ static unsigned int blockVersion = 0; // Block version number
|
|||||||
static void DisplayOptions (unsigned int validOptions);
|
static void DisplayOptions (unsigned int validOptions);
|
||||||
static unsigned int ConsumeOptions (int numOptions, char **options);
|
static unsigned int ConsumeOptions (int numOptions, char **options);
|
||||||
static int GetOptionValue (char *optionString);
|
static int GetOptionValue (char *optionString);
|
||||||
static void FormatBlock ();
|
static void FormatBlock (BlockNumber blkno);
|
||||||
static unsigned int GetBlockSize ();
|
static unsigned int GetBlockSize ();
|
||||||
static unsigned int GetSpecialSectionType (Page page);
|
static unsigned int GetSpecialSectionType (Page page);
|
||||||
static bool IsBtreeMetaPage(Page page);
|
static bool IsBtreeMetaPage(Page page);
|
||||||
static void CreateDumpFileHeader (int numOptions, char **options);
|
static void CreateDumpFileHeader (int numOptions, char **options);
|
||||||
static int FormatHeader (Page page);
|
static int FormatHeader (Page page, BlockNumber blkno);
|
||||||
static void FormatItemBlock (Page page);
|
static void FormatItemBlock (Page page);
|
||||||
static void FormatItem (unsigned int numBytes, unsigned int startIndex,
|
static void FormatItem (unsigned int numBytes, unsigned int startIndex,
|
||||||
unsigned int formatAs);
|
unsigned int formatAs);
|
||||||
@ -68,7 +75,7 @@ DisplayOptions (unsigned int validOptions)
|
|||||||
FD_VERSION, FD_PG_VERSION);
|
FD_VERSION, FD_PG_VERSION);
|
||||||
|
|
||||||
printf
|
printf
|
||||||
("\nUsage: pg_filedump [-abcdfhixy] [-R startblock [endblock]] [-S blocksize] file\n\n"
|
("\nUsage: pg_filedump [-abcdfhikxy] [-R startblock [endblock]] [-S blocksize] file\n\n"
|
||||||
"Display formatted contents of a PostgreSQL heap/index/control file\n"
|
"Display formatted contents of a PostgreSQL heap/index/control file\n"
|
||||||
"Defaults are: relative addressing, range of the entire file, block\n"
|
"Defaults are: relative addressing, range of the entire file, block\n"
|
||||||
" size as listed on block 0 in the file\n\n"
|
" size as listed on block 0 in the file\n\n"
|
||||||
@ -82,6 +89,7 @@ DisplayOptions (unsigned int validOptions)
|
|||||||
" -f Display formatted block content dump along with interpretation\n"
|
" -f Display formatted block content dump along with interpretation\n"
|
||||||
" -h Display this information\n"
|
" -h Display this information\n"
|
||||||
" -i Display interpreted item details\n"
|
" -i Display interpreted item details\n"
|
||||||
|
" -k Verify block checksums\n"
|
||||||
" -R Display specific block ranges within the file (Blocks are\n"
|
" -R Display specific block ranges within the file (Blocks are\n"
|
||||||
" indexed from 0)\n" " [startblock]: block to start at\n"
|
" indexed from 0)\n" " [startblock]: block to start at\n"
|
||||||
" [endblock]: block to end at\n"
|
" [endblock]: block to end at\n"
|
||||||
@ -288,6 +296,11 @@ ConsumeOptions (int numOptions, char **options)
|
|||||||
SET_OPTION (itemOptions, ITEM_DETAIL, 'i');
|
SET_OPTION (itemOptions, ITEM_DETAIL, 'i');
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
// Verify block checksums
|
||||||
|
case 'k':
|
||||||
|
SET_OPTION (blockOptions, BLOCK_CHECKSUMS, 'k');
|
||||||
|
break;
|
||||||
|
|
||||||
// Interpret items as standard index values
|
// Interpret items as standard index values
|
||||||
case 'x':
|
case 'x':
|
||||||
SET_OPTION (itemOptions, ITEM_INDEX, 'x');
|
SET_OPTION (itemOptions, ITEM_INDEX, 'x');
|
||||||
@ -555,7 +568,7 @@ CreateDumpFileHeader (int numOptions, char **options)
|
|||||||
|
|
||||||
// Dump out a formatted block header for the requested block
|
// Dump out a formatted block header for the requested block
|
||||||
static int
|
static int
|
||||||
FormatHeader (Page page)
|
FormatHeader (Page page, BlockNumber blkno)
|
||||||
{
|
{
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
unsigned int headerBytes;
|
unsigned int headerBytes;
|
||||||
@ -647,6 +660,14 @@ FormatHeader (Page page)
|
|||||||
|| (pageHeader->pd_upper < pageHeader->pd_lower)
|
|| (pageHeader->pd_upper < pageHeader->pd_lower)
|
||||||
|| (pageHeader->pd_special > blockSize))
|
|| (pageHeader->pd_special > blockSize))
|
||||||
printf (" Error: Invalid header information.\n\n");
|
printf (" Error: Invalid header information.\n\n");
|
||||||
|
|
||||||
|
if (blockOptions & BLOCK_CHECKSUMS)
|
||||||
|
{
|
||||||
|
uint16 calc_checksum = pg_checksum_page(page, blkno);
|
||||||
|
if (calc_checksum != pageHeader->pd_checksum)
|
||||||
|
printf(" Error: checksum failure: calculated 0x%04x.\n\n",
|
||||||
|
calc_checksum);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we have reached the end of file while interpreting the header, let
|
// If we have reached the end of file while interpreting the header, let
|
||||||
@ -1208,7 +1229,7 @@ FormatSpecial ()
|
|||||||
|
|
||||||
// For each block, dump out formatted header and content information
|
// For each block, dump out formatted header and content information
|
||||||
static void
|
static void
|
||||||
FormatBlock ()
|
FormatBlock (BlockNumber blkno)
|
||||||
{
|
{
|
||||||
Page page = (Page) buffer;
|
Page page = (Page) buffer;
|
||||||
pageOffset = blockSize * currentBlock;
|
pageOffset = blockSize * currentBlock;
|
||||||
@ -1228,7 +1249,7 @@ FormatBlock ()
|
|||||||
int rc;
|
int rc;
|
||||||
// Every block contains a header, items and possibly a special
|
// Every block contains a header, items and possibly a special
|
||||||
// section. Beware of partial block reads though
|
// section. Beware of partial block reads though
|
||||||
rc = FormatHeader (page);
|
rc = FormatHeader (page, blkno);
|
||||||
|
|
||||||
// If we didn't encounter a partial read in the header, carry on...
|
// If we didn't encounter a partial read in the header, carry on...
|
||||||
if (rc != EOF_ENCOUNTERED)
|
if (rc != EOF_ENCOUNTERED)
|
||||||
@ -1498,7 +1519,7 @@ DumpFileContents ()
|
|||||||
contentsToDump = false;
|
contentsToDump = false;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
FormatBlock ();
|
FormatBlock (currentBlock);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,8 +22,8 @@
|
|||||||
* Original Author: Patrick Macdonald <patrickm@redhat.com>
|
* Original Author: Patrick Macdonald <patrickm@redhat.com>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define FD_VERSION "9.3.0" /* version ID of pg_filedump */
|
#define FD_VERSION "9.4.0" /* version ID of pg_filedump */
|
||||||
#define FD_PG_VERSION "PostgreSQL 9.3.x" /* PG version it works with */
|
#define FD_PG_VERSION "PostgreSQL 9.4.x" /* PG version it works with */
|
||||||
|
|
||||||
#include "postgres.h"
|
#include "postgres.h"
|
||||||
|
|
||||||
@ -50,7 +50,8 @@ typedef enum
|
|||||||
BLOCK_FORMAT = 0x00000004, // -f: Formatted dump of blocks / control file
|
BLOCK_FORMAT = 0x00000004, // -f: Formatted dump of blocks / control file
|
||||||
BLOCK_FORCED = 0x00000008, // -S: Block size forced
|
BLOCK_FORCED = 0x00000008, // -S: Block size forced
|
||||||
BLOCK_NO_INTR = 0x00000010, // -d: Dump straight blocks
|
BLOCK_NO_INTR = 0x00000010, // -d: Dump straight blocks
|
||||||
BLOCK_RANGE = 0x00000020 // -R: Specific block range to dump
|
BLOCK_RANGE = 0x00000020, // -R: Specific block range to dump
|
||||||
|
BLOCK_CHECKSUMS = 0x00000040 // -k: verify block checksums
|
||||||
}
|
}
|
||||||
blockSwitches;
|
blockSwitches;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user