Hi,

The commit 44cac934 replaced "char buf[BLCKSZ]" with PGAlignedBlock to
avoid issues on alignment-picky hardware. While it replaced most of the
instances, there are still some more left. How about we use PGAlignedBlock
there too, something like the attached patch? A note [2] in the commit
44cac934 says that ensuring proper alignment makes kernel data transfers
fasters and the left-over "char buf[BLCKSZ]" either do read() or write()
system calls, so it might be worth to align them with PGAlignedBlock.

Thoughts?

PS: FWIW, I verified what difference actually char buf[BLCKSZ] and the
union PGAlignedBlock does make with alignment with a sample code like [3]
which gives a different alignment requirement, see below:

size of data 8192, alignment of data 1
size of data_aligned 8192, alignment of data_aligned 8

[1]
commit 44cac9346479d4b0cc9195b0267fd13eb4e7442c
Author: Tom Lane <t...@sss.pgh.pa.us>
Date:   Sat Sep 1 15:27:12 2018 -0400

    Avoid using potentially-under-aligned page buffers.

[2]
   I used these types even for variables where there's no risk of a
    misaligned access, since ensuring proper alignment should make
    kernel data transfers faster.  I also changed some places where
    we had been palloc'ing short-lived buffers, for coding style
    uniformity and to save palloc/pfree overhead.

[3]
#include <stdio.h>

#define BLCKSZ 8192

typedef union PGAlignedBlock
{
    char        data[BLCKSZ];
    double      force_align_d;
    long long int   force_align_i64;
} PGAlignedBlock;

int main(int argc, char **argv)
{
    char data[BLCKSZ];
    PGAlignedBlock data_aligned;

    printf("size of data %ld, alignment of data %ld\n", sizeof(data),
_Alignof(data));
    printf("size of data_aligned %ld, alignment of data_aligned %ld\n",
sizeof(data_aligned), _Alignof(data_aligned));

    return 0;
}


--
Bharath Rupireddy
PostgreSQL Contributors Team
RDS Open Source Databases
Amazon Web Services: https://aws.amazon.com
From 5b2f9d3db4f230c46382f9e1be8cacfeef4f537b Mon Sep 17 00:00:00 2001
From: Bharath Rupireddy <bharath.rupireddyforpostgres@gmail.com>
Date: Sun, 3 Dec 2023 09:33:37 +0000
Subject: [PATCH v1] Use PGAlignedBlock instead of "char buf[BLCKSZ]" in more
 places

Commit 44cac934 replaced "char buf[BLCKSZ]" with PGAlignedBlock to
avoid issues on alignment-picky hardware. While it replaced most
of the instances, there are still some more left. This commit
uses PGAlignedBlock in the left-over places. A note in the commit
44cac934 says that ensuring proper alignment makes kernel data
transfers fasters and the left-over "char buf[BLCKSZ]" either do
read() or write() system calls, so it might be worth to align them
with PGAlignedBlock.
---
 src/backend/access/transam/timeline.c | 12 +++++-----
 src/backend/utils/init/miscinit.c     | 32 +++++++++++++--------------
 2 files changed, 22 insertions(+), 22 deletions(-)

