@@ -152,10 +152,54 @@ doInflate(z_stream *zp, size_t in_size, size_t out_size,void *inbuf,
152152}
153153#endif
154154
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+
155198typedef union DataPage
156199{
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 ];
159203}DataPage ;
160204
161205typedef struct BackupPageHeader
@@ -166,32 +210,51 @@ typedef struct BackupPageHeader
166210}BackupPageHeader ;
167211
168212static bool
169- is_valid_header (const PageHeader page )
213+ parse_page (const DataPage * page ,int server_version ,
214+ XLogRecPtr * lsn ,uint16 * offset ,uint16 * length )
170215{
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 ;
173225
174226/* 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 )
190228{
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;
193240}
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;
195258}
196259
197260/*
@@ -213,6 +276,7 @@ backup_data_file(const char *from_root, const char *to_root,
213276size_t read_len ;
214277int errno_tmp ;
215278pg_crc32 crc ;
279+ int server_version ;
216280#ifdef HAVE_LIBZ
217281z_stream z ;
218282char outbuf [zlibOutSize ];
@@ -268,11 +332,15 @@ backup_data_file(const char *from_root, const char *to_root,
268332}
269333#endif
270334
335+ /* confirm server version */
336+ server_version = get_server_version ();
337+
271338/* read each page and write the page excluding hole */
272339for (blknum = 0 ;
273340 (read_len = fread (& page ,1 ,sizeof (page ),in ))== sizeof (page );
274341++ blknum )
275342{
343+ XLogRecPtr page_lsn ;
276344int upper_offset ;
277345int upper_length ;
278346
@@ -282,8 +350,8 @@ backup_data_file(const char *from_root, const char *to_root,
282350 * If a invalid data page was found, fallback to simple copy to ensure
283351 * all pages in the file don't have BackupPageHeader.
284352 */
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 ))
287355{
288356elog (LOG ,"%s fall back to simple copy" ,file -> path );
289357fclose (in );
@@ -297,13 +365,9 @@ backup_data_file(const char *from_root, const char *to_root,
297365file -> read_size += read_len ;
298366
299367/* 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 ))
302369continue ;
303370
304- header .hole_offset = page .header .pd_lower ;
305- header .hole_length = page .header .pd_upper - page .header .pd_lower ;
306-
307371upper_offset = header .hole_offset + header .hole_length ;
308372upper_length = BLCKSZ - upper_offset ;
309373