@@ -42,8 +42,7 @@ parse_page(const DataPage *page,
42
42
page_data -> pd_lower <=page_data -> pd_upper &&
43
43
page_data -> pd_upper <=page_data -> pd_special &&
44
44
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 ))
47
46
{
48
47
* offset = page_data -> pd_lower ;
49
48
* length = page_data -> pd_upper - page_data -> pd_lower ;
@@ -65,10 +64,10 @@ backup_data_file(const char *from_root, const char *to_root,
65
64
pgFile * file ,const XLogRecPtr * lsn )
66
65
{
67
66
char to_path [MAXPGPATH ];
68
- FILE * in ;
69
- FILE * out ;
67
+ FILE * in ;
68
+ FILE * out ;
70
69
BackupPageHeader header ;
71
- DataPage page ;/* used as read buffer */
70
+ DataPage page ;/* used as read buffer */
72
71
BlockNumber blknum = 0 ;
73
72
size_t read_len = 0 ;
74
73
pg_crc32 crc ;
@@ -131,30 +130,61 @@ backup_data_file(const char *from_root, const char *to_root,
131
130
int upper_offset ;
132
131
int upper_length ;
133
132
int try_checksum = 100 ;
133
+ bool stop_backup = false;
134
134
135
135
header .block = blknum ;
136
136
137
137
while (try_checksum )
138
138
{
139
+ try_checksum -- ;
139
140
/*
140
141
* If an invalid data page was found, fallback to simple copy to ensure
141
142
* all pages in the file don't have BackupPageHeader.
142
143
*/
143
144
if (!parse_page (& page ,& page_lsn ,
144
145
& header .hole_offset ,& header .hole_length ))
145
146
{
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 ;
152
149
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
+ }
156
187
157
- try_checksum -- ;
158
188
if (current .checksum_version &&
159
189
pg_checksum_page (page .data ,header .block )!= ((PageHeader )page .data )-> pd_checksum )
160
190
{
@@ -171,12 +201,12 @@ backup_data_file(const char *from_root, const char *to_root,
171
201
}
172
202
}
173
203
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 :
177
205
178
206
file -> read_size += read_len ;
179
207
208
+ if (stop_backup )
209
+ break ;
180
210
181
211
upper_offset = header .hole_offset + header .hole_length ;
182
212
upper_length = BLCKSZ - upper_offset ;
@@ -213,6 +243,7 @@ backup_data_file(const char *from_root, const char *to_root,
213
243
int upper_length ;
214
244
int ret ;
215
245
int try_checksum = 100 ;
246
+ bool stop_backup = false;
216
247
217
248
offset = blknum * BLCKSZ ;
218
249
while (try_checksum )
@@ -229,25 +260,51 @@ backup_data_file(const char *from_root, const char *to_root,
229
260
230
261
header .block = blknum ;
231
262
263
+ try_checksum -- ;
264
+
232
265
/*
233
266
* If an invalid data page was found, fallback to simple copy to ensure
234
267
* all pages in the file don't have BackupPageHeader.
235
268
*/
236
269
if (!parse_page (& page ,& page_lsn ,
237
270
& header .hole_offset ,& header .hole_length ))
238
271
{
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 ;
245
274
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 ++ );
249
276
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
+ }
251
308
252
309
if (current .checksum_version &&
253
310
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,
263
320
}
264
321
}
265
322
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
-
270
323
file -> read_size += read_len ;
324
+
325
+ if (stop_backup )
326
+ break ;
327
+
328
+ end_checks2 :
271
329
272
330
upper_offset = header .hole_offset + header .hole_length ;
273
331
upper_length = BLCKSZ - upper_offset ;
@@ -439,7 +497,19 @@ restore_data_file(const char *from_root,
439
497
440
498
/* update checksum because we are not save whole */
441
499
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
+ gotoskip_checksum ;
508
+ }
442
509
((PageHeader )page .data )-> pd_checksum = pg_checksum_page (page .data ,header .block );
510
+ }
511
+
512
+ skip_checksum :
443
513
444
514
/*
445
515
* Seek and write the restored page. Backup might have holes in