diff --git a/src/backend/access/transam/timeline.c b/src/backend/access/transam/timeline.c
index 94e152694e..7f1bf1fdc7 100644
--- a/src/backend/access/transam/timeline.c
+++ b/src/backend/access/transam/timeline.c
@@ -307,7 +307,7 @@ writeTimeLineHistory(TimeLineID newTLI, TimeLineID parentTLI,
 	char		path[MAXPGPATH];
 	char		tmppath[MAXPGPATH];
 	char		histfname[MAXFNAMELEN];
-	char		buffer[BLCKSZ];
+	PGAlignedBlock buffer;
 	int			srcfd;
 	int			fd;
 	int			nbytes;
@@ -354,7 +354,7 @@ writeTimeLineHistory(TimeLineID newTLI, TimeLineID parentTLI,
 		{
 			errno = 0;
 			pgstat_report_wait_start(WAIT_EVENT_TIMELINE_HISTORY_READ);
-			nbytes = (int) read(srcfd, buffer, sizeof(buffer));
+			nbytes = (int) read(srcfd, buffer.data, sizeof(buffer));
 			pgstat_report_wait_end();
 			if (nbytes < 0 || errno != 0)
 				ereport(ERROR,
@@ -364,7 +364,7 @@ writeTimeLineHistory(TimeLineID newTLI, TimeLineID parentTLI,
 				break;
 			errno = 0;
 			pgstat_report_wait_start(WAIT_EVENT_TIMELINE_HISTORY_WRITE);
-			if ((int) write(fd, buffer, nbytes) != nbytes)
+			if ((int) write(fd, buffer.data, nbytes) != nbytes)
 			{
 				int			save_errno = errno;
 
@@ -398,17 +398,17 @@ writeTimeLineHistory(TimeLineID newTLI, TimeLineID parentTLI,
 	 * If we did have a parent file, insert an extra newline just in case the
 	 * parent file failed to end with one.
 	 */
-	snprintf(buffer, sizeof(buffer),
+	snprintf(buffer.data, sizeof(buffer),
 			 "%s%u\t%X/%X\t%s\n",
 			 (srcfd < 0) ? "" : "\n",
 			 parentTLI,
 			 LSN_FORMAT_ARGS(switchpoint),
 			 reason);
 
-	nbytes = strlen(buffer);
+	nbytes = strlen(buffer.data);
 	errno = 0;
 	pgstat_report_wait_start(WAIT_EVENT_TIMELINE_HISTORY_WRITE);
-	if ((int) write(fd, buffer, nbytes) != nbytes)
+	if ((int) write(fd, buffer.data, nbytes) != nbytes)
 	{
 		int			save_errno = errno;
 
diff --git a/src/backend/utils/init/miscinit.c b/src/backend/utils/init/miscinit.c
index 819936ec02..c3c3fb325b 100644
--- a/src/backend/utils/init/miscinit.c
+++ b/src/backend/utils/init/miscinit.c
@@ -1508,8 +1508,8 @@ AddToDataDirLockFile(int target_line, const char *str)
 	int			lineno;
 	char	   *srcptr;
 	char	   *destptr;
-	char		srcbuffer[BLCKSZ];
-	char		destbuffer[BLCKSZ];
+	PGAlignedBlock srcbuffer;
+	PGAlignedBlock destbuffer;
 
 	fd = open(DIRECTORY_LOCK_FILE, O_RDWR | PG_BINARY, 0);
 	if (fd < 0)
@@ -1521,7 +1521,7 @@ AddToDataDirLockFile(int target_line, const char *str)
 		return;
 	}
 	pgstat_report_wait_start(WAIT_EVENT_LOCK_FILE_ADDTODATADIR_READ);
-	len = read(fd, srcbuffer, sizeof(srcbuffer) - 1);
+	len = read(fd, srcbuffer.data, sizeof(srcbuffer) - 1);
 	pgstat_report_wait_end();
 	if (len < 0)
 	{
@@ -1532,13 +1532,13 @@ AddToDataDirLockFile(int target_line, const char *str)
 		close(fd);
 		return;
 	}
-	srcbuffer[len] = '\0';
+	srcbuffer.data[len] = '\0';
 
 	/*
 	 * Advance over lines we are not supposed to rewrite, then copy them to
 	 * destbuffer.
 	 */
-	srcptr = srcbuffer;
+	srcptr = srcbuffer.data;
 	for (lineno = 1; lineno < target_line; lineno++)
 	{
 		char	   *eol = strchr(srcptr, '\n');
@@ -1547,8 +1547,8 @@ AddToDataDirLockFile(int target_line, const char *str)
 			break;				/* not enough lines in file yet */
 		srcptr = eol + 1;
 	}
-	memcpy(destbuffer, srcbuffer, srcptr - srcbuffer);
-	destptr = destbuffer + (srcptr - srcbuffer);
+	memcpy(destbuffer.data, srcbuffer.data, srcptr - srcbuffer.data);
+	destptr = destbuffer.data + (srcptr - srcbuffer.data);
 
 	/*
 	 * Fill in any missing lines before the target line, in case lines are
@@ -1556,14 +1556,14 @@ AddToDataDirLockFile(int target_line, const char *str)
 	 */
 	for (; lineno < target_line; lineno++)
 	{
-		if (destptr < destbuffer + sizeof(destbuffer))
+		if (destptr < destbuffer.data + sizeof(destbuffer))
 			*destptr++ = '\n';
 	}
 
 	/*
 	 * Write or rewrite the target line.
 	 */
-	snprintf(destptr, destbuffer + sizeof(destbuffer) - destptr, "%s\n", str);
+	snprintf(destptr, destbuffer.data + sizeof(destbuffer) - destptr, "%s\n", str);
 	destptr += strlen(destptr);
 
 	/*
@@ -1572,7 +1572,7 @@ AddToDataDirLockFile(int target_line, const char *str)
 	if ((srcptr = strchr(srcptr, '\n')) != NULL)
 	{
 		srcptr++;
-		snprintf(destptr, destbuffer + sizeof(destbuffer) - destptr, "%s",
+		snprintf(destptr, destbuffer.data + sizeof(destbuffer) - destptr, "%s",
 				 srcptr);
 	}
 
@@ -1580,10 +1580,10 @@ AddToDataDirLockFile(int target_line, const char *str)
 	 * And rewrite the data.  Since we write in a single kernel call, this
 	 * update should appear atomic to onlookers.
 	 */
-	len = strlen(destbuffer);
+	len = strlen(destbuffer.data);
 	errno = 0;
 	pgstat_report_wait_start(WAIT_EVENT_LOCK_FILE_ADDTODATADIR_WRITE);
-	if (pg_pwrite(fd, destbuffer, len, 0) != len)
+	if (pg_pwrite(fd, destbuffer.data, len, 0) != len)
 	{
 		pgstat_report_wait_end();
 		/* if write didn't set errno, assume problem is no disk space */
@@ -1633,7 +1633,7 @@ RecheckDataDirLockFile(void)
 	int			fd;
 	int			len;
 	long		file_pid;
-	char		buffer[BLCKSZ];
+	PGAlignedBlock buffer;
 
 	fd = open(DIRECTORY_LOCK_FILE, O_RDWR | PG_BINARY, 0);
 	if (fd < 0)
@@ -1663,7 +1663,7 @@ RecheckDataDirLockFile(void)
 		}
 	}
 	pgstat_report_wait_start(WAIT_EVENT_LOCK_FILE_RECHECKDATADIR_READ);
-	len = read(fd, buffer, sizeof(buffer) - 1);
+	len = read(fd, buffer.data, sizeof(buffer) - 1);
 	pgstat_report_wait_end();
 	if (len < 0)
 	{
@@ -1674,9 +1674,9 @@ RecheckDataDirLockFile(void)
 		close(fd);
 		return true;			/* treat read failure as nonfatal */
 	}
-	buffer[len] = '\0';
+	buffer.data[len] = '\0';
 	close(fd);
-	file_pid = atol(buffer);
+	file_pid = atol(buffer.data);
 	if (file_pid == getpid())
 		return true;			/* all is well */
 
-- 
2.34.1

Reply via email to