diff --git a/src/backend/access/transam/timeline.c b/src/backend/access/transam/timeline.c
index 61d3605..fd4d232 100644
--- a/src/backend/access/transam/timeline.c
+++ b/src/backend/access/transam/timeline.c
@@ -426,7 +426,7 @@ writeTimeLineHistory(TimeLineID newTLI, TimeLineID parentTLI,
 	 * Perform the rename using link if available, paranoidly trying to avoid
 	 * overwriting an existing file (there shouldn't be one).
 	 */
-	durable_link_or_rename(tmppath, path, ERROR);
+	durable_link_or_rename(tmppath, path, ERROR, true);
 
 	/* The history file can be archived immediately. */
 	if (XLogArchivingActive())
@@ -505,7 +505,7 @@ writeTimeLineHistoryFile(TimeLineID tli, char *content, int size)
 	 * Perform the rename using link if available, paranoidly trying to avoid
 	 * overwriting an existing file (there shouldn't be one).
 	 */
-	durable_link_or_rename(tmppath, path, ERROR);
+	durable_link_or_rename(tmppath, path, ERROR, true);
 }
 
 /*
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index e42b828..60890b5 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -58,6 +58,7 @@
 #include "storage/ipc.h"
 #include "storage/large_object.h"
 #include "storage/latch.h"
+#include "storage/pmem.h"
 #include "storage/pmsignal.h"
 #include "storage/predicate.h"
 #include "storage/proc.h"
@@ -146,6 +147,9 @@ const struct config_enum_entry sync_method_options[] = {
 #ifdef OPEN_DATASYNC_FLAG
 	{"open_datasync", SYNC_METHOD_OPEN_DSYNC, false},
 #endif
+#ifdef USE_LIBPMEM
+	{"pmem_drain", SYNC_METHOD_PMEM_DRAIN, false},
+#endif
 	{NULL, 0, false}
 };
 
@@ -774,6 +778,7 @@ static const char *xlogSourceNames[] = {"any", "archive", "pg_wal", "stream"};
 static int	openLogFile = -1;
 static XLogSegNo openLogSegNo = 0;
 static uint32 openLogOff = 0;
+static void	*mappedLogFileAddr = NULL;
 
 /*
  * These variables are used similarly to the ones above, but for reading
@@ -788,6 +793,7 @@ static XLogSegNo readSegNo = 0;
 static uint32 readOff = 0;
 static uint32 readLen = 0;
 static XLogSource readSource = 0;	/* XLOG_FROM_* code */
+static void	*mappedReadFileAddr = NULL;
 
 /*
  * Keeps track of which source we're currently reading from. This is
@@ -866,13 +872,15 @@ static XLogRecPtr XLogGetReplicationSlotMinimumLSN(void);
 
 static void AdvanceXLInsertBuffer(XLogRecPtr upto, bool opportunistic);
 static bool XLogCheckpointNeeded(XLogSegNo new_segno);
+static int do_XLogFileOpen(char *pathname, int flags, void **addr);
 static void XLogWrite(XLogwrtRqst WriteRqst, bool flexible);
 static bool InstallXLogFileSegment(XLogSegNo *segno, char *tmppath,
 					   bool find_free, XLogSegNo max_segno,
-					   bool use_lock);
+					   bool use_lock, bool fsync_file);
 static int XLogFileRead(XLogSegNo segno, int emode, TimeLineID tli,
-			 int source, bool notfoundOk);
-static int	XLogFileReadAnyTLI(XLogSegNo segno, int emode, int source);
+			 int source, bool notfoundOk, void **addr);
+static int	XLogFileReadAnyTLI(XLogSegNo segno, int emode, int source,
+		void **addr);
 static int XLogPageRead(XLogReaderState *xlogreader, XLogRecPtr targetPagePtr,
 			 int reqLen, XLogRecPtr targetRecPtr, char *readBuf,
 			 TimeLineID *readTLI);
@@ -2321,6 +2329,15 @@ XLogCheckpointNeeded(XLogSegNo new_segno)
 	return false;
 }
 
+static int
+do_XLogFileOpen(char *pathname, int flags,  void **addr)
+{
+	if (sync_method == SYNC_METHOD_PMEM_DRAIN)
+		return PmemFileOpen(pathname, flags, wal_segment_size, addr);
+	else
+		return BasicOpenFile(pathname, flags);
+}
+
 /*
  * Write and/or fsync the log at least as far as WriteRqst indicates.
  *
@@ -2400,23 +2417,25 @@ XLogWrite(XLogwrtRqst WriteRqst, bool flexible)
 			 * pages here (since we dump what we have at segment end).
 			 */
 			Assert(npages == 0);
-			if (openLogFile >= 0)
+			if (openLogFile >= 0 || mappedLogFileAddr != NULL)
 				XLogFileClose();
 			XLByteToPrevSeg(LogwrtResult.Write, openLogSegNo,
 							wal_segment_size);
 
 			/* create/use new log file */
 			use_existent = true;
-			openLogFile = XLogFileInit(openLogSegNo, &use_existent, true);
+			openLogFile = XLogFileInit(openLogSegNo, &use_existent,
+					true, &mappedLogFileAddr);
 			openLogOff = 0;
 		}
 
 		/* Make sure we have the current logfile open */
-		if (openLogFile < 0)
+		if (openLogFile < 0 && mappedLogFileAddr == NULL)
 		{
 			XLByteToPrevSeg(LogwrtResult.Write, openLogSegNo,
 							wal_segment_size);
-			openLogFile = XLogFileOpen(openLogSegNo);
+			openLogFile = XLogFileOpen(openLogSegNo,
+					&mappedLogFileAddr);
 			openLogOff = 0;
 		}
 
@@ -2453,12 +2472,13 @@ XLogWrite(XLogwrtRqst WriteRqst, bool flexible)
 			/* Need to seek in the file? */
 			if (openLogOff != startoffset)
 			{
-				if (lseek(openLogFile, (off_t) startoffset, SEEK_SET) < 0)
-					ereport(PANIC,
-							(errcode_for_file_access(),
-							 errmsg("could not seek in log file %s to offset %u: %m",
-									XLogFileNameP(ThisTimeLineID, openLogSegNo),
-									startoffset)));
+				if (mappedLogFileAddr == NULL)
+					if (lseek(openLogFile, (off_t) startoffset, SEEK_SET) < 0)
+						ereport(PANIC,
+								(errcode_for_file_access(),
+								 errmsg("could not seek in log file %s to offset %u: %m",
+									 XLogFileNameP(ThisTimeLineID, openLogSegNo),
+									 startoffset)));
 				openLogOff = startoffset;
 			}
 
@@ -2469,6 +2489,13 @@ XLogWrite(XLogwrtRqst WriteRqst, bool flexible)
 			do
 			{
 				errno = 0;
+				if (mappedLogFileAddr != NULL)
+				{
+					pgstat_report_wait_start(WAIT_EVENT_WAL_WRITE);
+					PmemFileWrite((char *)mappedLogFileAddr+openLogOff, from, nleft);
+					pgstat_report_wait_end();
+					break;
+				}
 				pgstat_report_wait_start(WAIT_EVENT_WAL_WRITE);
 				written = write(openLogFile, from, nleft);
 				pgstat_report_wait_end();
@@ -2565,15 +2592,16 @@ XLogWrite(XLogwrtRqst WriteRqst, bool flexible)
 		if (sync_method != SYNC_METHOD_OPEN &&
 			sync_method != SYNC_METHOD_OPEN_DSYNC)
 		{
-			if (openLogFile >= 0 &&
+			if ((openLogFile >= 0 || mappedLogFileAddr != NULL) &&
 				!XLByteInPrevSeg(LogwrtResult.Write, openLogSegNo,
 								 wal_segment_size))
 				XLogFileClose();
-			if (openLogFile < 0)
+			if (openLogFile < 0 && mappedLogFileAddr == NULL)
 			{
 				XLByteToPrevSeg(LogwrtResult.Write, openLogSegNo,
 								wal_segment_size);
-				openLogFile = XLogFileOpen(openLogSegNo);
+				openLogFile = XLogFileOpen(openLogSegNo,
+						&mappedLogFileAddr);
 				openLogOff = 0;
 			}
 
@@ -2986,7 +3014,7 @@ XLogBackgroundFlush(void)
 	 */
 	if (WriteRqst.Write <= LogwrtResult.Flush)
 	{
-		if (openLogFile >= 0)
+		if (openLogFile >= 0 || mappedLogFileAddr != NULL)
 		{
 			if (!XLByteInPrevSeg(LogwrtResult.Write, openLogSegNo,
 								 wal_segment_size))
@@ -3157,7 +3185,8 @@ XLogNeedsFlush(XLogRecPtr record)
  * in a critical section.
  */
 int
-XLogFileInit(XLogSegNo logsegno, bool *use_existent, bool use_lock)
+XLogFileInit(XLogSegNo logsegno, bool *use_existent, bool use_lock,
+		void **addr)
 {
 	char		path[MAXPGPATH];
 	char		tmppath[MAXPGPATH];
@@ -3167,6 +3196,8 @@ XLogFileInit(XLogSegNo logsegno, bool *use_existent, bool use_lock)
 	XLogSegNo	max_segno;
 	int			fd;
 	int			nbytes;
+	void	*tmpaddr = NULL;
+	bool	fsync_file = true;
 
 	XLogFilePath(path, ThisTimeLineID, logsegno, wal_segment_size);
 
@@ -3175,16 +3206,20 @@ XLogFileInit(XLogSegNo logsegno, bool *use_existent, bool use_lock)
 	 */
 	if (*use_existent)
 	{
-		fd = BasicOpenFile(path, O_RDWR | PG_BINARY | get_sync_bit(sync_method));
-		if (fd < 0)
+		fd = do_XLogFileOpen(path,
+				O_RDWR | PG_BINARY | get_sync_bit(sync_method),
+				&tmpaddr);
+		if (fd < 0 && tmpaddr == NULL)
 		{
 			if (errno != ENOENT)
 				ereport(ERROR,
 						(errcode_for_file_access(),
 						 errmsg("could not open file \"%s\": %m", path)));
 		}
-		else
+		else {
+			*addr = tmpaddr;
 			return fd;
+		}
 	}
 
 	/*
@@ -3200,8 +3235,9 @@ XLogFileInit(XLogSegNo logsegno, bool *use_existent, bool use_lock)
 	unlink(tmppath);
 
 	/* do not use get_sync_bit() here --- want to fsync only at end of fill */
-	fd = BasicOpenFile(tmppath, O_RDWR | O_CREAT | O_EXCL | PG_BINARY);
-	if (fd < 0)
+	fd = do_XLogFileOpen(tmppath, O_RDWR | O_CREAT | O_EXCL | PG_BINARY,
+			&tmpaddr);
+	if (fd < 0 && tmpaddr == NULL)
 		ereport(ERROR,
 				(errcode_for_file_access(),
 				 errmsg("could not create file \"%s\": %m", tmppath)));
@@ -3222,40 +3258,53 @@ XLogFileInit(XLogSegNo logsegno, bool *use_existent, bool use_lock)
 	memset(zbuffer, 0, XLOG_BLCKSZ);
 	for (nbytes = 0; nbytes < wal_segment_size; nbytes += XLOG_BLCKSZ)
 	{
-		errno = 0;
-		pgstat_report_wait_start(WAIT_EVENT_WAL_INIT_WRITE);
-		if ((int) write(fd, zbuffer, XLOG_BLCKSZ) != (int) XLOG_BLCKSZ)
+		if (tmpaddr != NULL)
 		{
-			int			save_errno = errno;
+			fsync_file = false;
+			pgstat_report_wait_start(WAIT_EVENT_WAL_INIT_WRITE);
+			PmemFileWrite((char *)tmpaddr+nbytes, zbuffer,
+					XLOG_BLCKSZ);
+		}
+		else
+		{
+			errno = 0;
+			pgstat_report_wait_start(WAIT_EVENT_WAL_INIT_WRITE);
+			if ((int) write(fd, zbuffer, XLOG_BLCKSZ) != (int) XLOG_BLCKSZ)
+			{
+				int			save_errno = errno;
 
-			/*
-			 * If we fail to make the file, delete it to release disk space
-			 */
-			unlink(tmppath);
+				/*
+				 * If we fail to make the file, delete it
+				 * to release disk space
+				 */
+				unlink(tmppath);
 
-			close(fd);
+				close(fd);
 
-			/* if write didn't set errno, assume problem is no disk space */
-			errno = save_errno ? save_errno : ENOSPC;
+				/* if write didn't set errno, assume problem is
+				 * no disk space */
+				errno = save_errno ? save_errno : ENOSPC;
 
-			ereport(ERROR,
-					(errcode_for_file_access(),
-					 errmsg("could not write to file \"%s\": %m", tmppath)));
+				ereport(ERROR,
+						(errcode_for_file_access(),
+						 errmsg("could not write to file \"%s\": %m",
+							 tmppath)));
+			}
 		}
 		pgstat_report_wait_end();
 	}
 
 	pgstat_report_wait_start(WAIT_EVENT_WAL_INIT_SYNC);
-	if (pg_fsync(fd) != 0)
+	if (xlog_fsync(fd, tmpaddr) != 0)
 	{
-		close(fd);
+		do_XLogFileClose(fd, tmpaddr);
 		ereport(ERROR,
 				(errcode_for_file_access(),
 				 errmsg("could not fsync file \"%s\": %m", tmppath)));
 	}
 	pgstat_report_wait_end();
 
-	if (close(fd))
+	if (do_XLogFileClose(fd, tmpaddr))
 		ereport(ERROR,
 				(errcode_for_file_access(),
 				 errmsg("could not close file \"%s\": %m", tmppath)));
@@ -3282,7 +3331,8 @@ XLogFileInit(XLogSegNo logsegno, bool *use_existent, bool use_lock)
 	max_segno = logsegno + CheckPointSegments;
 	if (!InstallXLogFileSegment(&installed_segno, tmppath,
 								*use_existent, max_segno,
-								use_lock))
+								use_lock,
+								fsync_file))
 	{
 		/*
 		 * No need for any more future segments, or InstallXLogFileSegment()
@@ -3296,8 +3346,10 @@ XLogFileInit(XLogSegNo logsegno, bool *use_existent, bool use_lock)
 	*use_existent = false;
 
 	/* Now open original target segment (might not be file I just made) */
-	fd = BasicOpenFile(path, O_RDWR | PG_BINARY | get_sync_bit(sync_method));
-	if (fd < 0)
+	fd = do_XLogFileOpen(path,
+			O_RDWR | PG_BINARY | get_sync_bit(sync_method), addr);
+
+	if (fd < 0 && *addr == NULL)
 		ereport(ERROR,
 				(errcode_for_file_access(),
 				 errmsg("could not open file \"%s\": %m", path)));
@@ -3332,13 +3384,21 @@ XLogFileCopy(XLogSegNo destsegno, TimeLineID srcTLI, XLogSegNo srcsegno,
 	int			srcfd;
 	int			fd;
 	int			nbytes;
+	void		*src_addr = NULL, *dst_addr = NULL;
+	bool		fsync_file = true;
 
 	/*
 	 * Open the source file
 	 */
 	XLogFilePath(path, srcTLI, srcsegno, wal_segment_size);
-	srcfd = OpenTransientFile(path, O_RDONLY | PG_BINARY);
-	if (srcfd < 0)
+	if (sync_method == SYNC_METHOD_PMEM_DRAIN)
+		srcfd = MapTransientFile(path, O_RDONLY | PG_BINARY,
+				wal_segment_size, &src_addr);
+
+	if (src_addr == NULL)
+		srcfd = OpenTransientFile(path, O_RDONLY | PG_BINARY);
+
+	if (srcfd < 0 && src_addr == NULL)
 		ereport(ERROR,
 				(errcode_for_file_access(),
 				 errmsg("could not open file \"%s\": %m", path)));
@@ -3351,15 +3411,32 @@ XLogFileCopy(XLogSegNo destsegno, TimeLineID srcTLI, XLogSegNo srcsegno,
 	unlink(tmppath);
 
 	/* do not use get_sync_bit() here --- want to fsync only at end of fill */
-	fd = OpenTransientFile(tmppath, O_RDWR | O_CREAT | O_EXCL | PG_BINARY);
-	if (fd < 0)
+	if ( src_addr != NULL && sync_method == SYNC_METHOD_PMEM_DRAIN)
+		fd = MapTransientFile(tmppath,
+				O_RDWR | O_CREAT | O_EXCL | PG_BINARY,
+				wal_segment_size, &dst_addr);
+	else
+		fd = OpenTransientFile(tmppath,
+				O_RDWR | O_CREAT | O_EXCL | PG_BINARY);
+
+	if (fd < 0 && dst_addr == NULL)
 		ereport(ERROR,
 				(errcode_for_file_access(),
-				 errmsg("could not create file \"%s\": %m", tmppath)));
+				 errmsg("could not create file \"%s\": %m",
+					 tmppath)));
 
 	/*
 	 * Do the data copying.
 	 */
+	if (src_addr && dst_addr) {
+		pgstat_report_wait_start(WAIT_EVENT_WAL_COPY_READ);
+		PmemFileWrite(dst_addr, src_addr, wal_segment_size);
+		pgstat_report_wait_end();
+		fsync_file = false;
+
+		goto done_copy;
+	}
+
 	for (nbytes = 0; nbytes < wal_segment_size; nbytes += sizeof(buffer))
 	{
 		int			nread;
@@ -3408,29 +3485,42 @@ XLogFileCopy(XLogSegNo destsegno, TimeLineID srcTLI, XLogSegNo srcsegno,
 
 			ereport(ERROR,
 					(errcode_for_file_access(),
-					 errmsg("could not write to file \"%s\": %m", tmppath)));
+					 errmsg("could not write to file \"%s\": %m",
+						 tmppath)));
 		}
 		pgstat_report_wait_end();
 	}
 
+done_copy:
 	pgstat_report_wait_start(WAIT_EVENT_WAL_COPY_SYNC);
-	if (pg_fsync(fd) != 0)
+	if (xlog_fsync(fd, dst_addr) != 0)
 		ereport(ERROR,
 				(errcode_for_file_access(),
 				 errmsg("could not fsync file \"%s\": %m", tmppath)));
 	pgstat_report_wait_end();
 
-	if (CloseTransientFile(fd))
+	if (dst_addr)
+	{
+		if (UnmapTransientFile(dst_addr, wal_segment_size))
+			ereport(ERROR,
+					(errcode_for_file_access(),
+					 errmsg("could not unmap file \"%s\": %m",
+						 tmppath)));
+	}
+	else if (CloseTransientFile(fd))
 		ereport(ERROR,
 				(errcode_for_file_access(),
 				 errmsg("could not close file \"%s\": %m", tmppath)));
 
-	CloseTransientFile(srcfd);
+	if (src_addr)
+		UnmapTransientFile(src_addr, wal_segment_size);
+	else
+		CloseTransientFile(srcfd);
 
 	/*
 	 * Now move the segment into place with its final name.
 	 */
-	if (!InstallXLogFileSegment(&destsegno, tmppath, false, 0, false))
+	if (!InstallXLogFileSegment(&destsegno, tmppath, false, 0, false, fsync_file))
 		elog(ERROR, "InstallXLogFileSegment should not have failed");
 }
 
@@ -3465,7 +3555,7 @@ XLogFileCopy(XLogSegNo destsegno, TimeLineID srcTLI, XLogSegNo srcsegno,
 static bool
 InstallXLogFileSegment(XLogSegNo *segno, char *tmppath,
 					   bool find_free, XLogSegNo max_segno,
-					   bool use_lock)
+					   bool use_lock, bool fsync_file)
 {
 	char		path[MAXPGPATH];
 	struct stat stat_buf;
@@ -3504,7 +3594,7 @@ InstallXLogFileSegment(XLogSegNo *segno, char *tmppath,
 	 * Perform the rename using link if available, paranoidly trying to avoid
 	 * overwriting an existing file (there shouldn't be one).
 	 */
-	if (durable_link_or_rename(tmppath, path, LOG) != 0)
+	if (durable_link_or_rename(tmppath, path, LOG, fsync_file) != 0)
 	{
 		if (use_lock)
 			LWLockRelease(ControlFileLock);
@@ -3522,15 +3612,16 @@ InstallXLogFileSegment(XLogSegNo *segno, char *tmppath,
  * Open a pre-existing logfile segment for writing.
  */
 int
-XLogFileOpen(XLogSegNo segno)
+XLogFileOpen(XLogSegNo segno, void **addr)
 {
 	char		path[MAXPGPATH];
 	int			fd;
 
 	XLogFilePath(path, ThisTimeLineID, segno, wal_segment_size);
 
-	fd = BasicOpenFile(path, O_RDWR | PG_BINARY | get_sync_bit(sync_method));
-	if (fd < 0)
+	fd = do_XLogFileOpen(path,
+			O_RDWR | PG_BINARY | get_sync_bit(sync_method), addr);
+	if (fd < 0 && *addr == NULL)
 		ereport(PANIC,
 				(errcode_for_file_access(),
 				 errmsg("could not open write-ahead log file \"%s\": %m", path)));
@@ -3546,7 +3637,7 @@ XLogFileOpen(XLogSegNo segno)
  */
 static int
 XLogFileRead(XLogSegNo segno, int emode, TimeLineID tli,
-			 int source, bool notfoundOk)
+			 int source, bool notfoundOk, void **addr)
 {
 	char		xlogfname[MAXFNAMELEN];
 	char		activitymsg[MAXFNAMELEN + 16];
@@ -3595,8 +3686,8 @@ XLogFileRead(XLogSegNo segno, int emode, TimeLineID tli,
 		snprintf(path, MAXPGPATH, XLOGDIR "/%s", xlogfname);
 	}
 
-	fd = BasicOpenFile(path, O_RDONLY | PG_BINARY);
-	if (fd >= 0)
+	fd = do_XLogFileOpen(path, O_RDONLY | PG_BINARY, addr);
+	if (fd >= 0 || *addr != NULL)
 	{
 		/* Success! */
 		curFileTLI = tli;
@@ -3628,7 +3719,7 @@ XLogFileRead(XLogSegNo segno, int emode, TimeLineID tli,
  * This version searches for the segment with any TLI listed in expectedTLEs.
  */
 static int
-XLogFileReadAnyTLI(XLogSegNo segno, int emode, int source)
+XLogFileReadAnyTLI(XLogSegNo segno, int emode, int source, void **addr)
 {
 	char		path[MAXPGPATH];
 	ListCell   *cell;
@@ -3668,8 +3759,8 @@ XLogFileReadAnyTLI(XLogSegNo segno, int emode, int source)
 		if (source == XLOG_FROM_ANY || source == XLOG_FROM_ARCHIVE)
 		{
 			fd = XLogFileRead(segno, emode, tli,
-							  XLOG_FROM_ARCHIVE, true);
-			if (fd != -1)
+					XLOG_FROM_ARCHIVE, true, addr);
+			if (fd != -1 || *addr != NULL)
 			{
 				elog(DEBUG1, "got WAL segment from archive");
 				if (!expectedTLEs)
@@ -3681,8 +3772,8 @@ XLogFileReadAnyTLI(XLogSegNo segno, int emode, int source)
 		if (source == XLOG_FROM_ANY || source == XLOG_FROM_PG_WAL)
 		{
 			fd = XLogFileRead(segno, emode, tli,
-							  XLOG_FROM_PG_WAL, true);
-			if (fd != -1)
+					XLOG_FROM_PG_WAL, true, addr);
+			if (fd != -1 || *addr != NULL)
 			{
 				if (!expectedTLEs)
 					expectedTLEs = tles;
@@ -3700,13 +3791,22 @@ XLogFileReadAnyTLI(XLogSegNo segno, int emode, int source)
 	return -1;
 }
 
+int
+do_XLogFileClose(int fd, void *addr)
+{
+	if (!addr)
+		return close(fd);
+
+	return PmemFileClose(addr, wal_segment_size);
+}
+
 /*
  * Close the current logfile segment for writing.
  */
 static void
 XLogFileClose(void)
 {
-	Assert(openLogFile >= 0);
+	Assert(openLogFile >= 0 || mappedLogFileAddr != NULL);
 
 	/*
 	 * WAL segment files will not be re-read in normal operation, so we advise
@@ -3715,15 +3815,16 @@ XLogFileClose(void)
 	 * use the cache to read the WAL segment.
 	 */
 #if defined(USE_POSIX_FADVISE) && defined(POSIX_FADV_DONTNEED)
-	if (!XLogIsNeeded())
+	if (!XLogIsNeeded() && openLogFile > 0)
 		(void) posix_fadvise(openLogFile, 0, 0, POSIX_FADV_DONTNEED);
 #endif
 
-	if (close(openLogFile))
+	if (do_XLogFileClose(openLogFile, mappedLogFileAddr))
 		ereport(PANIC,
 				(errcode_for_file_access(),
 				 errmsg("could not close log file %s: %m",
 						XLogFileNameP(ThisTimeLineID, openLogSegNo))));
+	mappedLogFileAddr = NULL;
 	openLogFile = -1;
 }
 
@@ -3743,6 +3844,7 @@ PreallocXlogFiles(XLogRecPtr endptr)
 	XLogSegNo	_logSegNo;
 	int			lf;
 	bool		use_existent;
+	void		*laddr = NULL;
 	uint64		offset;
 
 	XLByteToPrevSeg(endptr, _logSegNo, wal_segment_size);
@@ -3751,8 +3853,8 @@ PreallocXlogFiles(XLogRecPtr endptr)
 	{
 		_logSegNo++;
 		use_existent = true;
-		lf = XLogFileInit(_logSegNo, &use_existent, true);
-		close(lf);
+		lf = XLogFileInit(_logSegNo, &use_existent, true, &laddr);
+		do_XLogFileClose(lf, laddr);
 		if (!use_existent)
 			CheckpointStats.ckpt_segs_added++;
 	}
@@ -3972,6 +4074,7 @@ RemoveXlogFile(const char *segname, XLogRecPtr PriorRedoPtr, XLogRecPtr endptr)
 	struct stat statbuf;
 	XLogSegNo	endlogSegNo;
 	XLogSegNo	recycleSegNo;
+	bool		fsync_file = true;
 
 	/*
 	 * Initialize info about where to try to recycle to.
@@ -3984,6 +4087,9 @@ RemoveXlogFile(const char *segname, XLogRecPtr PriorRedoPtr, XLogRecPtr endptr)
 
 	snprintf(path, MAXPGPATH, XLOGDIR "/%s", segname);
 
+	if (sync_method == SYNC_METHOD_PMEM_DRAIN)
+		fsync_file = false;
+
 	/*
 	 * Before deleting the file, see if it can be recycled as a future log
 	 * segment. Only recycle normal files, pg_standby for example can create
@@ -3992,7 +4098,7 @@ RemoveXlogFile(const char *segname, XLogRecPtr PriorRedoPtr, XLogRecPtr endptr)
 	if (endlogSegNo <= recycleSegNo &&
 		lstat(path, &statbuf) == 0 && S_ISREG(statbuf.st_mode) &&
 		InstallXLogFileSegment(&endlogSegNo, path,
-							   true, recycleSegNo, true))
+			true, recycleSegNo, true, fsync_file))
 	{
 		ereport(DEBUG2,
 				(errmsg("recycled write-ahead log file \"%s\"",
@@ -4162,9 +4268,10 @@ ReadRecord(XLogReaderState *xlogreader, XLogRecPtr RecPtr, int emode,
 		EndRecPtr = xlogreader->EndRecPtr;
 		if (record == NULL)
 		{
-			if (readFile >= 0)
+			if (readFile >= 0 || mappedReadFileAddr != NULL)
 			{
-				close(readFile);
+				do_XLogFileClose(readFile, mappedReadFileAddr);
+				mappedReadFileAddr = NULL;
 				readFile = -1;
 			}
 
@@ -4682,7 +4789,8 @@ UpdateControlFile(void)
 	pgstat_report_wait_start(WAIT_EVENT_CONTROL_FILE_WRITE_UPDATE);
 	if (write(fd, ControlFile, sizeof(ControlFileData)) != sizeof(ControlFileData))
 	{
-		/* if write didn't set errno, assume problem is no disk space */
+		/* if write didn't set errno, assume problem is no disk
+		 * space */
 		if (errno == 0)
 			errno = ENOSPC;
 		ereport(PANIC,
@@ -5111,34 +5219,44 @@ BootStrapXLOG(void)
 
 	/* Create first XLOG segment file */
 	use_existent = false;
-	openLogFile = XLogFileInit(1, &use_existent, false);
+	openLogFile = XLogFileInit(1, &use_existent, false, &mappedLogFileAddr);
 
 	/* Write the first page with the initial record */
 	errno = 0;
-	pgstat_report_wait_start(WAIT_EVENT_WAL_BOOTSTRAP_WRITE);
-	if (write(openLogFile, page, XLOG_BLCKSZ) != XLOG_BLCKSZ)
+
+	if (mappedLogFileAddr != NULL)
 	{
-		/* if write didn't set errno, assume problem is no disk space */
-		if (errno == 0)
-			errno = ENOSPC;
-		ereport(PANIC,
-				(errcode_for_file_access(),
-				 errmsg("could not write bootstrap write-ahead log file: %m")));
+		pgstat_report_wait_start(WAIT_EVENT_WAL_BOOTSTRAP_WRITE);
+		PmemFileWrite(mappedLogFileAddr, page, XLOG_BLCKSZ);
+	}
+	else
+	{
+		pgstat_report_wait_start(WAIT_EVENT_WAL_BOOTSTRAP_WRITE);
+		if (write(openLogFile, page, XLOG_BLCKSZ) != XLOG_BLCKSZ)
+		{
+			/* if write didn't set errno, assume problem is no disk space */
+			if (errno == 0)
+				errno = ENOSPC;
+			ereport(PANIC,
+					(errcode_for_file_access(),
+					 errmsg("could not write bootstrap write-ahead log file: %m")));
+		}
 	}
 	pgstat_report_wait_end();
 
 	pgstat_report_wait_start(WAIT_EVENT_WAL_BOOTSTRAP_SYNC);
-	if (pg_fsync(openLogFile) != 0)
+	if (xlog_fsync(openLogFile, (void *)mappedLogFileAddr) != 0)
 		ereport(PANIC,
 				(errcode_for_file_access(),
 				 errmsg("could not fsync bootstrap write-ahead log file: %m")));
 	pgstat_report_wait_end();
 
-	if (close(openLogFile))
+	if (do_XLogFileClose(openLogFile, mappedLogFileAddr))
 		ereport(PANIC,
 				(errcode_for_file_access(),
 				 errmsg("could not close bootstrap write-ahead log file: %m")));
 
+	mappedLogFileAddr = NULL;
 	openLogFile = -1;
 
 	/* Now create pg_control */
@@ -5554,9 +5672,10 @@ exitArchiveRecovery(TimeLineID endTLI, XLogRecPtr endOfLog)
 	 * If the ending log segment is still open, close it (to avoid problems on
 	 * Windows with trying to rename or delete an open file).
 	 */
-	if (readFile >= 0)
+	if (readFile >= 0 || mappedReadFileAddr != NULL)
 	{
-		close(readFile);
+		do_XLogFileClose(readFile, mappedReadFileAddr);
+		mappedReadFileAddr = NULL;
 		readFile = -1;
 	}
 
@@ -5595,10 +5714,11 @@ exitArchiveRecovery(TimeLineID endTLI, XLogRecPtr endOfLog)
 		 */
 		bool		use_existent = true;
 		int			fd;
+		void		*tmpaddr = NULL;
 
-		fd = XLogFileInit(startLogSegNo, &use_existent, true);
+		fd = XLogFileInit(startLogSegNo, &use_existent, true, &tmpaddr);
 
-		if (close(fd))
+		if (do_XLogFileClose(fd, tmpaddr))
 			ereport(ERROR,
 					(errcode_for_file_access(),
 					 errmsg("could not close log file %s: %m",
@@ -7751,9 +7871,10 @@ StartupXLOG(void)
 		ShutdownRecoveryTransactionEnvironment();
 
 	/* Shut down xlogreader */
-	if (readFile >= 0)
+	if (readFile >= 0 || mappedReadFileAddr != NULL)
 	{
-		close(readFile);
+		do_XLogFileClose(readFile, mappedReadFileAddr);
+		mappedReadFileAddr = NULL;
 		readFile = -1;
 	}
 	XLogReaderFree(xlogreader);
@@ -10062,6 +10183,9 @@ get_sync_bit(int method)
 		case SYNC_METHOD_FSYNC:
 		case SYNC_METHOD_FSYNC_WRITETHROUGH:
 		case SYNC_METHOD_FDATASYNC:
+#ifdef USE_LIBPMEM
+		case SYNC_METHOD_PMEM_DRAIN:
+#endif
 			return 0;
 #ifdef OPEN_SYNC_FLAG
 		case SYNC_METHOD_OPEN:
@@ -10079,7 +10203,36 @@ get_sync_bit(int method)
 }
 
 /*
- * GUC support
+ * GUC check_hook for xlog_sync_method
+ */
+bool
+check_xlog_sync_method(int *newval, void **extra, GucSource source)
+{
+	bool ret;
+	char tmppath[MAXPGPATH] = {};
+	int val = newval ? *newval : sync_method;
+
+	if (val != SYNC_METHOD_PMEM_DRAIN)
+		return true;
+
+	snprintf(tmppath, MAXPGPATH, "%s/" XLOGDIR "/pmem.tmp", DataDir);
+
+	ret = CheckPmem(tmppath);
+
+	if (!ret)
+	{
+		GUC_check_errcode(ERRCODE_INVALID_PARAMETER_VALUE);
+		GUC_check_errmsg("invalid value for parameter \"wal_sync_method\": \"pmem_drain\"");
+		GUC_check_errmsg("%s isn't stored on persistent memory(pmem_is_pmem() returned false).",
+				XLOGDIR);
+		GUC_check_errhint("Please see also ENVIRONMENT VARIABLES section in man libpmem.");
+	}
+
+	return ret;
+}
+
+/*
+ * GUC assign_hook for xlog_sync_method
  */
 void
 assign_xlog_sync_method(int new_sync_method, void *extra)
@@ -10092,10 +10245,10 @@ assign_xlog_sync_method(int new_sync_method, void *extra)
 		 * changing, close the log file so it will be reopened (with new flag
 		 * bit) at next use.
 		 */
-		if (openLogFile >= 0)
+		if (openLogFile >= 0 || mappedLogFileAddr != NULL)
 		{
 			pgstat_report_wait_start(WAIT_EVENT_WAL_SYNC_METHOD_ASSIGN);
-			if (pg_fsync(openLogFile) != 0)
+			if (xlog_fsync(openLogFile, (void *)mappedLogFileAddr) != 0)
 				ereport(PANIC,
 						(errcode_for_file_access(),
 						 errmsg("could not fsync log segment %s: %m",
@@ -10144,6 +10297,11 @@ issue_xlog_fsync(int fd, XLogSegNo segno)
 								XLogFileNameP(ThisTimeLineID, segno))));
 			break;
 #endif
+#ifdef USE_LIBPMEM
+		case SYNC_METHOD_PMEM_DRAIN:
+			PmemFileSync();
+			break;
+#endif
 		case SYNC_METHOD_OPEN:
 		case SYNC_METHOD_OPEN_DSYNC:
 			/* write synced it already */
@@ -10154,6 +10312,17 @@ issue_xlog_fsync(int fd, XLogSegNo segno)
 	}
 }
 
+int
+xlog_fsync(int fd, void *addr)
+{
+	if (!addr)
+		return pg_fsync(fd);
+
+	PmemFileSync();
+	return 0;
+}
+
+
 /*
  * Return the filename of given log segment, as a palloc'd string.
  */
@@ -11565,7 +11734,7 @@ XLogPageRead(XLogReaderState *xlogreader, XLogRecPtr targetPagePtr, int reqLen,
 	 * See if we need to switch to a new segment because the requested record
 	 * is not in the currently open one.
 	 */
-	if (readFile >= 0 &&
+	if ((readFile >= 0 || mappedReadFileAddr != NULL) &&
 		!XLByteInSeg(targetPagePtr, readSegNo, wal_segment_size))
 	{
 		/*
@@ -11582,7 +11751,8 @@ XLogPageRead(XLogReaderState *xlogreader, XLogRecPtr targetPagePtr, int reqLen,
 			}
 		}
 
-		close(readFile);
+		do_XLogFileClose(readFile, mappedReadFileAddr);
+		mappedReadFileAddr = NULL;
 		readFile = -1;
 		readSource = 0;
 	}
@@ -11591,7 +11761,7 @@ XLogPageRead(XLogReaderState *xlogreader, XLogRecPtr targetPagePtr, int reqLen,
 
 retry:
 	/* See if we need to retrieve more data */
-	if (readFile < 0 ||
+	if ((readFile < 0 && mappedReadFileAddr == NULL) ||
 		(readSource == XLOG_FROM_STREAM &&
 		 receivedUpto < targetPagePtr + reqLen))
 	{
@@ -11600,8 +11770,9 @@ retry:
 										 private->fetching_ckpt,
 										 targetRecPtr))
 		{
-			if (readFile >= 0)
-				close(readFile);
+			if (readFile >= 0 || mappedReadFileAddr != NULL)
+				do_XLogFileClose(readFile, mappedReadFileAddr);
+			mappedReadFileAddr = NULL;
 			readFile = -1;
 			readLen = 0;
 			readSource = 0;
@@ -11614,7 +11785,7 @@ retry:
 	 * At this point, we have the right segment open and if we're streaming we
 	 * know the requested record is in it.
 	 */
-	Assert(readFile != -1);
+	Assert(readFile != -1 || mappedReadFileAddr != NULL);
 
 	/*
 	 * If the current segment is being streamed from master, calculate how
@@ -11635,30 +11806,44 @@ retry:
 
 	/* Read the requested page */
 	readOff = targetPageOff;
-	if (lseek(readFile, (off_t) readOff, SEEK_SET) < 0)
-	{
-		char		fname[MAXFNAMELEN];
+	if (mappedReadFileAddr == NULL) {
+		if (lseek(readFile, (off_t) readOff, SEEK_SET) < 0)
+		{
+			char		fname[MAXFNAMELEN];
 
-		XLogFileName(fname, curFileTLI, readSegNo, wal_segment_size);
-		ereport(emode_for_corrupt_record(emode, targetPagePtr + reqLen),
-				(errcode_for_file_access(),
-				 errmsg("could not seek in log segment %s to offset %u: %m",
-						fname, readOff)));
-		goto next_record_is_invalid;
+			XLogFileName(fname, curFileTLI, readSegNo,
+					wal_segment_size);
+			ereport(emode_for_corrupt_record(emode,
+						targetPagePtr + reqLen),
+					(errcode_for_file_access(),
+					 errmsg("could not seek in log segment %s to offset %u: %m",
+						 fname, readOff)));
+			goto next_record_is_invalid;
+		}
 	}
 
-	pgstat_report_wait_start(WAIT_EVENT_WAL_READ);
-	if (read(readFile, readBuf, XLOG_BLCKSZ) != XLOG_BLCKSZ)
-	{
-		char		fname[MAXFNAMELEN];
+	if (mappedReadFileAddr) {
+		pgstat_report_wait_start(WAIT_EVENT_WAL_READ);
+		PmemFileRead((char *)mappedReadFileAddr+readOff, readBuf,
+				XLOG_BLCKSZ);
 
-		pgstat_report_wait_end();
-		XLogFileName(fname, curFileTLI, readSegNo, wal_segment_size);
-		ereport(emode_for_corrupt_record(emode, targetPagePtr + reqLen),
-				(errcode_for_file_access(),
-				 errmsg("could not read from log segment %s, offset %u: %m",
-						fname, readOff)));
-		goto next_record_is_invalid;
+	}
+	else {
+		pgstat_report_wait_start(WAIT_EVENT_WAL_READ);
+		if (read(readFile, readBuf, XLOG_BLCKSZ) != XLOG_BLCKSZ)
+		{
+			char		fname[MAXFNAMELEN];
+
+			pgstat_report_wait_end();
+			XLogFileName(fname, curFileTLI, readSegNo,
+					wal_segment_size);
+			ereport(emode_for_corrupt_record(emode,
+						targetPagePtr + reqLen),
+					(errcode_for_file_access(),
+					 errmsg("could not read from log segment %s, offset %u: %m",
+						 fname, readOff)));
+			goto next_record_is_invalid;
+		}
 	}
 	pgstat_report_wait_end();
 
@@ -11672,8 +11857,9 @@ retry:
 next_record_is_invalid:
 	lastSourceFailed = true;
 
-	if (readFile >= 0)
-		close(readFile);
+	if (readFile >= 0 || mappedReadFileAddr != NULL)
+		do_XLogFileClose(readFile, mappedReadFileAddr);
+	mappedReadFileAddr = NULL;
 	readFile = -1;
 	readLen = 0;
 	readSource = 0;
@@ -11922,9 +12108,11 @@ WaitForWALToBecomeAvailable(XLogRecPtr RecPtr, bool randAccess,
 			case XLOG_FROM_ARCHIVE:
 			case XLOG_FROM_PG_WAL:
 				/* Close any old file we might have open. */
-				if (readFile >= 0)
+				if (readFile >= 0 || mappedReadFileAddr != NULL)
 				{
-					close(readFile);
+					do_XLogFileClose(readFile,
+							mappedReadFileAddr);
+					mappedReadFileAddr = NULL;
 					readFile = -1;
 				}
 				/* Reset curFileTLI if random fetch. */
@@ -11937,8 +12125,8 @@ WaitForWALToBecomeAvailable(XLogRecPtr RecPtr, bool randAccess,
 				 */
 				readFile = XLogFileReadAnyTLI(readSegNo, DEBUG2,
 											  currentSource == XLOG_FROM_ARCHIVE ? XLOG_FROM_ANY :
-											  currentSource);
-				if (readFile >= 0)
+											  currentSource, &mappedReadFileAddr);
+				if (readFile >= 0 || mappedReadFileAddr != NULL)
 					return true;	/* success! */
 
 				/*
@@ -12002,14 +12190,14 @@ WaitForWALToBecomeAvailable(XLogRecPtr RecPtr, bool randAccess,
 						 * info is set correctly and XLogReceiptTime isn't
 						 * changed.
 						 */
-						if (readFile < 0)
+						if (readFile < 0 && mappedReadFileAddr == NULL)
 						{
 							if (!expectedTLEs)
 								expectedTLEs = readTimeLineHistory(receiveTLI);
 							readFile = XLogFileRead(readSegNo, PANIC,
 													receiveTLI,
-													XLOG_FROM_STREAM, false);
-							Assert(readFile >= 0);
+													XLOG_FROM_STREAM, false, &mappedReadFileAddr);
+							Assert(readFile >= 0 || mappedReadFileAddr != NULL);
 						}
 						else
 						{
diff --git a/src/backend/storage/file/Makefile b/src/backend/storage/file/Makefile
index ca6a0e4..9271153 100644
--- a/src/backend/storage/file/Makefile
+++ b/src/backend/storage/file/Makefile
@@ -12,6 +12,6 @@ subdir = src/backend/storage/file
 top_builddir = ../../../..
 include $(top_builddir)/src/Makefile.global
 
-OBJS = fd.o buffile.o copydir.o reinit.o sharedfileset.o
+OBJS = fd.o buffile.o copydir.o reinit.o sharedfileset.o pmem.o
 
 include $(top_srcdir)/src/backend/common.mk
diff --git a/src/backend/storage/file/fd.c b/src/backend/storage/file/fd.c
index 71516a9..ec19e37 100644
--- a/src/backend/storage/file/fd.c
+++ b/src/backend/storage/file/fd.c
@@ -88,6 +88,7 @@
 #include "portability/mem.h"
 #include "storage/fd.h"
 #include "storage/ipc.h"
+#include "storage/pmem.h"
 #include "utils/guc.h"
 #include "utils/resowner_private.h"
 
@@ -125,12 +126,6 @@
 #define FD_MINFREE				10
 
 /*
- * Default mode for created files, unless something else is specified using
- * the *Perm() function variants.
- */
-#define PG_FILE_MODE_DEFAULT	(S_IRUSR | S_IWUSR)
-
-/*
  * A number of platforms allow individual processes to open many more files
  * than they can really support when *many* processes do the same thing.
  * This GUC parameter lets the DBA limit max_safe_fds to something less than
@@ -237,6 +232,9 @@ static uint64 temporary_files_size = 0;
 typedef enum
 {
 	AllocateDescFile,
+#ifdef USE_LIBPMEM
+	AllocateDescMap,
+#endif
 	AllocateDescPipe,
 	AllocateDescDir,
 	AllocateDescRawFD
@@ -251,6 +249,10 @@ typedef struct
 		FILE	   *file;
 		DIR		   *dir;
 		int			fd;
+#ifdef USE_LIBPMEM
+		size_t	fsize;
+		void	   *addr;
+#endif
 	}			desc;
 } AllocateDesc;
 
@@ -724,14 +726,16 @@ durable_unlink(const char *fname, int elevel)
  * valid upon return.
  */
 int
-durable_link_or_rename(const char *oldfile, const char *newfile, int elevel)
+durable_link_or_rename(const char *oldfile, const char *newfile, int elevel,
+		bool fsync_file)
 {
 	/*
 	 * Ensure that, if we crash directly after the rename/link, a file with
 	 * valid contents is moved into place.
 	 */
-	if (fsync_fname_ext(oldfile, false, false, elevel) != 0)
-		return -1;
+	if (fsync_file)
+		if (fsync_fname_ext(oldfile, false, false, elevel) != 0)
+			return -1;
 
 #if HAVE_WORKING_LINK
 	if (link(oldfile, newfile) < 0)
@@ -759,8 +763,9 @@ durable_link_or_rename(const char *oldfile, const char *newfile, int elevel)
 	 * Make change persistent in case of an OS crash, both the new entry and
 	 * its parent directory need to be flushed.
 	 */
-	if (fsync_fname_ext(newfile, false, false, elevel) != 0)
-		return -1;
+	if (fsync_file)
+		if (fsync_fname_ext(newfile, false, false, elevel) != 0)
+			return -1;
 
 	/* Same for parent directory */
 	if (fsync_parent_path(newfile, elevel) != 0)
@@ -1618,6 +1623,76 @@ OpenTemporaryFileInTablespace(Oid tblspcOid, bool rejectError)
 	return file;
 }
 
+#ifdef USE_LIBPMEM
+/*
+ * Mmap a file with MapTransientFilePerm() and pass default file mode for
+ * the fileMode parameter.
+ */
+int
+MapTransientFile(const char *fileName, int fileFlags, size_t fsize, void **addr)
+{
+	return MapTransientFilePerm(fileName, fileFlags, PG_FILE_MODE_DEFAULT,
+			fsize, addr);
+}
+
+/*
+ * Like AllocateFile, but returns an unbuffered pointer to the mapped area
+ * like mmap(2)
+ */
+int
+MapTransientFilePerm(const char *fileName, int fileFlags, int fileMode,
+		size_t fsize, void **addr)
+{
+	int			fd;
+
+	DO_DB(elog(LOG, "MapTransientFilePerm: Allocated %d (%s)",
+			   numAllocatedDescs, fileName));
+
+	/* Can we allocate another non-virtual FD? */
+	if (!reserveAllocatedDesc())
+		ereport(ERROR,
+				(errcode(ERRCODE_INSUFFICIENT_RESOURCES),
+				 errmsg("exceeded maxAllocatedDescs (%d) while trying to open file \"%s\"",
+						maxAllocatedDescs, fileName)));
+
+	/* Close excess kernel FDs. */
+	ReleaseLruFiles();
+
+	if (addr != NULL)
+	{
+		void *ret_addr = NULL;
+		fd = PmemFileOpenPerm(fileName, fileFlags, fileMode, fsize, &ret_addr);
+		if (ret_addr != NULL)
+		{
+			AllocateDesc *desc = &allocatedDescs[numAllocatedDescs];
+			*addr = ret_addr;
+
+			desc->kind = AllocateDescMap;
+			desc->desc.addr = ret_addr;
+			desc->desc.fsize = fsize;
+			desc->create_subid = GetCurrentSubTransactionId();
+			numAllocatedDescs++;
+
+			return fd;
+		}
+	}
+
+	return -1;					/* failure */
+}
+#else
+int
+MapTransientFile(const char *fileName, int fileFlags, size_t fsize, void **addr)
+{
+	return -1;
+}
+
+int
+MapTransientFilePerm(const char *fileName, int fileFlags, int fileMode,
+		size_t fsize, void **addr)
+{
+	return -1;
+}
+#endif
 
 /*
  * Create a new file.  The directory containing it must already exist.  Files
@@ -2512,6 +2587,11 @@ FreeDesc(AllocateDesc *desc)
 		case AllocateDescRawFD:
 			result = close(desc->desc.fd);
 			break;
+#ifdef USE_LIBPMEM
+		case AllocateDescMap:
+			result = PmemFileClose(desc->desc.addr, desc->desc.fsize);
+			break;
+#endif
 		default:
 			elog(ERROR, "AllocateDesc kind not recognized");
 			result = 0;			/* keep compiler quiet */
@@ -2553,6 +2633,42 @@ FreeFile(FILE *file)
 	return fclose(file);
 }
 
+#ifdef USE_LIBPMEM
+/*
+ * Unmap a file returned by MapTransientFile.
+ *
+ * Note we do not check unmap's return value --- it is up to the caller
+ * to handle unmap errors.
+ */
+int
+UnmapTransientFile(void *addr, size_t fsize)
+{
+	int			i;
+
+	DO_DB(elog(LOG, "UnmapTransientFile: Allocated %d", numAllocatedDescs));
+
+	/* Remove fd from list of allocated files, if it's present */
+	for (i = numAllocatedDescs; --i >= 0;)
+	{
+		AllocateDesc *desc = &allocatedDescs[i];
+
+		if (desc->kind == AllocateDescMap && desc->desc.addr == addr)
+			return FreeDesc(desc);
+	}
+
+	/* Only get here if someone passes us a file not in allocatedDescs */
+	elog(WARNING, "fd passed to UnmapTransientFile was not obtained from MapTransientFile");
+
+	return PmemFileClose(addr, fsize);
+}
+#else
+int
+UnmapTransientFile(void *addr, size_t fsize)
+{
+	return -1;
+}
+#endif
+
 /*
  * Close a file returned by OpenTransientFile.
  *
diff --git a/src/backend/storage/file/pmem.c b/src/backend/storage/file/pmem.c
new file mode 100644
index 0000000..85fed32
--- /dev/null
+++ b/src/backend/storage/file/pmem.c
@@ -0,0 +1,188 @@
+/*-------------------------------------------------------------------------
+ *
+ * pmem.c
+ *	  Virtual file descriptor code.
+ *
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * IDENTIFICATION
+ *	  src/backend/storage/file/pmem.c
+ *
+ * NOTES:
+ *
+ * This code manages an memory-mapped file on a filesystem mounted with DAX on
+ * persistent memory device using the Persistent Memory Development Kit
+ * (http://pmem.io/pmdk/).
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#include "postgres.h"
+
+#include "storage/pmem.h"
+#include "storage/fd.h"
+
+#ifdef USE_LIBPMEM
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <libpmem.h>
+#include <sys/mman.h>
+#include <string.h>
+
+#define PmemFileSize 32
+
+/*
+ * This function returns true, only if the file is stored on persistent memory.
+ */
+bool
+CheckPmem(const char *path)
+{
+	int    is_pmem = 0; /* false */
+	size_t mapped_len = 0;
+	bool   ret = true;
+	void   *tmpaddr;
+
+	/*
+	 * The value of is_pmem is 0, if the file(path) isn't stored on
+	 * persistent memory.
+	 */
+	tmpaddr = pmem_map_file(path, PmemFileSize, PMEM_FILE_CREATE,
+			PG_FILE_MODE_DEFAULT, &mapped_len, &is_pmem);
+
+	if (tmpaddr)
+	{
+		pmem_unmap(tmpaddr, mapped_len);
+		unlink(path);
+	}
+
+	if (is_pmem)
+		elog(LOG, "%s is stored on persistent memory.", path);
+	else
+		ret = false;
+
+	return ret;
+}
+
+int
+PmemFileOpen(const char *pathname, int flags, size_t fsize, void **addr)
+{
+	return PmemFileOpenPerm(pathname, flags, PG_FILE_MODE_DEFAULT, fsize, addr);
+}
+
+int
+PmemFileOpenPerm(const char *pathname, int flags, int mode, size_t fsize,
+		void **addr)
+{
+	int mapped_flag = 0;
+	size_t mapped_len = 0, size = 0;
+	void *ret_addr;
+
+	if (addr == NULL)
+		return BasicOpenFile(pathname, flags);
+
+	/* non-zero 'len' not allowed without PMEM_FILE_CREATE */
+	if (flags & O_CREAT)
+	{
+		mapped_flag = PMEM_FILE_CREATE;
+		size = fsize;
+	}
+
+	if (flags & O_EXCL)
+		mapped_flag |= PMEM_FILE_EXCL;
+
+	ret_addr = pmem_map_file(pathname, size, mapped_flag, mode, &mapped_len,
+			NULL);
+
+	if (fsize != mapped_len)
+	{
+		if (ret_addr != NULL)
+			pmem_unmap(ret_addr, mapped_len);
+
+		return -1;
+	}
+
+	if (mapped_flag & PMEM_FILE_CREATE)
+		if (msync(ret_addr, mapped_len, MS_SYNC))
+			ereport(PANIC,
+					(errcode_for_file_access(),
+					 errmsg("could not msync log file %s: %m", pathname)));
+
+	*addr = ret_addr;
+
+	return NO_FD_FOR_MAPPED_FILE;
+}
+
+void
+PmemFileWrite(void *dest, void *src, size_t len)
+{
+	pmem_memcpy_nodrain((void *)dest, src, len);
+}
+
+void
+PmemFileRead(void *map_addr, void *buf, size_t len)
+{
+	memcpy(buf, (void *)map_addr, len);
+}
+
+void
+PmemFileSync(void)
+{
+	return pmem_drain();
+}
+
+int
+PmemFileClose(void *addr, size_t fsize)
+{
+	return pmem_unmap((void *)addr, fsize);
+}
+
+
+#else
+bool
+CheckPmem(const char *path)
+{
+	return true;
+}
+
+int
+PmemFileOpen(const char *pathname, int flags, size_t fsize, void **addr)
+{
+	return BasicOpenFile(pathname, flags);
+}
+
+int
+PmemFileOpenPerm(const char *pathname, int flags, int mode, size_t fsize,
+		void **addr)
+{
+	return BasicOpenFilePerm(pathname, flags, mode);
+}
+
+void
+PmemFileWrite(void *dest, void *src, size_t len)
+{
+	ereport(PANIC, (errmsg("don't have the pmem device")));
+}
+
+void
+PmemFileRead(void *map_addr, void *buf, size_t len)
+{
+	ereport(PANIC, (errmsg("don't have the pmem device")));
+}
+
+void
+PmemFileSync(void)
+{
+	ereport(PANIC, (errmsg("don't have the pmem device")));
+}
+
+int
+PmemFileClose(void *addr, size_t fsize)
+{
+	ereport(PANIC, (errmsg("don't have the pmem device")));
+	return -1;
+}
+#endif
+
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 72f6be3..e60310c 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -3887,7 +3887,7 @@ static struct config_enum ConfigureNamesEnum[] =
 		},
 		&sync_method,
 		DEFAULT_SYNC_METHOD, sync_method_options,
-		NULL, assign_xlog_sync_method, NULL
+		check_xlog_sync_method, assign_xlog_sync_method, NULL
 	},
 
 	{
diff --git a/src/backend/utils/misc/postgresql.conf.sample b/src/backend/utils/misc/postgresql.conf.sample
index 69f40f0..7b70ba0 100644
--- a/src/backend/utils/misc/postgresql.conf.sample
+++ b/src/backend/utils/misc/postgresql.conf.sample
@@ -190,6 +190,7 @@
 					#   fsync
 					#   fsync_writethrough
 					#   open_sync
+					#   pmem_drain
 #full_page_writes = on			# recover from partial page writes
 #wal_compression = off			# enable compression of full-page writes
 #wal_log_hints = off			# also do full page writes of non-critical updates
diff --git a/src/include/access/xlog.h b/src/include/access/xlog.h
index 421ba6d..f1e886f 100644
--- a/src/include/access/xlog.h
+++ b/src/include/access/xlog.h
@@ -27,6 +27,7 @@
 #define SYNC_METHOD_OPEN		2	/* for O_SYNC */
 #define SYNC_METHOD_FSYNC_WRITETHROUGH	3
 #define SYNC_METHOD_OPEN_DSYNC	4	/* for O_DSYNC */
+#define SYNC_METHOD_PMEM_DRAIN	5		/* for Persistent Memory Development Kit */
 extern int	sync_method;
 
 extern PGDLLIMPORT TimeLineID ThisTimeLineID;	/* current TLI */
@@ -226,8 +227,10 @@ extern XLogRecPtr XLogInsertRecord(struct XLogRecData *rdata,
 extern void XLogFlush(XLogRecPtr RecPtr);
 extern bool XLogBackgroundFlush(void);
 extern bool XLogNeedsFlush(XLogRecPtr RecPtr);
-extern int	XLogFileInit(XLogSegNo segno, bool *use_existent, bool use_lock);
-extern int	XLogFileOpen(XLogSegNo segno);
+extern int	XLogFileInit(XLogSegNo logsegno, bool *use_existent, bool use_lock,
+		void **addr);
+extern int	XLogFileOpen(XLogSegNo segno, void **addr);
+extern int	do_XLogFileClose(int fd, void *addr);
 
 extern void CheckXLogRemoved(XLogSegNo segno, TimeLineID tli);
 extern XLogSegNo XLogGetLastRemovedSegno(void);
@@ -239,6 +242,7 @@ extern void xlog_desc(StringInfo buf, XLogReaderState *record);
 extern const char *xlog_identify(uint8 info);
 
 extern void issue_xlog_fsync(int fd, XLogSegNo segno);
+extern int	xlog_fsync(int fd, void *addr);
 
 extern bool RecoveryInProgress(void);
 extern bool HotStandbyActive(void);
diff --git a/src/include/storage/fd.h b/src/include/storage/fd.h
index db5ca16..b48bed9 100644
--- a/src/include/storage/fd.h
+++ b/src/include/storage/fd.h
@@ -49,6 +49,13 @@
 typedef int File;
 
 
+/*
+ * Default mode for created files, unless something else is specified using
+ * the *Perm() function variants.
+ */
+#define PG_FILE_MODE_DEFAULT	(S_IRUSR | S_IWUSR)
+
+
 /* GUC parameter */
 extern PGDLLIMPORT int max_files_per_process;
 
@@ -107,6 +114,13 @@ extern int	OpenTransientFile(const char *fileName, int fileFlags);
 extern int	OpenTransientFilePerm(const char *fileName, int fileFlags, mode_t fileMode);
 extern int	CloseTransientFile(int fd);
 
+/* Operations to allow use of a memory-mapped file */
+extern int	MapTransientFile(const char *fileName, int fileFlags, size_t fsize,
+		void **addr);
+extern int	MapTransientFilePerm(const char *fileName, int fileFlags, int fileMode,
+		size_t fsize, void **addr);
+extern int	UnmapTransientFile(void *addr, size_t fsize);
+
 /* If you've really really gotta have a plain kernel FD, use this */
 extern int	BasicOpenFile(const char *fileName, int fileFlags);
 extern int	BasicOpenFilePerm(const char *fileName, int fileFlags, mode_t fileMode);
@@ -132,7 +146,8 @@ extern void pg_flush_data(int fd, off_t offset, off_t amount);
 extern void fsync_fname(const char *fname, bool isdir);
 extern int	durable_rename(const char *oldfile, const char *newfile, int loglevel);
 extern int	durable_unlink(const char *fname, int loglevel);
-extern int	durable_link_or_rename(const char *oldfile, const char *newfile, int loglevel);
+extern int	durable_link_or_rename(const char *oldfile, const char *newfile,
+		int loglevel, bool fsync_fname);
 extern void SyncDataDirectory(void);
 
 /* Filename components */
diff --git a/src/include/storage/pmem.h b/src/include/storage/pmem.h
new file mode 100644
index 0000000..823889a
--- /dev/null
+++ b/src/include/storage/pmem.h
@@ -0,0 +1,32 @@
+/*-------------------------------------------------------------------------
+ *
+ * pmem.h
+ *		Virtual file descriptor definitions for persistent memory.
+ *
+ *
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/storage/pmem.h
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#ifndef PMEM_H
+#define PMEM_H
+
+#include "postgres.h"
+
+#define NO_FD_FOR_MAPPED_FILE -2
+
+extern bool	CheckPmem(const char *path);
+extern int	PmemFileOpen(const char *pathname, int flags, size_t fsize,
+		void **addr);
+extern int	PmemFileOpenPerm(const char *pathname, int flags, int mode,
+		size_t fsize, void **addr);
+extern void	PmemFileWrite(void *dest, void *src, size_t len);
+extern void	PmemFileRead(void *map_addr, void *buf, size_t len);
+extern void	PmemFileSync(void);
+extern int	PmemFileClose(void *addr, size_t fsize);
+
+#endif /* PMEM_H */
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index 77daa5a..9319271 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -432,6 +432,7 @@ extern void assign_search_path(const char *newval, void *extra);
 
 /* in access/transam/xlog.c */
 extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
+extern bool check_xlog_sync_method(int *newval, void **extra, GucSource source);
 extern void assign_xlog_sync_method(int new_sync_method, void *extra);
 
 #endif							/* GUC_H */
