diff -rcN postgresql/src/backend/access/transam/xlog.c postgresql_with_patch/src/backend/access/transam/xlog.c
*** postgresql/src/backend/access/transam/xlog.c	2011-08-03 05:18:32.000000000 +0900
--- postgresql_with_patch/src/backend/access/transam/xlog.c	2011-08-03 19:03:00.000000000 +0900
***************
*** 6053,6059 ****
  		ereport(LOG,
  				(errmsg("database system was interrupted while in recovery at log time %s",
  						str_time(ControlFile->checkPointCopy.time)),
! 				 errhint("If this has occurred more than once some data might be corrupted"
  			  " and you might need to choose an earlier recovery target.")));
  	else if (ControlFile->state == DB_IN_PRODUCTION)
  		ereport(LOG,
--- 6053,6059 ----
  		ereport(LOG,
  				(errmsg("database system was interrupted while in recovery at log time %s",
  						str_time(ControlFile->checkPointCopy.time)),
! 				 errhint("If this has occurred more than once some data might be corrupted unless take backup from slave"
  			  " and you might need to choose an earlier recovery target.")));
  	else if (ControlFile->state == DB_IN_PRODUCTION)
  		ereport(LOG,
***************
*** 6299,6304 ****
--- 6299,6318 ----
  		/* use volatile pointer to prevent code rearrangement */
  		volatile XLogCtlData *xlogctl = XLogCtl;
  
+ 		/* 
+ 		 * get minRecoveryPoint before the value is changed for 
+ 		 * getting backup on standby server.
+ 		 * check the result, set to pg_control.
+ 		 */
+ 		XLogRecPtr prevminRecoveryPoint = ControlFile->minRecoveryPoint;
+ 		if (!ControlFile->backupserver)
+ 		{
+ 			if (prevminRecoveryPoint.xlogid == 0 && prevminRecoveryPoint.xrecoff == 0)
+ 				ControlFile->backupserver = BACKUPSERVER_MASTER;
+ 			else
+ 				ControlFile->backupserver = BACKUPSERVER_SLAVE;
+ 		}
+ 
  		/*
  		 * Update pg_control to show that we are recovering and to show the
  		 * selected checkpoint as the place we are starting from. We also mark
***************
*** 6607,6612 ****
--- 6621,6646 ----
  				/* Pop the error context stack */
  				error_context_stack = errcontext.previous;
  
+ 				/* 
+ 				 * Check whether to reach minRecoveryPoint when getting backup 
+ 				 * on standby server.
+ 				 */
+ 				if (ControlFile->backupserver == BACKUPSERVER_SLAVE)
+ 				{
+ 					if (XLByteLE(prevminRecoveryPoint, EndRecPtr))
+ 					{
+ 						elog(DEBUG1, "end of backup reached in the control file");
+ 
+ 						LWLockAcquire(ControlFileLock, LW_EXCLUSIVE);
+ 
+ 						MemSet(&ControlFile->backupStartPoint, 0, sizeof(XLogRecPtr));
+ 						ControlFile->backupserver = BACKUPSERVER_NONE;
+ 						UpdateControlFile();
+ 
+ 						LWLockRelease(ControlFileLock);
+ 					}
+ 				}
+ 
  				/*
  				 * Update shared recoveryLastRecPtr after this record has been
  				 * replayed.
***************
*** 8402,8408 ****
  		 * never arrive.
  		 */
  		if (InArchiveRecovery &&
! 			!XLogRecPtrIsInvalid(ControlFile->backupStartPoint))
  			ereport(ERROR,
  					(errmsg("online backup was canceled, recovery cannot continue")));
  
--- 8436,8443 ----
  		 * never arrive.
  		 */
  		if (InArchiveRecovery &&
! 			!XLogRecPtrIsInvalid(ControlFile->backupStartPoint) &&
! 			ControlFile->backupserver == BACKUPSERVER_MASTER)
  			ereport(ERROR,
  					(errmsg("online backup was canceled, recovery cannot continue")));
  
***************
*** 8531,8536 ****
--- 8566,8572 ----
  			if (XLByteLT(ControlFile->minRecoveryPoint, lsn))
  				ControlFile->minRecoveryPoint = lsn;
  			MemSet(&ControlFile->backupStartPoint, 0, sizeof(XLogRecPtr));
+ 			ControlFile->backupserver = BACKUPSERVER_NONE;
  			UpdateControlFile();
  
  			LWLockRelease(ControlFileLock);
***************
*** 8864,8869 ****
--- 8900,8906 ----
  do_pg_start_backup(const char *backupidstr, bool fast, char **labelfile)
  {
  	bool		exclusive = (labelfile == NULL);
+ 	bool		duringrecovery = false;
  	XLogRecPtr	checkpointloc;
  	XLogRecPtr	startpoint;
  	pg_time_t	stamp_time;
***************
*** 8881,8892 ****
  		   errmsg("must be superuser or replication role to run a backup")));
  
  	if (RecoveryInProgress())
! 		ereport(ERROR,
! 				(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
! 				 errmsg("recovery is in progress"),
! 				 errhint("WAL control functions cannot be executed during recovery.")));
  
! 	if (!XLogIsNeeded())
  		ereport(ERROR,
  				(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
  			  errmsg("WAL level not sufficient for making an online backup"),
--- 8918,8926 ----
  		   errmsg("must be superuser or replication role to run a backup")));
  
  	if (RecoveryInProgress())
! 		duringrecovery = true;
  
! 	if (!XLogIsNeeded() && !duringrecovery)
  		ereport(ERROR,
  				(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
  			  errmsg("WAL level not sufficient for making an online backup"),
***************
*** 8909,8915 ****
  	 * directory was not included in the base backup and the WAL archive was
  	 * cleared too before starting the backup.
  	 */
! 	RequestXLogSwitch();
  
  	/*
  	 * Mark backup active in shared memory.  We must do full-page WAL writes
--- 8943,8950 ----
  	 * directory was not included in the base backup and the WAL archive was
  	 * cleared too before starting the backup.
  	 */
! 	if (!duringrecovery)
! 		RequestXLogSwitch();
  
  	/*
  	 * Mark backup active in shared memory.  We must do full-page WAL writes
***************
*** 8943,8949 ****
  	}
  	else
  		XLogCtl->Insert.nonExclusiveBackups++;
! 	XLogCtl->Insert.forcePageWrites = true;
  	LWLockRelease(WALInsertLock);
  
  	/* Ensure we release forcePageWrites if fail below */
--- 8978,8985 ----
  	}
  	else
  		XLogCtl->Insert.nonExclusiveBackups++;
! 	if (!duringrecovery)
! 		XLogCtl->Insert.forcePageWrites = true;
  	LWLockRelease(WALInsertLock);
  
  	/* Ensure we release forcePageWrites if fail below */
***************
*** 8994,9000 ****
  				gotUniqueStartpoint = true;
  			}
  			LWLockRelease(WALInsertLock);
! 		} while (!gotUniqueStartpoint);
  
  		XLByteToSeg(startpoint, _logId, _logSeg);
  		XLogFileName(xlogfilename, ThisTimeLineID, _logId, _logSeg);
