Skip to content

Commit a6f774e

Browse files
committed
PG-1444 Move relation key deleteion to smgr_unlink()
Replaces the old way we deleted keys which was built for tde_heap_basic with deleting the the relation key when smgr_unlink() is called on the main fork. This function is always called after commit/abort when a relation deletion has been registered, even if no main fork would exist. This approach means we do not need to WAL log any event for deleting relation keys, the normal SMGR unlink also handles that which fits well into the current approach of doing most of the encryption at the SMGR layer. We also remove the subtransaction test which is no longer useful since it tested things very specific to the old key deleteion.
1 parent ec51d08 commit a6f774e

File tree

10 files changed

+40
-342
lines changed

10 files changed

+40
-342
lines changed

contrib/pg_tde/Makefile

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ partition_table \
2121
pg_tde_is_encrypted \
2222
recreate_storage \
2323
relocate \
24-
subtransaction \
2524
tablespace \
2625
vault_v2_test \
2726
version \
@@ -33,7 +32,6 @@ src/encryption/enc_aes.o \
3332
src/access/pg_tde_tdemap.o \
3433
src/access/pg_tde_xlog.o \
3534
src/access/pg_tde_xlog_encrypt.o \
36-
src/transam/pg_tde_xact_handler.o \
3735
src/keyring/keyring_curl.o \
3836
src/keyring/keyring_file.o \
3937
src/keyring/keyring_vault.o \

contrib/pg_tde/expected/subtransaction.out

Lines changed: 0 additions & 30 deletions
This file was deleted.

contrib/pg_tde/meson.build

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ pg_tde_sources = files(
2121
'src/pg_tde_event_capture.c',
2222
'src/pg_tde_guc.c',
2323
'src/smgr/pg_tde_smgr.c',
24-
'src/transam/pg_tde_xact_handler.c',
2524
)
2625

