On 2019-04-30 17:17, Andres Freund wrote:
>       indOid = RangeVarGetRelidExtended(indexRelation,
>                                                                         
> concurrent ? ShareUpdateExclusiveLock : AccessExclusiveLock,
>                                                                         0,
>                                                                         
> RangeVarCallbackForReindexIndex,
>                                                                         (void 
> *) &heapOid);
> 
> doesn't pass concurrent-ness to RangeVarCallbackForReindexIndex(). Which
> then goes on to lock the table
> 
> static void
> RangeVarCallbackForReindexIndex(const RangeVar *relation,
>                                                               Oid relId, Oid 
> oldRelId, void *arg)
> 
>               if (OidIsValid(*heapOid))
>                       LockRelationOid(*heapOid, ShareLock);
> 
> without knowing that it should use ShareUpdateExclusive. Which
> e.g. ReindexTable knows:
> 
>       /* The lock level used here should match reindex_relation(). */
>       heapOid = RangeVarGetRelidExtended(relation,
>                                                                          
> concurrent ? ShareUpdateExclusiveLock : ShareLock,
>                                                                          0,
>                                                                          
> RangeVarCallbackOwnsTable, NULL);
> 
> so there's a lock upgrade hazard.

Confirmed.

What seems weird to me is that the existing callback argument heapOid
isn't used at all.  It seems to have been like that since the original
commit of the callback infrastructure.  Therefore also, this code

    if (relId != oldRelId && OidIsValid(oldRelId))
    {
        /* lock level here should match reindex_index() heap lock */
        UnlockRelationOid(*heapOid, ShareLock);

in RangeVarCallbackForReindexIndex() can't ever do anything useful.

Patch to remove the unused code attached; but needs some checking for
this dubious conditional block.

Thoughts?


-- 
Peter Eisentraut              http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services
From 89db1445787b3fb676ecfa07964682e72a58e7bb Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <pe...@eisentraut.org>
Date: Thu, 2 May 2019 10:38:06 +0200
Subject: [PATCH] Remove unused argument of RangeVarCallbackForReindexIndex()

---
 src/backend/commands/indexcmds.c | 22 ++++------------------
 1 file changed, 4 insertions(+), 18 deletions(-)

diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c
index fabba3bacd..2800255d9d 100644
--- a/src/backend/commands/indexcmds.c
+++ b/src/backend/commands/indexcmds.c
@@ -2304,7 +2304,6 @@ void
 ReindexIndex(RangeVar *indexRelation, int options, bool concurrent)
 {
        Oid                     indOid;
-       Oid                     heapOid = InvalidOid;
        Relation        irel;
        char            persistence;
 
@@ -2317,7 +2316,7 @@ ReindexIndex(RangeVar *indexRelation, int options, bool 
concurrent)
                                                                          
concurrent ? ShareUpdateExclusiveLock : AccessExclusiveLock,
                                                                          0,
                                                                          
RangeVarCallbackForReindexIndex,
-                                                                         (void 
*) &heapOid);
+                                                                         NULL);
 
        /*
         * Obtain the current persistence of the existing index.  We already 
hold
@@ -2350,19 +2349,6 @@ RangeVarCallbackForReindexIndex(const RangeVar *relation,
                                                                Oid relId, Oid 
oldRelId, void *arg)
 {
        char            relkind;
-       Oid                *heapOid = (Oid *) arg;
-
-       /*
-        * If we previously locked some other index's heap, and the name we're
-        * looking up no longer refers to that relation, release the now-useless
-        * lock.
-        */
-       if (relId != oldRelId && OidIsValid(oldRelId))
-       {
-               /* lock level here should match reindex_index() heap lock */
-               UnlockRelationOid(*heapOid, ShareLock);
-               *heapOid = InvalidOid;
-       }
 
        /* If the relation does not exist, there's nothing more to do. */
        if (!OidIsValid(relId))
@@ -2394,9 +2380,9 @@ RangeVarCallbackForReindexIndex(const RangeVar *relation,
                 * isn't valid, it means the index as concurrently dropped, 
which is
                 * not a problem for us; just return normally.
                 */
-               *heapOid = IndexGetRelation(relId, true);
-               if (OidIsValid(*heapOid))
-                       LockRelationOid(*heapOid, ShareLock);
+               Oid                     heapOid = IndexGetRelation(relId, true);
+               if (OidIsValid(heapOid))
+                       LockRelationOid(heapOid, ShareLock);
        }
 }
 
-- 
2.21.0

Reply via email to