@@ -72,6 +72,7 @@ static void pg_tde_sign_principal_key_info(TDESignedPrincipalKeyInfo *signed_key
72
72
static void pg_tde_write_one_map_entry (int fd , const TDEMapEntry * map_entry , off_t * offset , const char * db_map_path );
73
73
static int keyrotation_init_file (const TDESignedPrincipalKeyInfo * signed_key_info , char * rotated_filename , const char * filename , off_t * curr_pos );
74
74
static void finalize_key_rotation (const char * path_old , const char * path_new );
75
+ static void pg_tde_replace_key_map_entry (const RelFileLocator * rlocator , const InternalKey * rel_key_data , TDEPrincipalKey * principal_key );
75
76
76
77
void
77
78
pg_tde_save_smgr_key (RelFileLocator rel , const InternalKey * rel_key_data )
@@ -88,7 +89,7 @@ pg_tde_save_smgr_key(RelFileLocator rel, const InternalKey *rel_key_data)
88
89
errhint ("Use pg_tde_set_key_using_database_key_provider() or pg_tde_set_key_using_global_key_provider() to configure one." ));
89
90
}
90
91
91
- pg_tde_write_key_map_entry (& rel , rel_key_data , principal_key );
92
+ pg_tde_replace_key_map_entry (& rel , rel_key_data , principal_key );
92
93
LWLockRelease (lock_pk );
93
94
}
94
95
@@ -362,6 +363,65 @@ pg_tde_delete_principal_key(Oid dbOid)
362
363
durable_unlink (path , ERROR );
363
364
}
364
365
366
+ /*
367
+ * The caller must hold an exclusive lock on the key file to avoid
368
+ * concurrent in place updates leading to data conflicts.
369
+ */
370
+ void
371
+ pg_tde_replace_key_map_entry (const RelFileLocator * rlocator , const InternalKey * rel_key_data , TDEPrincipalKey * principal_key )
372
+ {
373
+ char db_map_path [MAXPGPATH ];
374
+ int map_fd ;
375
+ off_t curr_pos = 0 ;
376
+ off_t write_pos = 0 ;
377
+ TDEMapEntry write_map_entry ;
378
+ TDESignedPrincipalKeyInfo signed_key_Info ;
379
+
380
+ Assert (rlocator );
381
+
382
+ pg_tde_set_db_file_path (rlocator -> dbOid , db_map_path );
383
+
384
+ pg_tde_sign_principal_key_info (& signed_key_Info , principal_key );
385
+
386
+ /* Open and validate file for basic correctness. */
387
+ map_fd = pg_tde_open_file_write (db_map_path , & signed_key_Info , false, & curr_pos );
388
+
389
+ /*
390
+ * Read until we find an empty slot. Otherwise, read until end. This seems
391
+ * to be less frequent than vacuum. So let's keep this function here
392
+ * rather than overloading the vacuum process.
393
+ */
394
+ while (1 )
395
+ {
396
+ TDEMapEntry read_map_entry ;
397
+ off_t prev_pos = curr_pos ;
398
+
399
+ if (!pg_tde_read_one_map_entry (map_fd , & read_map_entry , & curr_pos ))
400
+ {
401
+ if (write_pos == 0 )
402
+ write_pos = prev_pos ;
403
+ break ;
404
+ }
405
+
406
+ if (read_map_entry .spcOid == rlocator -> spcOid && read_map_entry .relNumber == rlocator -> relNumber )
407
+ {
408
+ write_pos = prev_pos ;
409
+ break ;
410
+ }
411
+
412
+ if (write_pos == 0 && read_map_entry .type == MAP_ENTRY_EMPTY )
413
+ write_pos = prev_pos ;
414
+ }
415
+
416
+ /* Initialize map entry and encrypt key */
417
+ pg_tde_initialize_map_entry (& write_map_entry , principal_key , rlocator , rel_key_data );
418
+
419
+ /* Write the given entry at curr_pos; i.e. the free entry. */
420
+ pg_tde_write_one_map_entry (map_fd , & write_map_entry , & write_pos , db_map_path );
421
+
422
+ CloseTransientFile (map_fd );
423
+ }
424
+
365
425
#endif /* !FRONTEND */
366
426
367
427
/*
0 commit comments