From e8f67e3c27ff553f6a3a26947cac8df91136e8f5 Mon Sep 17 00:00:00 2001
From: Andres Freund <andres@anarazel.de>
Date: Mon, 7 Nov 2022 09:05:35 -0800
Subject: [PATCH] allow-smaller-segsize

---
 doc/src/sgml/installation.sgml |  6 +++---
 doc/src/sgml/storage.sgml      |  2 +-
 .cirrus.yml                    |  1 +
 configure                      | 27 ++++++++++++++-------------
 configure.ac                   | 12 ++++++------
 meson.build                    |  6 ++++--
 meson_options.txt              |  4 ++--
 7 files changed, 31 insertions(+), 27 deletions(-)

diff --git a/doc/src/sgml/installation.sgml b/doc/src/sgml/installation.sgml
index 319c7e69660..20a98c3887c 100644
--- a/doc/src/sgml/installation.sgml
+++ b/doc/src/sgml/installation.sgml
@@ -1458,13 +1458,13 @@ build-postgresql:
       </varlistentry>
 
       <varlistentry>
-       <term><option>--with-segsize=<replaceable>SEGSIZE</replaceable></option></term>
+       <term><option>--with-segsize-mb=<replaceable>SEGSIZE</replaceable></option></term>
        <listitem>
         <para>
-         Set the <firstterm>segment size</firstterm>, in gigabytes.  Large tables are
+         Set the <firstterm>segment size</firstterm>, in megabytes.  Large tables are
          divided into multiple operating-system files, each of size equal
          to the segment size.  This avoids problems with file size limits
-         that exist on many platforms.  The default segment size, 1 gigabyte,
+         that exist on many platforms.  The default segment size, 1024 megabytes,
          is safe on all supported platforms.  If your operating system has
          <quote>largefile</quote> support (which most do, nowadays), you can use
          a larger segment size.  This can be helpful to reduce the number of
diff --git a/doc/src/sgml/storage.sgml b/doc/src/sgml/storage.sgml
index e5b9f3f1ffa..03e0bb0ecbf 100644
--- a/doc/src/sgml/storage.sgml
+++ b/doc/src/sgml/storage.sgml
@@ -236,7 +236,7 @@ When a table or index exceeds 1 GB, it is divided into gigabyte-sized
 filenode; subsequent segments are named filenode.1, filenode.2, etc.
 This arrangement avoids problems on platforms that have file size limitations.
 (Actually, 1 GB is just the default segment size.  The segment size can be
-adjusted using the configuration option <option>--with-segsize</option>
+adjusted using the configuration option <option>--with-segsize-mb</option>
 when building <productname>PostgreSQL</productname>.)
 In principle, free space map and visibility map forks could require multiple
 segments as well, though this is unlikely to happen in practice.
diff --git a/.cirrus.yml b/.cirrus.yml
index 9f2282471a9..b0543f20175 100644
--- a/.cirrus.yml
+++ b/.cirrus.yml
@@ -377,6 +377,7 @@ task:
       -Dextra_lib_dirs=${brewpath}/lib \
       -Dcassert=true \
       -Dssl=openssl -Duuid=e2fs -Ddtrace=auto \
+      -Dsegsize_mb=1 \
       -DPG_TEST_EXTRA="$PG_TEST_EXTRA" \
       build
 
diff --git a/configure b/configure
index 3966368b8d9..fb55792f51b 100755
--- a/configure
+++ b/configure
@@ -843,7 +843,7 @@ enable_coverage
 enable_dtrace
 enable_tap_tests
 with_blocksize
-with_segsize
+with_segsize_mb
 with_wal_blocksize
 with_CC
 with_llvm
@@ -1553,7 +1553,8 @@ Optional Packages:
   --with-pgport=PORTNUM   set default port number [5432]
   --with-blocksize=BLOCKSIZE
                           set table block size in kB [8]
-  --with-segsize=SEGSIZE  set table segment size in GB [1]
+  --with-segsize-mb=SEGSIZE
+                          set table segment size in MB [1024]
   --with-wal-blocksize=BLOCKSIZE
                           set WAL block size in kB [8]
   --with-CC=CMD           set compiler (deprecated)
@@ -3740,32 +3741,32 @@ $as_echo_n "checking for segment size... " >&6; }
 
 
 
-# Check whether --with-segsize was given.
-if test "${with_segsize+set}" = set; then :
-  withval=$with_segsize;
+# Check whether --with-segsize-mb was given.
+if test "${with_segsize_mb+set}" = set; then :
+  withval=$with_segsize_mb;
   case $withval in
     yes)
-      as_fn_error $? "argument required for --with-segsize option" "$LINENO" 5
+      as_fn_error $? "argument required for --with-segsize-mb option" "$LINENO" 5
       ;;
     no)
-      as_fn_error $? "argument required for --with-segsize option" "$LINENO" 5
+      as_fn_error $? "argument required for --with-segsize-mb option" "$LINENO" 5
       ;;
     *)
-      segsize=$withval
+      segsize_mb=$withval
       ;;
   esac
 
 else
-  segsize=1
+  segsize_mb=1024
 fi
 
 
 # this expression is set up to avoid unnecessary integer overflow
 # blocksize is already guaranteed to be a factor of 1024
