diff --git a/src/backend/access/gin/ginxlog.c b/src/backend/access/gin/ginxlog.c
index a33874224187b8a66f060104288423c2fc2f2d23..265e7de70c48278c985a0ba56e634e59df3eb6b6 100644
--- a/src/backend/access/gin/ginxlog.c
+++ b/src/backend/access/gin/ginxlog.c
@@ -8,7 +8,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *			 $PostgreSQL: pgsql/src/backend/access/gin/ginxlog.c,v 1.3 2006/07/14 14:52:16 momjian Exp $
+ *			 $PostgreSQL: pgsql/src/backend/access/gin/ginxlog.c,v 1.4 2006/08/07 16:57:56 tgl Exp $
  *-------------------------------------------------------------------------
  */
 #include "postgres.h"
@@ -528,7 +528,8 @@ gin_xlog_cleanup(void) {
 
 	topCtx = MemoryContextSwitchTo(opCtx);
 
-	foreach(l, incomplete_splits) {
+	foreach(l, incomplete_splits)
+	{
 		ginIncompleteSplit *split = (ginIncompleteSplit *) lfirst(l);
 		ginContinueSplit( split );
 		MemoryContextReset( opCtx );
@@ -538,3 +539,10 @@ gin_xlog_cleanup(void) {
 	MemoryContextDelete(opCtx);
 }
 
+bool
+gin_safe_restartpoint(void)
+{
+	if (incomplete_splits)
+		return false;
+	return true;
+}
diff --git a/src/backend/access/gist/gistxlog.c b/src/backend/access/gist/gistxlog.c
index 9694e32384e1f84c73d1add22641bffcd593d1f6..9680ed96192c29da878d6c900b58368635d2611a 100644
--- a/src/backend/access/gist/gistxlog.c
+++ b/src/backend/access/gist/gistxlog.c
@@ -8,7 +8,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *			 $PostgreSQL: pgsql/src/backend/access/gist/gistxlog.c,v 1.22 2006/07/14 14:52:16 momjian Exp $
+ *			 $PostgreSQL: pgsql/src/backend/access/gist/gistxlog.c,v 1.23 2006/08/07 16:57:56 tgl Exp $
  *-------------------------------------------------------------------------
  */
 #include "postgres.h"
@@ -818,6 +818,14 @@ gist_xlog_cleanup(void)
 	MemoryContextDelete(insertCtx);
 }
 
+bool
+gist_safe_restartpoint(void)
+{
+	if (incomplete_inserts)
+		return false;
+	return true;
+}
+
 
 XLogRecData *
 formSplitRdata(RelFileNode node, BlockNumber blkno, bool page_is_leaf,
diff --git a/src/backend/access/nbtree/nbtxlog.c b/src/backend/access/nbtree/nbtxlog.c
index 126f593cd96f7cb8c031f56c4b90922cff73d136..88962ccfcecbaf04c6a1b896797b7ab3d7266bd0 100644
--- a/src/backend/access/nbtree/nbtxlog.c
+++ b/src/backend/access/nbtree/nbtxlog.c
@@ -8,7 +8,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/access/nbtree/nbtxlog.c,v 1.36 2006/07/25 19:13:00 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/access/nbtree/nbtxlog.c,v 1.37 2006/08/07 16:57:56 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -794,3 +794,11 @@ btree_xlog_cleanup(void)
 	}
 	incomplete_splits = NIL;
 }
+
+bool
+btree_safe_restartpoint(void)
+{
+	if (incomplete_splits)
+		return false;
+	return true;
+}
diff --git a/src/backend/access/transam/rmgr.c b/src/backend/access/transam/rmgr.c
index 331816f5e6df7db13d0fb294b810d60b1888d7c0..7db05c9c482bac4906fed9a2686b325a2e1b6015 100644
--- a/src/backend/access/transam/rmgr.c
+++ b/src/backend/access/transam/rmgr.c
@@ -3,7 +3,7 @@
  *
  * Resource managers definition
  *
- * $PostgreSQL: pgsql/src/backend/access/transam/rmgr.c,v 1.23 2006/07/11 17:26:58 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/access/transam/rmgr.c,v 1.24 2006/08/07 16:57:56 tgl Exp $
  */
 #include "postgres.h"
 
@@ -23,20 +23,20 @@
 
 
 const RmgrData RmgrTable[RM_MAX_ID + 1] = {
-	{"XLOG", xlog_redo, xlog_desc, NULL, NULL},
-	{"Transaction", xact_redo, xact_desc, NULL, NULL},
-	{"Storage", smgr_redo, smgr_desc, NULL, NULL},
-	{"CLOG", clog_redo, clog_desc, NULL, NULL},
-	{"Database", dbase_redo, dbase_desc, NULL, NULL},
-	{"Tablespace", tblspc_redo, tblspc_desc, NULL, NULL},
-	{"MultiXact", multixact_redo, multixact_desc, NULL, NULL},
-	{"Reserved 7", NULL, NULL, NULL, NULL},
-	{"Reserved 8", NULL, NULL, NULL, NULL},
-	{"Reserved 9", NULL, NULL, NULL, NULL},
-	{"Heap", heap_redo, heap_desc, NULL, NULL},
-	{"Btree", btree_redo, btree_desc, btree_xlog_startup, btree_xlog_cleanup},
-	{"Hash", hash_redo, hash_desc, NULL, NULL},
-	{"Gin", gin_redo, gin_desc, gin_xlog_startup, gin_xlog_cleanup},
-	{"Gist", gist_redo, gist_desc, gist_xlog_startup, gist_xlog_cleanup},
-	{"Sequence", seq_redo, seq_desc, NULL, NULL}
+	{"XLOG", xlog_redo, xlog_desc, NULL, NULL, NULL},
+	{"Transaction", xact_redo, xact_desc, NULL, NULL, NULL},
+	{"Storage", smgr_redo, smgr_desc, NULL, NULL, NULL},
+	{"CLOG", clog_redo, clog_desc, NULL, NULL, NULL},
+	{"Database", dbase_redo, dbase_desc, NULL, NULL, NULL},
+	{"Tablespace", tblspc_redo, tblspc_desc, NULL, NULL, NULL},
+	{"MultiXact", multixact_redo, multixact_desc, NULL, NULL, NULL},
+	{"Reserved 7", NULL, NULL, NULL, NULL, NULL},
+	{"Reserved 8", NULL, NULL, NULL, NULL, NULL},
+	{"Reserved 9", NULL, NULL, NULL, NULL, NULL},
+	{"Heap", heap_redo, heap_desc, NULL, NULL, NULL},
+	{"Btree", btree_redo, btree_desc, btree_xlog_startup, btree_xlog_cleanup, btree_safe_restartpoint},
+	{"Hash", hash_redo, hash_desc, NULL, NULL, NULL},
+	{"Gin", gin_redo, gin_desc, gin_xlog_startup, gin_xlog_cleanup, gin_safe_restartpoint},
+	{"Gist", gist_redo, gist_desc, gist_xlog_startup, gist_xlog_cleanup, gist_safe_restartpoint},
+	{"Sequence", seq_redo, seq_desc, NULL, NULL, NULL}
 };
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index de8e682d84975a2ee41b136aeae8188d26fe4ae3..21e7b47206d5a3fe0d891e6bbcc7d46c32bc257a 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/backend/access/transam/xlog.c,v 1.246 2006/08/06 03:53:44 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/access/transam/xlog.c,v 1.247 2006/08/07 16:57:56 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -120,6 +120,7 @@
 
 /* File path names (all relative to $PGDATA) */
 #define BACKUP_LABEL_FILE		"backup_label"
+#define BACKUP_LABEL_OLD		"backup_label.old"
 #define RECOVERY_COMMAND_FILE	"recovery.conf"
 #define RECOVERY_COMMAND_DONE	"recovery.done"
 
@@ -185,9 +186,6 @@ static TransactionId recoveryStopXid;
 static time_t recoveryStopTime;
 static bool recoveryStopAfter;
 
-/* constraint set by read_backup_label */
-static XLogRecPtr recoveryMinXlogOffset = {0, 0};
-
 /*
  * During normal operation, the only timeline we care about is ThisTimeLineID.
  * During recovery, however, things are more complicated.  To simplify life
@@ -463,6 +461,7 @@ static void readRecoveryCommandFile(void);
 static void exitArchiveRecovery(TimeLineID endTLI,
 					uint32 endLogId, uint32 endLogSeg);
 static bool recoveryStopsHere(XLogRecord *record, bool *includeThis);
+static void CheckPointGuts(XLogRecPtr checkPointRedo);
 
 static bool XLogCheckBuffer(XLogRecData *rdata, bool doPageWrites,
 				XLogRecPtr *lsn, BkpBlock *bkpb);
@@ -499,8 +498,8 @@ static void issue_xlog_fsync(void);
 #ifdef WAL_DEBUG
 static void xlog_outrec(StringInfo buf, XLogRecord *record);
 #endif
-static bool read_backup_label(XLogRecPtr *checkPointLoc);
-static void remove_backup_label(void);
+static bool read_backup_label(XLogRecPtr *checkPointLoc,
+							  XLogRecPtr *minRecoveryLoc);
 static void rm_redo_error_callback(void *arg);
 
 
@@ -4594,9 +4593,11 @@ StartupXLOG(void)
 	CheckPoint	checkPoint;
 	bool		wasShutdown;
 	bool		needNewTimeLine = false;
+	bool		haveBackupLabel = false;
 	XLogRecPtr	RecPtr,
 				LastRec,
 				checkPointLoc,
+				minRecoveryLoc,
 				EndOfLog;
 	uint32		endLogId;
 	uint32		endLogSeg;
@@ -4629,12 +4630,18 @@ StartupXLOG(void)
 		ereport(LOG,
 				(errmsg("database system shutdown was interrupted at %s",
 						str_time(ControlFile->time))));
-	else if (ControlFile->state == DB_IN_RECOVERY)
+	else if (ControlFile->state == DB_IN_CRASH_RECOVERY)
 		ereport(LOG,
 		   (errmsg("database system was interrupted while in recovery at %s",
 				   str_time(ControlFile->time)),
 			errhint("This probably means that some data is corrupted and"
 					" you will have to use the last backup for recovery.")));
+	else if (ControlFile->state == DB_IN_ARCHIVE_RECOVERY)
+		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 may be corrupted"
+					" and you may need to choose an earlier recovery target.")));
 	else if (ControlFile->state == DB_IN_PRODUCTION)
 		ereport(LOG,
 				(errmsg("database system was interrupted at %s",
@@ -4673,7 +4680,7 @@ StartupXLOG(void)
 						recoveryTargetTLI,
 						ControlFile->checkPointCopy.ThisTimeLineID)));
 
-	if (read_backup_label(&checkPointLoc))
+	if (read_backup_label(&checkPointLoc, &minRecoveryLoc))
 	{
 		/*
 		 * When a backup_label file is present, we want to roll forward from
@@ -4693,6 +4700,8 @@ StartupXLOG(void)
 					(errmsg("could not locate required checkpoint record"),
 					 errhint("If you are not restoring from a backup, try removing the file \"%s/backup_label\".", DataDir)));
 		}
+		/* set flag to delete it later */
+		haveBackupLabel = true;
 	}
 	else
 	{
@@ -4790,17 +4799,51 @@ StartupXLOG(void)
 	{
 		int			rmid;
 
+		/*
+		 * 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 pg_control with any minimum recovery stop point
+		 * obtained from a backup history file.
+		 */
 		if (InArchiveRecovery)
+		{
 			ereport(LOG,
 					(errmsg("automatic recovery in progress")));
+			ControlFile->state = DB_IN_ARCHIVE_RECOVERY;
+		}
 		else
+		{
 			ereport(LOG,
 					(errmsg("database system was not properly shut down; "
 							"automatic recovery in progress")));
-		ControlFile->state = DB_IN_RECOVERY;
+			ControlFile->state = DB_IN_CRASH_RECOVERY;
+		}
+		ControlFile->prevCheckPoint = ControlFile->checkPoint;
+		ControlFile->checkPoint = checkPointLoc;
+		ControlFile->checkPointCopy = checkPoint;
+		if (minRecoveryLoc.xlogid != 0 || minRecoveryLoc.xrecoff != 0)
+			ControlFile->minRecoveryPoint = minRecoveryLoc;
 		ControlFile->time = time(NULL);
 		UpdateControlFile();
 
+		/*
+		 * If there was a backup label file, it's done its job and the
+		 * info has now been propagated into pg_control.  We must get rid of
+		 * the label file so that if we crash during recovery, we'll pick up
+		 * at the latest recovery restartpoint instead of going all the way
+		 * back to the backup start point.  It seems prudent though to just
+		 * rename the file out of the way rather than delete it completely.
+		 */
+		if (haveBackupLabel)
+		{
+			unlink(BACKUP_LABEL_OLD);
+			if (rename(BACKUP_LABEL_FILE, BACKUP_LABEL_OLD) != 0)
+				ereport(FATAL,
+						(errcode_for_file_access(),
+						 errmsg("could not rename file \"%s\" to \"%s\": %m",
+								BACKUP_LABEL_FILE, BACKUP_LABEL_OLD)));
+		}
+
 		/* Start up the recovery environment */
 		XLogInitRelationCache();
 
@@ -4927,7 +4970,7 @@ StartupXLOG(void)
 	 * Complain if we did not roll forward far enough to render the backup
 	 * dump consistent.
 	 */
-	if (XLByteLT(EndOfLog, recoveryMinXlogOffset))
+	if (XLByteLT(EndOfLog, ControlFile->minRecoveryPoint))
 	{
 		if (needNewTimeLine)	/* stopped because of stop request */
 			ereport(FATAL,
@@ -5051,34 +5094,20 @@ StartupXLOG(void)
 		pgstat_reset_all();
 
 		/*
-		 * Perform a new checkpoint to update our recovery activity to disk.
+		 * Perform a checkpoint to update all our recovery activity to disk.
 		 *
 		 * Note that we write a shutdown checkpoint rather than an on-line
 		 * one. This is not particularly critical, but since we may be
 		 * assigning a new TLI, using a shutdown checkpoint allows us to have
 		 * the rule that TLI only changes in shutdown checkpoints, which
 		 * allows some extra error checking in xlog_redo.
-		 *
-		 * In case we had to use the secondary checkpoint, make sure that it
-		 * will still be shown as the secondary checkpoint after this
-		 * CreateCheckPoint operation; we don't want the broken primary
-		 * checkpoint to become prevCheckPoint...
 		 */
-		if (XLByteEQ(checkPointLoc, ControlFile->prevCheckPoint))
-			ControlFile->checkPoint = checkPointLoc;
-
 		CreateCheckPoint(true, true);
 
 		/*
 		 * Close down recovery environment
 		 */
 		XLogCloseRelationCache();
-
-		/*
-		 * Now that we've checkpointed the recovery, it's safe to flush old
-		 * backup_label, if present.
-		 */
-		remove_backup_label();
 	}
 
 	/*
@@ -5464,6 +5493,10 @@ CreateCheckPoint(bool shutdown, bool force)
 
 	LWLockRelease(CheckpointStartLock);
 
+	if (!shutdown)
+		ereport(DEBUG2,
+				(errmsg("checkpoint starting")));
+
 	/*
 	 * Get the other info we need for the checkpoint record.
 	 */
@@ -5494,16 +5527,7 @@ CreateCheckPoint(bool shutdown, bool force)
 	 */
 	END_CRIT_SECTION();
 
-	if (!shutdown)
-		ereport(DEBUG2,
-				(errmsg("checkpoint starting")));
-
-	CheckPointCLOG();
-	CheckPointSUBTRANS();
-	CheckPointMultiXact();
-	FlushBufferPool();
-	/* We deliberately delay 2PC checkpointing as long as possible */
-	CheckPointTwoPhase(checkPoint.redo);
+	CheckPointGuts(checkPoint.redo);
 
 	START_CRIT_SECTION();
 
@@ -5591,6 +5615,85 @@ CreateCheckPoint(bool shutdown, bool force)
 	LWLockRelease(CheckpointLock);
 }
 
+/*
+ * Flush all data in shared memory to disk, and fsync
+ *
+ * This is the common code shared between regular checkpoints and
+ * recovery restartpoints.
+ */
+static void
+CheckPointGuts(XLogRecPtr checkPointRedo)
+{
+	CheckPointCLOG();
+	CheckPointSUBTRANS();
+	CheckPointMultiXact();
+	FlushBufferPool();     /* performs all required fsyncs */
+	/* We deliberately delay 2PC checkpointing as long as possible */
+	CheckPointTwoPhase(checkPointRedo);
+}
+
+/*
+ * Set a recovery restart point if appropriate
+ *
+ * This is similar to CreateCheckpoint, but is used during WAL recovery
+ * to establish a point from which recovery can roll forward without
+ * replaying the entire recovery log.  This function is called each time
+ * a checkpoint record is read from XLOG; it must determine whether a
+ * restartpoint is needed or not.
+ */
+static void
+RecoveryRestartPoint(const CheckPoint *checkPoint)
+{
+	int		elapsed_secs;
+	int     rmid;
+
+	/*
+	 * Do nothing if the elapsed time since the last restartpoint is less
+	 * than half of checkpoint_timeout.  (We use a value less than
+	 * checkpoint_timeout so that variations in the timing of checkpoints on
+	 * the master, or speed of transmission of WAL segments to a slave, won't
+	 * make the slave skip a restartpoint once it's synced with the master.)
+	 * Checking true elapsed time keeps us from doing restartpoints too often
+	 * while rapidly scanning large amounts of WAL.
+	 */
+	elapsed_secs = time(NULL) - ControlFile->time;
+	if (elapsed_secs < CheckPointTimeout / 2)
+		return;
+
+	/*
+	 * Is it safe to checkpoint?  We must ask each of the resource managers
+	 * whether they have any partial state information that might prevent a
+	 * correct restart from this point.  If so, we skip this opportunity, but
+	 * return at the next checkpoint record for another try.
+	 */
+	for (rmid = 0; rmid <= RM_MAX_ID; rmid++)
+	{
+		if (RmgrTable[rmid].rm_safe_restartpoint != NULL)
+			if (!(RmgrTable[rmid].rm_safe_restartpoint()))
+				return;
+	}
+
+	/*
+	 * OK, force data out to disk
+	 */
+	CheckPointGuts(checkPoint->redo);
+
+	/*
+	 * Update pg_control so that any subsequent crash will restart from
+	 * this checkpoint.  Note: ReadRecPtr gives the XLOG address of the
+	 * checkpoint record itself.
+	 */
+	ControlFile->prevCheckPoint = ControlFile->checkPoint;
+	ControlFile->checkPoint = ReadRecPtr;
+	ControlFile->checkPointCopy = *checkPoint;
+	ControlFile->time = time(NULL);
+	UpdateControlFile();
+
+	ereport(DEBUG2,
+			(errmsg("recovery restart point at %X/%X",
+					checkPoint->redo.xlogid, checkPoint->redo.xrecoff)));
+}
+
 /*
  * Write a NEXTOID log record
  */
@@ -5687,6 +5790,8 @@ xlog_redo(XLogRecPtr lsn, XLogRecord *record)
 			/* Following WAL records should be run with new TLI */
 			ThisTimeLineID = checkPoint.ThisTimeLineID;
 		}
+
+		RecoveryRestartPoint(&checkPoint);
 	}
 	else if (info == XLOG_CHECKPOINT_ONLINE)
 	{
@@ -5709,6 +5814,8 @@ xlog_redo(XLogRecPtr lsn, XLogRecord *record)
 			ereport(PANIC,
 					(errmsg("unexpected timeline ID %u (should be %u) in checkpoint record",
 							checkPoint.ThisTimeLineID, ThisTimeLineID)));
+
+		RecoveryRestartPoint(&checkPoint);
 	}
 	else if (info == XLOG_SWITCH)
 	{
@@ -6349,14 +6456,14 @@ pg_xlogfile_name(PG_FUNCTION_ARGS)
  * point, we will fail to restore a consistent database state.
  *
  * We also attempt to retrieve the corresponding backup history file.
- * If successful, set recoveryMinXlogOffset to constrain valid PITR stopping
+ * If successful, set *minRecoveryLoc to constrain valid PITR stopping
  * points.
  *
  * Returns TRUE if a backup_label was found (and fills the checkpoint
  * location into *checkPointLoc); returns FALSE if not.
  */
 static bool
-read_backup_label(XLogRecPtr *checkPointLoc)
+read_backup_label(XLogRecPtr *checkPointLoc, XLogRecPtr *minRecoveryLoc)
 {
 	XLogRecPtr	startpoint;
 	XLogRecPtr	stoppoint;
@@ -6371,6 +6478,10 @@ read_backup_label(XLogRecPtr *checkPointLoc)
 	FILE	   *fp;
 	char		ch;
 
+	/* Default is to not constrain recovery stop point */
+	minRecoveryLoc->xlogid = 0;
+	minRecoveryLoc->xrecoff = 0;
+
 	/*
 	 * See if label file is present
 	 */
@@ -6439,7 +6550,7 @@ read_backup_label(XLogRecPtr *checkPointLoc)
 			ereport(FATAL,
 					(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
 					 errmsg("invalid data in file \"%s\"", histfilename)));
-		recoveryMinXlogOffset = stoppoint;
+		*minRecoveryLoc = stoppoint;
 		if (ferror(fp) || FreeFile(fp))
 			ereport(FATAL,
 					(errcode_for_file_access(),
@@ -6450,24 +6561,6 @@ read_backup_label(XLogRecPtr *checkPointLoc)
 	return true;
 }
 
-/*
- * remove_backup_label: remove any extant backup_label after successful
- * recovery.  Once we have completed the end-of-recovery checkpoint there
- * is no reason to have to replay from the start point indicated by the
- * label (and indeed we'll probably have removed/recycled the needed WAL
- * segments), so remove the label to prevent trouble in later crash recoveries.
- */
-static void
-remove_backup_label(void)
-{
-	if (unlink(BACKUP_LABEL_FILE) != 0)
-		if (errno != ENOENT)
-			ereport(FATAL,
-					(errcode_for_file_access(),
-					 errmsg("could not remove file \"%s\": %m",
-							BACKUP_LABEL_FILE)));
-}
-
 /*
  * Error context callback for errors occurring during rm_redo().
  */
diff --git a/src/bin/pg_controldata/pg_controldata.c b/src/bin/pg_controldata/pg_controldata.c
index dd56ea787e6259e33a844beeb1b4e53327aef625..e0f3cfd2d9aad66b667abf2e425808fdd0643de4 100644
--- a/src/bin/pg_controldata/pg_controldata.c
+++ b/src/bin/pg_controldata/pg_controldata.c
@@ -6,7 +6,7 @@
  * copyright (c) Oliver Elphick <olly@lfix.co.uk>, 2001;
  * licence: BSD
  *
- * $PostgreSQL: pgsql/src/bin/pg_controldata/pg_controldata.c,v 1.29 2006/06/07 22:24:44 momjian Exp $
+ * $PostgreSQL: pgsql/src/bin/pg_controldata/pg_controldata.c,v 1.30 2006/08/07 16:57:56 tgl Exp $
  */
 #include "postgres.h"
 
@@ -50,8 +50,10 @@ dbState(DBState state)
 			return _("shut down");
 		case DB_SHUTDOWNING:
 			return _("shutting down");
-		case DB_IN_RECOVERY:
-			return _("in recovery");
+		case DB_IN_CRASH_RECOVERY:
+			return _("in crash recovery");
+		case DB_IN_ARCHIVE_RECOVERY:
+			return _("in archive recovery");
 		case DB_IN_PRODUCTION:
 			return _("in production");
 	}
@@ -147,40 +149,70 @@ main(int argc, char *argv[])
 	snprintf(sysident_str, sizeof(sysident_str), UINT64_FORMAT,
 			 ControlFile.system_identifier);
 
-	printf(_("pg_control version number:            %u\n"), ControlFile.pg_control_version);
-	printf(_("Catalog version number:               %u\n"), ControlFile.catalog_version_no);
-	printf(_("Database system identifier:           %s\n"), sysident_str);
-	printf(_("Database cluster state:               %s\n"), dbState(ControlFile.state));
-	printf(_("pg_control last modified:             %s\n"), pgctime_str);
-	printf(_("Current log file ID:                  %u\n"), ControlFile.logId);
-	printf(_("Next log file segment:                %u\n"), ControlFile.logSeg);
+	printf(_("pg_control version number:            %u\n"),
+		   ControlFile.pg_control_version);
+	printf(_("Catalog version number:               %u\n"),
+		   ControlFile.catalog_version_no);
+	printf(_("Database system identifier:           %s\n"),
+		   sysident_str);
+	printf(_("Database cluster state:               %s\n"),
+		   dbState(ControlFile.state));
+	printf(_("pg_control last modified:             %s\n"),
+		   pgctime_str);
+	printf(_("Current log file ID:                  %u\n"),
+		   ControlFile.logId);
+	printf(_("Next log file segment:                %u\n"),
+		   ControlFile.logSeg);
 	printf(_("Latest checkpoint location:           %X/%X\n"),
-		   ControlFile.checkPoint.xlogid, ControlFile.checkPoint.xrecoff);
+		   ControlFile.checkPoint.xlogid,
+		   ControlFile.checkPoint.xrecoff);
 	printf(_("Prior checkpoint location:            %X/%X\n"),
-	  ControlFile.prevCheckPoint.xlogid, ControlFile.prevCheckPoint.xrecoff);
+		   ControlFile.prevCheckPoint.xlogid,
+		   ControlFile.prevCheckPoint.xrecoff);
 	printf(_("Latest checkpoint's REDO location:    %X/%X\n"),
-		   ControlFile.checkPointCopy.redo.xlogid, ControlFile.checkPointCopy.redo.xrecoff);
+		   ControlFile.checkPointCopy.redo.xlogid,
+		   ControlFile.checkPointCopy.redo.xrecoff);
 	printf(_("Latest checkpoint's UNDO location:    %X/%X\n"),
-		   ControlFile.checkPointCopy.undo.xlogid, ControlFile.checkPointCopy.undo.xrecoff);
-	printf(_("Latest checkpoint's TimeLineID:       %u\n"), ControlFile.checkPointCopy.ThisTimeLineID);
-	printf(_("Latest checkpoint's NextXID:          %u\n"), ControlFile.checkPointCopy.nextXid);
-	printf(_("Latest checkpoint's NextOID:          %u\n"), ControlFile.checkPointCopy.nextOid);
-	printf(_("Latest checkpoint's NextMultiXactId:  %u\n"), ControlFile.checkPointCopy.nextMulti);
-	printf(_("Latest checkpoint's NextMultiOffset:  %u\n"), ControlFile.checkPointCopy.nextMultiOffset);
-	printf(_("Time of latest checkpoint:            %s\n"), ckpttime_str);
-	printf(_("Maximum data alignment:               %u\n"), ControlFile.maxAlign);
+		   ControlFile.checkPointCopy.undo.xlogid,
+		   ControlFile.checkPointCopy.undo.xrecoff);
+	printf(_("Latest checkpoint's TimeLineID:       %u\n"),
+		   ControlFile.checkPointCopy.ThisTimeLineID);
+	printf(_("Latest checkpoint's NextXID:          %u\n"),
+		   ControlFile.checkPointCopy.nextXid);
+	printf(_("Latest checkpoint's NextOID:          %u\n"),
+		   ControlFile.checkPointCopy.nextOid);
+	printf(_("Latest checkpoint's NextMultiXactId:  %u\n"),
+		   ControlFile.checkPointCopy.nextMulti);
+	printf(_("Latest checkpoint's NextMultiOffset:  %u\n"),
+		   ControlFile.checkPointCopy.nextMultiOffset);
+	printf(_("Time of latest checkpoint:            %s\n"),
+		   ckpttime_str);
+	printf(_("Minimum recovery ending location:     %X/%X\n"),
+		   ControlFile.minRecoveryPoint.xlogid,
+		   ControlFile.minRecoveryPoint.xrecoff);
+	printf(_("Maximum data alignment:               %u\n"),
+		   ControlFile.maxAlign);
 	/* we don't print floatFormat since can't say much useful about it */
