*** a/src/backend/access/transam/xlog.c
--- b/src/backend/access/transam/xlog.c
***************
*** 463,468 **** typedef union WALInsertLockPadded
--- 463,491 ----
  } WALInsertLockPadded;
  
  /*
+  * State of an exclusive backup, necessary to control concurrent activities
+  * across sessions when working on exclusive backups.
+  *
+  * EXCLUSIVE_BACKUP_NONE means that there is no exclusive backup actually
+  * running, to be more precise pg_start_backup() is not being executed for
+  * an exclusive backup and there is no exclusive backup in progress.
+  * EXCLUSIVE_BACKUP_STARTING means that pg_start_backup() is starting an
+  * exclusive backup.
+  * EXCLUSIVE_BACKUP_IN_PROGRESS means that pg_start_backup() has finished
+  * running and an exclusive backup is in progress. pg_stop_backup() is
+  * needed to finish it.
+  * EXCLUSIVE_BACKUP_STOPPING means that pg_stop_backup() is stopping an
+  * exclusive backup.
+  */
+ typedef enum ExclusiveBackupState
+ {
+ 	EXCLUSIVE_BACKUP_NONE = 0,
+ 	EXCLUSIVE_BACKUP_STARTING,
+ 	EXCLUSIVE_BACKUP_IN_PROGRESS,
+ 	EXCLUSIVE_BACKUP_STOPPING
+ } ExclusiveBackupState;
+ 
+ /*
   * Shared state data for WAL insertion.
   */
  typedef struct XLogCtlInsert
***************
*** 503,515 **** typedef struct XLogCtlInsert
  	bool		fullPageWrites;
  
  	/*
! 	 * exclusiveBackup is true if a backup started with pg_start_backup() is
! 	 * in progress, and nonExclusiveBackups is a counter indicating the number
  	 * of streaming base backups currently in progress. forcePageWrites is set
  	 * to true when either of these is non-zero. lastBackupStart is the latest
  	 * checkpoint redo location used as a starting point for an online backup.
  	 */
! 	bool		exclusiveBackup;
  	int			nonExclusiveBackups;
  	XLogRecPtr	lastBackupStart;
  
--- 526,539 ----
  	bool		fullPageWrites;
  
  	/*
! 	 * exclusiveBackupState indicates the state of an exclusive backup
! 	 * (see comments for ExclusiveBackupState for more detail).
! 	 * nonExclusiveBackups is a counter indicating the number
  	 * of streaming base backups currently in progress. forcePageWrites is set
  	 * to true when either of these is non-zero. lastBackupStart is the latest
  	 * checkpoint redo location used as a starting point for an online backup.
  	 */
! 	ExclusiveBackupState exclusiveBackupState;
  	int			nonExclusiveBackups;
  	XLogRecPtr	lastBackupStart;
  
***************
*** 848,853 **** static void xlog_outrec(StringInfo buf, XLogReaderState *record);
--- 872,878 ----
  #endif
  static void xlog_outdesc(StringInfo buf, XLogReaderState *record);
  static void pg_start_backup_callback(int code, Datum arg);
+ static void pg_stop_backup_callback(int code, Datum arg);
  static bool read_backup_label(XLogRecPtr *checkPointLoc,
  				  bool *backupEndRequired, bool *backupFromStandby);
  static bool read_tablespace_map(List **tablespaces);
***************
*** 9957,9963 **** do_pg_start_backup(const char *backupidstr, bool fast, TimeLineID *starttli_p,
  	WALInsertLockAcquireExclusive();
  	if (exclusive)
  	{
! 		if (XLogCtl->Insert.exclusiveBackup)
  		{
  			WALInsertLockRelease();
  			ereport(ERROR,
--- 9982,9993 ----
  	WALInsertLockAcquireExclusive();
  	if (exclusive)
  	{
! 		/*
! 		 * At first, mark that we're now starting an exclusive backup,
! 		 * to ensure that there are no other sessions currently running
! 		 * pg_start_backup() or pg_stop_backup().
! 		 */
! 		if (XLogCtl->Insert.exclusiveBackupState != EXCLUSIVE_BACKUP_NONE)
  		{
  			WALInsertLockRelease();
  			ereport(ERROR,
***************
*** 9965,9971 **** do_pg_start_backup(const char *backupidstr, bool fast, TimeLineID *starttli_p,
  					 errmsg("a backup is already in progress"),
  					 errhint("Run pg_stop_backup() and try again.")));
  		}
! 		XLogCtl->Insert.exclusiveBackup = true;
  	}
  	else
  		XLogCtl->Insert.nonExclusiveBackups++;
--- 9995,10001 ----
  					 errmsg("a backup is already in progress"),
  					 errhint("Run pg_stop_backup() and try again.")));
  		}
! 		XLogCtl->Insert.exclusiveBackupState = EXCLUSIVE_BACKUP_STARTING;
  	}
  	else
  		XLogCtl->Insert.nonExclusiveBackups++;
