|
8 | 8 | *
|
9 | 9 | *
|
10 | 10 | * IDENTIFICATION
|
11 |
| - * $PostgreSQL: pgsql/src/backend/utils/cache/relcache.c,v 1.270 2008/04/01 00:48:33 tgl Exp $ |
| 11 | + * $PostgreSQL: pgsql/src/backend/utils/cache/relcache.c,v 1.271 2008/04/16 18:23:04 tgl Exp $ |
12 | 12 | *
|
13 | 13 | *-------------------------------------------------------------------------
|
14 | 14 | */
|
@@ -220,8 +220,11 @@ static OpClassCacheEnt *LookupOpclassInfo(Oid operatorClassOid,
|
220 | 220 | /*
|
221 | 221 | * ScanPgRelation
|
222 | 222 | *
|
223 |
| - * this is used by RelationBuildDesc to find a pg_class |
224 |
| - * tuple matching targetRelId. |
| 223 | + * This is used by RelationBuildDesc to find a pg_class |
| 224 | + * tuple matching targetRelId. The caller must hold at least |
| 225 | + * AccessShareLock on the target relid to prevent concurrent-update |
| 226 | + * scenarios --- else our SnapshotNow scan might fail to find any |
| 227 | + * version that it thinks is live. |
225 | 228 | *
|
226 | 229 | * NB: the returned tuple has been copied into palloc'd storage
|
227 | 230 | * and must eventually be freed with heap_freetuple.
|
@@ -773,18 +776,18 @@ equalRuleLocks(RuleLock *rlock1, RuleLock *rlock2)
|
773 | 776 | }
|
774 | 777 |
|
775 | 778 |
|
776 |
| -/* ---------------------------------- |
| 779 | +/* |
777 | 780 | * RelationBuildDesc
|
778 | 781 | *
|
779 | 782 | * Build a relation descriptor --- either a new one, or by
|
780 | 783 | * recycling the given old relation object. The latter case
|
781 | 784 | * supports rebuilding a relcache entry without invalidating
|
782 |
| - * pointers to it. |
| 785 | + * pointers to it. The caller must hold at least |
| 786 | + * AccessShareLock on the target relid. |
783 | 787 | *
|
784 | 788 | * Returns NULL if no pg_class row could be found for the given relid
|
785 | 789 | * (suggesting we are trying to access a just-deleted relation).
|
786 | 790 | * Any other error is reported via elog.
|
787 |
| - * -------------------------------- |
788 | 791 | */
|
789 | 792 | static Relation
|
790 | 793 | RelationBuildDesc(Oid targetRelId, Relation oldrelation)
|
@@ -1608,6 +1611,10 @@ RelationClose(Relation relation)
|
1608 | 1611 | * RelationClearRelation just marks the entry as invalid by setting
|
1609 | 1612 | * rd_isvalid to false. This routine is called to fix the entry when it
|
1610 | 1613 | * is next needed.
|
| 1614 | + * |
| 1615 | + * We assume that at the time we are called, we have at least AccessShareLock |
| 1616 | + * on the target index. (Note: in the calls from RelationClearRelation, |
| 1617 | + * this is legitimate because we know the rel has positive refcount.) |
1611 | 1618 | */
|
1612 | 1619 | static void
|
1613 | 1620 | RelationReloadIndexInfo(Relation relation)
|
@@ -1692,6 +1699,9 @@ RelationReloadIndexInfo(Relation relation)
|
1692 | 1699 | * usually used when we are notified of a change to an open relation
|
1693 | 1700 | * (one with refcount > 0). However, this routine just does whichever
|
1694 | 1701 | * it's told to do; callers must determine which they want.
|
| 1702 | + * |
| 1703 | + * NB: when rebuilding, we'd better hold some lock on the relation. |
| 1704 | + * In current usages this is presumed true because it has refcnt > 0. |
1695 | 1705 | */
|
1696 | 1706 | static void
|
1697 | 1707 | RelationClearRelation(Relation relation, bool rebuild)
|
@@ -2542,12 +2552,14 @@ RelationCacheInitializePhase2(void)
|
2542 | 2552 |
|
2543 | 2553 | #define LOAD_CRIT_INDEX(indexoid) \
|
2544 | 2554 | do { \
|
| 2555 | + LockRelationOid(indexoid, AccessShareLock); \ |
2545 | 2556 | ird = RelationBuildDesc(indexoid, NULL); \
|
2546 | 2557 | if (ird == NULL) \
|
2547 | 2558 | elog(PANIC, "could not open critical system index %u", \
|
2548 | 2559 | indexoid); \
|
2549 | 2560 | ird->rd_isnailed = true; \
|
2550 | 2561 | ird->rd_refcnt = 1; \
|
| 2562 | + UnlockRelationOid(indexoid, AccessShareLock); \ |
2551 | 2563 | } while (0)
|
2552 | 2564 |
|
2553 | 2565 | LOAD_CRIT_INDEX(ClassOidIndexId);
|
|
0 commit comments