You've already forked pg_probackup
mirror of
https://github.com/postgrespro/pg_probackup.git
synced 2025-07-17 07:22:20 +02:00
Change fallback logic and checks page header.
This commit is contained in:
122
data.c
122
data.c
@ -42,8 +42,7 @@ parse_page(const DataPage *page,
|
|||||||
page_data->pd_lower <= page_data->pd_upper &&
|
page_data->pd_lower <= page_data->pd_upper &&
|
||||||
page_data->pd_upper <= page_data->pd_special &&
|
page_data->pd_upper <= page_data->pd_special &&
|
||||||
page_data->pd_special <= BLCKSZ &&
|
page_data->pd_special <= BLCKSZ &&
|
||||||
page_data->pd_special == MAXALIGN(page_data->pd_special) &&
|
page_data->pd_special == MAXALIGN(page_data->pd_special))
|
||||||
!XLogRecPtrIsInvalid(*lsn))
|
|
||||||
{
|
{
|
||||||
*offset = page_data->pd_lower;
|
*offset = page_data->pd_lower;
|
||||||
*length = page_data->pd_upper - page_data->pd_lower;
|
*length = page_data->pd_upper - page_data->pd_lower;
|
||||||
@ -131,11 +130,13 @@ backup_data_file(const char *from_root, const char *to_root,
|
|||||||
int upper_offset;
|
int upper_offset;
|
||||||
int upper_length;
|
int upper_length;
|
||||||
int try_checksum = 100;
|
int try_checksum = 100;
|
||||||
|
bool stop_backup = false;
|
||||||
|
|
||||||
header.block = blknum;
|
header.block = blknum;
|
||||||
|
|
||||||
while(try_checksum)
|
while(try_checksum)
|
||||||
{
|
{
|
||||||
|
try_checksum--;
|
||||||
/*
|
/*
|
||||||
* If an invalid data page was found, fallback to simple copy to ensure
|
* If an invalid data page was found, fallback to simple copy to ensure
|
||||||
* all pages in the file don't have BackupPageHeader.
|
* all pages in the file don't have BackupPageHeader.
|
||||||
@ -143,18 +144,47 @@ backup_data_file(const char *from_root, const char *to_root,
|
|||||||
if (!parse_page(&page, &page_lsn,
|
if (!parse_page(&page, &page_lsn,
|
||||||
&header.hole_offset, &header.hole_length))
|
&header.hole_offset, &header.hole_length))
|
||||||
{
|
{
|
||||||
elog(LOG, "%s fall back to simple copy", file->path);
|
struct stat st;
|
||||||
fclose(in);
|
int i;
|
||||||
fclose(out);
|
|
||||||
file->is_datafile = false;
|
for(i=0; i<BLCKSZ && page.data[i] == 0; i++);
|
||||||
return copy_file(from_root, to_root, file);
|
if (i == BLCKSZ)
|
||||||
|
{
|
||||||
|
elog(WARNING, "File: %s blknum %u, empty page", file->path, blknum);
|
||||||
|
goto end_checks;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* if the page has not been modified since last backup, skip it */
|
stat(file->path, &st);
|
||||||
if (lsn && !XLogRecPtrIsInvalid(page_lsn) && page_lsn < *lsn)
|
elog(WARNING, "SIZE: %lu %lu pages:%lu pages:%lu i:%i", file->size, st.st_size, file->size/BLCKSZ, st.st_size/BLCKSZ, i);
|
||||||
|
if (st.st_size != file->size && blknum >= file->size/BLCKSZ-1)
|
||||||
|
{
|
||||||
|
stop_backup = true;
|
||||||
|
elog(WARNING, "File: %s blknum %u, file size has changed before backup start", file->path, blknum);
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
if (blknum >= file->size/BLCKSZ-1)
|
||||||
|
{
|
||||||
|
stop_backup = true;
|
||||||
|
elog(WARNING, "File: %s blknum %u, the last page is empty, skip", file->path, blknum);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (st.st_size != file->size && blknum < file->size/BLCKSZ-1)
|
||||||
|
{
|
||||||
|
elog(WARNING, "File: %s blknum %u, file size has changed before backup start, it seems bad", file->path, blknum);
|
||||||
|
if (!try_checksum)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (try_checksum)
|
||||||
|
{
|
||||||
|
elog(WARNING, "File: %s blknum %u have wrong page header, try again", file->path, blknum);
|
||||||
|
fseek(in, -sizeof(page), SEEK_CUR);
|
||||||
|
fread(&page, 1, sizeof(page), in);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
elog(ERROR, "File: %s blknum %u have wrong page header.", file->path, blknum);
|
||||||
|
}
|
||||||
|
|
||||||
try_checksum--;
|
|
||||||
if(current.checksum_version &&
|
if(current.checksum_version &&
|
||||||
pg_checksum_page(page.data, header.block) != ((PageHeader) page.data)->pd_checksum)
|
pg_checksum_page(page.data, header.block) != ((PageHeader) page.data)->pd_checksum)
|
||||||
{
|
{
|
||||||
@ -171,12 +201,12 @@ backup_data_file(const char *from_root, const char *to_root,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* if the page has not been modified since last backup, skip it */
|
end_checks:
|
||||||
if (lsn && !XLogRecPtrIsInvalid(page_lsn) && page_lsn < *lsn)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
file->read_size += read_len;
|
file->read_size += read_len;
|
||||||
|
|
||||||
|
if(stop_backup)
|
||||||
|
break;
|
||||||
|
|
||||||
upper_offset = header.hole_offset + header.hole_length;
|
upper_offset = header.hole_offset + header.hole_length;
|
||||||
upper_length = BLCKSZ - upper_offset;
|
upper_length = BLCKSZ - upper_offset;
|
||||||
@ -213,6 +243,7 @@ backup_data_file(const char *from_root, const char *to_root,
|
|||||||
int upper_length;
|
int upper_length;
|
||||||
int ret;
|
int ret;
|
||||||
int try_checksum = 100;
|
int try_checksum = 100;
|
||||||
|
bool stop_backup = false;
|
||||||
|
|
||||||
offset = blknum * BLCKSZ;
|
offset = blknum * BLCKSZ;
|
||||||
while(try_checksum)
|
while(try_checksum)
|
||||||
@ -229,6 +260,8 @@ backup_data_file(const char *from_root, const char *to_root,
|
|||||||
|
|
||||||
header.block = blknum;
|
header.block = blknum;
|
||||||
|
|
||||||
|
try_checksum--;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If an invalid data page was found, fallback to simple copy to ensure
|
* If an invalid data page was found, fallback to simple copy to ensure
|
||||||
* all pages in the file don't have BackupPageHeader.
|
* all pages in the file don't have BackupPageHeader.
|
||||||
@ -236,18 +269,42 @@ backup_data_file(const char *from_root, const char *to_root,
|
|||||||
if (!parse_page(&page, &page_lsn,
|
if (!parse_page(&page, &page_lsn,
|
||||||
&header.hole_offset, &header.hole_length))
|
&header.hole_offset, &header.hole_length))
|
||||||
{
|
{
|
||||||
elog(LOG, "%s fall back to simple copy", file->path);
|
struct stat st;
|
||||||
fclose(in);
|
int i;
|
||||||
fclose(out);
|
|
||||||
file->is_datafile = false;
|
for(i=0; i<BLCKSZ && page.data[i] == 0; i++);
|
||||||
return copy_file(from_root, to_root, file);
|
|
||||||
|
|
||||||
|
if (i == BLCKSZ)
|
||||||
|
{
|
||||||
|
elog(WARNING, "File: %s blknum %u, empty page", file->path, blknum);
|
||||||
|
goto end_checks2;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* if the page has not been modified since last backup, skip it */
|
stat(file->path, &st);
|
||||||
if (lsn && !XLogRecPtrIsInvalid(page_lsn) && page_lsn < *lsn)
|
elog(WARNING, "PTRACK SIZE: %lu %lu pages:%lu pages:%lu i:%i", file->size, st.st_size, file->size/BLCKSZ, st.st_size/BLCKSZ, i);
|
||||||
|
if (st.st_size != file->size && blknum >= file->size/BLCKSZ-1)
|
||||||
|
{
|
||||||
|
stop_backup = true;
|
||||||
|
elog(WARNING, "File: %s blknum %u, file size has changed before backup start", file->path, blknum);
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
try_checksum--;
|
if (st.st_size != file->size && blknum < file->size/BLCKSZ-1)
|
||||||
|
{
|
||||||
|
elog(WARNING, "File: %s blknum %u, file size has changed before backup start, it seems bad", file->path, blknum);
|
||||||
|
if (!try_checksum)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (try_checksum)
|
||||||
|
{
|
||||||
|
elog(WARNING, "File: %s blknum %u have wrong page header, try again", file->path, blknum);
|
||||||
|
fseek(in, -sizeof(page), SEEK_CUR);
|
||||||
|
fread(&page, 1, sizeof(page), in);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
elog(ERROR, "File: %s blknum %u have wrong page header.", file->path, blknum);
|
||||||
|
}
|
||||||
|
|
||||||
if(current.checksum_version &&
|
if(current.checksum_version &&
|
||||||
pg_checksum_page(page.data, header.block) != ((PageHeader) page.data)->pd_checksum)
|
pg_checksum_page(page.data, header.block) != ((PageHeader) page.data)->pd_checksum)
|
||||||
@ -263,12 +320,13 @@ backup_data_file(const char *from_root, const char *to_root,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* if the page has not been modified since last backup, skip it */
|
|
||||||
if (lsn && !XLogRecPtrIsInvalid(page_lsn) && page_lsn < *lsn)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
file->read_size += read_len;
|
file->read_size += read_len;
|
||||||
|
|
||||||
|
if(stop_backup)
|
||||||
|
break;
|
||||||
|
|
||||||
|
end_checks2:
|
||||||
|
|
||||||
upper_offset = header.hole_offset + header.hole_length;
|
upper_offset = header.hole_offset + header.hole_length;
|
||||||
upper_length = BLCKSZ - upper_offset;
|
upper_length = BLCKSZ - upper_offset;
|
||||||
|
|
||||||
@ -439,7 +497,19 @@ restore_data_file(const char *from_root,
|
|||||||
|
|
||||||
/* update checksum because we are not save whole */
|
/* update checksum because we are not save whole */
|
||||||
if(backup->checksum_version)
|
if(backup->checksum_version)
|
||||||
|
{
|
||||||
|
/* skip calc checksum if zero page */
|
||||||
|
if(page.page_data.pd_upper == 0)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
for(i=0; i<BLCKSZ && page.data[i] == 0; i++);
|
||||||
|
if (i == BLCKSZ)
|
||||||
|
goto skip_checksum;
|
||||||
|
}
|
||||||
((PageHeader) page.data)->pd_checksum = pg_checksum_page(page.data, header.block);
|
((PageHeader) page.data)->pd_checksum = pg_checksum_page(page.data, header.block);
|
||||||
|
}
|
||||||
|
|
||||||
|
skip_checksum:
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Seek and write the restored page. Backup might have holes in
|
* Seek and write the restored page. Backup might have holes in
|
||||||
|
Reference in New Issue
Block a user