***************
*** 10220,10226 **** do_pg_start_backup(const char *backupidstr, bool fast, TimeLineID *starttli_p,
  		{
  			/*
  			 * Check for existing backup label --- implies a backup is already
! 			 * running.  (XXX given that we checked exclusiveBackup above,
  			 * maybe it would be OK to just unlink any such label file?)
  			 */
  			if (stat(BACKUP_LABEL_FILE, &stat_buf) != 0)
--- 10250,10256 ----
  		{
  			/*
  			 * Check for existing backup label --- implies a backup is already
! 			 * running.  (XXX given that we checked exclusiveBackupState above,
  			 * maybe it would be OK to just unlink any such label file?)
  			 */
  			if (stat(BACKUP_LABEL_FILE, &stat_buf) != 0)
***************
*** 10302,10307 **** do_pg_start_backup(const char *backupidstr, bool fast, TimeLineID *starttli_p,
--- 10332,10347 ----
  	PG_END_ENSURE_ERROR_CLEANUP(pg_start_backup_callback, (Datum) BoolGetDatum(exclusive));
  
  	/*
+ 	 * Mark that start phase has correctly finished for an exclusive backup.
+ 	 */
+ 	if (exclusive)
+ 	{
+ 		WALInsertLockAcquireExclusive();
+ 		XLogCtl->Insert.exclusiveBackupState = EXCLUSIVE_BACKUP_IN_PROGRESS;
+ 		WALInsertLockRelease();
+ 	}
+ 
+ 	/*
  	 * We're done.  As a convenience, return the starting WAL location.
  	 */
  	if (starttli_p)
***************
*** 10319,10326 **** pg_start_backup_callback(int code, Datum arg)
  	WALInsertLockAcquireExclusive();
  	if (exclusive)
  	{
! 		Assert(XLogCtl->Insert.exclusiveBackup);
! 		XLogCtl->Insert.exclusiveBackup = false;
  	}
  	else
  	{
--- 10359,10366 ----
  	WALInsertLockAcquireExclusive();
  	if (exclusive)
  	{
! 		Assert(XLogCtl->Insert.exclusiveBackupState == EXCLUSIVE_BACKUP_STARTING);
! 		XLogCtl->Insert.exclusiveBackupState = EXCLUSIVE_BACKUP_NONE;
  	}
  	else
  	{
***************
*** 10328,10334 **** pg_start_backup_callback(int code, Datum arg)
  		XLogCtl->Insert.nonExclusiveBackups--;
  	}
  
! 	if (!XLogCtl->Insert.exclusiveBackup &&
  		XLogCtl->Insert.nonExclusiveBackups == 0)
  	{
  		XLogCtl->Insert.forcePageWrites = false;
--- 10368,10374 ----
  		XLogCtl->Insert.nonExclusiveBackups--;
  	}
  
! 	if (XLogCtl->Insert.exclusiveBackupState == EXCLUSIVE_BACKUP_NONE &&
  		XLogCtl->Insert.nonExclusiveBackups == 0)
  	{
  		XLogCtl->Insert.forcePageWrites = false;
***************
*** 10337,10342 **** pg_start_backup_callback(int code, Datum arg)
--- 10377,10400 ----
  }
  
  /*
+  * Error cleanup callback for pg_stop_backup
+  */
+ static void
+ pg_stop_backup_callback(int code, Datum arg)
+ {
+ 	bool		exclusive = DatumGetBool(arg);
+ 
+ 	/* Update backup status on failure */
+ 	WALInsertLockAcquireExclusive();
+ 	if (exclusive)
+ 	{
+ 		Assert(XLogCtl->Insert.exclusiveBackupState == EXCLUSIVE_BACKUP_STOPPING);
+ 		XLogCtl->Insert.exclusiveBackupState = EXCLUSIVE_BACKUP_IN_PROGRESS;
+ 	}
+ 	WALInsertLockRelease();
+ }
+ 
+ /*
   * do_pg_stop_backup is the workhorse of the user-visible pg_stop_backup()
   * function.
   *
***************
*** 10398,10417 **** do_pg_stop_backup(char *labelfile, bool waitforarchive, TimeLineID *stoptli_p)
  			  errmsg("WAL level not sufficient for making an online backup"),
  				 errhint("wal_level must be set to \"replica\" or \"logical\" at server start.")));
  
- 	/*
- 	 * OK to update backup counters and forcePageWrites
- 	 */
- 	WALInsertLockAcquireExclusive();
  	if (exclusive)
  	{
! 		if (!XLogCtl->Insert.exclusiveBackup)
  		{
  			WALInsertLockRelease();
  			ereport(ERROR,
  					(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
  					 errmsg("exclusive backup not in progress")));
  		}
! 		XLogCtl->Insert.exclusiveBackup = false;
  	}
  	else
  	{
--- 10456,10546 ----
  			  errmsg("WAL level not sufficient for making an online backup"),
  				 errhint("wal_level must be set to \"replica\" or \"logical\" at server start.")));
  
  	if (exclusive)
  	{
! 		/*
! 		 * At first, mark that we're now stopping an exclusive backup,
! 		 * to ensure that there are no other sessions currently running
! 		 * pg_start_backup() or pg_stop_backup().
! 		 */
! 		WALInsertLockAcquireExclusive();
! 		if (XLogCtl->Insert.exclusiveBackupState != EXCLUSIVE_BACKUP_IN_PROGRESS)
  		{
  			WALInsertLockRelease();
  			ereport(ERROR,
  					(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
  					 errmsg("exclusive backup not in progress")));
  		}
! 		XLogCtl->Insert.exclusiveBackupState = EXCLUSIVE_BACKUP_STOPPING;
! 		WALInsertLockRelease();
! 
! 		/*
! 		 * Remove backup_label. In case of failure, the state for an exclusive
! 		 * backup is switched back to in-progress.
! 		 */
! 		PG_ENSURE_ERROR_CLEANUP(pg_stop_backup_callback, (Datum) BoolGetDatum(exclusive));
! 		{
! 			/*
! 			 * Read the existing label file into memory.
! 			 */
! 			struct stat statbuf;
! 			int			r;
! 
! 			if (stat(BACKUP_LABEL_FILE, &statbuf))
! 			{
! 				/* should not happen per the upper checks */
! 				if (errno != ENOENT)
! 					ereport(ERROR,
! 							(errcode_for_file_access(),
! 							 errmsg("could not stat file \"%s\": %m",
! 									BACKUP_LABEL_FILE)));
! 				ereport(ERROR,
! 						(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
! 						 errmsg("a backup is not in progress")));
! 			}
! 
! 			lfp = AllocateFile(BACKUP_LABEL_FILE, "r");
! 			if (!lfp)
! 			{
! 				ereport(ERROR,
! 						(errcode_for_file_access(),
! 						 errmsg("could not read file \"%s\": %m",
! 								BACKUP_LABEL_FILE)));
! 			}
! 			labelfile = palloc(statbuf.st_size + 1);
! 			r = fread(labelfile, statbuf.st_size, 1, lfp);
! 			labelfile[statbuf.st_size] = '\0';
! 
! 			/*
! 			 * Close and remove the backup label file
! 			 */
! 			if (r != 1 || ferror(lfp) || FreeFile(lfp))
! 				ereport(ERROR,
! 						(errcode_for_file_access(),
! 						 errmsg("could not read file \"%s\": %m",
! 								BACKUP_LABEL_FILE)));
! 			if (unlink(BACKUP_LABEL_FILE) != 0)
! 				ereport(ERROR,
! 						(errcode_for_file_access(),
! 						 errmsg("could not remove file \"%s\": %m",
! 								BACKUP_LABEL_FILE)));
! 
! 			/*
! 			 * Remove tablespace_map file if present, it is created only if there
! 			 * are tablespaces.
! 			 */
! 			unlink(TABLESPACE_MAP);
! 		}
! 		PG_END_ENSURE_ERROR_CLEANUP(pg_stop_backup_callback, (Datum) BoolGetDatum(exclusive));
! 	}
! 
! 	/*
! 	 * OK to update backup counters and forcePageWrites
! 	 */
! 	WALInsertLockAcquireExclusive();
! 	if (exclusive)
! 	{
! 		XLogCtl->Insert.exclusiveBackupState = EXCLUSIVE_BACKUP_NONE;
  	}
  	else
  	{
***************
*** 10425,10490 **** do_pg_stop_backup(char *labelfile, bool waitforarchive, TimeLineID *stoptli_p)
  		XLogCtl->Insert.nonExclusiveBackups--;
  	}
  
! 	if (!XLogCtl->Insert.exclusiveBackup &&
  		XLogCtl->Insert.nonExclusiveBackups == 0)
  	{
  		XLogCtl->Insert.forcePageWrites = false;
  	}
  	WALInsertLockRelease();
  
- 	if (exclusive)
- 	{
- 		/*
- 		 * Read the existing label file into memory.
- 		 */
- 		struct stat statbuf;
- 		int			r;
- 
- 		if (stat(BACKUP_LABEL_FILE, &statbuf))
- 		{
- 			if (errno != ENOENT)
- 				ereport(ERROR,
- 						(errcode_for_file_access(),
- 						 errmsg("could not stat file \"%s\": %m",
- 								BACKUP_LABEL_FILE)));
- 			ereport(ERROR,
- 					(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
- 					 errmsg("a backup is not in progress")));
- 		}
- 
- 		lfp = AllocateFile(BACKUP_LABEL_FILE, "r");
- 		if (!lfp)
- 		{
- 			ereport(ERROR,
- 					(errcode_for_file_access(),
- 					 errmsg("could not read file \"%s\": %m",
- 							BACKUP_LABEL_FILE)));
- 		}
- 		labelfile = palloc(statbuf.st_size + 1);
- 		r = fread(labelfile, statbuf.st_size, 1, lfp);
- 		labelfile[statbuf.st_size] = '\0';
- 
- 		/*
- 		 * Close and remove the backup label file
- 		 */
- 		if (r != 1 || ferror(lfp) || FreeFile(lfp))
- 			ereport(ERROR,
- 					(errcode_for_file_access(),
- 					 errmsg("could not read file \"%s\": %m",
- 							BACKUP_LABEL_FILE)));
- 		if (unlink(BACKUP_LABEL_FILE) != 0)
- 			ereport(ERROR,
- 					(errcode_for_file_access(),
- 					 errmsg("could not remove file \"%s\": %m",
- 							BACKUP_LABEL_FILE)));
- 
- 		/*
- 		 * Remove tablespace_map file if present, it is created only if there
- 		 * are tablespaces.
- 		 */
- 		unlink(TABLESPACE_MAP);
- 	}
- 
  	/*
  	 * Read and parse the START WAL LOCATION line (this code is pretty crude,
  	 * but we are not expecting any variability in the file format).
--- 10554,10566 ----
  		XLogCtl->Insert.nonExclusiveBackups--;
  	}
  
! 	if (XLogCtl->Insert.exclusiveBackupState == EXCLUSIVE_BACKUP_NONE &&
  		XLogCtl->Insert.nonExclusiveBackups == 0)
  	{
  		XLogCtl->Insert.forcePageWrites = false;
  	}
  	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).
***************
*** 10721,10727 **** do_pg_abort_backup(void)
  	Assert(XLogCtl->Insert.nonExclusiveBackups > 0);
  	XLogCtl->Insert.nonExclusiveBackups--;
  
! 	if (!XLogCtl->Insert.exclusiveBackup &&
  		XLogCtl->Insert.nonExclusiveBackups == 0)
  	{
  		XLogCtl->Insert.forcePageWrites = false;
--- 10797,10803 ----
  	Assert(XLogCtl->Insert.nonExclusiveBackups > 0);
  	XLogCtl->Insert.nonExclusiveBackups--;
  
! 	if (XLogCtl->Insert.exclusiveBackupState == EXCLUSIVE_BACKUP_NONE &&
  		XLogCtl->Insert.nonExclusiveBackups == 0)
  	{
  		XLogCtl->Insert.forcePageWrites = false;
