diff --git a/contrib/pg_upgrade/function.c b/contrib/pg_upgrade/function.c
new file mode 100644
index 90e8a9f..58b341a
*** a/contrib/pg_upgrade/function.c
--- b/contrib/pg_upgrade/function.c
*************** get_loadable_libraries(void)
*** 132,138 ****
  	PGresult  **ress;
  	int			totaltups;
  	int			dbnum;
! 
  	ress = (PGresult **) pg_malloc(old_cluster.dbarr.ndbs * sizeof(PGresult *));
  	totaltups = 0;
  
--- 132,139 ----
  	PGresult  **ress;
  	int			totaltups;
  	int			dbnum;
! 	bool		found_public_plpython_handler = false;
! 	
  	ress = (PGresult **) pg_malloc(old_cluster.dbarr.ndbs * sizeof(PGresult *));
  	totaltups = 0;
  
*************** get_loadable_libraries(void)
*** 157,165 ****
--- 158,224 ----
  										FirstNormalObjectId);
  		totaltups += PQntuples(ress[dbnum]);
  
+ 		 /*
+ 		 *	Systems that install plpython before 8.1 have
+ 		 *	plpython_call_handler() defined in the "public" schema, causing
+ 		 *	pg_dumpall to dump it.  However that function still references
+ 		 *	"plpython" (no "2"), so it throws an error on restore.  This code
+ 		 *	checks for the problem function, reports affected databases to the
+ 		 *	user and explains how to remove them.
+ 		 *	8.1 git commit: e0dedd0559f005d60c69c9772163e69c204bac69
+ 		 *	http://archives.postgresql.org/pgsql-hackers/2012-03/msg01101.php
+ 		 *	http://archives.postgresql.org/pgsql-bugs/2012-05/msg00206.php
+ 		 */
+ 		if (GET_MAJOR_VERSION(old_cluster.major_version) < 901)
+ 		{
+ 			PGresult  *res;
+ 
+ 			res = executeQueryOrDie(conn,
+ 									"SELECT 1 "
+ 									"FROM	pg_catalog.pg_proc JOIN pg_namespace "
+ 									"		ON pronamespace = pg_namespace.oid "
+ 									"WHERE proname = 'plpython_call_handler' AND "
+ 									"nspname = 'public' AND "
+ 									"prolang = 13 /* C */ AND "
+ 									"probin IS NOT NULL AND "
+ 									"pg_proc.oid >= %u;",
+ 									FirstNormalObjectId);
+ 			if (PQntuples(res) > 0)
+ 			{
+ 				if (!found_public_plpython_handler)
+ 				{
+ 					pg_log(PG_WARNING,
+ 		   "\nThe old cluster has a \"plpython_call_handler\" function defined\n"
+ 	   		"in the \"public\" schema which is a duplicate of the one defined\n"
+ 		    "in the \"pg_catalog\" schema.  You can confirm this by executing\n"
+ 			"in psql:\n"
+ 			"\n"
+ 			"	\\df *.plpython_call_handler\n"
+ 			"\n"
+ 			"The \"public\" schema version of this function was created by a\n"
+ 			"pre-8.1 install of plpython, and must be removed for pg_upgrade\n"
+ 			"to complete because it references a now-obsolete \"plpython\"\n"
+ 			"shared object file.  You can remove the \"public\" schema version\n"
+ 			"of this function by running the following command:\n"
+ 			"\n"
+ 			"	DROP FUNCTION public.plpython_call_handler()\n"
+ 			"\n"
+ 			"in each affected database:\n"
+ 			"\n");
+ 				}
+ 				pg_log(PG_WARNING, "	%s\n", active_db->db_name);
+ 				found_public_plpython_handler = true;
+ 			}
+ 			PQclear(res);
+ 		}
+ 
  		PQfinish(conn);
  	}
  
+ 	if (found_public_plpython_handler)
+ 		pg_log(PG_FATAL,
+ 		   "Remove the problem functions from the old cluster to continue.\n");
+ 	
  	totaltups++;	/* reserve for pg_upgrade_support */
  
  	/* Allocate what's certainly enough space */
*************** check_loadable_libraries(void)
*** 245,256 ****
  		 *	For this case, we could check pg_pltemplate, but that only works
  		 *	for languages, and does not help with function shared objects,
  		 *	so we just do a general fix.
- 		 *
- 		 *	Some systems have plpython_call_handler() that references
- 		 *	"plpython" defined in the "public" schema, causing pg_dump to
- 		 *	dump it an generate an error on pg_dumpall restore;  not sure
- 		 *	on the cause, see:
- 		 *	http://archives.postgresql.org/pgsql-hackers/2012-03/msg01101.php
  		 */
  		if (GET_MAJOR_VERSION(old_cluster.major_version) < 901 &&
  			strcmp(lib, "$libdir/plpython") == 0)
--- 304,309 ----