-	printf(_("Database block size:                  %u\n"), ControlFile.blcksz);
-	printf(_("Blocks per segment of large relation: %u\n"), ControlFile.relseg_size);
-	printf(_("WAL block size:                       %u\n"), ControlFile.xlog_blcksz);
-	printf(_("Bytes per WAL segment:                %u\n"), ControlFile.xlog_seg_size);
-	printf(_("Maximum length of identifiers:        %u\n"), ControlFile.nameDataLen);
-	printf(_("Maximum columns in an index:          %u\n"), ControlFile.indexMaxKeys);
+	printf(_("Database block size:                  %u\n"),
+		   ControlFile.blcksz);
+	printf(_("Blocks per segment of large relation: %u\n"),
+		   ControlFile.relseg_size);
+	printf(_("WAL block size:                       %u\n"),
+		   ControlFile.xlog_blcksz);
+	printf(_("Bytes per WAL segment:                %u\n"),
+		   ControlFile.xlog_seg_size);
+	printf(_("Maximum length of identifiers:        %u\n"),
+		   ControlFile.nameDataLen);
+	printf(_("Maximum columns in an index:          %u\n"),
+		   ControlFile.indexMaxKeys);
 	printf(_("Date/time type storage:               %s\n"),
 		   (ControlFile.enableIntTimes ? _("64-bit integers") : _("floating-point numbers")));
