@@ -67,6 +67,7 @@ typedef struct EncryptionStateData
67
67
{
68
68
char db_map_path [MAXPGPATH ];
69
69
pg_atomic_uint64 enc_key_lsn ; /* to sync with readers */
70
+ pg_atomic_uint64 enc_key_tli ; /* to sync with readers */
70
71
} EncryptionStateData ;
71
72
72
73
static EncryptionStateData * EncryptionState = NULL ;
@@ -85,6 +86,18 @@ TDEXLogSetEncKeyLsn(XLogRecPtr start_lsn)
85
86
pg_atomic_write_u64 (& EncryptionState -> enc_key_lsn , start_lsn );
86
87
}
87
88
89
+ static TimeLineID
90
+ TDEXLogGetEncKeyTli ()
91
+ {
92
+ return (TimeLineID ) pg_atomic_read_u64 (& EncryptionState -> enc_key_tli );
93
+ }
94
+
95
+ static void
96
+ TDEXLogSetEncKeyTli (TimeLineID tli )
97
+ {
98
+ pg_atomic_write_u64 (& EncryptionState -> enc_key_tli , tli );
99
+ }
100
+
88
101
static Size TDEXLogEncryptBuffSize (void );
89
102
90
103
static int XLOGChooseNumBuffers (void );
@@ -159,6 +172,7 @@ TDEXLogShmemInit(void)
159
172
}
160
173
161
174
pg_atomic_init_u64 (& EncryptionState -> enc_key_lsn , 0 );
175
+ pg_atomic_init_u64 (& EncryptionState -> enc_key_tli , 0 );
162
176
163
177
elog (DEBUG1 , "pg_tde: initialized encryption buffer %lu bytes" , TDEXLogEncryptStateSize ());
164
178
}
@@ -169,6 +183,7 @@ typedef struct EncryptionStateData
169
183
{
170
184
char db_map_path [MAXPGPATH ];
171
185
XLogRecPtr enc_key_lsn ; /* to sync with reader */
186
+ XLogRecPtr enc_key_tli ; /* to sync with reader */
172
187
} EncryptionStateData ;
173
188
174
189
static EncryptionStateData EncryptionStateD = {0 };
@@ -186,7 +201,19 @@ TDEXLogGetEncKeyLsn()
186
201
static void
187
202
TDEXLogSetEncKeyLsn (XLogRecPtr start_lsn )
188
203
{
189
- EncryptionState -> enc_key_lsn = EncryptionKey .start_lsn ;
204
+ EncryptionState -> enc_key_lsn = start_lsn ;
205
+ }
206
+
207
+ static TimeLineID
208
+ TDEXLogGetEncKeyTli ()
209
+ {
210
+ return (TimeLineID ) EncryptionState -> enc_key_tli ;
211
+ }
212
+
213
+ static void
214
+ TDEXLogSetEncKeyTli (TimeLineID tli )
215
+ {
216
+ EncryptionState -> enc_key_lsn = tli ;
190
217
}
191
218
192
219
#endif /* FRONTEND */
@@ -221,6 +248,7 @@ TDEXLogSmgrInitWrite(bool encrypt_xlog)
221
248
{
222
249
EncryptionKey = * key ;
223
250
TDEXLogSetEncKeyLsn (EncryptionKey .start_lsn );
251
+ TDEXLogSetEncKeyTli (EncryptionKey .tli );
224
252
}
225
253
226
254
if (key )
@@ -245,8 +273,8 @@ TDEXLogWriteEncryptedPages(int fd, const void *buf, size_t count, off_t offset,
245
273
#endif
246
274
247
275
#ifdef TDE_XLOG_DEBUG
248
- elog (DEBUG1 , "write encrypted WAL, size: %lu, offset: %ld [%lX], seg: %X/%X, key_start_lsn: %X/%X" ,
249
- count , offset , offset , LSN_FORMAT_ARGS (segno ), LSN_FORMAT_ARGS (key -> start_lsn ));
276
+ elog (DEBUG1 , "write encrypted WAL, size: %lu, offset: %ld [%lX] tli %u , seg: %X/%X, key_start: %u_ %X/%X" ,
277
+ count , offset , offset , tli , LSN_FORMAT_ARGS (segno ), key -> tli , LSN_FORMAT_ARGS (key -> start_lsn ));
250
278
#endif
251
279
252
280
CalcXLogPageIVPrefix (tli , segno , key -> base_iv , iv_prefix );
@@ -272,9 +300,11 @@ tdeheap_xlog_seg_write(int fd, const void *buf, size_t count, off_t offset,
272
300
273
301
XLogSegNoOffsetToRecPtr (segno , offset , segSize , lsn );
274
302
275
- pg_tde_wal_last_key_set_lsn (lsn , EncryptionState -> db_map_path );
303
+ pg_tde_wal_last_key_set_lsn (lsn , tli , EncryptionState -> db_map_path );
276
304
EncryptionKey .start_lsn = lsn ;
305
+ EncryptionKey .tli = tli ;
277
306
TDEXLogSetEncKeyLsn (lsn );
307
+ TDEXLogSetEncKeyTli (tli );
278
308
}
279
309
280
310
if (EncryptionKey .type == TDE_KEY_TYPE_WAL_ENCRYPTED )
@@ -293,8 +323,8 @@ tdeheap_xlog_seg_read(int fd, void *buf, size_t count, off_t offset,
293
323
ssize_t readsz ;
294
324
295
325
#ifdef TDE_XLOG_DEBUG
296
- elog (DEBUG1 , "read from a WAL segment, size: %lu offset: %ld [%lX], seg: %X/%X" ,
297
- count , offset , offset , LSN_FORMAT_ARGS (segno ));
326
+ elog (DEBUG1 , "read from a WAL segment, size: %lu offset: %ld [%lX], tli: %u, seg: %X/%X" ,
327
+ count , offset , offset , tli , LSN_FORMAT_ARGS (segno ));
298
328
#endif
299
329
300
330
readsz = pg_pread (fd , buf , count , offset );
@@ -318,6 +348,8 @@ TDEXLogCryptBuffer(void *buf, size_t count, off_t offset,
318
348
XLogRecPtr write_key_lsn ;
319
349
XLogRecPtr data_start ;
320
350
XLogRecPtr data_end ;
351
+ KeyTliLsn data_start_t = {.tli = tli };
352
+ KeyTliLsn data_end_t = {.tli = tli };
321
353
322
354
if (!keys )
323
355
{
@@ -330,11 +362,14 @@ TDEXLogCryptBuffer(void *buf, size_t count, off_t offset,
330
362
if (!XLogRecPtrIsInvalid (write_key_lsn ))
331
363
{
332
364
WALKeyCacheRec * last_key = pg_tde_get_last_wal_key ();
365
+ KeyTliLsn last_key_time = {.tli = last_key -> start_tli , .lsn = last_key -> start_lsn };
366
+ KeyTliLsn write_key_time = {.tli = TDEXLogGetEncKeyTli (), .lsn = write_key_lsn };
333
367
334
368
Assert (last_key );
335
369
336
370
/* write has generated a new key, need to fetch it */
337
- if (last_key -> start_lsn < write_key_lsn )
371
+ if (key_tli_lsn_cmp (last_key_time , write_key_time ) == -1 )
372
+ // if (last_key->start_lsn < write_key_lsn)
338
373
{
339
374
pg_tde_fetch_wal_keys (write_key_lsn );
340
375
@@ -346,16 +381,22 @@ TDEXLogCryptBuffer(void *buf, size_t count, off_t offset,
346
381
XLogSegNoOffsetToRecPtr (segno , offset , segSize , data_start );
347
382
XLogSegNoOffsetToRecPtr (segno , offset + count , segSize , data_end );
348
383
384
+ data_start_t .lsn = data_start ;
385
+ data_end_t .lsn = data_end ;
386
+
349
387
/*
350
388
* TODO: this is higly ineffective. We should get rid of linked list and
351
389
* search from the last key as this is what the walsender is useing.
352
390
*/
353
391
for (WALKeyCacheRec * curr_key = keys ; curr_key != NULL ; curr_key = curr_key -> next )
354
392
{
393
+ KeyTliLsn key_start_t = {.lsn = curr_key -> start_lsn , .tli = curr_key -> start_tli };
394
+ KeyTliLsn key_end_t = {.lsn = curr_key -> end_lsn , .tli = curr_key -> end_tli };
395
+
355
396
#ifdef TDE_XLOG_DEBUG
356
- elog (DEBUG1 , "WAL key %X/%X- %X/%X, encrypted: %s" ,
357
- LSN_FORMAT_ARGS (curr_key -> start_lsn ),
358
- LSN_FORMAT_ARGS (curr_key -> end_lsn ),
397
+ elog (DEBUG1 , "WAL key %u_% X/%X - %u_ %X/%X, encrypted: %s" ,
398
+ curr_key -> start_tli , LSN_FORMAT_ARGS (curr_key -> start_lsn ),
399
+ curr_key -> end_tli , LSN_FORMAT_ARGS (curr_key -> end_lsn ),
359
400
curr_key -> key .type == TDE_KEY_TYPE_WAL_ENCRYPTED ? "yes" : "no" );
360
401
#endif
361
402
@@ -366,7 +407,7 @@ TDEXLogCryptBuffer(void *buf, size_t count, off_t offset,
366
407
* Check if the key's range overlaps with the buffer's and decypt
367
408
* the part that does.
368
409
*/
369
- if (data_start < curr_key -> end_lsn && data_end > curr_key -> start_lsn )
410
+ if (key_tli_lsn_cmp ( data_start_t , key_end_t ) == -1 && key_tli_lsn_cmp ( data_end_t , key_start_t ) == 1 )
370
411
{
371
412
char iv_prefix [16 ];
372
413
off_t dec_off = XLogSegmentOffset (Max (data_start , curr_key -> start_lsn ), segSize );
@@ -387,8 +428,8 @@ TDEXLogCryptBuffer(void *buf, size_t count, off_t offset,
387
428
dec_sz = dec_end - dec_off ;
388
429
389
430
#ifdef TDE_XLOG_DEBUG
390
- elog (DEBUG1 , "decrypt WAL, dec_off: %lu [buff_off %lu], sz: %lu | key %X/%X" ,
391
- dec_off , dec_off - offset , dec_sz , LSN_FORMAT_ARGS ( curr_key -> key -> start_lsn ));
431
+ elog (DEBUG1 , "decrypt WAL, dec_off: %lu [buff_off %lu] tli %u , sz: %lu | key %u_ %X/%X" ,
432
+ dec_off , dec_off - offset , tli , dec_sz , curr_key -> key . tli , LSN_FORMAT_ARGS ( curr_key -> start_lsn ));
392
433
#endif
393
434
pg_tde_stream_crypt (iv_prefix , dec_off , dec_buf , dec_sz , dec_buf ,
394
435
& curr_key -> key , & curr_key -> crypt_ctx );
0 commit comments