Skip to content

Commit 9618f69

Browse files
committed
Move SMGR specific logic out of the TDE map code
Especially all code realted to the keys of temporary tables did not belong in the TDE map code and fit better in the SMGR code. Additionally we speed up pg_tde_is_encrypted() by relying on the SMGR to cache the relations. This might in some cases lead to blow up of the SMGR relation cache if you query every relation in the database but given the small size I am not overly worried.
1 parent 5fd8d16 commit 9618f69

File tree

9 files changed

+229
-209
lines changed

9 files changed

+229
-209
lines changed

contrib/pg_tde/src/access/pg_tde_tdemap.c

Lines changed: 27 additions & 185 deletions
Original file line numberDiff line numberDiff line change
@@ -20,14 +20,14 @@
2020
#include "access/xlog_internal.h"
2121
#include "access/xloginsert.h"
2222
#include "utils/builtins.h"
23-
#include "utils/hsearch.h"
2423
#include "miscadmin.h"
2524

2625
#include "access/pg_tde_tdemap.h"
2726
#include "access/pg_tde_xlog.h"
2827
#include "catalog/tde_global_space.h"
2928
#include "catalog/tde_principal_key.h"
3029
#include "encryption/enc_aes.h"
30+
#include "encryption/enc_tde.h"
3131
#include "keyring/keyring_api.h"
3232

3333
#include <openssl/rand.h>
@@ -66,24 +66,6 @@ typedef struct TDEFileHeader
6666
TDESignedPrincipalKeyInfo signed_key_info;
6767
} TDEFileHeader;
6868

69-
typedef struct
70-
{
71-
RelFileLocator rel;
72-
InternalKey key;
73-
} TempRelKeyEntry;
74-
75-
#ifndef FRONTEND
76-
77-
/* Arbitrarily picked small number of temporary relations */
78-
#define INIT_TEMP_RELS 16
79-
80-
/*
81-
* Each backend has a hashtable that stores the keys for all temporary tables.
82-
*/
83-
static HTAB *TempRelKeys = NULL;
84-
85-
#endif
86-
8769
static WALKeyCacheRec *tde_wal_key_cache = NULL;
8870
static WALKeyCacheRec *tde_wal_key_last_rec = NULL;
8971