-	printf(_("Maximum length of locale name:        %u\n"), ControlFile.localeBuflen);
-	printf(_("LC_COLLATE:                           %s\n"), ControlFile.lc_collate);
-	printf(_("LC_CTYPE:                             %s\n"), ControlFile.lc_ctype);
+	printf(_("Maximum length of locale name:        %u\n"),
+		   ControlFile.localeBuflen);
+	printf(_("LC_COLLATE:                           %s\n"),
+		   ControlFile.lc_collate);
+	printf(_("LC_CTYPE:                             %s\n"),
+		   ControlFile.lc_ctype);
 
 	return 0;
 }
diff --git a/src/bin/pg_resetxlog/pg_resetxlog.c b/src/bin/pg_resetxlog/pg_resetxlog.c
index 46fe088028a35c82e0d34e19a0ea2afbf0c5a2d9..c7589e92c1e548acfe1eecef2d35c162088eeec5 100644
--- a/src/bin/pg_resetxlog/pg_resetxlog.c
+++ b/src/bin/pg_resetxlog/pg_resetxlog.c
@@ -23,7 +23,7 @@
  * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/bin/pg_resetxlog/pg_resetxlog.c,v 1.50 2006/07/14 14:52:26 momjian Exp $
+ * $PostgreSQL: pgsql/src/bin/pg_resetxlog/pg_resetxlog.c,v 1.51 2006/08/07 16:57:56 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -578,6 +578,8 @@ RewriteControlFile(void)
 	ControlFile.checkPoint = ControlFile.checkPointCopy.redo;
 	ControlFile.prevCheckPoint.xlogid = 0;
 	ControlFile.prevCheckPoint.xrecoff = 0;
