1
0
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:
stalkerg
2016-08-30 15:53:38 +03:00
parent a34152b4aa
commit 0fa7e2fdbd

122
data.c
View File

@ -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