@@ -98,138 +80,45 @@ static int pg_tde_open_file_read(const char *tde_filename, bool ignore_missing,
9880
static WALKeyCacheRec *pg_tde_add_wal_key_to_cache(InternalKey *cached_key, XLogRecPtr start_lsn);
9981

10082
#ifndef FRONTEND
101-
static InternalKey *pg_tde_create_smgr_key_temp(const RelFileLocator *newrlocator);
102-
static InternalKey *pg_tde_create_smgr_key_perm(const RelFileLocator *newrlocator);
103-
static void pg_tde_generate_internal_key(InternalKey *int_key, TDEMapEntryType entry_type);
10483
static int pg_tde_file_header_write(const char *tde_filename, int fd, const TDESignedPrincipalKeyInfo *signed_key_info, off_t *bytes_written);
10584
static void pg_tde_sign_principal_key_info(TDESignedPrincipalKeyInfo *signed_key_info, const TDEPrincipalKey *principal_key);
10685
static void pg_tde_write_one_map_entry(int fd, const TDEMapEntry *map_entry, off_t *offset, const char *db_map_path);
107-
static void pg_tde_write_key_map_entry(const RelFileLocator *rlocator, InternalKey *rel_key_data, TDEPrincipalKey *principal_key);
108-
static void pg_tde_free_key_map_entry(const RelFileLocator *rlocator);
86+
static void pg_tde_write_key_map_entry(const RelFileLocator *rlocator, const InternalKey *rel_key_data, TDEPrincipalKey *principal_key);
10987
static int keyrotation_init_file(const TDESignedPrincipalKeyInfo *signed_key_info, char *rotated_filename, const char *filename, off_t *curr_pos);
11088
static void finalize_key_rotation(const char *path_old, const char *path_new);
11189
static int pg_tde_open_file_write(const char *tde_filename, const TDESignedPrincipalKeyInfo *signed_key_info, bool truncate, off_t *curr_pos);
11290

113-
InternalKey *
114-
pg_tde_create_smgr_key(const RelFileLocatorBackend *newrlocator)
115-
{
116-
if (RelFileLocatorBackendIsTemp(*newrlocator))
117-
return pg_tde_create_smgr_key_temp(&newrlocator->locator);
118-
else
119-
return pg_tde_create_smgr_key_perm(&newrlocator->locator);
120-
}
121-
122-
static InternalKey *
123-
pg_tde_create_smgr_key_temp(const RelFileLocator *newrlocator)
124-
{
125-
InternalKey *rel_key_data = palloc_object(InternalKey);
126-
TempRelKeyEntry *entry;
127-
bool found;
128-
129-
pg_tde_generate_internal_key(rel_key_data, TDE_KEY_TYPE_SMGR);
130-
131-
if (TempRelKeys == NULL)
132-
{
133-
HASHCTL ctl;
134-
135-
ctl.keysize = sizeof(RelFileLocator);
136-
ctl.entrysize = sizeof(TempRelKeyEntry);
137-
TempRelKeys = hash_create("pg_tde temporary relation keys",
138-
INIT_TEMP_RELS,
139-
&ctl,
140-
HASH_ELEM | HASH_BLOBS);
141-
}
142-
143-
entry = (TempRelKeyEntry *) hash_search(TempRelKeys,
144-
newrlocator,
145-
HASH_ENTER, &found);
146-
Assert(!found);
147-
148-
entry->key = *rel_key_data;
149-
150-
return rel_key_data;
151-
}
152-
153-
static InternalKey *
154-
pg_tde_create_smgr_key_perm(const RelFileLocator *newrlocator)
91+
void
92+
pg_tde_save_smgr_key(RelFileLocator rel, const InternalKey *rel_key_data, bool write_xlog)
15593
{
156-
InternalKey *rel_key_data = palloc_object(InternalKey);
15794
TDEPrincipalKey *principal_key;
15895
LWLock *lock_pk = tde_lwlock_enc_keys();
15996
XLogRelKey xlrec = {
160-
.rlocator = *newrlocator,
97+
.rlocator = rel,
16198
};
16299

163-
pg_tde_generate_internal_key(rel_key_data, TDE_KEY_TYPE_SMGR);
164-
165100
LWLockAcquire(lock_pk, LW_EXCLUSIVE);
166-
principal_key = GetPrincipalKey(newrlocator->dbOid, LW_EXCLUSIVE);
101+
principal_key = GetPrincipalKey(rel.dbOid, LW_EXCLUSIVE);
167102
if (principal_key == NULL)
168103
{
169104
ereport(ERROR,
170105
errmsg("principal key not configured"),
171106
errhint("create one using pg_tde_set_key before using encrypted tables"));
172107
}
173108

174-
pg_tde_write_key_map_entry(newrlocator, rel_key_data, principal_key);
109+
pg_tde_write_key_map_entry(&rel, rel_key_data, principal_key);
175110
LWLockRelease(lock_pk);
176111

177-
/*
178-
* It is fine to write the to WAL after writing to the file since we have
179-
* not WAL logged the SMGR CREATE event either.
180-
*/
181-
XLogBeginInsert();
182-
XLogRegisterData((char *) &xlrec, sizeof(xlrec));
183-
XLogInsert(RM_TDERMGR_ID, XLOG_TDE_ADD_RELATION_KEY);
184-
185-
return rel_key_data;
186-
}
187-
188-
void
189-
pg_tde_create_smgr_key_perm_redo(const RelFileLocator *newrlocator)
190-
{
191-
InternalKey rel_key_data;
192-
InternalKey *old_key;
193-
TDEPrincipalKey *principal_key;
194-
LWLock *lock_pk = tde_lwlock_enc_keys();
195-
196-
if ((old_key = pg_tde_get_key_from_file(newrlocator, TDE_KEY_TYPE_SMGR)))
197-
{
198-
pfree(old_key);
199-
return;
200-
}
201-
202-
pg_tde_generate_internal_key(&rel_key_data, TDE_KEY_TYPE_SMGR);
203-
204-
LWLockAcquire(lock_pk, LW_EXCLUSIVE);
205-
principal_key = GetPrincipalKey(newrlocator->dbOid, LW_EXCLUSIVE);
206-
if (principal_key == NULL)
112+
if (write_xlog)
207113
{
208-
ereport(ERROR,
209-
errmsg("principal key not configured"),
210-
errhint("create one using pg_tde_set_key before using encrypted tables"));
114+
/*
115+
* It is fine to write the to WAL after writing to the file since we
116+
* have not WAL logged the SMGR CREATE event either.
117+
*/
118+
XLogBeginInsert();
119+
XLogRegisterData((char *) &xlrec, sizeof(xlrec));
120+
XLogInsert(RM_TDERMGR_ID, XLOG_TDE_ADD_RELATION_KEY);
211121
}
212-
213-
pg_tde_write_key_map_entry(newrlocator, &rel_key_data, principal_key);
214-
LWLockRelease(lock_pk);
215-
}
216-
217-
static void
218-
pg_tde_generate_internal_key(InternalKey *int_key, TDEMapEntryType entry_type)
219-
{
220-
int_key->type = entry_type;
221-
int_key->start_lsn = InvalidXLogRecPtr;
222-
223-
if (!RAND_bytes(int_key->key, INTERNAL_KEY_LEN))
224-
ereport(ERROR,
225-
errcode(ERRCODE_INTERNAL_ERROR),
226-
errmsg("could not generate internal key: %s",
227-
ERR_error_string(ERR_get_error(), NULL)));
228-
if (!RAND_bytes(int_key->base_iv, INTERNAL_KEY_IV_LEN))
229-
ereport(ERROR,
230-
errcode(ERRCODE_INTERNAL_ERROR),
231-
errmsg("could not generate IV: %s",
232-
ERR_error_string(ERR_get_error(), NULL)));
233122
}
234123

235124
const char *
@@ -275,18 +164,6 @@ pg_tde_create_wal_key(InternalKey *rel_key_data, const RelFileLocator *newrlocat
275164
LWLockRelease(tde_lwlock_enc_keys());
276165
}
277166

278-
void
279-
DeleteSMGRRelationKey(RelFileLocatorBackend rel)
280-
{
281-
if (RelFileLocatorBackendIsTemp(rel))
282-
{
283-
Assert(TempRelKeys);
284-
hash_search(TempRelKeys, &rel.locator, HASH_REMOVE, NULL);
285-
}
286-
else
287-
pg_tde_free_key_map_entry(&rel.locator);
288-
}
289-
290167
/*
291168
* Deletes the key map file for a given database.
292169
*/
@@ -463,7 +340,7 @@ pg_tde_write_one_map_entry(int fd, const TDEMapEntry *map_entry, off_t *offset,
463340
* concurrent in place updates leading to data conflicts.
464341
*/
465342
void
466-
pg_tde_write_key_map_entry(const RelFileLocator *rlocator, InternalKey *rel_key_data, TDEPrincipalKey *principal_key)
343+
pg_tde_write_key_map_entry(const RelFileLocator *rlocator, const InternalKey *rel_key_data, TDEPrincipalKey *principal_key)
467344
{
468345
char db_map_path[MAXPGPATH];
469346
int map_fd;
@@ -518,16 +395,14 @@ pg_tde_write_key_map_entry(const RelFileLocator *rlocator, InternalKey *rel_key_
518395
* This fucntion is called by the pg_tde SMGR when storage is unlinked on
519396
* transaction commit/abort.
520397
*/
521-
static void
522-
pg_tde_free_key_map_entry(const RelFileLocator *rlocator)
398+
void
399+
pg_tde_free_key_map_entry(const RelFileLocator rlocator)
523400
{
524401
char db_map_path[MAXPGPATH];
525402
File map_fd;
526403
off_t curr_pos = 0;
527404

528-
Assert(rlocator);
529-
530-
pg_tde_set_db_file_path(rlocator->dbOid, db_map_path);
405+
pg_tde_set_db_file_path(rlocator.dbOid, db_map_path);
531406

532407
LWLockAcquire(tde_lwlock_enc_keys(), LW_EXCLUSIVE);
533408

@@ -542,7 +417,7 @@ pg_tde_free_key_map_entry(const RelFileLocator *rlocator)
542417
if (!pg_tde_read_one_map_entry(map_fd, &map_entry, &curr_pos))
543418
break;
544419

545-
if (map_entry.type != MAP_ENTRY_EMPTY && map_entry.spcOid == rlocator->spcOid && map_entry.relNumber == rlocator->relNumber)
420+
if (map_entry.type != MAP_ENTRY_EMPTY && map_entry.spcOid == rlocator.spcOid && map_entry.relNumber == rlocator.relNumber)
546421
{
547422
TDEMapEntry empty_map_entry = {
548423
.type = MAP_ENTRY_EMPTY,
@@ -1084,57 +959,27 @@ pg_tde_get_principal_key_info(Oid dbOid)
1084959
return signed_key_info;
1085960
}
1086961

1087-
static InternalKey *
1088-
pg_tde_get_temporary_rel_key(const RelFileLocator *rel)
1089-
{
1090-
#ifndef FRONTEND
1091-
TempRelKeyEntry *entry;
1092-
1093-
if (TempRelKeys == NULL)
1094-
return NULL;
1095-
1096-
entry = hash_search(TempRelKeys, rel, HASH_FIND, NULL);
1097-
1098-
if (entry)
1099-
{
1100-
InternalKey *key = palloc_object(InternalKey);
1101-
1102-
*key = entry->key;
1103-
return key;
1104-
}
1105-
#endif
1106-
1107-
return NULL;
1108-
}
1109-
1110962
/*
1111963
* Figures out whether a relation is encrypted or not, but without trying to
1112964
* decrypt the key if it is.
1113965
*/
1114966
bool
1115-
IsSMGRRelationEncrypted(RelFileLocatorBackend rel)
967+
pg_tde_has_smgr_key(RelFileLocator rel)
1116968
{
1117969
bool result;
1118970
TDEMapEntry map_entry;
1119971
char db_map_path[MAXPGPATH];
1120972

1121-
Assert(rel.locator.relNumber != InvalidRelFileNumber);
1122-
1123-
if (RelFileLocatorBackendIsTemp(rel))
1124-
#ifndef FRONTEND
1125-
return TempRelKeys && hash_search(TempRelKeys, &rel.locator, HASH_FIND, NULL);
1126-
#else
1127-
return false;
1128-
#endif
973+
Assert(rel.relNumber != InvalidRelFileNumber);
1129974

1130-
pg_tde_set_db_file_path(rel.locator.dbOid, db_map_path);
975+
pg_tde_set_db_file_path(rel.dbOid, db_map_path);
1131976

1132977
if (access(db_map_path, F_OK) == -1)
1133978
return false;
1134979

1135980
LWLockAcquire(tde_lwlock_enc_keys(), LW_SHARED);
1136981

1137-
result = pg_tde_find_map_entry(&rel.locator, TDE_KEY_TYPE_SMGR, db_map_path, &map_entry);
982+
result = pg_tde_find_map_entry(&rel, TDE_KEY_TYPE_SMGR, db_map_path, &map_entry);
1138983

1139984
LWLockRelease(tde_lwlock_enc_keys());
1140985
return result;
@@ -1144,14 +989,11 @@ IsSMGRRelationEncrypted(RelFileLocatorBackend rel)
1144989
* Returns TDE key for a given relation.
1145990
*/
1146991
InternalKey *
1147-
GetSMGRRelationKey(RelFileLocatorBackend rel)
992+
pg_tde_get_smgr_key(RelFileLocator rel)
1148993
{
1149-
Assert(rel.locator.relNumber != InvalidRelFileNumber);
994+
Assert(rel.relNumber != InvalidRelFileNumber);
1150995

1151-
if (RelFileLocatorBackendIsTemp(rel))
1152-
return pg_tde_get_temporary_rel_key(&rel.locator);
1153-
else
1154-
return pg_tde_get_key_from_file(&rel.locator, TDE_KEY_TYPE_SMGR);
996+
return pg_tde_get_key_from_file(&rel, TDE_KEY_TYPE_SMGR);
1155997
}
1156998

1157999
/*

contrib/pg_tde/src/access/pg_tde_xlog.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525

2626
#include "access/pg_tde_xlog.h"
2727
#include "encryption/enc_tde.h"
28+
#include "smgr/pg_tde_smgr.h"
2829

2930
static void tdeheap_rmgr_redo(XLogReaderState *record);
3031
static void tdeheap_rmgr_desc(StringInfo buf, XLogReaderState *record);
@@ -52,7 +53,7 @@ tdeheap_rmgr_redo(XLogReaderState *record)
5253
{
5354
XLogRelKey *xlrec = (XLogRelKey *) XLogRecGetData(record);
5455

55-
pg_tde_create_smgr_key_perm_redo(&xlrec->rlocator);
56+
tde_smgr_create_key_redo(&xlrec->rlocator);
5657
}
5758
else if (info == XLOG_TDE_ADD_PRINCIPAL_KEY)
5859
{

contrib/pg_tde/src/common/pg_tde_utils.c

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,7 @@
1616

1717
#ifndef FRONTEND
1818
#include "fmgr.h"
19-
#include "catalog/pg_class.h"
20-
#include "access/pg_tde_tdemap.h"
19+
#include "smgr/pg_tde_smgr.h"
2120
#include "access/relation.h"
2221
#include "utils/rel.h"
2322

@@ -28,7 +27,6 @@ pg_tde_is_encrypted(PG_FUNCTION_ARGS)
2827
Oid relationOid = PG_GETARG_OID(0);
2928
LOCKMODE lockmode = AccessShareLock;
3029
Relation rel = relation_open(relationOid, lockmode);
31-
RelFileLocatorBackend rlocator = {.locator = rel->rd_locator,.backend = rel->rd_backend};
3230
bool result;
3331

3432
if (!RELKIND_HAS_STORAGE(rel->rd_rel->relkind))
@@ -42,7 +40,7 @@ pg_tde_is_encrypted(PG_FUNCTION_ARGS)
4240
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4341
errmsg("we cannot check if temporary relations from other backends are encrypted"));
4442

45-
result = IsSMGRRelationEncrypted(rlocator);
43+
result = tde_smgr_rel_is_encrypted(RelationGetSmgr(rel));
4644

4745
relation_close(rel, lockmode);
4846

0 commit comments

Comments
 (0)