-RELSEG_SIZE=`expr '(' 1024 / ${blocksize} ')' '*' ${segsize} '*' 1024`
+RELSEG_SIZE=`expr '(' 1024 / ${blocksize} ')' '*' ${segsize_mb}`
 test $? -eq 0 || exit 1
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: ${segsize}GB" >&5
-$as_echo "${segsize}GB" >&6; }
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: ${segsize_mb}MB" >&5
+$as_echo "${segsize_mb}MB" >&6; }
 
 
 cat >>confdefs.h <<_ACEOF
@@ -15555,7 +15556,7 @@ _ACEOF
 
 
 # If we don't have largefile support, can't handle segsize >= 2GB.
-if test "$ac_cv_sizeof_off_t" -lt 8 -a "$segsize" != "1"; then
+if test "$ac_cv_sizeof_off_t" -lt 8 -a "$segsize_mb" -gt "1024"; then
    as_fn_error $? "Large file support is not enabled. Segment size cannot be larger than 1GB." "$LINENO" 5
 fi
 
diff --git a/configure.ac b/configure.ac
index f76b7ee31fc..6abefa0de58 100644
--- a/configure.ac
+++ b/configure.ac
@@ -286,14 +286,14 @@ AC_DEFINE_UNQUOTED([BLCKSZ], ${BLCKSZ}, [
 # Relation segment size
 #
 AC_MSG_CHECKING([for segment size])
-PGAC_ARG_REQ(with, segsize, [SEGSIZE], [set table segment size in GB [1]],
-             [segsize=$withval],
-             [segsize=1])
+PGAC_ARG_REQ(with, segsize-mb, [SEGSIZE], [set table segment size in MB [1024]],
+             [segsize_mb=$withval],
+             [segsize_mb=1024])
 # this expression is set up to avoid unnecessary integer overflow
 # blocksize is already guaranteed to be a factor of 1024
-RELSEG_SIZE=`expr '(' 1024 / ${blocksize} ')' '*' ${segsize} '*' 1024`
+RELSEG_SIZE=`expr '(' 1024 / ${blocksize} ')' '*' ${segsize_mb}`
 test $? -eq 0 || exit 1
-AC_MSG_RESULT([${segsize}GB])
+AC_MSG_RESULT([${segsize_mb}MB])
 
 AC_DEFINE_UNQUOTED([RELSEG_SIZE], ${RELSEG_SIZE}, [
  RELSEG_SIZE is the maximum number of blocks allowed in one disk file.
@@ -1737,7 +1737,7 @@ dnl Check for largefile support (must be after AC_SYS_LARGEFILE)
 AC_CHECK_SIZEOF([off_t])
 
 # If we don't have largefile support, can't handle segsize >= 2GB.
-if test "$ac_cv_sizeof_off_t" -lt 8 -a "$segsize" != "1"; then
+if test "$ac_cv_sizeof_off_t" -lt 8 -a "$segsize_mb" -gt "1024"; then
    AC_MSG_ERROR([Large file support is not enabled. Segment size cannot be larger than 1GB.])
 fi
 
diff --git a/meson.build b/meson.build
index ce2f223a409..eb242d24665 100644
--- a/meson.build
+++ b/meson.build
@@ -418,7 +418,9 @@ meson_bin = find_program(meson_binpath, native: true)
 
 cdata.set('USE_ASSERT_CHECKING', get_option('cassert') ? 1 : false)
 
-cdata.set('BLCKSZ', get_option('blocksize').to_int() * 1024, description:
+blocksize = get_option('blocksize').to_int() * 1024
+segsize = (get_option('segsize_mb') * 1024 * 1024) / blocksize
+cdata.set('BLCKSZ', blocksize, description:
 '''Size of a disk block --- this also limits the size of a tuple. You can set
    it bigger if you need bigger tuples (although TOAST should reduce the need
    to have large tuples, since fields can be spread across multiple tuples).
@@ -428,7 +430,7 @@ cdata.set('BLCKSZ', get_option('blocksize').to_int() * 1024, description:
    Changing BLCKSZ requires an initdb.''')
 
 cdata.set('XLOG_BLCKSZ', get_option('wal_blocksize').to_int() * 1024)
-cdata.set('RELSEG_SIZE', get_option('segsize') * 131072)
+cdata.set('RELSEG_SIZE', segsize)
 cdata.set('DEF_PGPORT', get_option('pgport'))
 cdata.set_quoted('DEF_PGPORT_STR', get_option('pgport').to_string())
 cdata.set_quoted('PG_KRB_SRVNAM', get_option('krb_srvnam'))
diff --git a/meson_options.txt b/meson_options.txt
index c7ea57994dc..b0bd3f4cbe8 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -10,8 +10,8 @@ option('wal_blocksize', type : 'combo',
   value: '8',
   description : '''WAL block size, in kilobytes''')
 
-option('segsize', type : 'integer', value : 1,
-  description : '''Segment size, in gigabytes''')
+option('segsize_mb', type : 'integer', value : 1024,
+  description : '''Segment size, in megabytes''')
 
 
 # Miscellaneous options
-- 
2.38.0

