</listitem>
       </varlistentry>
  
 +     <varlistentry id="guc-huge-page-size" xreflabel="huge_page_size">
 +      <term><varname>huge_page_size</varname> (<type>integer</type>)
 +      <indexterm>
 +       <primary><varname>huge_page_size</varname> configuration parameter</primary>
 +      </indexterm>
 +      </term>
 +      <listitem>
 +       <para>
 +        Controls the size of huge pages, when they are enabled with
 +        <xref linkend="guc-huge-pages"/>.
 +        The default is zero (<literal>0</literal>).
 +        When set to <literal>0</literal>, the default huge page size on the
 +        system will be used.
 +       </para>
 +       <para>
 +        Some commonly available page sizes on modern 64 bit server architectures include:
 +        <literal>2MB</literal> and <literal>1GB</literal> (Intel and AMD), <literal>16MB</literal> and
 +        <literal>16GB</literal> (IBM POWER), and <literal>64kB</literal>, <literal>2MB</literal>,
 +        <literal>32MB</literal> and <literal>1GB</literal> (ARM). For more information
 +        about usage and support, see <xref linkend="linux-huge-pages"/>.
 +       </para>
 +       <para>
 +        Non-default settings are currently supported only on Linux.
 +       </para>
 +      </listitem>
 +     </varlistentry>
 +
       <varlistentry id="guc-temp-buffers" xreflabel="temp_buffers">
        <term><varname>temp_buffers</varname> (<type>integer</type>)
        <indexterm>
              using large values of <xref linkend="guc-shared-buffers"/>.  To use this
      feature in <productname>PostgreSQL</productname> you need a kernel
      with <varname>CONFIG_HUGETLBFS=y</varname> and
 -    <varname>CONFIG_HUGETLB_PAGE=y</varname>. You will also have to adjust
 -    the kernel setting <varname>vm.nr_hugepages</varname>. To estimate the
 -    number of huge pages needed, start <productname>PostgreSQL</productname>
 -    without huge pages enabled and check the
 -    postmaster's anonymous shared memory segment size, as well as the system's
 -    huge page size, using the <filename>/proc</filename> file system.  This might
 -    look like:
 +    <varname>CONFIG_HUGETLB_PAGE=y</varname>. You will also have to configure
 +    the operating system to provide enough huge pages of the desired size.
 +    To estimate the number of huge pages needed, start
 +    <productname>PostgreSQL</productname> without huge pages enabled and check
 +    the postmaster's anonymous shared memory segment size, as well as the
 +    system's default and supported huge page sizes, using the
 +    <filename>/proc</filename> and <filename>/sys</filename> file systems.
 +    This might look like:
  <programlisting>
  $ <userinput>head -1 $PGDATA/postmaster.pid</userinput>
  4170
   6490428K
  $ <userinput>grep ^Hugepagesize /proc/meminfo</userinput>
  Hugepagesize:       2048 kB
 +$ <userinput>ls /sys/kernel/mm/hugepages</userinput>
 +hugepages-1048576kB  hugepages-2048kB
  </programlisting>
 +
 +     In this example the default is 2MB, but you can also explicitly request
 +     either 2MB or 1GB with <xref linkend="guc-huge-page-size"/>.
 +
 +     Assuming <literal>2MB</literal> huge pages,
       <literal>6490428</literal> / <literal>2048</literal> gives approximately
       <literal>3169.154</literal>, so in this example we need at
 -     least <literal>3170</literal> huge pages, which we can set with:
 +     least <literal>3170</literal> huge pages.  A larger setting would be
 +     appropriate if other programs on the machine also need huge pages.
 +     We can set this with:
 +<programlisting>
 +# <userinput>sysctl -w vm.nr_hugepages=3170</userinput>
 +</programlisting>
 +     Don't forget to add this setting to <filename>/etc/sysctl.conf</filename>
 +     so that it is reapplied after reboots.  For non-default huge page sizes,
 +     we can instead use:
  <programlisting>
 -$ <userinput>sysctl -w vm.nr_hugepages=3170</userinput>
 +# <userinput>echo 3170 > /sys/kernel/mm/hugepages/hugepages-2048kB/nr_hugepages</userinput>
  </programlisting>
 -    A larger setting would be appropriate if other programs on the machine
 -    also need huge pages.  Don't forget to add this setting
 -    to <filename>/etc/sysctl.conf</filename> so that it will be reapplied
 -    after reboots.
 +    It is also possible to provide these settings at boot time using
 +    kernel parameters such as <literal>hugepagesz=2M hugepages=3170</literal>.
     </para>
  
     <para>
      Sometimes the kernel is not able to allocate the desired number of huge
 -    pages immediately, so it might be necessary to repeat the command or to
 -    reboot.  (Immediately after a reboot, most of the machine's memory
 -    should be available to convert into huge pages.)  To verify the huge
 -    page allocation situation, use:
 +    pages immediately due to fragmentation, so it might be necessary
 +    to repeat the command or to reboot.  (Immediately after a reboot, most of
 +    the machine's memory should be available to convert into huge pages.)
 +    To verify the huge page allocation situation for a given size, use:
  <programlisting>
 -$ <userinput>grep Huge /proc/meminfo</userinput>
 +$ <userinput>cat /sys/kernel/mm/hugepages/hugepages-2048kB/nr_hugepages</userinput>
  </programlisting>
     </para>
  
   
     <para>
      The default behavior for huge pages in
 -    <productname>PostgreSQL</productname> is to use them when possible and
 -    to fall back to normal pages when failing. To enforce the use of huge
 +    <productname>PostgreSQL</productname> is to use them when possible, with
 +    the system's default huge page size, and
 +    to fall back to normal pages on failure. To enforce the use of huge
      pages, you can set <xref linkend="guc-huge-pages"/>
      to <literal>on</literal> in <filename>postgresql.conf</filename>.
      Note that with this setting <productname>PostgreSQL</productname> will fail to
          #endif
  
  #include "miscadmin.h"
 +#include "port/pg_bitutils.h"
  #include "portability/mem.h"
  #include "storage/dsm.h"
  #include "storage/fd.h"
   #ifdef MAP_HUGETLB
  
  /*
 - * Identify the huge page size to use.
 + * Identify the huge page size to use, and compute the related mmap flags.
   *
   * Some Linux kernel versions have a bug causing mmap() to fail on requests
   * that are not a multiple of the hugepage size.  Versions without that bug
    * hugepage sizes, we might want to think about more invasive strategies,
   * such as increasing shared_buffers to absorb the extra space.
   *
 - * Returns the (real or assumed) page size into *hugepagesize,
 + * Returns the (real, assumed or config provided) page size into *hugepagesize,
   * and the hugepage-related mmap flags to use into *mmap_flags.
 - *
 - * Currently *mmap_flags is always just MAP_HUGETLB.  Someday, on systems
 - * that support it, we might OR in additional bits to specify a particular
 - * non-default huge page size.
   */
  static void
  GetHugePageSize(Size *hugepagesize, int *mmap_flags)
  {
 -   /*
 -    * If we fail to find out the system's default huge page size, assume it
 -    * is 2MB.  This will work fine when the actual size is less.  If it's
 -    * more, we might get mmap() or munmap() failures due to unaligned
 -    * requests; but at this writing, there are no reports of any non-Linux
 -    * systems being picky about that.
 -    */
 -   *hugepagesize = 2 * 1024 * 1024;
 -   *mmap_flags = MAP_HUGETLB;
 +   Size        default_hugepagesize = 0;
  
     /*
      * System-dependent code to find out the default huge page size.
       * nnnn kB".  Ignore any failures, falling back to the preset default.
      */
  #ifdef __linux__
 +
     {
         FILE       *fp = AllocateFile("/proc/meminfo", "r");
         char        buf[128];
                  {
                     if (ch == 'k')
                     {
 -                       *hugepagesize = sz * (Size) 1024;
 +                       default_hugepagesize = sz * (Size) 1024;
                         break;
                     }
                     /* We could accept other units besides kB, if needed */
          }
     }
  #endif                         /* __linux__ */
 +
 +   if (huge_page_size != 0)
 +   {
 +       /* If huge page size is requested explicitly, use that. */
 +       *hugepagesize = (Size) huge_page_size * 1024;
 +   }
 +   else if (default_hugepagesize != 0)
 +   {
 +       /* Otherwise use the system default, if we have it. */
 +       *hugepagesize = default_hugepagesize;
 +   }
 +   else
 +   {
 +       /*
 +        * If we fail to find out the system's default huge page size, or no
 +        * huge page size is requested explicitly, assume it is 2MB. This will
 +        * work fine when the actual size is less.  If it's more, we might get
 +        * mmap() or munmap() failures due to unaligned requests; but at this
 +        * writing, there are no reports of any non-Linux systems being picky
 +        * about that.
 +        */
 +       *hugepagesize = 2 * 1024 * 1024;
 +   }
 +
 +   *mmap_flags = MAP_HUGETLB;
 +
 +   /*
 +    * On recent enough Linux, also include the explicit page size, if
 +    * necessary.
 +    */
 +#if defined(MAP_HUGE_MASK) && defined(MAP_HUGE_SHIFT)
 +   if (*hugepagesize != default_hugepagesize)
 +   {
 +       int         shift = pg_ceil_log2_64(*hugepagesize);
 +
 +       *mmap_flags |= (shift & MAP_HUGE_MASK) << MAP_HUGE_SHIFT;
 +   }
 +#endif
  }
  
  #endif                         /* MAP_HUGETLB */
                           "(currently %zu bytes), reduce PostgreSQL's shared "
                          "memory usage, perhaps by reducing shared_buffers or "
                          "max_connections.",
 -                        *size) : 0));
 +                        allocsize) : 0));
     }
  
     *size = allocsize;
          #include <float.h>
  #include <math.h>
  #include <limits.h>
 -#include <unistd.h>
 +#ifndef WIN32
 +#include <sys/mman.h>
 +#endif
  #include <sys/stat.h>
  #ifdef HAVE_SYSLOG
  #include <syslog.h>
  #endif
 +#include <unistd.h>
  
  #include "access/commit_ts.h"
  #include "access/gin.h"
   static bool check_autovacuum_work_mem(int *newval, void **extra, GucSource source);
  static bool check_effective_io_concurrency(int *newval, void **extra, GucSource source);
  static bool check_maintenance_io_concurrency(int *newval, void **extra, GucSource source);
 +static bool check_huge_page_size(int *newval, void **extra, GucSource source);
  static void assign_pgstat_temp_directory(const char *newval, void *extra);
  static bool check_application_name(char **newval, void **extra, GucSource source);
  static void assign_application_name(const char *newval, void *extra);
    * need to be duplicated in all the different implementations of pg_shmem.c.
   */
  int            huge_pages;
 +int            huge_page_size;
  
  /*
   * These variables are all dummies that don't do anything, except in some
          NULL, assign_tcp_user_timeout, show_tcp_user_timeout
     },
  
 +   {
 +       {"huge_page_size", PGC_POSTMASTER, RESOURCES_MEM,
 +           gettext_noop("The size of huge page that should be requested."),
 +           NULL,
 +           GUC_UNIT_KB
 +       },
 +       &huge_page_size,
 +       0, 0, INT_MAX,
 +       check_huge_page_size, NULL, NULL
 +   },
 +
     /* End-of-list marker */
     {
         {NULL, 0, 0, NULL, NULL}, NULL, 0, 0, 0, NULL, NULL, NULL
      return true;
  }
  
 +static bool
 +check_huge_page_size(int *newval, void **extra, GucSource source)
 +{
 +#if !(defined(MAP_HUGE_MASK) && defined(MAP_HUGE_SHIFT))
 +   /* Recent enough Linux only, for now.  See GetHugePageSize(). */
 +   if (*newval != 0)
 +   {
 +       GUC_check_errdetail("huge_page_size must be 0 on this platform.");
 +       return false;
 +   }
 +#endif
 +   return true;
 +}
 +
  static void
  assign_pgstat_temp_directory(const char *newval, void *extra)
  {
                             # (change requires restart)
  #huge_pages = try          # on, off, or try
                     # (change requires restart)
 +#huge_page_size = 0            # zero for system default
 +                   # (change requires restart)
  #temp_buffers = 8MB            # min 800kB
  #max_prepared_transactions = 0     # zero disables the feature
                     # (change requires restart)
          /* GUC variables */
  extern int shared_memory_type;
  extern int huge_pages;
 +extern int huge_page_size;
  
  /* Possible values for huge_pages */
  typedef enum