diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 642c129..893acf8 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -370,6 +370,11 @@ typedef struct XLogCtlWrite
 {
 	int			curridx;		/* cache index of next block to write */
 	pg_time_t	lastSegSwitchTime;		/* time of last xlog segment switch */
+
+	/*
+	 * Counter for WAL dirty buffer writes.
+	 */
+	uint64		WalBufferWriteDirtyCount;
 } XLogCtlWrite;
 
 /*
@@ -1504,6 +1509,8 @@ AdvanceXLInsertBuffer(bool new_segment)
 			}
 			else
 			{
+				XLogCtlWrite *Write = &XLogCtl->Write;
+
 				/*
 				 * Have to write buffers while holding insert lock. This is
 				 * not good, so only write as much as we absolutely must.
@@ -1512,6 +1519,10 @@ AdvanceXLInsertBuffer(bool new_segment)
 				WriteRqst.Write = OldPageRqstPtr;
 				WriteRqst.Flush = 0;
 				XLogWrite(WriteRqst, false, false);
+				/*
+				 * XLogCtrlWrite must be protected with WALWriteLock.
+				 */
+				Write->WalBufferWriteDirtyCount++;
 				LWLockRelease(WALWriteLock);
 				TRACE_POSTGRESQL_WAL_BUFFER_WRITE_DIRTY_DONE();
 			}
@@ -10492,3 +10503,26 @@ SetWalWriterSleeping(bool sleeping)
 	xlogctl->WalWriterSleeping = sleeping;
 	SpinLockRelease(&xlogctl->info_lck);
 }
+
+uint64
+xlog_dirty_write_counter_get()
+{
+	XLogCtlWrite *Write = &XLogCtl->Write;
+	uint64 count;
+
+	LWLockAcquire(WALWriteLock, LW_SHARED);
+	count =	Write->WalBufferWriteDirtyCount;
+	LWLockRelease(WALWriteLock);
+
+	return count;
+}
+
+void
+xlog_dirty_write_counter_reset()
+{
+	XLogCtlWrite *Write = &XLogCtl->Write;
+
+	LWLockAcquire(WALWriteLock, LW_EXCLUSIVE);
+	Write->WalBufferWriteDirtyCount = 0;
+	LWLockRelease(WALWriteLock);
+}
diff --git a/src/backend/utils/adt/pgstatfuncs.c b/src/backend/utils/adt/pgstatfuncs.c
index 7c0705a..d544a5b 100644
--- a/src/backend/utils/adt/pgstatfuncs.c
+++ b/src/backend/utils/adt/pgstatfuncs.c
@@ -117,6 +117,9 @@ extern Datum pg_stat_reset_shared(PG_FUNCTION_ARGS);
 extern Datum pg_stat_reset_single_table_counters(PG_FUNCTION_ARGS);
 extern Datum pg_stat_reset_single_function_counters(PG_FUNCTION_ARGS);
 
+extern Datum pg_stat_get_xlog_dirty_write(PG_FUNCTION_ARGS);
+extern Datum pg_stat_reset_xlog_dirty_write(PG_FUNCTION_ARGS);
+
 /* Global bgwriter statistics, from bgwriter.c */
 extern PgStat_MsgBgWriter bgwriterStats;
 
@@ -1700,3 +1703,16 @@ pg_stat_reset_single_function_counters(PG_FUNCTION_ARGS)
 
 	PG_RETURN_VOID();
 }
+
+Datum
+pg_stat_get_xlog_dirty_write(PG_FUNCTION_ARGS)
+{
+	PG_RETURN_INT64(xlog_dirty_write_counter_get());
+}
+
+Datum
+pg_stat_reset_xlog_dirty_write(PG_FUNCTION_ARGS)
+{
+	xlog_dirty_write_counter_reset();
+	PG_RETURN_VOID();
+}
diff --git a/src/include/access/xlog.h b/src/include/access/xlog.h
index ec79870..01343b9 100644
--- a/src/include/access/xlog.h
+++ b/src/include/access/xlog.h
@@ -325,6 +325,9 @@ extern XLogRecPtr do_pg_start_backup(const char *backupidstr, bool fast, char **
 extern XLogRecPtr do_pg_stop_backup(char *labelfile, bool waitforarchive);
 extern void do_pg_abort_backup(void);
 
+extern uint64 xlog_dirty_write_counter_get(void);
+extern void xlog_dirty_write_counter_reset(void);
+
 /* File path names (all relative to $PGDATA) */
 #define BACKUP_LABEL_FILE		"backup_label"
 #define BACKUP_LABEL_OLD		"backup_label.old"
diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h
index bee7154..e21f57e 100644
--- a/src/include/catalog/pg_proc.h
+++ b/src/include/catalog/pg_proc.h
@@ -2736,6 +2736,11 @@ DESCR("statistics: reset collected statistics for a single table or index in the
 DATA(insert OID = 3777 (  pg_stat_reset_single_function_counters	PGNSP PGUID 12 1 0 0 0 f f f f f f v 1 0 2278 "26" _null_ _null_ _null_ _null_	pg_stat_reset_single_function_counters _null_ _null_ _null_ ));
 DESCR("statistics: reset collected statistics for a single function in the current database");
 
+DATA(insert OID = 3766 (  pg_stat_get_xlog_dirty_write  PGNSP PGUID 12 1 0 0 0 f f f f f f v 0 0 20 "" _null_ _null_ _null_ _null_ pg_stat_get_xlog_dirty_write _null_ _null_ _null_ ));
+DESCR("statistics: get xlog dirty buffer write statistics");
+DATA(insert OID = 3767 (  pg_stat_reset_xlog_dirty_write  PGNSP PGUID 12 1 0 0 0 f f f f f f v 0 0 2278 "" _null_ _null_ _null_ _null_ pg_stat_reset_xlog_dirty_write _null_ _null_ _null_ ));
+DESCR("statistics: reset xlog dirty buffer write statistics");
+
 DATA(insert OID = 3163 (  pg_trigger_depth				PGNSP PGUID 12 1 0 0 0 f f f f t f s 0 0 23 "" _null_ _null_ _null_ _null_ pg_trigger_depth _null_ _null_ _null_ ));
 DESCR("current trigger depth");
 
