Skip to content

Commit 0fa7e2f

Browse files
committed
Change fallback logic and checks page header.
1 parent a34152b commit 0fa7e2f

File tree

1 file changed

+102
-32
lines changed

1 file changed

+102
-32
lines changed

data.c

Lines changed: 102 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,7 @@ parse_page(const DataPage *page,
4242
page_data->pd_lower <= page_data->pd_upper &&
4343
page_data->pd_upper <= page_data->pd_special &&
4444
page_data->pd_special <= BLCKSZ &&
45-
page_data->pd_special == MAXALIGN(page_data->pd_special) &&
46-
!XLogRecPtrIsInvalid(*lsn))
45+
page_data->pd_special == MAXALIGN(page_data->pd_special))
4746
{
4847
*offset = page_data->pd_lower;
4948
*length = page_data->pd_upper - page_data->pd_lower;
@@ -65,10 +64,10 @@ backup_data_file(const char *from_root, const char *to_root,
6564
pgFile *file, const XLogRecPtr *lsn)
6665
{
6766
char to_path[MAXPGPATH];
68-
FILE *in;
69-
FILE *out;
67+
FILE *in;
68+
FILE *out;
7069
BackupPageHeader header;
71-
DataPage page; /* used as read buffer */
70+
DataPage page; /* used as read buffer */
7271
BlockNumber blknum = 0;
7372
size_t read_len = 0;
7473
pg_crc32 crc;
@@ -131,30 +130,61 @@ backup_data_file(const char *from_root, const char *to_root,
131130
int upper_offset;
132131
int upper_length;
133132
int try_checksum = 100;
133+
bool stop_backup = false;
134134

135135
header.block = blknum;
136136

137137
while(try_checksum)
138138
{
139+
try_checksum--;
139140
/*
140141
* If an invalid data page was found, fallback to simple copy to ensure
141142
* all pages in the file don't have BackupPageHeader.
142143
*/
143144
if (!parse_page(&page, &page_lsn,
144145
&header.hole_offset, &header.hole_length))
145146
{
146-
elog(LOG, "%s fall back to simple copy", file->path);
147-
fclose(in);
148-
fclose(out);
149-
file->is_datafile = false;
150-
return copy_file(from_root, to_root, file);
151-
}
147+
struct stat st;
148+
int i;
152149

153-
/* if the page has not been modified since last backup, skip it */
154-
if (lsn && !XLogRecPtrIsInvalid(page_lsn) && page_lsn < *lsn)
155-
break;
150+
for(i=0; i<BLCKSZ && page.data[i] == 0; i++);
151+
if (i == BLCKSZ)
152+
{
153+
elog(WARNING, "File: %s blknum %u, empty page", file->path, blknum);
154+
goto end_checks;
155+
}
156+
157+
stat(file->path, &st);
158+
elog(WARNING, "SIZE: %lu %lu pages:%lu pages:%lu i:%i", file->size, st.st_size, file->size/BLCKSZ, st.st_size/BLCKSZ, i);
159+
if (st.st_size != file->size && blknum >= file->size/BLCKSZ-1)
160+
{
161+
stop_backup = true;
162+
elog(WARNING, "File: %s blknum %u, file size has changed before backup start", file->path, blknum);
163+
break;
164+
}
165+
if (blknum >= file->size/BLCKSZ-1)
166+
{
167+
stop_backup = true;
168+
elog(WARNING, "File: %s blknum %u, the last page is empty, skip", file->path, blknum);
169+
break;
170+
}
171+
if (st.st_size != file->size && blknum < file->size/BLCKSZ-1)
172+
{
173+
elog(WARNING, "File: %s blknum %u, file size has changed before backup start, it seems bad", file->path, blknum);
174+
if (!try_checksum)
175+
break;
176+
}
177+
if (try_checksum)
178+
{
179+
elog(WARNING, "File: %s blknum %u have wrong page header, try again", file->path, blknum);
180+
fseek(in, -sizeof(page), SEEK_CUR);
181+
fread(&page, 1, sizeof(page), in);
182+
continue;
183+
}
184+
else
185+
elog(ERROR, "File: %s blknum %u have wrong page header.", file->path, blknum);
186+
}
156187

157-
try_checksum--;
158188
if(current.checksum_version &&
159189
pg_checksum_page(page.data, header.block) != ((PageHeader) page.data)->pd_checksum)
160190
{
@@ -171,12 +201,12 @@ backup_data_file(const char *from_root, const char *to_root,
171201
}
172202
}
173203

174-
/* if the page has not been modified since last backup, skip it */
175-
if (lsn && !XLogRecPtrIsInvalid(page_lsn) && page_lsn < *lsn)
176-
continue;
204+
end_checks:
177205

178206
file->read_size += read_len;
179207

208+
if(stop_backup)
209+
break;
180210

181211
upper_offset = header.hole_offset + header.hole_length;
182212
upper_length = BLCKSZ - upper_offset;
@@ -213,6 +243,7 @@ backup_data_file(const char *from_root, const char *to_root,
213243
int upper_length;
214244
int ret;
215245
int try_checksum = 100;
246+
bool stop_backup = false;
216247

217248
offset = blknum * BLCKSZ;
218249
while(try_checksum)
@@ -229,25 +260,51 @@ backup_data_file(const char *from_root, const char *to_root,
229260

230261
header.block = blknum;
231262

263+
try_checksum--;
264+
232265
/*
233266
* If an invalid data page was found, fallback to simple copy to ensure
234267
* all pages in the file don't have BackupPageHeader.
235268
*/
236269
if (!parse_page(&page, &page_lsn,
237270
&header.hole_offset, &header.hole_length))
238271
{
239-
elog(LOG, "%s fall back to simple copy", file->path);
240-
fclose(in);
241-
fclose(out);
242-
file->is_datafile = false;
243-
return copy_file(from_root, to_root, file);
244-
}
272+
struct stat st;
273+
int i;
245274

246-
/* if the page has not been modified since last backup, skip it */
247-
if (lsn && !XLogRecPtrIsInvalid(page_lsn) && page_lsn < *lsn)
248-
break;
275+
for(i=0; i<BLCKSZ && page.data[i] == 0; i++);
249276

250-
try_checksum--;
277+
278+
if (i == BLCKSZ)
279+
{
280+
elog(WARNING, "File: %s blknum %u, empty page", file->path, blknum);
281+
goto end_checks2;
282+
}
283+
284+
stat(file->path, &st);
285+
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);
286+
if (st.st_size != file->size && blknum >= file->size/BLCKSZ-1)
287+
{
288+
stop_backup = true;
289+
elog(WARNING, "File: %s blknum %u, file size has changed before backup start", file->path, blknum);
290+
break;
291+
}
292+
if (st.st_size != file->size && blknum < file->size/BLCKSZ-1)
293+
{
294+
elog(WARNING, "File: %s blknum %u, file size has changed before backup start, it seems bad", file->path, blknum);
295+
if (!try_checksum)
296+
break;
297+
}
298+
if (try_checksum)
299+
{
300+
elog(WARNING, "File: %s blknum %u have wrong page header, try again", file->path, blknum);
301+
fseek(in, -sizeof(page), SEEK_CUR);
302+
fread(&page, 1, sizeof(page), in);
303+
continue;
304+
}
305+
else
306+
elog(ERROR, "File: %s blknum %u have wrong page header.", file->path, blknum);
307+
}
251308

252309
if(current.checksum_version &&
253310
pg_checksum_page(page.data, header.block) != ((PageHeader) page.data)->pd_checksum)
@@ -263,11 +320,12 @@ backup_data_file(const char *from_root, const char *to_root,
263320
}
264321
}
265322

266-
/* if the page has not been modified since last backup, skip it */
267-
if (lsn && !XLogRecPtrIsInvalid(page_lsn) && page_lsn < *lsn)
268-
continue;
269-
270323
file->read_size += read_len;
324+
325+
if(stop_backup)
326+
break;
327+
328+
end_checks2:
271329

272330
upper_offset = header.hole_offset + header.hole_length;
273331
upper_length = BLCKSZ - upper_offset;
@@ -439,7 +497,19 @@ restore_data_file(const char *from_root,
439497

440498
/* update checksum because we are not save whole */
441499
if(backup->checksum_version)
500+
{
501+
/* skip calc checksum if zero page */
502+
if(page.page_data.pd_upper == 0)
503+
{
504+
int i;
505+
for(i=0; i<BLCKSZ && page.data[i] == 0; i++);
506+
if (i == BLCKSZ)
507+
goto skip_checksum;
508+
}
442509
((PageHeader) page.data)->pd_checksum = pg_checksum_page(page.data, header.block);
510+
}
511+
512+
skip_checksum:
443513

444514
/*
445515
* Seek and write the restored page. Backup might have holes in

0 commit comments

Comments
 (0)