diff --git a/doc/src/sgml/ref/pg_resetxlog.sgml b/doc/src/sgml/ref/pg_resetxlog.sgml
index 11d5d1eef63bcb05c70c342358d7e84dfdf6ef73..c1c9754368fca53ef8ffe039bf34804b1116a39a 100644
--- a/doc/src/sgml/ref/pg_resetxlog.sgml
+++ b/doc/src/sgml/ref/pg_resetxlog.sgml
@@ -1,5 +1,5 @@
 <!--
-$PostgreSQL: pgsql/doc/src/sgml/ref/pg_resetxlog.sgml,v 1.18 2006/09/16 00:30:19 momjian Exp $
+$PostgreSQL: pgsql/doc/src/sgml/ref/pg_resetxlog.sgml,v 1.19 2006/12/08 19:50:52 tgl Exp $
 PostgreSQL documentation
 -->
 
@@ -72,7 +72,7 @@ PostgreSQL documentation
    <literal>-f</> can still be used, but
    the recovered database must be treated with even more suspicion than
    usual: an immediate dump and reload is imperative.  <emphasis>Do not</>
-   execute any data-modifying operations in the database before you dump;
+   execute any data-modifying operations in the database before you dump,
    as any such action is likely to make the corruption worse.
   </para>
 
@@ -127,7 +127,7 @@ PostgreSQL documentation
     <listitem>
      <para>
       The WAL starting address (<literal>-l</>) should be
-      larger than any file name currently existing in
+      larger than any WAL segment file name currently existing in
       the directory <filename>pg_xlog</> under the data directory.
       These names are also in hexadecimal and have three parts.  The first
       part is the <quote>timeline ID</> and should usually be kept the same.
@@ -139,6 +139,18 @@ PostgreSQL documentation
       <filename>000000010000003A000000FF</>, choose <literal>-l 0x1,0x3B,0x0</>
       or more.
      </para>
+
+     <note>
+      <para>
+       <command>pg_resetxlog</command> itself looks at the files in
+       <filename>pg_xlog</> and chooses a default <literal>-l</> setting
+       beyond the last existing file name.  Therefore, manual adjustment of
+       <literal>-l</> should only be needed if you are aware of WAL segment
+       files that are not currently present in <filename>pg_xlog</>, such as
+       entries in an offline archive; or if the contents of
+       <filename>pg_xlog</> have been lost entirely.
+      </para>
+     </note>
     </listitem>
 
     <listitem>
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 98c610dcadd5a021f0f906b6b3af162198ce86f1..4d4a17a3aa5ab0ffbcc42140d939483093136419 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.258 2006/11/30 18:29:11 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/access/transam/xlog.c,v 1.259 2006/12/08 19:50:53 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1538,54 +1538,6 @@ XLogWrite(XLogwrtRqst WriteRqst, bool flexible, bool xlog_switch)
 			openLogFile = XLogFileInit(openLogId, openLogSeg,
 									   &use_existent, true);
 			openLogOff = 0;
-
-			/* update pg_control, unless someone else already did */
-			LWLockAcquire(ControlFileLock, LW_EXCLUSIVE);
-			if (ControlFile->logId < openLogId ||
-				(ControlFile->logId == openLogId &&
-				 ControlFile->logSeg < openLogSeg + 1))
-			{
-				ControlFile->logId = openLogId;
-				ControlFile->logSeg = openLogSeg + 1;
-				ControlFile->time = time(NULL);
-				UpdateControlFile();
-
-				/*
-				 * Signal bgwriter to start a checkpoint if it's been too long
-				 * since the last one.	(We look at local copy of RedoRecPtr
-				 * which might be a little out of date, but should be close
-				 * enough for this purpose.)
-				 *
-				 * A straight computation of segment number could overflow 32
-				 * bits.  Rather than assuming we have working 64-bit
-				 * arithmetic, we compare the highest-order bits separately,
-				 * and force a checkpoint immediately when they change.
-				 */
-				if (IsUnderPostmaster)
-				{
-					uint32		old_segno,
-								new_segno;
-					uint32		old_highbits,
-								new_highbits;
-
-					old_segno = (RedoRecPtr.xlogid % XLogSegSize) * XLogSegsPerFile +
-						(RedoRecPtr.xrecoff / XLogSegSize);
-					old_highbits = RedoRecPtr.xlogid / XLogSegSize;
-					new_segno = (openLogId % XLogSegSize) * XLogSegsPerFile +
-						openLogSeg;
-					new_highbits = openLogId / XLogSegSize;
-					if (new_highbits != old_highbits ||
-						new_segno >= old_segno + (uint32) CheckPointSegments)
-					{
-#ifdef WAL_DEBUG
-						if (XLOG_DEBUG)
-							elog(LOG, "time for a checkpoint, signaling bgwriter");
-#endif
-						RequestCheckpoint(false, true);
-					}
-				}
-			}
-			LWLockRelease(ControlFileLock);
 		}
 
 		/* Make sure we have the current logfile open */
@@ -1669,7 +1621,9 @@ XLogWrite(XLogwrtRqst WriteRqst, bool flexible, bool xlog_switch)
 			 *
 			 * This is also the right place to notify the Archiver that the
 			 * segment is ready to copy to archival storage, and to update the
-			 * timer for archive_timeout.
+			 * timer for archive_timeout, and to signal for a checkpoint if
+			 * too many logfile segments have been used since the last
+			 * checkpoint.
 			 */
 			if (finishing_seg || (xlog_switch && last_iteration))
 			{
@@ -1680,6 +1634,41 @@ XLogWrite(XLogwrtRqst WriteRqst, bool flexible, bool xlog_switch)
 					XLogArchiveNotifySeg(openLogId, openLogSeg);
 
 				Write->lastSegSwitchTime = time(NULL);
+
+				/*
+				 * Signal bgwriter to start a checkpoint if it's been too long
+				 * since the last one.	(We look at local copy of RedoRecPtr
+				 * which might be a little out of date, but should be close
+				 * enough for this purpose.)
+				 *
+				 * A straight computation of segment number could overflow 32
+				 * bits.  Rather than assuming we have working 64-bit
+				 * arithmetic, we compare the highest-order bits separately,
+				 * and force a checkpoint immediately when they change.
+				 */
+				if (IsUnderPostmaster)
+				{
+					uint32		old_segno,
+								new_segno;
+					uint32		old_highbits,
+								new_highbits;
+
+					old_segno = (RedoRecPtr.xlogid % XLogSegSize) * XLogSegsPerFile +
+						(RedoRecPtr.xrecoff / XLogSegSize);
+					old_highbits = RedoRecPtr.xlogid / XLogSegSize;
+					new_segno = (openLogId % XLogSegSize) * XLogSegsPerFile +
+						openLogSeg;
+					new_highbits = openLogId / XLogSegSize;
+					if (new_highbits != old_highbits ||
+						new_segno >= old_segno + (uint32) (CheckPointSegments-1))
+					{
+#ifdef WAL_DEBUG
+						if (XLOG_DEBUG)
+							elog(LOG, "time for a checkpoint, signaling bgwriter");
+#endif
+						RequestCheckpoint(false, true);
+					}
+				}
 			}
 		}
 
@@ -4199,8 +4188,6 @@ BootStrapXLOG(void)
 	ControlFile->system_identifier = sysidentifier;
 	ControlFile->state = DB_SHUTDOWNED;
 	ControlFile->time = checkPoint.time;
-	ControlFile->logId = 0;
-	ControlFile->logSeg = 1;
 	ControlFile->checkPoint = checkPoint.redo;
 	ControlFile->checkPointCopy = checkPoint;
 	/* some additional ControlFile fields are set in WriteControlFile() */
@@ -4659,8 +4646,7 @@ StartupXLOG(void)
 	 */
 	ReadControlFile();
 
-	if (ControlFile->logSeg == 0 ||
-		ControlFile->state < DB_SHUTDOWNED ||
+	if (ControlFile->state < DB_SHUTDOWNED ||
 		ControlFile->state > DB_IN_PRODUCTION ||
 		!XRecOffIsValid(ControlFile->checkPoint.xrecoff))
 		ereport(FATAL,
@@ -4672,7 +4658,7 @@ StartupXLOG(void)
 						str_time(ControlFile->time))));
 	else if (ControlFile->state == DB_SHUTDOWNING)
 		ereport(LOG,
-				(errmsg("database system shutdown was interrupted at %s",
+				(errmsg("database system shutdown was interrupted; last known up at %s",
 						str_time(ControlFile->time))));
 	else if (ControlFile->state == DB_IN_CRASH_RECOVERY)
 		ereport(LOG,
@@ -4688,7 +4674,7 @@ StartupXLOG(void)
 				" 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",
+				(errmsg("database system was interrupted; last known up at %s",
 						str_time(ControlFile->time))));
 
 	/* This is just to allow attaching to startup process with a debugger */
@@ -5064,8 +5050,6 @@ StartupXLOG(void)
 	openLogSeg = endLogSeg;
 	openLogFile = XLogFileOpen(openLogId, openLogSeg);
 	openLogOff = 0;
-	ControlFile->logId = openLogId;
-	ControlFile->logSeg = openLogSeg + 1;
 	Insert = &XLogCtl->Insert;
 	Insert->PrevRecord = LastRec;
 	XLogCtl->xlblocks[0].xlogid = openLogId;
diff --git a/src/bin/pg_controldata/pg_controldata.c b/src/bin/pg_controldata/pg_controldata.c
index cbde5357edf45067d6010943b7acdfb064b95d4b..6805af615364da667380f1d836d5fa2d70b0d2e7 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.31 2006/08/21 16:16:31 tgl Exp $
+ * $PostgreSQL: pgsql/src/bin/pg_controldata/pg_controldata.c,v 1.32 2006/12/08 19:50:53 tgl Exp $
  */
 #include "postgres.h"
 
@@ -159,10 +159,6 @@ main(int argc, char *argv[])
 		   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);
diff --git a/src/bin/pg_resetxlog/pg_resetxlog.c b/src/bin/pg_resetxlog/pg_resetxlog.c
index 15613832792ccb7048ba6035ea3a106580e0960d..9212ccc5b766a93c4f53ba35f0e5238f9ecdf280 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.53 2006/10/04 00:30:05 momjian Exp $
+ * $PostgreSQL: pgsql/src/bin/pg_resetxlog/pg_resetxlog.c,v 1.54 2006/12/08 19:50:53 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -60,6 +60,7 @@ static bool ReadControlFile(void);
 static void GuessControlValues(void);
 static void PrintControlValues(bool guessed);
 static void RewriteControlFile(void);
+static void FindEndOfXLOG(void);
 static void KillExistingXLOG(void);
 static void WriteEmptyXLOG(void);
 static void usage(void);
@@ -283,6 +284,11 @@ main(int argc, char *argv[])
 	if (!ReadControlFile())
 		GuessControlValues();
 
+	/*
+	 * Also look at existing segment files to set up newXlogId/newXlogSeg
+	 */
+	FindEndOfXLOG();
+
 	/*
 	 * Adjust fields if required by switches.  (Do this now so that printout,
 	 * if any, includes these values.)
@@ -305,12 +311,12 @@ main(int argc, char *argv[])
 	if (minXlogTli > ControlFile.checkPointCopy.ThisTimeLineID)
 		ControlFile.checkPointCopy.ThisTimeLineID = minXlogTli;
 
-	if (minXlogId > ControlFile.logId ||
-		(minXlogId == ControlFile.logId &&
-		 minXlogSeg > ControlFile.logSeg))
+	if (minXlogId > newXlogId ||
+		(minXlogId == newXlogId &&
+		 minXlogSeg > newXlogSeg))
 	{
-		ControlFile.logId = minXlogId;
-		ControlFile.logSeg = minXlogSeg;
+		newXlogId = minXlogId;
+		newXlogSeg = minXlogSeg;
 	}
 
 	/*
@@ -469,8 +475,6 @@ GuessControlValues(void)
 
 	ControlFile.state = DB_SHUTDOWNED;
 	ControlFile.time = time(NULL);
-	ControlFile.logId = 0;
-	ControlFile.logSeg = 1;
 	ControlFile.checkPoint = ControlFile.checkPointCopy.redo;
 
 	ControlFile.maxAlign = MAXIMUM_ALIGNOF;
@@ -533,16 +537,16 @@ PrintControlValues(bool guessed)
 	snprintf(sysident_str, sizeof(sysident_str), UINT64_FORMAT,
 			 ControlFile.system_identifier);
 
+	printf(_("First log file ID for new XLOG:       %u\n"),
+		   newXlogId);
+	printf(_("First log file segment for new XLOG:  %u\n"),
+		   newXlogSeg);
 	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(_("Current log file ID:                  %u\n"),
-		   ControlFile.logId);
-	printf(_("Next log file segment:                %u\n"),
-		   ControlFile.logSeg);
 	printf(_("Latest checkpoint's TimeLineID:       %u\n"),
 		   ControlFile.checkPointCopy.ThisTimeLineID);
 	printf(_("Latest checkpoint's NextXID:          %u/%u\n"),
@@ -590,22 +594,9 @@ RewriteControlFile(void)
 	char		buffer[PG_CONTROL_SIZE];		/* need not be aligned */
 
 	/*
-	 * Adjust fields as needed to force an empty XLOG starting at the next
-	 * available segment.
+	 * Adjust fields as needed to force an empty XLOG starting at
+	 * newXlogId/newXlogSeg.
 	 */
-	newXlogId = ControlFile.logId;
-	newXlogSeg = ControlFile.logSeg;
-
-	/* adjust in case we are changing segment size */
-	newXlogSeg *= ControlFile.xlog_seg_size;
-	newXlogSeg = (newXlogSeg + XLogSegSize - 1) / XLogSegSize;
-
-	/* be sure we wrap around correctly at end of a logfile */
-	NextLogSeg(newXlogId, newXlogSeg);
-
-	/* Now we can force the recorded xlog seg size to the right thing. */
-	ControlFile.xlog_seg_size = XLogSegSize;
-
 	ControlFile.checkPointCopy.redo.xlogid = newXlogId;
 	ControlFile.checkPointCopy.redo.xrecoff =
 		newXlogSeg * XLogSegSize + SizeOfXLogLongPHD;
@@ -614,14 +605,15 @@ RewriteControlFile(void)
 
 	ControlFile.state = DB_SHUTDOWNED;
 	ControlFile.time = time(NULL);
-	ControlFile.logId = newXlogId;
-	ControlFile.logSeg = newXlogSeg + 1;
 	ControlFile.checkPoint = ControlFile.checkPointCopy.redo;
 	ControlFile.prevCheckPoint.xlogid = 0;
 	ControlFile.prevCheckPoint.xrecoff = 0;
 	ControlFile.minRecoveryPoint.xlogid = 0;
 	ControlFile.minRecoveryPoint.xrecoff = 0;
 
+	/* Now we can force the recorded xlog seg size to the right thing. */
+	ControlFile.xlog_seg_size = XLogSegSize;
+
 	/* Contents are protected with a CRC */
 	INIT_CRC32(ControlFile.crc);
 	COMP_CRC32(ControlFile.crc,
@@ -680,6 +672,97 @@ RewriteControlFile(void)
 }
 
 
+/*
+ * Scan existing XLOG files and determine the highest existing WAL address
+ *
+ * On entry, ControlFile.checkPointCopy.redo and ControlFile.xlog_seg_size
+ * are assumed valid (note that we allow the old xlog seg size to differ
+ * from what we're using).  On exit, newXlogId and newXlogSeg are set to
+ * suitable values for the beginning of replacement WAL (in our seg size).
+ */
+static void
+FindEndOfXLOG(void)
+{
+	DIR		   *xldir;
+	struct dirent *xlde;
+
+	/*
+	 * Initialize the max() computation using the last checkpoint address
+	 * from old pg_control.  Note that for the moment we are working with
+	 * segment numbering according to the old xlog seg size.
+	 */
+	newXlogId = ControlFile.checkPointCopy.redo.xlogid;
+	newXlogSeg = ControlFile.checkPointCopy.redo.xrecoff / ControlFile.xlog_seg_size;
+
+	/*
+	 * Scan the pg_xlog directory to find existing WAL segment files.
+	 * We assume any present have been used; in most scenarios this should
+	 * be conservative, because of xlog.c's attempts to pre-create files.
+	 */
+	xldir = opendir(XLOGDIR);
+	if (xldir == NULL)
+	{
+		fprintf(stderr, _("%s: could not open directory \"%s\": %s\n"),
+				progname, XLOGDIR, strerror(errno));
+		exit(1);
+	}
+
+	errno = 0;
+	while ((xlde = readdir(xldir)) != NULL)
+	{
+		if (strlen(xlde->d_name) == 24 &&
+			strspn(xlde->d_name, "0123456789ABCDEF") == 24)
+		{
+			unsigned int	tli,
+							log,
+							seg;
+
+			sscanf(xlde->d_name, "%08X%08X%08X", &tli, &log, &seg);
+			/*
+			 * Note: we take the max of all files found, regardless of their
+			 * timelines.  Another possibility would be to ignore files of
+			 * timelines other than the target TLI, but this seems safer.
+			 * Better too large a result than too small...
+			 */
+			if (log > newXlogId ||
+				(log == newXlogId && seg > newXlogSeg))
+			{
+				newXlogId = log;
+				newXlogSeg = seg;
+			}
+		}
+		errno = 0;
+	}
+#ifdef WIN32
+
+	/*
+	 * This fix is in mingw cvs (runtime/mingwex/dirent.c rev 1.4), but not in
+	 * released version
+	 */
+	if (GetLastError() == ERROR_NO_MORE_FILES)
+		errno = 0;
+#endif
+
+	if (errno)
+	{
+		fprintf(stderr, _("%s: could not read from directory \"%s\": %s\n"),
+				progname, XLOGDIR, strerror(errno));
+		exit(1);
+	}
+	closedir(xldir);
+
+	/*
+	 * Finally, convert to new xlog seg size, and advance by one to ensure
+	 * we are in virgin territory.
+	 */
+	newXlogSeg *= ControlFile.xlog_seg_size;
+	newXlogSeg = (newXlogSeg + XLogSegSize - 1) / XLogSegSize;
+
+	/* be sure we wrap around correctly at end of a logfile */
+	NextLogSeg(newXlogId, newXlogSeg);
+}
+
+
 /*
  * Remove existing XLOG files
  */
diff --git a/src/include/catalog/pg_control.h b/src/include/catalog/pg_control.h
index 0e1132052e79626542a40bd207777e30e3701766..84c148c2abd07103fb36489bc86e164378ff75b0 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.33 2006/10/04 00:30:07 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/pg_control.h,v 1.34 2006/12/08 19:50:53 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -22,7 +22,7 @@
 
 
 /* Version identifier for this pg_control format */
-#define PG_CONTROL_VERSION	822
+#define PG_CONTROL_VERSION	831
 
 /*
  * Body of CheckPoint XLOG records.  This is declared here because we keep
@@ -102,8 +102,6 @@ typedef struct ControlFileData
 	 */
 	DBState		state;			/* see enum above */
 	time_t		time;			/* time stamp of last pg_control update */
-	uint32		logId;			/* current log file id */
-	uint32		logSeg;			/* current log file segment, + 1 */
 	XLogRecPtr	checkPoint;		/* last check point record ptr */
 	XLogRecPtr	prevCheckPoint; /* previous check point record ptr */