*** pgsql/src/backend/utils/cache/relcache.c 2008/04/01 00:48:33 1.270 --- pgsql/src/backend/utils/cache/relcache.c 2008/04/16 18:23:04 1.271 *************** *** 8,14 **** * * * IDENTIFICATION ! * $PostgreSQL: pgsql/src/backend/utils/cache/relcache.c,v 1.269 2008/03/26 21:10:39 alvherre Exp $ * *------------------------------------------------------------------------- */ --- 8,14 ---- * * * IDENTIFICATION ! * $PostgreSQL: pgsql/src/backend/utils/cache/relcache.c,v 1.270 2008/04/01 00:48:33 tgl Exp $ * *------------------------------------------------------------------------- */ *************** static OpClassCacheEnt *LookupOpclassInf *** 220,227 **** /* * ScanPgRelation * ! * this is used by RelationBuildDesc to find a pg_class ! * tuple matching targetRelId. * * NB: the returned tuple has been copied into palloc'd storage * and must eventually be freed with heap_freetuple. --- 220,230 ---- /* * ScanPgRelation * ! * This is used by RelationBuildDesc to find a pg_class ! * tuple matching targetRelId. The caller must hold at least ! * AccessShareLock on the target relid to prevent concurrent-update ! * scenarios --- else our SnapshotNow scan might fail to find any ! * version that it thinks is live. * * NB: the returned tuple has been copied into palloc'd storage * and must eventually be freed with heap_freetuple. *************** equalRuleLocks(RuleLock *rlock1, RuleLoc *** 773,790 **** } ! /* ---------------------------------- * RelationBuildDesc * * Build a relation descriptor --- either a new one, or by * recycling the given old relation object. The latter case * supports rebuilding a relcache entry without invalidating ! * pointers to it. * * Returns NULL if no pg_class row could be found for the given relid * (suggesting we are trying to access a just-deleted relation). * Any other error is reported via elog. - * -------------------------------- */ static Relation RelationBuildDesc(Oid targetRelId, Relation oldrelation) --- 776,793 ---- } ! /* * RelationBuildDesc * * Build a relation descriptor --- either a new one, or by * recycling the given old relation object. The latter case * supports rebuilding a relcache entry without invalidating ! * pointers to it. The caller must hold at least ! * AccessShareLock on the target relid. * * Returns NULL if no pg_class row could be found for the given relid * (suggesting we are trying to access a just-deleted relation). * Any other error is reported via elog. */ static Relation RelationBuildDesc(Oid targetRelId, Relation oldrelation) *************** RelationClose(Relation relation) *** 1608,1613 **** --- 1611,1620 ---- * RelationClearRelation just marks the entry as invalid by setting * rd_isvalid to false. This routine is called to fix the entry when it * is next needed. + * + * We assume that at the time we are called, we have at least AccessShareLock + * on the target index. (Note: in the calls from RelationClearRelation, + * this is legitimate because we know the rel has positive refcount.) */ static void RelationReloadIndexInfo(Relation relation) *************** RelationReloadIndexInfo(Relation relatio *** 1692,1697 **** --- 1699,1707 ---- * usually used when we are notified of a change to an open relation * (one with refcount > 0). However, this routine just does whichever * it's told to do; callers must determine which they want. + * + * NB: when rebuilding, we'd better hold some lock on the relation. + * In current usages this is presumed true because it has refcnt > 0. */ static void RelationClearRelation(Relation relation, bool rebuild) *************** RelationCacheInitializePhase2(void) *** 2542,2553 **** --- 2552,2565 ---- #define LOAD_CRIT_INDEX(indexoid) \ do { \ + LockRelationOid(indexoid, AccessShareLock); \ ird = RelationBuildDesc(indexoid, NULL); \ if (ird == NULL) \ elog(PANIC, "could not open critical system index %u", \ indexoid); \ ird->rd_isnailed = true; \ ird->rd_refcnt = 1; \ + UnlockRelationOid(indexoid, AccessShareLock); \ } while (0) LOAD_CRIT_INDEX(ClassOidIndexId);