--- 9030,9036 ----
  				gotUniqueStartpoint = true;
  			}
  			LWLockRelease(WALInsertLock);
! 		} while (!gotUniqueStartpoint && !duringrecovery);
  
  		XLByteToSeg(startpoint, _logId, _logSeg);
  		XLogFileName(xlogfilename, ThisTimeLineID, _logId, _logSeg);
***************
*** 9087,9093 ****
  	}
  
  	if (!XLogCtl->Insert.exclusiveBackup &&
! 		XLogCtl->Insert.nonExclusiveBackups == 0)
  	{
  		XLogCtl->Insert.forcePageWrites = false;
  	}
--- 9123,9130 ----
  	}
  
  	if (!XLogCtl->Insert.exclusiveBackup &&
! 		XLogCtl->Insert.nonExclusiveBackups == 0 &&
! 		!RecoveryInProgress())
  	{
  		XLogCtl->Insert.forcePageWrites = false;
  	}
***************
*** 9131,9136 ****
--- 9168,9174 ----
  do_pg_stop_backup(char *labelfile, bool waitforarchive)
  {
  	bool		exclusive = (labelfile == NULL);
+ 	bool		duringrecovery = false;
  	XLogRecPtr	startpoint;
  	XLogRecPtr	stoppoint;
  	XLogRecData rdata;
***************
*** 9157,9168 ****
  		 (errmsg("must be superuser or replication role to run a backup"))));
  
  	if (RecoveryInProgress())
! 		ereport(ERROR,
! 				(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
! 				 errmsg("recovery is in progress"),
! 				 errhint("WAL control functions cannot be executed during recovery.")));
  
! 	if (!XLogIsNeeded())
  		ereport(ERROR,
  				(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
  			  errmsg("WAL level not sufficient for making an online backup"),
--- 9195,9203 ----
  		 (errmsg("must be superuser or replication role to run a backup"))));
  
  	if (RecoveryInProgress())
! 		duringrecovery = true;
  
