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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy