fix_do_pg_abort_backup_v12_fujii.patch
application/octet-stream
Filename: fix_do_pg_abort_backup_v12_fujii.patch
Type: application/octet-stream
Part: 0
Patch
Format: context
Series: patch v12
| File | + | − |
|---|---|---|
| src/backend/access/transam/xlog.c | 32 | 0 |
| src/backend/replication/basebackup.c | 3 | 0 |
*** a/src/backend/access/transam/xlog.c
--- b/src/backend/access/transam/xlog.c
***************
*** 10628,10640 **** do_pg_start_backup(const char *backupidstr, bool fast, TimeLineID *starttli_p,
/*
* Mark that start phase has correctly finished for an exclusive backup.
* Session-level locks are updated as well to reflect that state.
*/
if (exclusive)
{
WALInsertLockAcquireExclusive();
XLogCtl->Insert.exclusiveBackupState = EXCLUSIVE_BACKUP_IN_PROGRESS;
! WALInsertLockRelease();
sessionBackupState = SESSION_BACKUP_EXCLUSIVE;
}
else
sessionBackupState = SESSION_BACKUP_NON_EXCLUSIVE;
--- 10628,10647 ----
/*
* Mark that start phase has correctly finished for an exclusive backup.
* Session-level locks are updated as well to reflect that state.
+ *
+ * Note that CHECK_FOR_INTERRUPTS() must not occur while updating
+ * backup counters and session-level lock. Otherwise they can be
+ * updated inconsistently, and which might cause do_pg_abort_backup()
+ * to fail.
*/
if (exclusive)
{
WALInsertLockAcquireExclusive();
XLogCtl->Insert.exclusiveBackupState = EXCLUSIVE_BACKUP_IN_PROGRESS;
!
! /* Set session-level lock */
sessionBackupState = SESSION_BACKUP_EXCLUSIVE;
+ WALInsertLockRelease();
}
else
sessionBackupState = SESSION_BACKUP_NON_EXCLUSIVE;
***************
*** 10838,10844 **** do_pg_stop_backup(char *labelfile, bool waitforarchive, TimeLineID *stoptli_p)
}
/*
! * OK to update backup counters and forcePageWrites
*/
WALInsertLockAcquireExclusive();
if (exclusive)
--- 10845,10855 ----
}
/*
! * OK to update backup counters, forcePageWrites and session-level lock.
! *
! * Note that CHECK_FOR_INTERRUPTS() must not occur while updating them.
! * Otherwise they can be updated inconsistently, and which might cause
! * do_pg_abort_backup() to fail.
*/
WALInsertLockAcquireExclusive();
if (exclusive)
***************
*** 10862,10872 **** do_pg_stop_backup(char *labelfile, bool waitforarchive, TimeLineID *stoptli_p)
{
XLogCtl->Insert.forcePageWrites = false;
}
- WALInsertLockRelease();
! /* Clean up session-level lock */
sessionBackupState = SESSION_BACKUP_NONE;
/*
* Read and parse the START WAL LOCATION line (this code is pretty crude,
* but we are not expecting any variability in the file format).
--- 10873,10892 ----
{
XLogCtl->Insert.forcePageWrites = false;
}
! /*
! * Clean up session-level lock.
! *
! * You might think that WALInsertLockRelease() can be called
! * before cleaning up session-level lock because session-level
! * lock doesn't need to be protected with WAL insertion lock.
! * But since CHECK_FOR_INTERRUPTS() can occur in it,
! * session-level lock must be cleaned up before it.
! */
sessionBackupState = SESSION_BACKUP_NONE;
+ WALInsertLockRelease();
+
/*
* Read and parse the START WAL LOCATION line (this code is pretty crude,
* but we are not expecting any variability in the file format).
***************
*** 11104,11111 **** do_pg_stop_backup(char *labelfile, bool waitforarchive, TimeLineID *stoptli_p)
--- 11124,11139 ----
void
do_pg_abort_backup(void)
{
+ /*
+ * Quick exit if session is not keeping around a non-exclusive backup
+ * already started.
+ */
+ if (sessionBackupState == SESSION_BACKUP_NONE)
+ return;
+
WALInsertLockAcquireExclusive();
Assert(XLogCtl->Insert.nonExclusiveBackups > 0);
+ Assert(sessionBackupState == SESSION_BACKUP_NON_EXCLUSIVE);
XLogCtl->Insert.nonExclusiveBackups--;
if (XLogCtl->Insert.exclusiveBackupState == EXCLUSIVE_BACKUP_NONE &&
*** a/src/backend/replication/basebackup.c
--- b/src/backend/replication/basebackup.c
***************
*** 215,221 **** perform_base_backup(basebackup_options *opt)
* Once do_pg_start_backup has been called, ensure that any failure causes
* us to abort the backup so we don't "leak" a backup counter. For this
* reason, *all* functionality between do_pg_start_backup() and
! * do_pg_stop_backup() should be inside the error cleanup block!
*/
PG_ENSURE_ERROR_CLEANUP(base_backup_cleanup, (Datum) 0);
--- 215,221 ----
* Once do_pg_start_backup has been called, ensure that any failure causes
* us to abort the backup so we don't "leak" a backup counter. For this
* reason, *all* functionality between do_pg_start_backup() and
! * the end of do_pg_stop_backup() should be inside the error cleanup block!
*/
PG_ENSURE_ERROR_CLEANUP(base_backup_cleanup, (Datum) 0);
***************
*** 324,333 **** perform_base_backup(basebackup_options *opt)
else
pq_putemptymessage('c'); /* CopyDone */
}
}
PG_END_ENSURE_ERROR_CLEANUP(base_backup_cleanup, (Datum) 0);
- endptr = do_pg_stop_backup(labelfile->data, !opt->nowait, &endtli);
if (opt->includewal)
{
--- 324,334 ----
else
pq_putemptymessage('c'); /* CopyDone */
}
+
+ endptr = do_pg_stop_backup(labelfile->data, !opt->nowait, &endtli);
}
PG_END_ENSURE_ERROR_CLEANUP(base_backup_cleanup, (Datum) 0);
if (opt->includewal)
{