! 	if (!XLogIsNeeded() && !duringrecovery)
  		ereport(ERROR,
  				(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
  			  errmsg("WAL level not sufficient for making an online backup"),
***************
*** 9187,9193 ****
  	}
  
  	if (!XLogCtl->Insert.exclusiveBackup &&
! 		XLogCtl->Insert.nonExclusiveBackups == 0)
  	{
  		XLogCtl->Insert.forcePageWrites = false;
  	}
--- 9222,9229 ----
  	}
  
  	if (!XLogCtl->Insert.exclusiveBackup &&
! 		XLogCtl->Insert.nonExclusiveBackups == 0 &&
! 	    !duringrecovery)
  	{
  		XLogCtl->Insert.forcePageWrites = false;
  	}
***************
*** 9241,9246 ****
--- 9277,9289 ----
  	}
  
  	/*
+ 	 * When pg_stop_backup is excuted on hot standby server, the result 
+ 	 * is minRecoveryPoint in the control file.
+ 	 */
+ 	if (duringrecovery)
+ 		return ControlFile->minRecoveryPoint;
+ 
+ 	/*
  	 * Read and parse the START WAL LOCATION line (this code is pretty crude,
  	 * but we are not expecting any variability in the file format).
  	 */
***************
*** 9398,9404 ****
  	XLogCtl->Insert.nonExclusiveBackups--;
  
  	if (!XLogCtl->Insert.exclusiveBackup &&
! 		XLogCtl->Insert.nonExclusiveBackups == 0)
  	{
  		XLogCtl->Insert.forcePageWrites = false;
  	}
--- 9441,9448 ----
  	XLogCtl->Insert.nonExclusiveBackups--;
  
  	if (!XLogCtl->Insert.exclusiveBackup &&
! 		XLogCtl->Insert.nonExclusiveBackups == 0 &&
! 		!RecoveryInProgress())
  	{
  		XLogCtl->Insert.forcePageWrites = false;
  	}
diff -rcN postgresql/src/backend/postmaster/postmaster.c postgresql_with_patch/src/backend/postmaster/postmaster.c
*** postgresql/src/backend/postmaster/postmaster.c	2011-08-03 05:18:32.000000000 +0900
--- postgresql_with_patch/src/backend/postmaster/postmaster.c	2011-08-03 10:10:06.000000000 +0900
***************
*** 286,293 ****
  
  static PMState pmState = PM_INIT;
  
- static bool ReachedNormalRunning = false;		/* T if we've reached PM_RUN */
- 
  bool		ClientAuthInProgress = false;		/* T during new-client
  												 * authentication */
  
--- 286,291 ----
***************
*** 2313,2319 ****
  			 * Startup succeeded, commence normal operations
  			 */
  			FatalError = false;
- 			ReachedNormalRunning = true;
  			pmState = PM_RUN;
  
  			/*
--- 2311,2316 ----
***************
*** 2853,2859 ****
  		 * backends to die off, but that doesn't work at present because
  		 * killing the startup process doesn't release its locks.
  		 */