2726
tde_frontend_sources = files(
@@ -97,7 +96,6 @@ sql_tests = [
9796
'pg_tde_is_encrypted',
9897
'relocate',
9998
'recreate_storage',
100-
'subtransaction',
10199
'tablespace',
102100
'vault_v2_test',
103101
'version',

contrib/pg_tde/sql/subtransaction.sql

Lines changed: 0 additions & 25 deletions
This file was deleted.

contrib/pg_tde/src/access/pg_tde_tdemap.c

Lines changed: 16 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@
1313
#include "postgres.h"
1414
#include "access/pg_tde_tdemap.h"
1515
#include "common/file_perm.h"
16-
#include "transam/pg_tde_xact_handler.h"
1716
#include "storage/fd.h"
1817
#include "utils/wait_event.h"
1918
#include "utils/memutils.h"
@@ -129,7 +128,6 @@ static int pg_tde_file_header_write(const char *tde_filename, int fd, const TDES
129128
static void pg_tde_sign_principal_key_info(TDESignedPrincipalKeyInfo *signed_key_info, const TDEPrincipalKey *principal_key);
130129
static off_t pg_tde_write_one_map_entry(int fd, const TDEMapEntry *map_entry, off_t *offset, const char *db_map_path);
131130
static void pg_tde_write_key_map_entry(const RelFileLocator *rlocator, InternalKey *rel_key_data, TDEPrincipalKey *principal_key, bool write_xlog);
132-
static bool pg_tde_delete_map_entry(const RelFileLocator *rlocator, char *db_map_path, off_t offset);
133131
static int keyrotation_init_file(const TDESignedPrincipalKeyInfo *signed_key_info, char *rotated_filename, const char *filename, off_t *curr_pos);
134132
static void finalize_key_rotation(const char *path_old, const char *path_new);
135133
static int pg_tde_open_file_write(const char *tde_filename, const TDESignedPrincipalKeyInfo *signed_key_info, bool truncate, off_t *curr_pos);
@@ -486,9 +484,6 @@ pg_tde_write_key_map_entry(const RelFileLocator *rlocator, InternalKey *rel_key_
486484

487485
/* Let's close the file. */
488486
close(map_fd);
489-
490-
/* Register the entry to be freed in case the transaction aborts */
491-
RegisterEntryForDeletion(rlocator, curr_pos, false);
492487
}
493488

494489
/*
@@ -548,51 +543,40 @@ pg_tde_write_key_map_entry_redo(const TDEMapEntry *write_map_entry, TDESignedPri
548543
LWLockRelease(tde_lwlock_enc_keys());
549544
}
550545

551-
static bool
552-
pg_tde_delete_map_entry(const RelFileLocator *rlocator, char *db_map_path, off_t offset)
546+
/*
547+
* Mark relation map entry as free and overwrite the key
548+
*
549+
* This fucntion is called by the pg_tde SMGR when storage is unlinked on
550+
* transaction commit/abort.
551+
*/
552+
void
553+
pg_tde_free_key_map_entry(const RelFileLocator *rlocator)
553554
{
555+
char db_map_path[MAXPGPATH];
554556
File map_fd;
555-
bool found = false;
556557
off_t curr_pos = 0;
557558

558-
/* Open and validate file for basic correctness. */
559-
map_fd = pg_tde_open_file_write(db_map_path, NULL, false, &curr_pos);
559+
Assert(rlocator);
560560

561-
/*
562-
* If we need to delete an entry, we expect an offset value to the start
563-
* of the entry to speed up the operation. Otherwise, we'd be sequentially
564-
* scanning the entire map file.
565-
*/
566-
if (offset > 0)
567-
{
568-
curr_pos = lseek(map_fd, offset, SEEK_SET);
561+
pg_tde_set_db_file_path(rlocator->dbOid, db_map_path);
569562

570-
if (curr_pos == -1)
571-
{
572-
ereport(ERROR,
573-
errcode_for_file_access(),
574-
errmsg("could not seek in tde map file \"%s\": %m",
575-
db_map_path));
576-
}
577-
}
563+
LWLockAcquire(tde_lwlock_enc_keys(), LW_EXCLUSIVE);
564+
565+
/* Open and validate file for basic correctness. */
566+
map_fd = pg_tde_open_file_write(db_map_path, NULL, false, &curr_pos);
578567

579-
/*
580-
* Read until we find an empty slot. Otherwise, read until end. This seems
581-
* to be less frequent than vacuum. So let's keep this function here
582-
* rather than overloading the vacuum process.
583-
*/
584568
while (1)
585569
{
586570
TDEMapEntry read_map_entry;
587571
off_t prev_pos = curr_pos;
572+
bool found;
588573

589574
found = pg_tde_read_one_map_entry(map_fd, rlocator, MAP_ENTRY_VALID, &read_map_entry, &curr_pos);
590575

591576
/* We've reached EOF */
592577
if (curr_pos == prev_pos)
593578
break;
594579

595-
/* We found a valid entry for the relation */
596580
if (found)
597581
{
598582
TDEMapEntry empty_map_entry = {
@@ -607,52 +591,9 @@ pg_tde_delete_map_entry(const RelFileLocator *rlocator, char *db_map_path, off_t
607591
}
608592
}
609593

610-
/* Let's close the file. */
611594
close(map_fd);
612595

613-
/* Return -1 indicating that no entry was removed */
614-
return found;
615-
}
616-
617-
/*
618-
* Called when transaction is being completed; either committed or aborted.
619-
* By default, when a transaction creates an entry, we mark it as MAP_ENTRY_VALID.
620-
* Only during the abort phase of the transaction that we are proceed on with
621-
* marking the entry as MAP_ENTRY_FREE. This optimistic strategy that assumes
622-
* that transaction will commit more often then getting aborted avoids
623-
* unnecessary locking.
624-
*
625-
* The offset allows us to simply seek to the desired location and mark the entry
626-
* as MAP_ENTRY_FREE without needing any further processing.
627-
*/
628-
void
629-
pg_tde_free_key_map_entry(const RelFileLocator *rlocator, off_t offset)
630-
{
631-
bool found;
632-
char db_map_path[MAXPGPATH] = {0};
633-
634-
Assert(rlocator);
635-
636-
/* Get the file paths */
637-
pg_tde_set_db_file_path(rlocator->dbOid, db_map_path);
638-
639-
LWLockAcquire(tde_lwlock_enc_keys(), LW_EXCLUSIVE);
640-
641-
/* Remove the map entry if found */
642-
found = pg_tde_delete_map_entry(rlocator, db_map_path, offset);
643-
644596
LWLockRelease(tde_lwlock_enc_keys());
645-
646-
if (!found)
647-
{
648-
ereport(WARNING,
649-
errcode(ERRCODE_NO_DATA_FOUND),
650-
errmsg("could not find the required map entry for deletion of relation %d in tablespace %d in tde map file \"%s\": %m",
651-
rlocator->relNumber,
652-
rlocator->spcOid,
653-
db_map_path));
654-
655-
}
656597
}
657598

658599
/*

contrib/pg_tde/src/include/access/pg_tde_tdemap.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ extern void pg_tde_wal_last_key_set_lsn(XLogRecPtr lsn, const char *keyfile_path
101101

102102
extern InternalKey *pg_tde_create_smgr_key(const RelFileLocatorBackend *newrlocator);
103103
extern void pg_tde_create_wal_key(InternalKey *rel_key_data, const RelFileLocator *newrlocator, uint32 flags);
104-
extern void pg_tde_free_key_map_entry(const RelFileLocator *rlocator, off_t offset);
104+
extern void pg_tde_free_key_map_entry(const RelFileLocator *rlocator);
105105
extern void pg_tde_write_key_map_entry_redo(const TDEMapEntry *write_map_entry, TDESignedPrincipalKeyInfo *signed_key_info);
106106

107107
#define PG_TDE_MAP_FILENAME "pg_tde_%d_map"

contrib/pg_tde/src/include/transam/pg_tde_xact_handler.h

Lines changed: 0 additions & 18 deletions
This file was deleted.

contrib/pg_tde/src/pg_tde.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@
1313
#include "postgres.h"
1414
#include "funcapi.h"
1515
#include "pg_tde.h"
16-
#include "transam/pg_tde_xact_handler.h"
1716
#include "miscadmin.h"
1817
#include "storage/ipc.h"
1918
#include "storage/lwlock.h"
@@ -121,7 +120,6 @@ _PG_init(void)
121120
prev_shmem_startup_hook = shmem_startup_hook;
122121
shmem_startup_hook = tde_shmem_startup;
123122

124-
RegisterTdeXactCallbacks();
125123
InstallFileKeyring();
126124
InstallVaultV2Keyring();
127125
InstallKmipKeyring();

contrib/pg_tde/src/smgr/pg_tde_smgr.c

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,28 @@ tde_mdwritev(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum,
115115
}
116116
}
117117

118+
static void
119+
tde_mdunlink(RelFileLocatorBackend rlocator, ForkNumber forknum, bool isRedo)
120+
{
121+
mdunlink(rlocator, forknum, isRedo);
122+
123+
/*
124+
* As of PostgreSQL 17 we are called once per forks, no matter if they
125+
* exist or not, from smgrdounlinkall() so deleting the relation key on
126+
* attempting to delete the main fork is safe. Additionally since we
127+
* unlink the files after commit/abort we do not need to care about
128+
* concurrent accesses.
129+
*
130+
* We support InvalidForkNumber to be similar to mdunlink() but it can
131+
* actually never happen.
132+
*/
133+
if (forknum == MAIN_FORKNUM || forknum == InvalidForkNumber)
134+
{
135+
if (!RelFileLocatorBackendIsTemp(rlocator) && GetSMGRRelationKey(rlocator))
136+
pg_tde_free_key_map_entry(&rlocator.locator);
137+
}
138+
}
139+
118140
static void
119141
tde_mdextend(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum,
120142
const void *buffer, bool skipFsync)
@@ -274,7 +296,7 @@ static const struct f_smgr tde_smgr = {
274296
.smgr_close = mdclose,
275297
.smgr_create = tde_mdcreate,
276298
.smgr_exists = mdexists,
277-
.smgr_unlink = mdunlink,
299+
.smgr_unlink = tde_mdunlink,
278300
.smgr_extend = tde_mdextend,
279301
.smgr_zeroextend = mdzeroextend,
280302
.smgr_prefetch = mdprefetch,

0 commit comments

Comments
 (0)