@@ -45,7 +45,7 @@ static void *EncryptionCryptCtx = NULL;
4545static InternalKey EncryptionKey =
4646{
4747 .type = MAP_ENTRY_EMPTY ,
48- .start_lsn = InvalidXLogRecPtr ,
48+ .wal_start = {. tli = 0 , . lsn = InvalidXLogRecPtr } ,
4949};
5050
5151/*
@@ -66,7 +66,13 @@ static InternalKey EncryptionKey =
6666typedef struct EncryptionStateData
6767{
6868 char db_map_path [MAXPGPATH ];
69- pg_atomic_uint64 enc_key_lsn ; /* to sync with readers */
69+
70+ /*
71+ * To sync with readers. We sync on LSN only and TLI here just to
72+ * communicate its value to readers.
73+ */
74+ pg_atomic_uint32 enc_key_tli ;
75+ pg_atomic_uint64 enc_key_lsn ;
7076} EncryptionStateData ;
7177
7278static EncryptionStateData * EncryptionState = NULL ;
@@ -80,11 +86,18 @@ TDEXLogGetEncKeyLsn()
8086}
8187
8288static void
83- TDEXLogSetEncKeyLsn ( XLogRecPtr start_lsn )
89+ TDEXLogSetEncKeyLocation ( WALLocation loc )
8490{
85- pg_atomic_write_u64 (& EncryptionState -> enc_key_lsn , start_lsn );
91+ pg_atomic_init_u32 (& EncryptionState -> enc_key_tli , loc .tli );
92+ pg_atomic_write_u64 (& EncryptionState -> enc_key_lsn , loc .lsn );
8693}
8794
95+ static TimeLineID
96+ TDEXLogGetEncKeyTli ()
97+ {
98+ return (TimeLineID ) pg_atomic_read_u32 (& EncryptionState -> enc_key_tli );
99+ }
100+
88101static Size TDEXLogEncryptBuffSize (void );
89102
90103static int XLOGChooseNumBuffers (void );
@@ -159,6 +172,7 @@ TDEXLogShmemInit(void)
159172 }
160173
161174 pg_atomic_init_u64 (& EncryptionState -> enc_key_lsn , 0 );
175+ pg_atomic_init_u32 (& EncryptionState -> enc_key_tli , 0 );
162176
163177 elog (DEBUG1 , "pg_tde: initialized encryption buffer %lu bytes" , TDEXLogEncryptStateSize ());
164178}
@@ -168,6 +182,7 @@ TDEXLogShmemInit(void)
168182typedef struct EncryptionStateData
169183{
170184 char db_map_path [MAXPGPATH ];
185+ XLogRecPtr enc_key_tli ; /* to sync with reader */
171186 XLogRecPtr enc_key_lsn ; /* to sync with reader */
172187} EncryptionStateData ;
173188
@@ -184,9 +199,16 @@ TDEXLogGetEncKeyLsn()
184199}
185200
186201static void
187- TDEXLogSetEncKeyLsn (XLogRecPtr start_lsn )
202+ TDEXLogSetEncKeyLocation (WALLocation loc )
203+ {
204+ EncryptionState -> enc_key_tli = loc .tli ;
205+ EncryptionState -> enc_key_lsn = loc .lsn ;
206+ }
207+
208+ static TimeLineID
209+ TDEXLogGetEncKeyTli ()
188210{
189- EncryptionState -> enc_key_lsn = EncryptionKey . start_lsn ;
211+ return ( TimeLineID ) EncryptionState -> enc_key_tli ;
190212}
191213
192214#endif /* FRONTEND */
@@ -197,6 +219,7 @@ TDEXLogSmgrInit()
197219 SetXLogSmgr (& tde_xlog_smgr );
198220}
199221
222+ /* On backend it should be called only during the startup */
200223void
201224TDEXLogSmgrInitWrite (bool encrypt_xlog )
202225{
@@ -220,7 +243,7 @@ TDEXLogSmgrInitWrite(bool encrypt_xlog)
220243 else if (key )
221244 {
222245 EncryptionKey = * key ;
223- TDEXLogSetEncKeyLsn (EncryptionKey .start_lsn );
246+ TDEXLogSetEncKeyLocation (EncryptionKey .wal_start );
224247 }
225248
226249 if (key )
@@ -237,7 +260,7 @@ TDEXLogSmgrInitWriteReuseKey()
237260 if (key )
238261 {
239262 EncryptionKey = * key ;
240- TDEXLogSetEncKeyLsn (EncryptionKey .start_lsn );
263+ TDEXLogSetEncKeyLocation (EncryptionKey .wal_start );
241264 pfree (key );
242265 }
243266
@@ -260,8 +283,8 @@ TDEXLogWriteEncryptedPages(int fd, const void *buf, size_t count, off_t offset,
260283#endif
261284
262285#ifdef TDE_XLOG_DEBUG
263- elog (DEBUG1 , "write encrypted WAL, size: %lu, offset: %ld [%lX], seg: %X/%X, key_start_lsn: %X/%X" ,
264- count , offset , offset , LSN_FORMAT_ARGS (segno ), LSN_FORMAT_ARGS (key -> start_lsn ));
286+ elog (DEBUG1 , "write encrypted WAL, size: %lu, offset: %ld [%lX], seg: %X/%X, key_start_lsn: %u_% X/%X" ,
287+ count , offset , offset , LSN_FORMAT_ARGS (segno ), key -> wal_start . tli , LSN_FORMAT_ARGS (key -> wal_start . lsn ));
265288#endif
266289
267290 CalcXLogPageIVPrefix (tli , segno , key -> base_iv , iv_prefix );
@@ -287,9 +310,10 @@ tdeheap_xlog_seg_write(int fd, const void *buf, size_t count, off_t offset,
287310
288311 XLogSegNoOffsetToRecPtr (segno , offset , segSize , lsn );
289312
290- pg_tde_wal_last_key_set_lsn (lsn , EncryptionState -> db_map_path );
291- EncryptionKey .start_lsn = lsn ;
292- TDEXLogSetEncKeyLsn (lsn );
313+ pg_tde_wal_last_key_set_lsn (lsn , tli , EncryptionState -> db_map_path );
314+ EncryptionKey .wal_start .tli = tli ;
315+ EncryptionKey .wal_start .lsn = lsn ;
316+ TDEXLogSetEncKeyLocation (EncryptionKey .wal_start );
293317 }
294318
295319 if (EncryptionKey .type == TDE_KEY_TYPE_WAL_ENCRYPTED )
@@ -308,12 +332,12 @@ tdeheap_xlog_seg_read(int fd, void *buf, size_t count, off_t offset,
308332 ssize_t readsz ;
309333 WALKeyCacheRec * keys = pg_tde_get_wal_cache_keys ();
310334 XLogRecPtr write_key_lsn ;
311- XLogRecPtr data_start ;
312- XLogRecPtr data_end ;
335+ WALLocation data_start = {. tli = tli } ;
336+ WALLocation data_end = {. tli = tli } ;
313337
314338#ifdef TDE_XLOG_DEBUG
315- elog (DEBUG1 , "read from a WAL segment, size: %lu offset: %ld [%lX], seg: %X/%X" ,
316- count , offset , offset , LSN_FORMAT_ARGS (segno ));
339+ elog (DEBUG1 , "read from a WAL segment, size: %lu offset: %ld [%lX], seg: %u_% X/%X" ,
340+ count , offset , offset , tli , LSN_FORMAT_ARGS (segno ));
317341#endif
318342
319343 readsz = pg_pread (fd , buf , count , offset );
@@ -323,30 +347,32 @@ tdeheap_xlog_seg_read(int fd, void *buf, size_t count, off_t offset,
323347
324348 if (!keys )
325349 {
350+ WALLocation start = {.tli = 1 , .lsn = 0 };
326351 /* cache is empty, try to read keys from disk */
327- keys = pg_tde_fetch_wal_keys (InvalidXLogRecPtr );
352+ keys = pg_tde_fetch_wal_keys (start );
328353 }
329354
330355 write_key_lsn = TDEXLogGetEncKeyLsn ();
331356
332357 if (!XLogRecPtrIsInvalid (write_key_lsn ))
333358 {
334359 WALKeyCacheRec * last_key = pg_tde_get_last_wal_key ();
360+ WALLocation write_loc = {.tli = TDEXLogGetEncKeyTli (), .lsn = write_key_lsn };
335361
336362 Assert (last_key );
337363
338364 /* write has generated a new key, need to fetch it */
339- if (last_key -> start_lsn < write_key_lsn )
365+ if (wal_location_cmp ( last_key -> start , write_loc ) < 0 )
340366 {
341- pg_tde_fetch_wal_keys (write_key_lsn );
367+ pg_tde_fetch_wal_keys (write_loc );
342368
343369 /* in case cache was empty before */
344370 keys = pg_tde_get_wal_cache_keys ();
345371 }
346372 }
347373
348- XLogSegNoOffsetToRecPtr (segno , offset , segSize , data_start );
349- XLogSegNoOffsetToRecPtr (segno , offset + readsz , segSize , data_end );
374+ XLogSegNoOffsetToRecPtr (segno , offset , segSize , data_start . lsn );
375+ XLogSegNoOffsetToRecPtr (segno , offset + readsz , segSize , data_end . lsn );
350376
351377 /*
352378 * TODO: this is higly ineffective. We should get rid of linked list and
@@ -355,24 +381,25 @@ tdeheap_xlog_seg_read(int fd, void *buf, size_t count, off_t offset,
355381 for (WALKeyCacheRec * curr_key = keys ; curr_key != NULL ; curr_key = curr_key -> next )
356382 {
357383#ifdef TDE_XLOG_DEBUG
358- elog (DEBUG1 , "WAL key %X/%X- %X/%X, encrypted: %s" ,
359- LSN_FORMAT_ARGS (curr_key -> start_lsn ),
360- LSN_FORMAT_ARGS (curr_key -> end_lsn ),
384+ elog (DEBUG1 , "WAL key %u_% X/%X - %u_ %X/%X, encrypted: %s" ,
385+ curr_key -> start . tli , LSN_FORMAT_ARGS (curr_key -> start . lsn ),
386+ curr_key -> end . tli , LSN_FORMAT_ARGS (curr_key -> end . lsn ),
361387 curr_key -> key .type == TDE_KEY_TYPE_WAL_ENCRYPTED ? "yes" : "no" );
362388#endif
363389
364- if (curr_key -> key .start_lsn != InvalidXLogRecPtr &&
390+ if (wal_location_valid ( curr_key -> key .wal_start ) &&
365391 curr_key -> key .type == TDE_KEY_TYPE_WAL_ENCRYPTED )
366392 {
367393 /*
368394 * Check if the key's range overlaps with the buffer's and decypt
369395 * the part that does.
370396 */
371- if (data_start < curr_key -> end_lsn && data_end > curr_key -> start_lsn )
397+
398+ if (wal_location_cmp (data_start , curr_key -> end ) < 0 && wal_location_cmp (data_end , curr_key -> start ) > 0 )
372399 {
373400 char iv_prefix [16 ];
374- off_t dec_off = XLogSegmentOffset (Max (data_start , curr_key -> start_lsn ), segSize );
375- off_t dec_end = XLogSegmentOffset (Min (data_end , curr_key -> end_lsn ), segSize );
401+ off_t dec_off = XLogSegmentOffset (Max (data_start . lsn , curr_key -> start . lsn ), segSize );
402+ off_t dec_end = XLogSegmentOffset (Min (data_end . lsn , curr_key -> end . lsn ), segSize );
376403 size_t dec_sz ;
377404 char * dec_buf = (char * ) buf + (dec_off - offset );
378405
@@ -389,8 +416,8 @@ tdeheap_xlog_seg_read(int fd, void *buf, size_t count, off_t offset,
389416 dec_sz = dec_end - dec_off ;
390417
391418#ifdef TDE_XLOG_DEBUG
392- elog (DEBUG1 , "decrypt WAL, dec_off: %lu [buff_off %lu], sz: %lu | key %X/%X" ,
393- dec_off , dec_off - offset , dec_sz , LSN_FORMAT_ARGS ( curr_key -> key -> start_lsn ));
419+ elog (DEBUG1 , "decrypt WAL, dec_off: %lu [buff_off %lu], sz: %lu | key %u_% X/%X" ,
420+ dec_off , dec_off - offset , dec_sz , curr_key -> key . wal_start . tli , LSN_FORMAT_ARGS ( curr_key -> key . wal_start . lsn ));
394421#endif
395422 pg_tde_stream_crypt (iv_prefix , dec_off , dec_buf , dec_sz , dec_buf ,
396423 & curr_key -> key , & curr_key -> crypt_ctx );
0 commit comments