@@ -45,7 +45,7 @@ static void *EncryptionCryptCtx = NULL;
45
45
static InternalKey EncryptionKey =
46
46
{
47
47
.type = MAP_ENTRY_EMPTY ,
48
- .start_lsn = InvalidXLogRecPtr ,
48
+ .wal_start = {. tli = 0 , . lsn = InvalidXLogRecPtr } ,
49
49
};
50
50
51
51
/*
@@ -66,7 +66,13 @@ static InternalKey EncryptionKey =
66
66
typedef struct EncryptionStateData
67
67
{
68
68
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 ;
70
76
} EncryptionStateData ;
71
77
72
78
static EncryptionStateData * EncryptionState = NULL ;
@@ -80,11 +86,18 @@ TDEXLogGetEncKeyLsn()
80
86
}
81
87
82
88
static void
83
- TDEXLogSetEncKeyLsn ( XLogRecPtr start_lsn )
89
+ TDEXLogSetEncKeyLocation ( WALLocation loc )
84
90
{
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 );
86
93
}
87
94
95
+ static TimeLineID
96
+ TDEXLogGetEncKeyTli ()
97
+ {
98
+ return (TimeLineID ) pg_atomic_read_u32 (& EncryptionState -> enc_key_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_u32 (& EncryptionState -> enc_key_tli , 0 );
162
176
163
177
elog (DEBUG1 , "pg_tde: initialized encryption buffer %lu bytes" , TDEXLogEncryptStateSize ());
164
178
}
@@ -168,6 +182,7 @@ TDEXLogShmemInit(void)
168
182
typedef struct EncryptionStateData
169
183
{
170
184
char db_map_path [MAXPGPATH ];
185
+ XLogRecPtr enc_key_tli ; /* to sync with reader */
171
186
XLogRecPtr enc_key_lsn ; /* to sync with reader */
172
187
} EncryptionStateData ;
173
188
@@ -184,9 +199,16 @@ TDEXLogGetEncKeyLsn()
184
199
}
185
200
186
201
static 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 ()
188
210
{
189
- EncryptionState -> enc_key_lsn = EncryptionKey . start_lsn ;
211
+ return ( TimeLineID ) EncryptionState -> enc_key_tli ;
190
212
}
191
213
192
214
#endif /* FRONTEND */
@@ -197,6 +219,7 @@ TDEXLogSmgrInit()
197
219
SetXLogSmgr (& tde_xlog_smgr );
198
220
}
199
221
222
+ /* On backend it should be called only during the startup */
200
223
void
201
224
TDEXLogSmgrInitWrite (bool encrypt_xlog )
202
225
{
@@ -220,7 +243,7 @@ TDEXLogSmgrInitWrite(bool encrypt_xlog)
220
243
else if (key )
221
244
{
222
245
EncryptionKey = * key ;
223
- TDEXLogSetEncKeyLsn (EncryptionKey .start_lsn );
246
+ TDEXLogSetEncKeyLocation (EncryptionKey .wal_start );
224
247
}
225
248
226
249
if (key )
@@ -245,8 +268,8 @@ TDEXLogWriteEncryptedPages(int fd, const void *buf, size_t count, off_t offset,
245
268
#endif
246
269
247
270
#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 ));
271
+ elog (DEBUG1 , "write encrypted WAL, size: %lu, offset: %ld [%lX], seg: %X/%X, key_start_lsn: %u_% X/%X" ,
272
+ count , offset , offset , LSN_FORMAT_ARGS (segno ), key -> wal_start . tli , LSN_FORMAT_ARGS (key -> wal_start . lsn ));
250
273
#endif
251
274
252
275
CalcXLogPageIVPrefix (tli , segno , key -> base_iv , iv_prefix );
@@ -272,9 +295,10 @@ tdeheap_xlog_seg_write(int fd, const void *buf, size_t count, off_t offset,
272
295
273
296
XLogSegNoOffsetToRecPtr (segno , offset , segSize , lsn );
274
297
275
- pg_tde_wal_last_key_set_lsn (lsn , EncryptionState -> db_map_path );
276
- EncryptionKey .start_lsn = lsn ;
277
- TDEXLogSetEncKeyLsn (lsn );
298
+ pg_tde_wal_last_key_set_lsn (lsn , tli , EncryptionState -> db_map_path );
299
+ EncryptionKey .wal_start .tli = tli ;
300
+ EncryptionKey .wal_start .lsn = lsn ;
301
+ TDEXLogSetEncKeyLocation (EncryptionKey .wal_start );
278
302
}
279
303
280
304
if (EncryptionKey .type == TDE_KEY_TYPE_WAL_ENCRYPTED )
@@ -293,12 +317,12 @@ tdeheap_xlog_seg_read(int fd, void *buf, size_t count, off_t offset,
293
317
ssize_t readsz ;
294
318
WALKeyCacheRec * keys = pg_tde_get_wal_cache_keys ();
295
319
XLogRecPtr write_key_lsn ;
296
- XLogRecPtr data_start ;
297
- XLogRecPtr data_end ;
320
+ WALLocation data_start = {. tli = tli } ;
321
+ WALLocation data_end = {. tli = tli } ;
298
322
299
323
#ifdef TDE_XLOG_DEBUG
300
- elog (DEBUG1 , "read from a WAL segment, size: %lu offset: %ld [%lX], seg: %X/%X" ,
301
- count , offset , offset , LSN_FORMAT_ARGS (segno ));
324
+ elog (DEBUG1 , "read from a WAL segment, size: %lu offset: %ld [%lX], seg: %u_% X/%X" ,
325
+ count , offset , offset , tli , LSN_FORMAT_ARGS (segno ));
302
326
#endif
303
327
304
328
readsz = pg_pread (fd , buf , count , offset );
@@ -308,30 +332,32 @@ tdeheap_xlog_seg_read(int fd, void *buf, size_t count, off_t offset,
308
332
309
333
if (!keys )
310
334
{
335
+ WALLocation start = {.tli = 1 , .lsn = 0 };
311
336
/* cache is empty, try to read keys from disk */
312
- keys = pg_tde_fetch_wal_keys (InvalidXLogRecPtr );
337
+ keys = pg_tde_fetch_wal_keys (start );
313
338
}
314
339
315
340
write_key_lsn = TDEXLogGetEncKeyLsn ();
316
341
317
342
if (!XLogRecPtrIsInvalid (write_key_lsn ))
318
343
{
319
344
WALKeyCacheRec * last_key = pg_tde_get_last_wal_key ();
345
+ WALLocation write_loc = {.tli = TDEXLogGetEncKeyTli (), .lsn = write_key_lsn };
320
346
321
347
Assert (last_key );
322
348
323
349
/* write has generated a new key, need to fetch it */
324
- if (last_key -> start_lsn < write_key_lsn )
350
+ if (wal_location_cmp ( last_key -> start , write_loc ) < 0 )
325
351
{
326
- pg_tde_fetch_wal_keys (write_key_lsn );
352
+ pg_tde_fetch_wal_keys (write_loc );
327
353
328
354
/* in case cache was empty before */
329
355
keys = pg_tde_get_wal_cache_keys ();
330
356
}
331
357
}
332
358
333
- XLogSegNoOffsetToRecPtr (segno , offset , segSize , data_start );
334
- XLogSegNoOffsetToRecPtr (segno , offset + readsz , segSize , data_end );
359
+ XLogSegNoOffsetToRecPtr (segno , offset , segSize , data_start . lsn );
360
+ XLogSegNoOffsetToRecPtr (segno , offset + readsz , segSize , data_end . lsn );
335
361
336
362
/*
337
363
* TODO: this is higly ineffective. We should get rid of linked list and
@@ -340,24 +366,25 @@ tdeheap_xlog_seg_read(int fd, void *buf, size_t count, off_t offset,
340
366
for (WALKeyCacheRec * curr_key = keys ; curr_key != NULL ; curr_key = curr_key -> next )
341
367
{
342
368
#ifdef TDE_XLOG_DEBUG
343
- elog (DEBUG1 , "WAL key %X/%X- %X/%X, encrypted: %s" ,
344
- LSN_FORMAT_ARGS (curr_key -> start_lsn ),
345
- LSN_FORMAT_ARGS (curr_key -> end_lsn ),
369
+ elog (DEBUG1 , "WAL key %u_% X/%X - %u_ %X/%X, encrypted: %s" ,
370
+ curr_key -> start . tli , LSN_FORMAT_ARGS (curr_key -> start . lsn ),
371
+ curr_key -> end . tli , LSN_FORMAT_ARGS (curr_key -> end . lsn ),
346
372
curr_key -> key .type == TDE_KEY_TYPE_WAL_ENCRYPTED ? "yes" : "no" );
347
373
#endif
348
374
349
- if (curr_key -> key .start_lsn != InvalidXLogRecPtr &&
375
+ if (wal_location_valid ( curr_key -> key .wal_start ) &&
350
376
curr_key -> key .type == TDE_KEY_TYPE_WAL_ENCRYPTED )
351
377
{
352
378
/*
353
379
* Check if the key's range overlaps with the buffer's and decypt
354
380
* the part that does.
355
381
*/
356
- if (data_start < curr_key -> end_lsn && data_end > curr_key -> start_lsn )
382
+
383
+ if (wal_location_cmp (data_start , curr_key -> end ) < 0 && wal_location_cmp (data_end , curr_key -> start ) > 0 )
357
384
{
358
385
char iv_prefix [16 ];
359
- off_t dec_off = XLogSegmentOffset (Max (data_start , curr_key -> start_lsn ), segSize );
360
- off_t dec_end = XLogSegmentOffset (Min (data_end , curr_key -> end_lsn ), segSize );
386
+ off_t dec_off = XLogSegmentOffset (Max (data_start . lsn , curr_key -> start . lsn ), segSize );
387
+ off_t dec_end = XLogSegmentOffset (Min (data_end . lsn , curr_key -> end . lsn ), segSize );
361
388
size_t dec_sz ;
362
389
char * dec_buf = (char * ) buf + (dec_off - offset );
363
390
@@ -374,8 +401,8 @@ tdeheap_xlog_seg_read(int fd, void *buf, size_t count, off_t offset,
374
401
dec_sz = dec_end - dec_off ;
375
402
376
403
#ifdef TDE_XLOG_DEBUG
377
- elog (DEBUG1 , "decrypt WAL, dec_off: %lu [buff_off %lu], sz: %lu | key %X/%X" ,
378
- dec_off , dec_off - offset , dec_sz , LSN_FORMAT_ARGS ( curr_key -> key -> start_lsn ));
404
+ elog (DEBUG1 , "decrypt WAL, dec_off: %lu [buff_off %lu], sz: %lu | key %u_% X/%X" ,
405
+ dec_off , dec_off - offset , dec_sz , curr_key -> key . wal_start . tli , LSN_FORMAT_ARGS ( curr_key -> key . wal_start . lsn ));
379
406
#endif
380
407
pg_tde_stream_crypt (iv_prefix , dec_off , dec_buf , dec_sz , dec_buf ,
381
408
& curr_key -> key , & curr_key -> crypt_ctx );
0 commit comments