From: Heikki Linnakangas Date: Fri, 4 Apr 2014 14:29:50 +0000 (+0300) Subject: In checkpoint, move the check for in-progress xacts out of critical section. X-Git-Tag: REL9_4_BETA1~232 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=d9e7873bbbdee76a49e76ddaa49787cab112bb2e;p=postgresql 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. --- diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c index e2a14de721..3a48227ad9 100644 --- a/src/backend/access/transam/xlog.c +++ b/src/backend/access/transam/xlog.c @@ -8076,6 +8076,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 @@ -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); /*