@@ -792,59 +792,74 @@ XLogInsertRecord(XLogRecData *rdata,
792792 *----------
793793 */
794794 START_CRIT_SECTION ();
795- if (isLogSwitch )
796- WALInsertLockAcquireExclusive ();
797- else
798- WALInsertLockAcquire ();
799795
800- /*
801- * Check to see if my copy of RedoRecPtr is out of date. If so, may have
802- * to go back and have the caller recompute everything. This can only
803- * happen just after a checkpoint, so it's better to be slow in this case
804- * and fast otherwise.
805- *
806- * Also check to see if fullPageWrites was just turned on or there's a
807- * running backup (which forces full-page writes); if we weren't already
808- * doing full-page writes then go back and recompute.
809- *
810- * If we aren't doing full-page writes then RedoRecPtr doesn't actually
811- * affect the contents of the XLOG record, so we'll update our local copy
812- * but not force a recomputation. (If doPageWrites was just turned off,
813- * we could recompute the record without full pages, but we choose not to
814- * bother.)
815- */
816- if (RedoRecPtr != Insert -> RedoRecPtr )
796+ if (likely (!isLogSwitch ))
817797 {
818- Assert (RedoRecPtr < Insert -> RedoRecPtr );
819- RedoRecPtr = Insert -> RedoRecPtr ;
820- }
821- doPageWrites = (Insert -> fullPageWrites || Insert -> runningBackups > 0 );
798+ WALInsertLockAcquire ();
822799
823- if (doPageWrites &&
824- (!prevDoPageWrites ||
825- (fpw_lsn != InvalidXLogRecPtr && fpw_lsn <= RedoRecPtr )))
826- {
827800 /*
828- * Oops, some buffer now needs to be backed up that the caller didn't
829- * back up. Start over.
801+ * Check to see if my copy of RedoRecPtr is out of date. If so, may
802+ * have to go back and have the caller recompute everything. This can
803+ * only happen just after a checkpoint, so it's better to be slow in
804+ * this case and fast otherwise.
805+ *
806+ * Also check to see if fullPageWrites was just turned on or there's a
807+ * running backup (which forces full-page writes); if we weren't
808+ * already doing full-page writes then go back and recompute.
809+ *
810+ * If we aren't doing full-page writes then RedoRecPtr doesn't
811+ * actually affect the contents of the XLOG record, so we'll update
812+ * our local copy but not force a recomputation. (If doPageWrites was
813+ * just turned off, we could recompute the record without full pages,
814+ * but we choose not to bother.)
830815 */
831- WALInsertLockRelease ();
832- END_CRIT_SECTION ();
833- return InvalidXLogRecPtr ;
834- }
816+ if (RedoRecPtr != Insert -> RedoRecPtr )
817+ {
818+ Assert (RedoRecPtr < Insert -> RedoRecPtr );
819+ RedoRecPtr = Insert -> RedoRecPtr ;
820+ }
821+ doPageWrites = (Insert -> fullPageWrites || Insert -> runningBackups > 0 );
835822
836- /*
837- * Reserve space for the record in the WAL. This also sets the xl_prev
838- * pointer.
839- */
840- if (isLogSwitch )
841- inserted = ReserveXLogSwitch (& StartPos , & EndPos , & rechdr -> xl_prev );
842- else
843- {
823+ if (doPageWrites &&
824+ (!prevDoPageWrites ||
825+ (fpw_lsn != InvalidXLogRecPtr && fpw_lsn <= RedoRecPtr )))
826+ {
827+ /*
828+ * Oops, some buffer now needs to be backed up that the caller
829+ * didn't back up. Start over.
830+ */
831+ WALInsertLockRelease ();
832+ END_CRIT_SECTION ();
833+ return InvalidXLogRecPtr ;
834+ }
835+
836+ /*
837+ * Reserve space for the record in the WAL. This also sets the xl_prev
838+ * pointer.
839+ */
844840 ReserveXLogInsertLocation (rechdr -> xl_tot_len , & StartPos , & EndPos ,
845841 & rechdr -> xl_prev );
842+
843+ /* Normal records are always inserted. */
846844 inserted = true;
847845 }
846+ else
847+ {
848+ /*
849+ * In order to insert an XLOG_SWITCH record, we need to hold all of
850+ * the WAL insertion locks, not just one, so that no one else can
851+ * begin inserting a record until we've figured out how much space
852+ * remains in the current WAL segment and claimed all of it.
853+ *
854+ * Nonetheless, this case is simpler than the normal cases handled
855+ * above, which must check for changes in doPageWrites and RedoRecPtr.
856+ * Those checks are only needed for records that can contain
857+ * full-pages images, and an XLOG_SWITCH record never does.
858+ */
859+ Assert (fpw_lsn == InvalidXLogRecPtr );
860+ WALInsertLockAcquireExclusive ();
861+ inserted = ReserveXLogSwitch (& StartPos , & EndPos , & rechdr -> xl_prev );
862+ }
848863
849864 if (inserted )
850865 {
0 commit comments