+	ControlFile.minRecoveryPoint.xlogid = 0;
+	ControlFile.minRecoveryPoint.xrecoff = 0;
 
 	/* Contents are protected with a CRC */
 	INIT_CRC32(ControlFile.crc);
diff --git a/src/include/access/gin.h b/src/include/access/gin.h
index ba7d15cf1fc729db4596f17bc7a23705a8ecc824..64aef37a94c5bd3f9aac0d6a7aa62ca4c87c46da 100644
--- a/src/include/access/gin.h
+++ b/src/include/access/gin.h
@@ -3,7 +3,7 @@
  *    header file for postgres inverted index access method implementation.
  *
  *  Copyright (c) 2006, PostgreSQL Global Development Group
- *  $PostgreSQL: pgsql/src/include/access/gin.h,v 1.5 2006/07/11 16:55:34 teodor Exp $
+ *  $PostgreSQL: pgsql/src/include/access/gin.h,v 1.6 2006/08/07 16:57:57 tgl Exp $
  *--------------------------------------------------------------------------
  */
 
@@ -234,6 +234,7 @@ extern void gin_redo(XLogRecPtr lsn, XLogRecord *record);
 extern void gin_desc(StringInfo buf, uint8 xl_info, char *rec);
 extern void gin_xlog_startup(void);
 extern void gin_xlog_cleanup(void);