! 		if (CountChildren(BACKEND_TYPE_NORMAL) == 0)
  		{
  			if (StartupPID != 0)
  				signal_child(StartupPID, SIGTERM);
--- 2850,2856 ----
  		 * backends to die off, but that doesn't work at present because
  		 * killing the startup process doesn't release its locks.
  		 */
! 		if (CountChildren(BACKEND_TYPE_NORMAL) == 0 && !BackupInProgress())
  		{
  			if (StartupPID != 0)
  				signal_child(StartupPID, SIGTERM);
***************
*** 3008,3022 ****
  		{
  			/*
  			 * Terminate backup mode to avoid recovery after a clean fast
! 			 * shutdown.  Since a backup can only be taken during normal
! 			 * running (and not, for example, while running under Hot Standby)
! 			 * it only makes sense to do this if we reached normal running. If
! 			 * we're still in recovery, the backup file is one we're
! 			 * recovering *from*, and we must keep it around so that recovery
! 			 * restarts from the right place.
  			 */
! 			if (ReachedNormalRunning)
! 				CancelBackup();
  
  			/* Normal exit from the postmaster is here */
  			ExitPostmaster(0);
--- 3005,3013 ----
  		{
  			/*
  			 * Terminate backup mode to avoid recovery after a clean fast
! 			 * shutdown.  
  			 */
! 			CancelBackup();
  
  			/* Normal exit from the postmaster is here */
  			ExitPostmaster(0);
***************
*** 4232,4237 ****
--- 4223,4233 ----
  		(pmState == PM_STARTUP || pmState == PM_RECOVERY ||
  		 pmState == PM_HOT_STANDBY || pmState == PM_WAIT_READONLY))
  	{
+ 		/*
+ 		 * Terminate backup mode to avoid recovery after a clean promote.  
+ 		 */
+ 		CancelBackup();
+ 
  		/* Tell startup process to finish recovery */
  		signal_child(StartupPID, SIGUSR2);
  	}
diff -rcN postgresql/src/bin/pg_controldata/pg_controldata.c postgresql_with_patch/src/bin/pg_controldata/pg_controldata.c
*** postgresql/src/bin/pg_controldata/pg_controldata.c	2011-08-03 05:18:32.000000000 +0900
--- postgresql_with_patch/src/bin/pg_controldata/pg_controldata.c	2011-08-03 10:10:06.000000000 +0900
***************
*** 86,91 ****
--- 86,105 ----
  	return _("unrecognized wal_level");
  }
  
+ static const char *
+ backupserver_str(BackupServer backupserver)
+ {
+ 	switch (backupserver)
+ 	{
+ 		case BACKUPSERVER_NONE:
+ 			return "none";
+ 		case BACKUPSERVER_MASTER:
+ 			return "master";
+ 		case BACKUPSERVER_SLAVE:
+ 			return "slave";
+ 	}
+ 	return _("unrecognized backupserver");
+ }
  
  int
  main(int argc, char *argv[])
***************
*** 232,237 ****
--- 246,253 ----
  	printf(_("Backup start location:                %X/%X\n"),
  		   ControlFile.backupStartPoint.xlogid,
  		   ControlFile.backupStartPoint.xrecoff);
+ 	printf(_("Backup from:                          %s\n"),
+ 		   backupserver_str(ControlFile.backupserver));
  	printf(_("Current wal_level setting:            %s\n"),
  		   wal_level_str(ControlFile.wal_level));
  	printf(_("Current max_connections setting:      %d\n"),
diff -rcN postgresql/src/bin/pg_ctl/pg_ctl.c postgresql_with_patch/src/bin/pg_ctl/pg_ctl.c
*** postgresql/src/bin/pg_ctl/pg_ctl.c	2011-08-03 05:18:32.000000000 +0900
--- postgresql_with_patch/src/bin/pg_ctl/pg_ctl.c	2011-08-03 10:10:06.000000000 +0900
***************
*** 882,894 ****
  	{
  		/*
  		 * If backup_label exists, an online backup is running. Warn the user
! 		 * that smart shutdown will wait for it to finish. However, if
! 		 * recovery.conf is also present, we're recovering from an online
! 		 * backup instead of performing one.
  		 */
  		if (shutdown_mode == SMART_MODE &&
! 			stat(backup_file, &statbuf) == 0 &&
! 			stat(recovery_file, &statbuf) != 0)
  		{
  			print_msg(_("WARNING: online backup mode is active\n"
  						"Shutdown will not complete until pg_stop_backup() is called.\n\n"));
--- 882,891 ----
  	{
  		/*
  		 * If backup_label exists, an online backup is running. Warn the user
! 		 * that smart shutdown will wait for it to finish. 
  		 */
  		if (shutdown_mode == SMART_MODE &&
! 			stat(backup_file, &statbuf) == 0)
  		{
  			print_msg(_("WARNING: online backup mode is active\n"
  						"Shutdown will not complete until pg_stop_backup() is called.\n\n"));
diff -rcN postgresql/src/include/access/xlog.h postgresql_with_patch/src/include/access/xlog.h
*** postgresql/src/include/access/xlog.h	2011-08-03 05:18:32.000000000 +0900
--- postgresql_with_patch/src/include/access/xlog.h	2011-08-03 10:10:06.000000000 +0900
***************
*** 209,214 ****
--- 209,222 ----
  } WalLevel;
  extern int	wal_level;
  
+ /* where to get backup */
+ typedef enum BackupServer
+ {
+ 	BACKUPSERVER_NONE = 0,
+ 	BACKUPSERVER_MASTER,
+ 	BACKUPSERVER_SLAVE,
+ } BackupServer;
+ 
  #define XLogArchivingActive()	(XLogArchiveMode && wal_level >= WAL_LEVEL_ARCHIVE)
  #define XLogArchiveCommandSet() (XLogArchiveCommand[0] != '\0')
  
diff -rcN postgresql/src/include/catalog/pg_control.h postgresql_with_patch/src/include/catalog/pg_control.h
*** postgresql/src/include/catalog/pg_control.h	2011-08-03 05:18:32.000000000 +0900
--- postgresql_with_patch/src/include/catalog/pg_control.h	2011-08-03 10:10:06.000000000 +0900
***************
*** 142,147 ****
--- 142,156 ----
  	XLogRecPtr	backupStartPoint;
  
  	/*
+ 	 * backupserver is used while postgresql is in recovery mode to
+ 	 * store the location of where the backup comes from.
+ 	 * When Postgres starts recovery operations
+ 	 * it is set to "none". During recovery it is updated to either "master", or "slave".
+ 	 * When recovery operations finish it is updated back to "none".
+ 	 */
+ 	int			backupserver;
+ 
+ 	/*
  	 * Parameter settings that determine if the WAL can be used for archival
  	 * or hot standby.
  	 */
