postgres.git / summary / log / commit / refs

commit    07615108062b2c271b4697ba68fa8c11335ecbce
Author:   Peter Geoghegan <pg@bowt.ie>
Date:     Wed Aug 19 16:30:58 2026 +0000

    Fix GIN VACUUM posting tree root split bug.
    
    ginVacuumPostingTreeLeaves swaps a shared buffer lock for an exclusive
    one when it encounters a leaf page.  It neglected to re-verify whether a
    page that was initially a leaf root page became an internal page due to
    a concurrent root page split (during the window when no lock was held).
    It was therefore possible for GIN VACUUM to spuriously treat an internal
    page as a leaf page, leading to data corruption.  VACUUM could miss dead
    TIDs that it was required to remove, leaving behind dangling references
    in the index.
    
    To fix, re-verify that a leaf page is still a leaf page after an
    exclusive lock is acquired.  If it isn't, drop our exclusive lock and
    acquire a shared lock so that the non-leaf root page gets processed in
    the usual way.
    
    Oversight in commit fd83c83d, which fixed a deadlock bug in GIN posting
    tree vacuuming.
    
    Author: Peter Geoghegan <pg@bowt.ie>
    Reviewed-by: Andrey Borodin <x4mmm@yandex-team.ru>
    Discussion: https://postgr.es/m/CAH2-Wz=RBpJTQgvOxr6C=J04dExmFSt1E3F-r+cRTQ56hEotkg@mail.gmail.com
    Backpatch-through: 14


src/backend/access/gin/ginvacuum.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/backend/access/gin/ginvacuum.c b/src/backend/access/gin/ginvacuum.c index fe004e6ffe3..f4d0e03bd51 100644 --- a/src/backend/access/gin/ginvacuum.c +++ b/src/backend/access/gin/ginvacuum.c @@ -366,6 +366,16 @@ ginVacuumPostingTreeLeaves(GinVacuumState *gvs, BlockNumber blkno) { LockBuffer(buffer, GIN_UNLOCK); LockBuffer(buffer, GIN_EXCLUSIVE); + + if (!GinPageIsLeaf(page)) + { + /* + * The root page was a leaf page, but became an internal page + * while no lock was held. Unlock and reacquire a share lock. + */ + UnlockReleaseBuffer(buffer); + continue; + } break; } [parent: bc18487fe1ca]