+extern bool gin_safe_restartpoint(void);
 
 /* ginbtree.c */
 
diff --git a/src/include/access/gist_private.h b/src/include/access/gist_private.h
index d6e5cf0603eb5eb4bdd0ba45cd1bfea796395b21..de917c8b83453e91d5ddb666e0b2e619e8543e06 100644
--- a/src/include/access/gist_private.h
+++ b/src/include/access/gist_private.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/access/gist_private.h,v 1.22 2006/07/11 21:05:57 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/access/gist_private.h,v 1.23 2006/08/07 16:57:57 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -251,6 +251,7 @@ extern void gist_redo(XLogRecPtr lsn, XLogRecord *record);
 extern void gist_desc(StringInfo buf, uint8 xl_info, char *rec);
 extern void gist_xlog_startup(void);
 extern void gist_xlog_cleanup(void);
+extern bool gist_safe_restartpoint(void);
 extern IndexTuple gist_form_invalid_tuple(BlockNumber blkno);
 
 extern XLogRecData *formUpdateRdata(RelFileNode node, Buffer buffer,
diff --git a/src/include/access/nbtree.h b/src/include/access/nbtree.h
index 232cbb92bdbbfe29a9e78ed5f387e506cffc2eb2..e460bbb0d50cf2bf39a50c14b3b512b0510734b9 100644
--- a/src/include/access/nbtree.h
+++ b/src/include/access/nbtree.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/access/nbtree.h,v 1.102 2006/07/25 19:13:00 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/access/nbtree.h,v 1.103 2006/08/07 16:57:57 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -545,5 +545,6 @@ extern void btree_redo(XLogRecPtr lsn, XLogRecord *record);
 extern void btree_desc(StringInfo buf, uint8 xl_info, char *rec);
 extern void btree_xlog_startup(void);
 extern void btree_xlog_cleanup(void);
+extern bool btree_safe_restartpoint(void);
 
 #endif   /* NBTREE_H */
diff --git a/src/include/access/xlog_internal.h b/src/include/access/xlog_internal.h
index 6aeda55429d28cbc2c6dccd87d572d2d1228581c..03bf0e86231def31bf33a424074110d79ff15eb2 100644
--- a/src/include/access/xlog_internal.h
+++ b/src/include/access/xlog_internal.h
@@ -11,7 +11,7 @@
  * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/access/xlog_internal.h,v 1.14 2006/08/06 03:53:44 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/access/xlog_internal.h,v 1.15 2006/08/07 16:57:57 tgl Exp $
  */
 #ifndef XLOG_INTERNAL_H
 #define XLOG_INTERNAL_H
@@ -232,6 +232,7 @@ typedef struct RmgrData
 	void		(*rm_desc) (StringInfo buf, uint8 xl_info, char *rec);
 	void		(*rm_startup) (void);
 	void		(*rm_cleanup) (void);
+	bool		(*rm_safe_restartpoint) (void);
 } RmgrData;
 
 extern const RmgrData RmgrTable[];
