|
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 | staticRelation
|
790 | 793 | RelationBuildDesc(OidtargetRelId,Relationoldrelation)
|
@@ -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 | staticvoid
|
1613 | 1620 | RelationReloadIndexInfo(Relationrelation)
|
@@ -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 | staticvoid
|
1697 | 1707 | RelationClearRelation(Relationrelation,boolrebuild)
|
@@ -2542,12 +2552,14 @@ RelationCacheInitializePhase2(void)
|
2542 | 2552 |
|
2543 | 2553 | #defineLOAD_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);
|
|