diff --git a/contrib/adminpack/adminpack.c b/contrib/adminpack/adminpack.c
index f3f8e7f1e4..e46a64a898 100644
--- a/contrib/adminpack/adminpack.c
+++ b/contrib/adminpack/adminpack.c
@@ -319,7 +319,7 @@ pg_logdir_ls(PG_FUNCTION_ARGS)
 		if (!fctx->dirdesc)
 			ereport(ERROR,
 					(errcode_for_file_access(),
-					 errmsg("could not read directory \"%s\": %m",
+					 errmsg("could not open directory \"%s\": %m",
 							fctx->location)));
 
 		funcctx->user_fctx = fctx;
diff --git a/src/backend/access/transam/twophase.c b/src/backend/access/transam/twophase.c
index b715152e8d..6f4df68d46 100644
--- a/src/backend/access/transam/twophase.c
+++ b/src/backend/access/transam/twophase.c
@@ -1736,6 +1736,12 @@ restoreTwoPhaseData(void)
 	struct dirent *clde;
 
 	cldir = AllocateDir(TWOPHASE_DIR);
+	if (cldir == NULL)
+		ereport(ERROR,
+				(errcode_for_file_access(),
+				 errmsg("could not open directory \"%s\": %m",
+						TWOPHASE_DIR)));
+
 	LWLockAcquire(TwoPhaseStateLock, LW_EXCLUSIVE);
 	while ((clde = ReadDir(cldir, TWOPHASE_DIR)) != NULL)
 	{
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index fba201f659..0559c748e9 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -3841,7 +3841,7 @@ RemoveOldXlogFiles(XLogSegNo segno, XLogRecPtr PriorRedoPtr, XLogRecPtr endptr)
 	if (xldir == NULL)
 		ereport(ERROR,
 				(errcode_for_file_access(),
-				 errmsg("could not open write-ahead log directory \"%s\": %m",
+				 errmsg("could not open directory \"%s\": %m",
 						XLOGDIR)));
 
 	/*
@@ -3916,7 +3916,7 @@ RemoveNonParentXlogFiles(XLogRecPtr switchpoint, TimeLineID newTLI)
 	if (xldir == NULL)
 		ereport(ERROR,
 				(errcode_for_file_access(),
-				 errmsg("could not open write-ahead log directory \"%s\": %m",
+				 errmsg("could not open directory \"%s\": %m",
 						XLOGDIR)));
 
 	/*
@@ -4108,11 +4108,6 @@ CleanupBackupHistory(void)
 	char		path[MAXPGPATH + sizeof(XLOGDIR)];
 
 	xldir = AllocateDir(XLOGDIR);
-	if (xldir == NULL)
-		ereport(ERROR,
-				(errcode_for_file_access(),
-				 errmsg("could not open write-ahead log directory \"%s\": %m",
-						XLOGDIR)));
 
 	while ((xlde = ReadDir(xldir, XLOGDIR)) != NULL)
 	{
diff --git a/src/backend/access/transam/xlogfuncs.c b/src/backend/access/transam/xlogfuncs.c
index 443ccd6411..48d85c1ce5 100644
--- a/src/backend/access/transam/xlogfuncs.c
+++ b/src/backend/access/transam/xlogfuncs.c
@@ -89,7 +89,9 @@ pg_start_backup(PG_FUNCTION_ARGS)
 	dir = AllocateDir("pg_tblspc");
 	if (!dir)
 		ereport(ERROR,
-				(errmsg("could not open directory \"%s\": %m", "pg_tblspc")));
+				(errcode_for_file_access(),
+				 errmsg("could not open directory \"%s\": %m",
+						"pg_tblspc")));
 
 	if (exclusive)
 	{
diff --git a/src/backend/postmaster/pgarch.c b/src/backend/postmaster/pgarch.c
index 1c6cf83f8c..3d8c02e865 100644
--- a/src/backend/postmaster/pgarch.c
+++ b/src/backend/postmaster/pgarch.c
@@ -673,11 +673,6 @@ pgarch_readyXlog(char *xlog)
 
 	snprintf(XLogArchiveStatusDir, MAXPGPATH, XLOGDIR "/archive_status");
 	rldir = AllocateDir(XLogArchiveStatusDir);
-	if (rldir == NULL)
-		ereport(ERROR,
-				(errcode_for_file_access(),
-				 errmsg("could not open archive status directory \"%s\": %m",
-						XLogArchiveStatusDir)));
 
 	while ((rlde = ReadDir(rldir, XLogArchiveStatusDir)) != NULL)
 	{
diff --git a/src/backend/replication/basebackup.c b/src/backend/replication/basebackup.c
index ebb8fde3bc..348913509d 100644
--- a/src/backend/replication/basebackup.c
+++ b/src/backend/replication/basebackup.c
@@ -367,9 +367,6 @@ perform_base_backup(basebackup_options *opt, DIR *tblspcdir)
 		XLogFileName(lastoff, ThisTimeLineID, endsegno, wal_segment_size);
 
 		dir = AllocateDir("pg_wal");
-		if (!dir)
-			ereport(ERROR,
-					(errmsg("could not open directory \"%s\": %m", "pg_wal")));
 		while ((de = ReadDir(dir, "pg_wal")) != NULL)
 		{
 			/* Does it look like a WAL segment, and is it in the range? */
@@ -468,6 +465,8 @@ perform_base_backup(basebackup_options *opt, DIR *tblspcdir)
 			fp = AllocateFile(pathbuf, "rb");
 			if (fp == NULL)
 			{
+				int save_errno = errno;
+
 				/*
 				 * Most likely reason for this is that the file was already
 				 * removed by a checkpoint, so check for that to get a better
@@ -475,6 +474,7 @@ perform_base_backup(basebackup_options *opt, DIR *tblspcdir)
 				 */
 				CheckXLogRemoved(segno, tli);
 
+				errno = save_errno;
 				ereport(ERROR,
 						(errcode_for_file_access(),
 						 errmsg("could not open file \"%s\": %m", pathbuf)));
@@ -713,7 +713,9 @@ SendBaseBackup(BaseBackupCmd *cmd)
 	dir = AllocateDir("pg_tblspc");
 	if (!dir)
 		ereport(ERROR,
-				(errmsg("could not open directory \"%s\": %m", "pg_tblspc")));
+				(errcode_for_file_access(),
+				 errmsg("could not open directory \"%s\": %m",
+						"pg_tblspc")));
 
 	perform_base_backup(&opt, dir);
 
diff --git a/src/backend/storage/file/copydir.c b/src/backend/storage/file/copydir.c
index eae9f5a1f2..d169e9c8bb 100644
--- a/src/backend/storage/file/copydir.c
+++ b/src/backend/storage/file/copydir.c
@@ -47,10 +47,6 @@ copydir(char *fromdir, char *todir, bool recurse)
 				 errmsg("could not create directory \"%s\": %m", todir)));
 
 	xldir = AllocateDir(fromdir);
-	if (xldir == NULL)
-		ereport(ERROR,
-				(errcode_for_file_access(),
-				 errmsg("could not open directory \"%s\": %m", fromdir)));
 
 	while ((xlde = ReadDir(xldir, fromdir)) != NULL)
 	{
@@ -90,10 +86,6 @@ copydir(char *fromdir, char *todir, bool recurse)
 		return;
 
 	xldir = AllocateDir(todir);
-	if (xldir == NULL)
-		ereport(ERROR,
-				(errcode_for_file_access(),
-				 errmsg("could not open directory \"%s\": %m", todir)));
 
 	while ((xlde = ReadDir(xldir, todir)) != NULL)
 	{
diff --git a/src/backend/storage/file/fd.c b/src/backend/storage/file/fd.c
index ecd6d85270..8ea891c181 100644
--- a/src/backend/storage/file/fd.c
+++ b/src/backend/storage/file/fd.c
@@ -318,7 +318,6 @@ static int	FileAccess(File file);
 static File OpenTemporaryFileInTablespace(Oid tblspcOid, bool rejectError);
 static bool reserveAllocatedDesc(void);
 static int	FreeDesc(AllocateDesc *desc);
-static struct dirent *ReadDirExtended(DIR *dir, const char *dirname, int elevel);
 
 static void AtProcExit_Files(int code, Datum arg);
 static void CleanupTempFiles(bool isProcExit);
@@ -2665,7 +2664,7 @@ ReadDir(DIR *dir, const char *dirname)
  * Alternate version that allows caller to specify the elevel for any
  * error report.  If elevel < ERROR, returns NULL on any error.
  */
-static struct dirent *
+struct dirent *
 ReadDirExtended(DIR *dir, const char *dirname, int elevel)
 {
 	struct dirent *dent;
@@ -2696,13 +2695,18 @@ ReadDirExtended(DIR *dir, const char *dirname, int elevel)
  * Close a directory opened with AllocateDir.
  *
  * Note we do not check closedir's return value --- it is up to the caller
- * to handle close errors.
+ * to handle close errors. Do nothing if caller is using NULL as input
+ * directory.
  */
 int
 FreeDir(DIR *dir)
 {
 	int			i;
 
+	/* Nothing to do if no directory defined */
+	if (dir == NULL)
+		return 0;
+
 	DO_DB(elog(LOG, "FreeDir: Allocated %d", numAllocatedDescs));
 
 	/* Remove dir from list of allocated dirs, if it's present */
@@ -3043,9 +3047,10 @@ RemovePgTempFilesInDir(const char *tmpdirname, bool unlink_all)
 	{
 		/* anything except ENOENT is fishy */
 		if (errno != ENOENT)
-			elog(LOG,
-				 "could not open temporary-files directory \"%s\": %m",
-				 tmpdirname);
+			ereport(LOG,
+					(errcode_for_file_access(),
+					 errmsg("could not open directory \"%s\": %m",
+							tmpdirname)));
 		return;
 	}
 
@@ -3099,9 +3104,10 @@ RemovePgTempRelationFiles(const char *tsdirname)
 	{
 		/* anything except ENOENT is fishy */
 		if (errno != ENOENT)
-			elog(LOG,
-				 "could not open tablespace directory \"%s\": %m",
-				 tsdirname);
+			ereport(LOG,
+					(errcode_for_file_access(),
+					 errmsg("could not open directory \"%s\": %m",
+							tsdirname)));
 		return;
 	}
 
@@ -3136,16 +3142,8 @@ RemovePgTempRelationFilesInDbspace(const char *dbspacedirname)
 	char		rm_path[MAXPGPATH * 2];
 
 	dbspace_dir = AllocateDir(dbspacedirname);
-	if (dbspace_dir == NULL)
-	{
-		/* we just saw this directory, so it really ought to be there */
-		elog(LOG,
-			 "could not open dbspace directory \"%s\": %m",
-			 dbspacedirname);
-		return;
-	}
 
-	while ((de = ReadDir(dbspace_dir, dbspacedirname)) != NULL)
+	while ((de = ReadDirExtended(dbspace_dir, dbspacedirname, LOG)) != NULL)
 	{
 		if (!looks_like_temp_rel_name(de->d_name))
 			continue;
diff --git a/src/backend/storage/file/reinit.c b/src/backend/storage/file/reinit.c
index f331e7bc21..99c443c753 100644
--- a/src/backend/storage/file/reinit.c
+++ b/src/backend/storage/file/reinit.c
@@ -111,9 +111,10 @@ ResetUnloggedRelationsInTablespaceDir(const char *tsdirname, int op)
 	{
 		/* anything except ENOENT is fishy */
 		if (errno != ENOENT)
-			elog(LOG,
-				 "could not open tablespace directory \"%s\": %m",
-				 tsdirname);
+			ereport(LOG,
+					(errcode_for_file_access(),
+					 errmsg("could not open directory \"%s\": %m",
+							tsdirname)));
 		return;
 	}
 
@@ -164,9 +165,10 @@ ResetUnloggedRelationsInDbspaceDir(const char *dbspacedirname, int op)
 		dbspace_dir = AllocateDir(dbspacedirname);
 		if (dbspace_dir == NULL)
 		{
-			elog(LOG,
-				 "could not open dbspace directory \"%s\": %m",
-				 dbspacedirname);
+			ereport(LOG,
+					(errcode_for_file_access(),
+					 errmsg("could not open directory \"%s\": %m",
+							dbspacedirname)));
 			return;
 		}
 
@@ -226,9 +228,10 @@ ResetUnloggedRelationsInDbspaceDir(const char *dbspacedirname, int op)
 		dbspace_dir = AllocateDir(dbspacedirname);
 		if (dbspace_dir == NULL)
 		{
-			elog(LOG,
-				 "could not open dbspace directory \"%s\": %m",
-				 dbspacedirname);
+			ereport(LOG,
+					(errcode_for_file_access(),
+					 errmsg("could not open directory \"%s\": %m",
+							dbspacedirname)));
 			hash_destroy(hash);
 			return;
 		}
@@ -296,9 +299,10 @@ ResetUnloggedRelationsInDbspaceDir(const char *dbspacedirname, int op)
 		if (dbspace_dir == NULL)
 		{
 			/* we just saw this directory, so it really ought to be there */
-			elog(LOG,
-				 "could not open dbspace directory \"%s\": %m",
-				 dbspacedirname);
+			ereport(LOG,
+					(errcode_for_file_access(),
+					 errmsg("could not open directory \"%s\": %m",
+							dbspacedirname)));
 			return;
 		}
 
@@ -349,9 +353,10 @@ ResetUnloggedRelationsInDbspaceDir(const char *dbspacedirname, int op)
 		if (dbspace_dir == NULL)
 		{
 			/* we just saw this directory, so it really ought to be there */
-			elog(LOG,
-				 "could not open dbspace directory \"%s\": %m",
-				 dbspacedirname);
+			ereport(LOG,
+					(errcode_for_file_access(),
+					 errmsg("could not open directory \"%s\": %m",
+							dbspacedirname)));
 			return;
 		}
 
diff --git a/src/backend/storage/ipc/dsm.c b/src/backend/storage/ipc/dsm.c
index 36904d2676..9cb456eaa6 100644
--- a/src/backend/storage/ipc/dsm.c
+++ b/src/backend/storage/ipc/dsm.c
@@ -295,11 +295,7 @@ dsm_cleanup_for_mmap(void)
 	struct dirent *dent;
 
 	/* Open the directory; can't use AllocateDir in postmaster. */
-	if ((dir = AllocateDir(PG_DYNSHMEM_DIR)) == NULL)
-		ereport(ERROR,
-				(errcode_for_file_access(),
-				 errmsg("could not open directory \"%s\": %m",
-						PG_DYNSHMEM_DIR)));
+	dir = AllocateDir(PG_DYNSHMEM_DIR);
 
 	/* Scan for something with a name of the correct format. */
 	while ((dent = ReadDir(dir, PG_DYNSHMEM_DIR)) != NULL)
diff --git a/src/backend/utils/adt/dbsize.c b/src/backend/utils/adt/dbsize.c
index 515e30d177..58c0b01bdc 100644
--- a/src/backend/utils/adt/dbsize.c
+++ b/src/backend/utils/adt/dbsize.c
@@ -110,11 +110,6 @@ calculate_database_size(Oid dbOid)
 	/* Scan the non-default tablespaces */
 	snprintf(dirpath, MAXPGPATH, "pg_tblspc");
 	dirdesc = AllocateDir(dirpath);
-	if (!dirdesc)
-		ereport(ERROR,
-				(errcode_for_file_access(),
-				 errmsg("could not open tablespace directory \"%s\": %m",
-						dirpath)));
 
 	while ((direntry = ReadDir(dirdesc, dirpath)) != NULL)
 	{
diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c
index 1908420d82..12a5f157c0 100644
--- a/src/backend/utils/cache/relcache.c
+++ b/src/backend/utils/cache/relcache.c
@@ -6119,14 +6119,8 @@ RelationCacheInitFileRemove(void)
 
 	/* Scan the tablespace link directory to find non-default tablespaces */
 	dir = AllocateDir(tblspcdir);
-	if (dir == NULL)
-	{
-		elog(LOG, "could not open tablespace link directory \"%s\": %m",
-			 tblspcdir);
-		return;
-	}
 
-	while ((de = ReadDir(dir, tblspcdir)) != NULL)
+	while ((de = ReadDirExtended(dir, tblspcdir, LOG)) != NULL)
 	{
 		if (strspn(de->d_name, "0123456789") == strlen(de->d_name))
 		{
@@ -6150,14 +6144,8 @@ RelationCacheInitFileRemoveInDir(const char *tblspcpath)
 
 	/* Scan the tablespace directory to find per-database directories */
 	dir = AllocateDir(tblspcpath);
-	if (dir == NULL)
-	{
-		elog(LOG, "could not open tablespace directory \"%s\": %m",
-			 tblspcpath);
-		return;
-	}
 
-	while ((de = ReadDir(dir, tblspcpath)) != NULL)
+	while ((de = ReadDirExtended(dir, tblspcpath, LOG)) != NULL)
 	{
 		if (strspn(de->d_name, "0123456789") == strlen(de->d_name))
 		{
diff --git a/src/backend/utils/time/snapmgr.c b/src/backend/utils/time/snapmgr.c
index addf87dc3b..17616a76ba 100644
--- a/src/backend/utils/time/snapmgr.c
+++ b/src/backend/utils/time/snapmgr.c
@@ -1619,18 +1619,9 @@ DeleteAllExportedSnapshotFiles(void)
 	DIR		   *s_dir;
 	struct dirent *s_de;
 
-	if (!(s_dir = AllocateDir(SNAPSHOT_EXPORT_DIR)))
-	{
-		/*
-		 * We really should have that directory in a sane cluster setup. But
-		 * then again if we don't, it's not fatal enough to make it FATAL.
-		 * Since we're running in the postmaster, LOG is our best bet.
-		 */
-		elog(LOG, "could not open directory \"%s\": %m", SNAPSHOT_EXPORT_DIR);
-		return;
-	}
+	s_dir = AllocateDir(SNAPSHOT_EXPORT_DIR);
 
-	while ((s_de = ReadDir(s_dir, SNAPSHOT_EXPORT_DIR)) != NULL)
+	while ((s_de = ReadDirExtended(s_dir, SNAPSHOT_EXPORT_DIR, LOG)) != NULL)
 	{
 		if (strcmp(s_de->d_name, ".") == 0 ||
 			strcmp(s_de->d_name, "..") == 0)
diff --git a/src/include/storage/fd.h b/src/include/storage/fd.h
index 9829281509..a2880a0049 100644
--- a/src/include/storage/fd.h
+++ b/src/include/storage/fd.h
@@ -98,6 +98,8 @@ extern int	ClosePipeStream(FILE *file);
 /* Operations to allow use of the <dirent.h> library routines */
 extern DIR *AllocateDir(const char *dirname);
 extern struct dirent *ReadDir(DIR *dir, const char *dirname);
+extern struct dirent *ReadDirExtended(DIR *dir, const char *dirname,
+									  int elevel);
 extern int	FreeDir(DIR *dir);
 
 /* Operations to allow use of a plain kernel FD, with automatic cleanup */
diff --git a/src/timezone/pgtz.c b/src/timezone/pgtz.c
index a73dc6188b..4018310a5c 100644
--- a/src/timezone/pgtz.c
+++ b/src/timezone/pgtz.c
@@ -156,15 +156,8 @@ scan_directory_ci(const char *dirname, const char *fname, int fnamelen,
 	struct dirent *direntry;
 
 	dirdesc = AllocateDir(dirname);
-	if (!dirdesc)
-	{
-		ereport(LOG,
-				(errcode_for_file_access(),
-				 errmsg("could not open directory \"%s\": %m", dirname)));
-		return false;
-	}
 
-	while ((direntry = ReadDir(dirdesc, dirname)) != NULL)
+	while ((direntry = ReadDirExtended(dirdesc, dirname, LOG)) != NULL)
 	{
 		/*
 		 * Ignore . and .., plus any other "hidden" files.  This is a security
