|
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); |
|