Skip to content

Commit e7a9020

Browse files
committed
Code review for recent changes in relcache.c.
rd_replidindex should be managed the same as rd_oidindex, and rd_keyattr and rd_idattr should be managed like rd_indexattr. Omissions in this area meant that the bitmapsets computed for rd_keyattr and rd_idattr would be leaked during any relcache flush, resulting in a slow but permanent leak in CacheMemoryContext. There was also a tiny probability of relcache entry corruption if we ran out of memory at just the wrong point in RelationGetIndexAttrBitmap. Otherwise, the fields were not zeroed where expected, which would not bother the code any AFAICS but could greatly confuse anyone examining the relcache entry while debugging. Also, create an API function RelationGetReplicaIndex rather than letting non-relcache code be intimate with the mechanisms underlying caching of that value (we won't even mention the memory leak there). Also, fix a relcache flush hazard identified by Andres Freund: RelationGetIndexAttrBitmap must not assume that rd_replidindex stays valid across index_open. The aspects of this involving rd_keyattr date back to 9.3, so back-patch those changes.
1 parent d5b912c commit e7a9020

File tree

1 file changed

+12
-3
lines changed

1 file changed

+12
-3
lines changed

src/backend/utils/cache/relcache.c

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1829,6 +1829,7 @@ RelationDestroyRelation(Relation relation)
18291829
FreeTupleDesc(relation->rd_att);
18301830
list_free(relation->rd_indexlist);
18311831
bms_free(relation->rd_indexattr);
1832+
bms_free(relation->rd_keyattr);
18321833
FreeTriggerDesc(relation->trigdesc);
18331834
if (relation->rd_options)
18341835
pfree(relation->rd_options);
@@ -3594,7 +3595,8 @@ insert_ordered_oid(List *list, Oid datum)
35943595
* correctly with respect to the full index set. It is up to the caller
35953596
* to ensure that a correct rd_indexattr set has been cached before first
35963597
* calling RelationSetIndexList; else a subsequent inquiry might cause a
3597-
* wrong rd_indexattr set to get computed and cached.
3598+
* wrong rd_indexattr set to get computed and cached. Likewise, we do not
3599+
* touch rd_keyattr.
35983600
*/
35993601
void
36003602
RelationSetIndexList(Relation relation, List *indexIds, Oid oidIndex)
@@ -3875,10 +3877,16 @@ RelationGetIndexAttrBitmap(Relation relation, bool keyAttrs)
38753877

38763878
list_free(indexoidlist);
38773879

3878-
/* Now save a copy of the bitmap in the relcache entry. */
3880+
/*
3881+
* Now save copies of the bitmaps in the relcache entry. We intentionally
3882+
* set rd_indexattr last, because that's the one that signals validity of
3883+
* the values; if we run out of memory before making that copy, we won't
3884+
* leave the relcache entry looking like the other ones are valid but
3885+
* empty.
3886+
*/
38793887
oldcxt = MemoryContextSwitchTo(CacheMemoryContext);
3880-
relation->rd_indexattr = bms_copy(indexattrs);
38813888
relation->rd_keyattr = bms_copy(uindexattrs);
3889+
relation->rd_indexattr = bms_copy(indexattrs);
38823890
MemoryContextSwitchTo(oldcxt);
38833891

38843892
/* We return our original working copy for caller to play with */
@@ -4423,6 +4431,7 @@ load_relcache_init_file(bool shared)
44234431
rel->rd_indexvalid = 0;
44244432
rel->rd_indexlist = NIL;
44254433
rel->rd_indexattr = NULL;
4434+
rel->rd_keyattr = NULL;
44264435
rel->rd_oidindex = InvalidOid;
44274436
rel->rd_createSubid = InvalidSubTransactionId;
44284437
rel->rd_newRelfilenodeSubid = InvalidSubTransactionId;

0 commit comments

Comments
 (0)