From 87a0c14600506d2a33a5a6bedc6e58d70ff7acc7 Mon Sep 17 00:00:00 2001
From: Andres Freund <andres@anarazel.de>
Date: Wed, 24 Jun 2020 16:35:49 -0700
Subject: [PATCH 1/3] Align PGAlignedBlock to expected page size.

In order to be allowed to use O_DIRECT, we need to align buffers to the
page or sector size.

Author: Andres Freund <andres@anarazel.de>
Author: Thomas Munro <thomas.munro@gmail.com>
---
 src/include/c.h                | 20 ++++++++++++--------
 src/include/pg_config_manual.h |  8 ++++++++
 2 files changed, 20 insertions(+), 8 deletions(-)

diff --git a/src/include/c.h b/src/include/c.h
index d70ed84ac5..0deaca0414 100644
--- a/src/include/c.h
+++ b/src/include/c.h
@@ -1070,17 +1070,18 @@ extern void ExceptionalCondition(const char *conditionName,
 
 /*
  * Use this, not "char buf[BLCKSZ]", to declare a field or local variable
- * holding a page buffer, if that page might be accessed as a page and not
- * just a string of bytes.  Otherwise the variable might be under-aligned,
- * causing problems on alignment-picky hardware.  (In some places, we use
- * this to declare buffers even though we only pass them to read() and
- * write(), because copying to/from aligned buffers is usually faster than
- * using unaligned buffers.)  We include both "double" and "int64" in the
- * union to ensure that the compiler knows the value must be MAXALIGN'ed
- * (cf. configure's computation of MAXIMUM_ALIGNOF).
+ * holding a page buffer, if that page might be accessed as a page or passed to
+ * an I/O function and not just a string of bytes.  Otherwise the variable
+ * might be under-aligned, causing problems on alignment-picky hardware, or if
+ * PG_O_DIRECT is used.  We include both "double" and "int64" in the union to
+ * ensure that the compiler knows the value must be MAXALIGN'ed (cf.
+ * configure's computation of MAXIMUM_ALIGNOF).
  */
 typedef union PGAlignedBlock
 {
+#ifdef pg_attribute_aligned
+	pg_attribute_aligned(PG_IO_ALIGN_SIZE)
+#endif
 	char		data[BLCKSZ];
 	double		force_align_d;
 	int64		force_align_i64;
@@ -1089,6 +1090,9 @@ typedef union PGAlignedBlock
 /* Same, but for an XLOG_BLCKSZ-sized buffer */
 typedef union PGAlignedXLogBlock
 {
+#ifdef pg_attribute_aligned
+	pg_attribute_aligned(PG_IO_ALIGN_SIZE)
+#endif
 	char		data[XLOG_BLCKSZ];
 	double		force_align_d;
 	int64		force_align_i64;
diff --git a/src/include/pg_config_manual.h b/src/include/pg_config_manual.h
index f2a106f983..a2ad08a110 100644
--- a/src/include/pg_config_manual.h
+++ b/src/include/pg_config_manual.h
@@ -227,6 +227,14 @@
  */
 #define PG_CACHE_LINE_SIZE		128
 
+/*
+ * Assumed memory alignment requirement for direct I/O.  The real requirement
+ * may be based on sectors or pages.  The default is the typical modern sector
+ * size and virtual memory page size, which is enough for currently known
+ * systems.
+ */
+#define PG_IO_ALIGN_SIZE		4096
+
 /*
  *------------------------------------------------------------------------
  * The following symbols are for enabling debugging code, not for
-- 
2.35.1

