Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit4513d9d

Browse files
committed
It turns out that TablespaceCreateDbspace fails badly if a relcache flush
occurs when it tries to heap_open pg_tablespace. When control returns tosmgrcreate, that routine will be holding a dangling pointer to a closedSMgrRelation, resulting in mayhem. This is of course a consequence ofthe violation of proper module layering inherent in having smgr.c calla tablespace command routine, but the simplest fix seems to be to changethe locking mechanism. There's no real need for TablespaceCreateDbspaceto touch pg_tablespace at all --- it's only opening it as a way of lockingagainst a parallel DROP TABLESPACE command. A much better answer is tocreate a special-purpose LWLock to interlock these two operations.This drops TablespaceCreateDbspace quite a few layers down the food chainand makes it something reasonably safe for smgr to call.
1 parentb0be247 commit4513d9d

File tree

2 files changed

+27
-30
lines changed

2 files changed

+27
-30
lines changed

‎src/backend/commands/tablespace.c

Lines changed: 25 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@
3737
*
3838
*
3939
* IDENTIFICATION
40-
* $PostgreSQL: pgsql/src/backend/commands/tablespace.c,v 1.28 2005/10/15 02:49:15 momjian Exp $
40+
* $PostgreSQL: pgsql/src/backend/commands/tablespace.c,v 1.29 2006/01/19 04:45:38 tgl Exp $
4141
*
4242
*-------------------------------------------------------------------------
4343
*/
@@ -83,12 +83,9 @@ static void set_short_version(const char *path);
8383
* If tablespaces are not supported, this is just a no-op; CREATE DATABASE
8484
* is expected to create the default subdirectory for the database.
8585
*
86-
* isRedo indicates that we are creating an object during WAL replay;
87-
* we can skip doing locking in that case (and should do so to avoid
88-
* any possible problems with pg_tablespace not being valid).
89-
*
90-
* Also, when isRedo is true, we will cope with the possibility of the
91-
* tablespace not being there either --- this could happen if we are
86+
* isRedo indicates that we are creating an object during WAL replay.
87+
* In this case we will cope with the possibility of the tablespace
88+
* directory not being there either --- this could happen if we are
9289
* replaying an operation on a table in a subsequently-dropped tablespace.
9390
* We handle this by making a directory in the place where the tablespace
9491
* symlink would normally be. This isn't an exact replay of course, but
@@ -118,16 +115,10 @@ TablespaceCreateDbspace(Oid spcNode, Oid dbNode, bool isRedo)
118115
if (errno==ENOENT)
119116
{
120117
/*
121-
* Acquire ExclusiveLock on pg_tablespace to ensure that no DROP
122-
* TABLESPACE or TablespaceCreateDbspace is running concurrently.
123-
* Simple reads from pg_tablespace are OK.
118+
* Acquire TablespaceCreateLock to ensure that no DROP TABLESPACE
119+
* or TablespaceCreateDbspace is running concurrently.
124120
*/
125-
Relationrel;
126-
127-
if (!isRedo)
128-
rel=heap_open(TableSpaceRelationId,ExclusiveLock);
129-
else
130-
rel=NULL;
121+
LWLockAcquire(TablespaceCreateLock,LW_EXCLUSIVE);
131122

132123
/*
133124
* Recheck to see if someone created the directory while we were
@@ -166,9 +157,7 @@ TablespaceCreateDbspace(Oid spcNode, Oid dbNode, bool isRedo)
166157
}
167158
}
168159

169-
/* OK to drop the exclusive lock */
170-
if (!isRedo)
171-
heap_close(rel,ExclusiveLock);
160+
LWLockRelease(TablespaceCreateLock);
172161
}
173162
else
174163
{
@@ -401,15 +390,11 @@ DropTableSpace(DropTableSpaceStmt *stmt)
401390
/* don't call this in a transaction block */
402391
PreventTransactionChain((void*)stmt,"DROP TABLESPACE");
403392

404-
/*
405-
* Acquire ExclusiveLock on pg_tablespace to ensure that no one else is
406-
* trying to do DROP TABLESPACE or TablespaceCreateDbspace concurrently.
407-
*/
408-
rel=heap_open(TableSpaceRelationId,ExclusiveLock);
409-
410393
/*
411394
* Find the target tuple
412395
*/
396+
rel=heap_open(TableSpaceRelationId,RowExclusiveLock);
397+
413398
ScanKeyInit(&entry[0],
414399
Anum_pg_tablespace_spcname,
415400
BTEqualStrategyNumber,F_NAMEEQ,
@@ -448,6 +433,12 @@ DropTableSpace(DropTableSpaceStmt *stmt)
448433
*/
449434
deleteSharedDependencyRecordsFor(TableSpaceRelationId,tablespaceoid);
450435

436+
/*
437+
* Acquire TablespaceCreateLock to ensure that no TablespaceCreateDbspace
438+
* is running concurrently.
439+
*/
440+
LWLockAcquire(TablespaceCreateLock,LW_EXCLUSIVE);
441+
451442
/*
452443
* Try to remove the physical infrastructure
453444
*/
@@ -471,6 +462,11 @@ DropTableSpace(DropTableSpaceStmt *stmt)
471462
(void)XLogInsert(RM_TBLSPC_ID,XLOG_TBLSPC_DROP,rdata);
472463
}
473464

465+
/*
466+
* Allow TablespaceCreateDbspace again.
467+
*/
468+
LWLockRelease(TablespaceCreateLock);
469+
474470
/* We keep the lock on pg_tablespace until commit */
475471
heap_close(rel,NoLock);
476472
#else/* !HAVE_SYMLINK */
@@ -507,10 +503,10 @@ remove_tablespace_directories(Oid tablespaceoid, bool redo)
507503
* use the tablespace from that database will simply recreate the
508504
* subdirectory via TablespaceCreateDbspace.)
509505
*
510-
* Since we holdexclusive lock, no one else should be creating any fresh
511-
* subdirectories in parallel.It is possible that new files are being
512-
* created within subdirectories, though, so the rmdir call could fail.
513-
* Worst consequence is a less friendly error message.
506+
* Since we holdTablespaceCreateLock, no one else should be creating any
507+
*freshsubdirectories in parallel.It is possible that new files are
508+
*beingcreated within subdirectories, though, so the rmdir call could
509+
*fail.Worst consequence is a less friendly error message.
514510
*/
515511
dirdesc=AllocateDir(location);
516512
if (dirdesc==NULL)

‎src/include/storage/lwlock.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
88
* Portions Copyright (c) 1994, Regents of the University of California
99
*
10-
* $PostgreSQL: pgsql/src/include/storage/lwlock.h,v 1.25 2006/01/04 21:06:32 tgl Exp $
10+
* $PostgreSQL: pgsql/src/include/storage/lwlock.h,v 1.26 2006/01/19 04:45:38 tgl Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -46,6 +46,7 @@ typedef enum LWLockId
4646
RelCacheInitLock,
4747
BgWriterCommLock,
4848
TwoPhaseStateLock,
49+
TablespaceCreateLock,
4950
FirstLockMgrLock,/* must be last except for MaxDynamicLWLock */
5051

5152
MaxDynamicLWLock=1000000000

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp