diff --git a/src/bin/pg_upgrade/controldata.c b/src/bin/pg_upgrade/controldata.c
new file mode 100644
index 0fe98a5..bba3b1b
*** a/src/bin/pg_upgrade/controldata.c
--- b/src/bin/pg_upgrade/controldata.c
*************** get_control_data(ClusterInfo *cluster, b
*** 58,63 ****
--- 58,64 ----
  	bool		got_large_object = false;
  	bool		got_date_is_int = false;
  	bool		got_data_checksum_version = false;
+ 	bool		got_cluster_state = false;
  	char	   *lc_collate = NULL;
  	char	   *lc_ctype = NULL;
  	char	   *lc_monetary = NULL;
*************** get_control_data(ClusterInfo *cluster, b
*** 423,428 ****
--- 424,487 ----
  	pclose(output);
  
  	/*
+ 	 * Check for clean shutdown
+ 	 */
+ 
+ 	/* only pg_controldata outputs the cluster state */
+ 	snprintf(cmd, sizeof(cmd), "\"%s/pg_controldata\" \"%s\"",
+ 			 cluster->bindir, cluster->pgdata);
+ 	fflush(stdout);
+ 	fflush(stderr);
+ 
+ 	if ((output = popen(cmd, "r")) == NULL)
+ 		pg_fatal("could not get control data using %s: %s\n",
+ 				 cmd, strerror(errno));
+ 
+ 	/* we have the result of cmd in "output". so parse it line by line now */
+ 	while (fgets(bufin, sizeof(bufin), output))
+ 	{
+ 		if ((!live_check || cluster == &new_cluster) &&
+ 			(p = strstr(bufin, "Database cluster state:")) != NULL)
+ 		{
+ 			p = strchr(p, ':');
+ 
+ 			if (p == NULL || strlen(p) <= 1)
+ 				pg_fatal("%d: database cluster state problem\n", __LINE__);
+ 
+ 			p++;				/* remove ':' char */
+ 
+ 			/*
+ 			 * We checked earlier for a postmaster lock file, and if we found
+ 			 * one, we tried to start/stop the server to replay the WAL.  However,
+ 			 * pg_ctl -m immediate doesn't leave a lock file, but does require
+ 			 * WAL replay, so we check here that the server was shut down cleanly,
+ 			 * from the controldata perspective.
+ 			 */
+ 			/* remove leading spaces */
+ 			while (*p == ' ')
+ 				p++;
+ 			if (strcmp(p, "shut down\n") != 0)
+ 			{
+ 				if (cluster == &old_cluster)
+ 					pg_fatal("The source cluster was not shut down cleanly.\n");
+ 				else
+ 					pg_fatal("The target cluster was not shut down cleanly.\n");
+ 			}
+ 			got_cluster_state = true;
+ 		}
+ 	}
+ 
+ 	pclose(output);
+ 
+ 	if (!got_cluster_state)
+ 	{
+ 		if (cluster == &old_cluster)
+ 			pg_fatal("The source cluster lacks cluster state information:\n");
+ 		else
+ 			pg_fatal("The target cluster lacks cluster state information:\n");
+ 	}
+ 
+ 	/*
  	 * Restore environment variables
  	 */
  	pg_putenv("LC_COLLATE", lc_collate);