diff --git a/src/include/catalog/pg_control.h b/src/include/catalog/pg_control.h
index 86722953dda075e3f5f061440cb4394042553354..8e405f607eb25e70a757b1563765933a41b233b5 100644
--- a/src/include/catalog/pg_control.h
+++ b/src/include/catalog/pg_control.h
@@ -8,7 +8,7 @@
  * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/catalog/pg_control.h,v 1.30 2006/08/06 03:53:44 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/pg_control.h,v 1.31 2006/08/07 16:57:57 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -22,7 +22,7 @@
 
 
 /* Version identifier for this pg_control format */
-#define PG_CONTROL_VERSION	820
+#define PG_CONTROL_VERSION	821
 
 /*
  * Body of CheckPoint XLOG records.  This is declared here because we keep
@@ -56,7 +56,8 @@ typedef enum DBState
 	DB_STARTUP = 0,
 	DB_SHUTDOWNED,
 	DB_SHUTDOWNING,
-	DB_IN_RECOVERY,
+	DB_IN_CRASH_RECOVERY,
+	DB_IN_ARCHIVE_RECOVERY,
 	DB_IN_PRODUCTION
 } DBState;
 
@@ -107,6 +108,8 @@ typedef struct ControlFileData
 
 	CheckPoint	checkPointCopy; /* copy of last check point record */
 
+	XLogRecPtr	minRecoveryPoint;	/* must replay xlog to here */
+
 	/*
 	 * This data is used to check for hardware-architecture compatibility of
 	 * the database and the backend executable.  We need not check endianness