Skip to content

Commit 4fc7c92

Browse files
committed
WIP: Delete old key in the same scan as we add the new one
1 parent 2d5282c commit 4fc7c92

File tree

2 files changed

+69
-11
lines changed

2 files changed

+69
-11
lines changed

contrib/pg_tde/src/access/pg_tde_tdemap.c

Lines changed: 61 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ static void pg_tde_sign_principal_key_info(TDESignedPrincipalKeyInfo *signed_key
7272
static void pg_tde_write_one_map_entry(int fd, const TDEMapEntry *map_entry, off_t *offset, const char *db_map_path);
7373
static int keyrotation_init_file(const TDESignedPrincipalKeyInfo *signed_key_info, char *rotated_filename, const char *filename, off_t *curr_pos);
7474
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);
7576

7677
void
7778
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)
8889
errhint("Use pg_tde_set_key_using_database_key_provider() or pg_tde_set_key_using_global_key_provider() to configure one."));
8990
}
9091

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);
9293
LWLockRelease(lock_pk);
9394
}
9495

@@ -362,6 +363,65 @@ pg_tde_delete_principal_key(Oid dbOid)
362363
durable_unlink(path, ERROR);
363364
}
364365

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+
365425
#endif /* !FRONTEND */
366426

367427
/*

contrib/pg_tde/src/smgr/pg_tde_smgr.c

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -102,8 +102,6 @@ tde_smgr_create_key_redo(const RelFileLocator *rlocator)
102102
{
103103
InternalKey key;
104104

105-
pg_tde_free_key_map_entry(*rlocator);
106-
107105
pg_tde_generate_internal_key(&key, TDE_KEY_TYPE_SMGR);
108106

109107
pg_tde_save_smgr_key(*rlocator, &key);
@@ -373,18 +371,18 @@ tde_mdcreate(RelFileLocator relold, SMgrRelation reln, ForkNumber forknum, bool
373371
if (forknum != MAIN_FORKNUM)
374372
return;
375373

376-
/*
377-
* If we have a key for this relation already, we need to remove it. This
378-
* can happen if OID is re-used after a crash left a key for a
379-
* non-existing relation in the key file.
380-
*/
381-
if (!RelFileLocatorBackendIsTemp(reln->smgr_rlocator))
382-
pg_tde_free_key_map_entry(reln->smgr_rlocator.locator);
383-
384374
if (!tde_smgr_should_encrypt(&reln->smgr_rlocator, &relold))
385375
{
376+
/*
377+
* If we have a key for this relation already, we need to remove it.
378+
* This can happen if OID is re-used after a crash left a key for a
379+
* non-existing relation in the key file.
380+
*/
386381
if (!RelFileLocatorBackendIsTemp(reln->smgr_rlocator))
382+
{
383+
pg_tde_free_key_map_entry(reln->smgr_rlocator.locator);
387384
tde_smgr_log_delete_key(&reln->smgr_rlocator);
385+
}
388386

389387
tdereln->encryption_status = RELATION_NOT_ENCRYPTED;
390388
return;

0 commit comments

Comments
 (0)