aboutsummaryrefslogtreecommitdiff
path: root/src/backend/access/transam/xlog.c
diff options
context:
space:
mode:
authorHeikki Linnakangas <heikki.linnakangas@iki.fi>2014-04-04 17:29:50 +0300
committerHeikki Linnakangas <heikki.linnakangas@iki.fi>2014-04-04 17:31:22 +0300
commitd9e7873bbbdee76a49e76ddaa49787cab112bb2e (patch)
tree7444a92e486cb257900f1dc78fe742e40b7ba26a /src/backend/access/transam/xlog.c
parent4a170ee9e0ebd7021cb1190fabd5b0cbe2effb8e (diff)
downloadpostgresql-d9e7873bbbdee76a49e76ddaa49787cab112bb2e.tar.gz
postgresql-d9e7873bbbdee76a49e76ddaa49787cab112bb2e.zip
In checkpoint, move the check for in-progress xacts out of critical section.
GetVirtualXIDsDelayingChkpt calls palloc, which isn't safe in a critical section. I thought I covered this case with the exemption for the checkpointer, but CreateCheckPoint is also called from the startup process.
Diffstat (limited to 'src/backend/access/transam/xlog.c')
-rw-r--r--src/backend/access/transam/xlog.c72
1 files changed, 36 insertions, 36 deletions
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index e2a14de7212..3a48227ad93 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -8077,6 +8077,42 @@ CreateCheckPoint(int flags)
TRACE_POSTGRESQL_CHECKPOINT_START(flags);
/*
+ * Get the other info we need for the checkpoint record.
+ */
+ LWLockAcquire(XidGenLock, LW_SHARED);
+ checkPoint.nextXid = ShmemVariableCache->nextXid;
+ checkPoint.oldestXid = ShmemVariableCache->oldestXid;
+ checkPoint.oldestXidDB = ShmemVariableCache->oldestXidDB;
+ LWLockRelease(XidGenLock);
+
+ /* Increase XID epoch if we've wrapped around since last checkpoint */
+ checkPoint.nextXidEpoch = ControlFile->checkPointCopy.nextXidEpoch;
+ if (checkPoint.nextXid < ControlFile->checkPointCopy.nextXid)
+ checkPoint.nextXidEpoch++;
+
+ LWLockAcquire(OidGenLock, LW_SHARED);
+ checkPoint.nextOid = ShmemVariableCache->nextOid;
+ if (!shutdown)
+ checkPoint.nextOid += ShmemVariableCache->oidCount;
+ LWLockRelease(OidGenLock);
+
+ MultiXactGetCheckptMulti(shutdown,
+ &checkPoint.nextMulti,
+ &checkPoint.nextMultiOffset,
+ &checkPoint.oldestMulti,
+ &checkPoint.oldestMultiDB);
+
+ /*
+ * Having constructed the checkpoint record, ensure all shmem disk buffers
+ * and commit-log buffers are flushed to disk.
+ *
+ * This I/O could fail for various reasons. If so, we will fail to
+ * complete the checkpoint, but there is no reason to force a system
+ * panic. Accordingly, exit critical section while doing it.
+ */
+ END_CRIT_SECTION();
+
+ /*
* In some cases there are groups of actions that must all occur on one
* side or the other of a checkpoint record. Before flushing the
* checkpoint record we must explicitly wait for any backend currently
@@ -8116,42 +8152,6 @@ CreateCheckPoint(int flags)
}
pfree(vxids);
- /*
- * Get the other info we need for the checkpoint record.
- */
- LWLockAcquire(XidGenLock, LW_SHARED);
- checkPoint.nextXid = ShmemVariableCache->nextXid;
- checkPoint.oldestXid = ShmemVariableCache->oldestXid;
- checkPoint.oldestXidDB = ShmemVariableCache->oldestXidDB;
- LWLockRelease(XidGenLock);
-
- /* Increase XID epoch if we've wrapped around since last checkpoint */
- checkPoint.nextXidEpoch = ControlFile->checkPointCopy.nextXidEpoch;
- if (checkPoint.nextXid < ControlFile->checkPointCopy.nextXid)
- checkPoint.nextXidEpoch++;
-
- LWLockAcquire(OidGenLock, LW_SHARED);
- checkPoint.nextOid = ShmemVariableCache->nextOid;
- if (!shutdown)
- checkPoint.nextOid += ShmemVariableCache->oidCount;
- LWLockRelease(OidGenLock);
-
- MultiXactGetCheckptMulti(shutdown,
- &checkPoint.nextMulti,
- &checkPoint.nextMultiOffset,
- &checkPoint.oldestMulti,
- &checkPoint.oldestMultiDB);
-
- /*
- * Having constructed the checkpoint record, ensure all shmem disk buffers
- * and commit-log buffers are flushed to disk.
- *
- * This I/O could fail for various reasons. If so, we will fail to
- * complete the checkpoint, but there is no reason to force a system
- * panic. Accordingly, exit critical section while doing it.
- */
- END_CRIT_SECTION();
-
CheckPointGuts(checkPoint.redo, flags);
/*