@@ -42,8 +42,7 @@ parse_page(const DataPage *page,
4242page_data -> pd_lower <=page_data -> pd_upper &&
4343page_data -> pd_upper <=page_data -> pd_special &&
4444page_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,
6564pgFile * file ,const XLogRecPtr * lsn )
6665{
6766char to_path [MAXPGPATH ];
68- FILE * in ;
69- FILE * out ;
67+ FILE * in ;
68+ FILE * out ;
7069BackupPageHeader header ;
71- DataPage page ;/* used as read buffer */
70+ DataPage page ;/* used as read buffer */
7271BlockNumber blknum = 0 ;
7372size_t read_len = 0 ;
7473pg_crc32 crc ;
@@ -131,30 +130,61 @@ backup_data_file(const char *from_root, const char *to_root,
131130int upper_offset ;
132131int upper_length ;
133132int try_checksum = 100 ;
133+ bool stop_backup = false;
134134
135135header .block = blknum ;
136136
137137while (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 */
143144if (!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+ gotoend_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 -- ;
158188if (current .checksum_version &&
159189pg_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
178206file -> read_size += read_len ;
179207
208+ if (stop_backup )
209+ break ;
180210
181211upper_offset = header .hole_offset + header .hole_length ;
182212upper_length = BLCKSZ - upper_offset ;
@@ -213,6 +243,7 @@ backup_data_file(const char *from_root, const char *to_root,
213243int upper_length ;
214244int ret ;
215245int try_checksum = 100 ;
246+ bool stop_backup = false;
216247
217248offset = blknum * BLCKSZ ;
218249while (try_checksum )
@@ -229,25 +260,51 @@ backup_data_file(const char *from_root, const char *to_root,
229260
230261header .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 */
236269if (!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+ gotoend_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
252309if (current .checksum_version &&
253310pg_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-
270323file -> read_size += read_len ;
324+
325+ if (stop_backup )
326+ break ;
327+
328+ end_checks2 :
271329
272330upper_offset = header .hole_offset + header .hole_length ;
273331upper_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 */
441499if (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+ gotoskip_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