@@ -152,10 +152,54 @@ doInflate(z_stream *zp, size_t in_size, size_t out_size,void *inbuf,
152
152
}
153
153
#endif
154
154
155
+ #define PG_PAGE_LAYOUT_VERSION_v80 2 /* 8.0 */
156
+ #define PG_PAGE_LAYOUT_VERSION_v81 3 /* 8.1 - 8.2 */
157
+ #define PG_PAGE_LAYOUT_VERSION_v83 4 /* 8.3 - */
158
+
159
+ /* 80000 <= PG_VERSION_NUM < 80300 */
160
+ typedef struct PageHeaderData_v80
161
+ {
162
+ XLogRecPtr pd_lsn ;
163
+ TimeLineID pd_tli ;
164
+ LocationIndex pd_lower ;
165
+ LocationIndex pd_upper ;
166
+ LocationIndex pd_special ;
167
+ uint16 pd_pagesize_version ;
168
+ ItemIdData pd_linp [1 ];
169
+ } PageHeaderData_v80 ;
170
+
171
+ #define PageGetPageSize_v80 (page ) \
172
+ ((Size) ((page)->pd_pagesize_version & (uint16) 0xFF00))
173
+ #define PageGetPageLayoutVersion_v80 (page ) \
174
+ ((page)->pd_pagesize_version & 0x00FF)
175
+ #define SizeOfPageHeaderData_v80 (offsetof(PageHeaderData_v80, pd_linp))
176
+
177
+ /* 80300 <= PG_VERSION_NUM */
178
+ typedef struct PageHeaderData_v83
179
+ {
180
+ XLogRecPtr pd_lsn ;
181
+ uint16 pd_tli ;
182
+ uint16 pd_flags ;
183
+ LocationIndex pd_lower ;
184
+ LocationIndex pd_upper ;
185
+ LocationIndex pd_special ;
186
+ uint16 pd_pagesize_version ;
187
+ TransactionId pd_prune_xid ;
188
+ ItemIdData pd_linp [1 ];
189
+ } PageHeaderData_v83 ;
190
+
191
+ #define PageGetPageSize_v83 (page ) \
192
+ ((Size) ((page)->pd_pagesize_version & (uint16) 0xFF00))
193
+ #define PageGetPageLayoutVersion_v83 (page ) \
194
+ ((page)->pd_pagesize_version & 0x00FF)
195
+ #define SizeOfPageHeaderData_v83 (offsetof(PageHeaderData_v83, pd_linp))
196
+ #define PD_VALID_FLAG_BITS_v83 0x0007
197
+
155
198
typedef union DataPage
156
199
{
157
- PageHeaderData header ;
158
- char data [BLCKSZ ];
200
+ PageHeaderData_v80 v80 ; /* 8.0 - 8.2 */
201
+ PageHeaderData_v83 v83 ; /* 8.3 - */
202
+ char data [BLCKSZ ];
159
203
} DataPage ;
160
204
161
205
typedef struct BackupPageHeader
@@ -166,32 +210,51 @@ typedef struct BackupPageHeader
166
210
} BackupPageHeader ;
167
211
168
212
static bool
169
- is_valid_header (const PageHeader page )
213
+ parse_page (const DataPage * page , int server_version ,
214
+ XLogRecPtr * lsn , uint16 * offset , uint16 * length )
170
215
{
171
- const char * pagebytes ;
172
- int i ;
216
+ uint16 page_layout_version ;
217
+
218
+ /* Determine page layout version */
219
+ if (server_version < 80100 )
220
+ page_layout_version = PG_PAGE_LAYOUT_VERSION_v80 ;
221
+ else if (server_version < 80300 )
222
+ page_layout_version = PG_PAGE_LAYOUT_VERSION_v81 ;
223
+ else
224
+ page_layout_version = PG_PAGE_LAYOUT_VERSION_v83 ;
173
225
174
226
/* Check normal case */
175
- if (PageGetPageSize (page ) == BLCKSZ &&
176
- PageGetPageLayoutVersion (page ) == PG_PAGE_LAYOUT_VERSION &&
177
- #if PG_VERSION_NUM >= 80300
178
- (page -> pd_flags & ~PD_VALID_FLAG_BITS ) == 0 &&
179
- #endif
180
- page -> pd_lower >= SizeOfPageHeaderData &&
181
- page -> pd_lower <= page -> pd_upper &&
182
- page -> pd_upper <= page -> pd_special &&
183
- page -> pd_special <= BLCKSZ &&
184
- page -> pd_special == MAXALIGN (page -> pd_special ))
185
- return true;
186
-
187
- /* Check all-zeroes case */
188
- pagebytes = (char * ) page ;
189
- for (i = 0 ; i < BLCKSZ ; i ++ )
227
+ if (server_version < 80300 )
190
228
{
191
- if (pagebytes [i ] != 0 )
192
- return false;
229
+ const PageHeaderData_v80 * v80 = & page -> v80 ;
230
+
231
+ if (PageGetPageSize_v80 (v80 ) == BLCKSZ &&
232
+ PageGetPageLayoutVersion_v80 (v80 ) == page_layout_version &&
233
+ v80 -> pd_lower >= SizeOfPageHeaderData_v80 &&
234
+ v80 -> pd_lower <= v80 -> pd_upper &&
235
+ v80 -> pd_upper <= v80 -> pd_special &&
236
+ v80 -> pd_special <= BLCKSZ &&
237
+ v80 -> pd_special == MAXALIGN (v80 -> pd_special ) &&
238
+ !XLogRecPtrIsInvalid (* lsn = v80 -> pd_lsn ))
239
+ return true;
193
240
}
194
- return true;
241
+ else
242
+ {
243
+ const PageHeaderData_v83 * v83 = & page -> v83 ;
244
+
245
+ if (PageGetPageSize_v83 (v83 ) == BLCKSZ &&
246
+ PageGetPageLayoutVersion_v83 (v83 ) == page_layout_version &&
247
+ (v83 -> pd_flags & ~PD_VALID_FLAG_BITS_v83 ) == 0 &&
248
+ v83 -> pd_lower >= SizeOfPageHeaderData_v83 &&
249
+ v83 -> pd_lower <= v83 -> pd_upper &&
250
+ v83 -> pd_upper <= v83 -> pd_special &&
251
+ v83 -> pd_special <= BLCKSZ &&
252
+ v83 -> pd_special == MAXALIGN (v83 -> pd_special ) &&
253
+ !XLogRecPtrIsInvalid (* lsn = v83 -> pd_lsn ))
254
+ return true;
255
+ }
256
+
257
+ return false;
195
258
}
196
259
197
260
/*
@@ -213,6 +276,7 @@ backup_data_file(const char *from_root, const char *to_root,
213
276
size_t read_len ;
214
277
int errno_tmp ;
215
278
pg_crc32 crc ;
279
+ int server_version ;
216
280
#ifdef HAVE_LIBZ
217
281
z_stream z ;
218
282
char outbuf [zlibOutSize ];
@@ -268,11 +332,15 @@ backup_data_file(const char *from_root, const char *to_root,
268
332
}
269
333
#endif
270
334
335
+ /* confirm server version */
336
+ server_version = get_server_version ();
337
+
271
338
/* read each page and write the page excluding hole */
272
339
for (blknum = 0 ;
273
340
(read_len = fread (& page , 1 , sizeof (page ), in )) == sizeof (page );
274
341
++ blknum )
275
342
{
343
+ XLogRecPtr page_lsn ;
276
344
int upper_offset ;
277
345
int upper_length ;
278
346
@@ -282,8 +350,8 @@ backup_data_file(const char *from_root, const char *to_root,
282
350
* If a invalid data page was found, fallback to simple copy to ensure
283
351
* all pages in the file don't have BackupPageHeader.
284
352
*/
285
- if (!is_valid_header (& page . header ) ||
286
- ! XLogRecPtrIsInvalid ( PageGetLSN ( & page . header ) ))
353
+ if (!parse_page (& page , server_version , & page_lsn ,
354
+ & header . hole_offset , & header . hole_length ))
287
355
{
288
356
elog (LOG , "%s fall back to simple copy" , file -> path );
289
357
fclose (in );
@@ -297,13 +365,9 @@ backup_data_file(const char *from_root, const char *to_root,
297
365
file -> read_size += read_len ;
298
366
299
367
/* if the page has not been modified since last backup, skip it */
300
- if (lsn && !XLogRecPtrIsInvalid (PageGetLSN (& page .header )) &&
301
- XLByteLT (PageGetLSN (& page .header ), * lsn ))
368
+ if (lsn && !XLogRecPtrIsInvalid (page_lsn ) && XLByteLT (page_lsn , * lsn ))
302
369
continue ;
303
370
304
- header .hole_offset = page .header .pd_lower ;
305
- header .hole_length = page .header .pd_upper - page .header .pd_lower ;
306
-
307
371
upper_offset = header .hole_offset + header .hole_length ;
308
372
upper_length = BLCKSZ - upper_offset ;
309
373
0 commit comments