diff options
Diffstat (limited to 'src/backend/access/nbtree/nbtree.c')
-rw-r--r-- | src/backend/access/nbtree/nbtree.c | 26 |
1 files changed, 25 insertions, 1 deletions
diff --git a/src/backend/access/nbtree/nbtree.c b/src/backend/access/nbtree/nbtree.c index 3979f79c358..07b3c8d6f68 100644 --- a/src/backend/access/nbtree/nbtree.c +++ b/src/backend/access/nbtree/nbtree.c @@ -12,7 +12,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtree.c,v 1.106 2003/09/29 23:40:26 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtree.c,v 1.106.2.1 2005/05/07 21:33:21 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -707,11 +707,35 @@ btvacuumcleanup(PG_FUNCTION_ARGS) BlockNumber pages_deleted = 0; MemoryContext mycontext; MemoryContext oldcontext; + bool needLock; Assert(stats != NULL); + /* + * First find out the number of pages in the index. We must acquire + * the relation-extension lock while doing this to avoid a race + * condition: if someone else is extending the relation, there is + * a window where bufmgr/smgr have created a new all-zero page but + * it hasn't yet been write-locked by _bt_getbuf(). If we manage to + * scan such a page here, we'll improperly assume it can be recycled. + * Taking the lock synchronizes things enough to prevent a problem: + * either num_pages won't include the new page, or _bt_getbuf already + * has write lock on the buffer and it will be fully initialized before + * we can examine it. (See also vacuumlazy.c, which has the same issue.) + * + * We can skip locking for new or temp relations, + * however, since no one else could be accessing them. + */ + needLock = !(rel->rd_isnew || rel->rd_istemp); + + if (needLock) + LockPage(rel, 0, ExclusiveLock); + num_pages = RelationGetNumberOfBlocks(rel); + if (needLock) + UnlockPage(rel, 0, ExclusiveLock); + /* No point in remembering more than MaxFSMPages pages */ maxFreePages = MaxFSMPages; if ((BlockNumber) maxFreePages > num_pages) |