1
0
mirror of https://github.com/postgres/postgres.git synced 2025-06-26 12:21:12 +03:00

Add GUC parameter "huge_pages_status"

This is useful to show the allocation state of huge pages when setting
up a server with "huge_pages = try", where allocating huge pages would
be attempted but the server would continue its startup sequence even if
the allocation fails.  The effective status of huge pages is not easily
visible without OS-level tools (or for instance, a lookup at
/proc/N/smaps), and the environments where Postgres runs may not
authorize that.  Like the other GUCs related to huge pages, this works
for Linux and Windows.

This GUC can report as values:
- "on", if huge pages were allocated.
- "off", if huge pages were not allocated.
- "unknown", a special state that could only be seen when using for
example postgres -C because it is only possible to know if the shared
memory allocation worked after we can check for the GUC values, even if
checking a runtime-computed GUC.  This value should never be seen when
querying for the GUC on a running server.  An assertion is added to
check that.

The discussion has also turned around having a new function to grab this
status, but this would have required more tricks for -DEXEC_BACKEND,
something that GUCs already handle.

Noriyoshi Shinoda has initiated the thread that has led to the result of
this commit.

Author: Justin Pryzby
Reviewed-by: Nathan Bossart, Kyotaro Horiguchi, Michael Paquier
Discussion: https://postgr.es/m/TU4PR8401MB1152EBB0D271F827E2E37A01EECC9@TU4PR8401MB1152.NAMPRD84.PROD.OUTLOOK.COM
This commit is contained in:
Michael Paquier
2023-07-06 14:42:36 +09:00
parent cf05113eb0
commit a14354cac0
8 changed files with 80 additions and 3 deletions

View File

@ -1727,7 +1727,9 @@ include_dir 'conf.d'
server will try to request huge pages, but fall back to the default if server will try to request huge pages, but fall back to the default if
that fails. With <literal>on</literal>, failure to request huge pages that fails. With <literal>on</literal>, failure to request huge pages
will prevent the server from starting up. With <literal>off</literal>, will prevent the server from starting up. With <literal>off</literal>,
huge pages will not be requested. huge pages will not be requested. The actual state of huge pages is
indicated by the server variable
<xref linkend="guc-huge-pages-status"/>.
</para> </para>
<para> <para>
@ -10738,6 +10740,25 @@ dynamic_library_path = 'C:\tools\postgresql;H:\my_project\lib;$libdir'
</listitem> </listitem>
</varlistentry> </varlistentry>
<varlistentry id="guc-huge-pages-status" xreflabel="huge_pages_status">
<term><varname>huge_pages_status</varname> (<type>enum</type>)
<indexterm>
<primary><varname>huge_pages_status</varname> configuration parameter</primary>
</indexterm>
</term>
<listitem>
<para>
Reports the state of huge pages in the current instance:
<literal>on</literal>, <literal>off</literal>, or
<literal>unknown</literal> (if displayed with
<literal>postgres -C</literal>).
This parameter is useful to determine whether allocation of huge pages
was successful under <literal>huge_pages=try</literal>.
See <xref linkend="guc-huge-pages"/> for more information.
</para>
</listitem>
</varlistentry>
<varlistentry id="guc-integer-datetimes" xreflabel="integer_datetimes"> <varlistentry id="guc-integer-datetimes" xreflabel="integer_datetimes">
<term><varname>integer_datetimes</varname> (<type>boolean</type>) <term><varname>integer_datetimes</varname> (<type>boolean</type>)
<indexterm> <indexterm>

View File

@ -627,6 +627,14 @@ CreateAnonymousSegment(Size *size)
} }
#endif #endif
/*
* Report whether huge pages are in use. This needs to be tracked before
* the second mmap() call if attempting to use huge pages failed
* previously.
*/
SetConfigOption("huge_pages_status", (ptr == MAP_FAILED) ? "off" : "on",
PGC_INTERNAL, PGC_S_DYNAMIC_DEFAULT);
if (ptr == MAP_FAILED && huge_pages != HUGE_PAGES_ON) if (ptr == MAP_FAILED && huge_pages != HUGE_PAGES_ON)
{ {
/* /*
@ -737,8 +745,14 @@ PGSharedMemoryCreate(Size size,
sysvsize = sizeof(PGShmemHeader); sysvsize = sizeof(PGShmemHeader);
} }
else else
{
sysvsize = size; sysvsize = size;
/* huge pages are only available with mmap */
SetConfigOption("huge_pages_status", "off",
PGC_INTERNAL, PGC_S_DYNAMIC_DEFAULT);
}
/* /*
* Loop till we find a free IPC key. Trust CreateDataDirLockFile() to * Loop till we find a free IPC key. Trust CreateDataDirLockFile() to
* ensure no more than one postmaster per data directory can enter this * ensure no more than one postmaster per data directory can enter this

View File

@ -401,6 +401,11 @@ retry:
on_shmem_exit(pgwin32_SharedMemoryDelete, PointerGetDatum(hmap2)); on_shmem_exit(pgwin32_SharedMemoryDelete, PointerGetDatum(hmap2));
*shim = hdr; *shim = hdr;
/* Report whether huge pages are in use */
SetConfigOption("huge_pages_status", (flProtect & SEC_LARGE_PAGES) ?
"on" : "off", PGC_INTERNAL, PGC_S_DYNAMIC_DEFAULT);
return hdr; return hdr;
} }

View File

@ -190,6 +190,13 @@ CreateSharedMemoryAndSemaphores(void)
*/ */
seghdr = PGSharedMemoryCreate(size, &shim); seghdr = PGSharedMemoryCreate(size, &shim);
/*
* Make sure that huge pages are never reported as "unknown" while the
* server is running.
*/
Assert(strcmp("unknown",
GetConfigOption("huge_pages_status", false, false)) != 0);
InitShmemAccess(seghdr); InitShmemAccess(seghdr);
/* /*

View File

@ -365,6 +365,13 @@ static const struct config_enum_entry huge_pages_options[] = {
{NULL, 0, false} {NULL, 0, false}
}; };
static const struct config_enum_entry huge_pages_status_options[] = {
{"off", HUGE_PAGES_OFF, false},
{"on", HUGE_PAGES_ON, false},
{"unknown", HUGE_PAGES_UNKNOWN, false},
{NULL, 0, false}
};
static const struct config_enum_entry recovery_prefetch_options[] = { static const struct config_enum_entry recovery_prefetch_options[] = {
{"off", RECOVERY_PREFETCH_OFF, false}, {"off", RECOVERY_PREFETCH_OFF, false},
{"on", RECOVERY_PREFETCH_ON, false}, {"on", RECOVERY_PREFETCH_ON, false},
@ -550,6 +557,7 @@ int ssl_renegotiation_limit;
*/ */
int huge_pages = HUGE_PAGES_TRY; int huge_pages = HUGE_PAGES_TRY;
int huge_page_size; int huge_page_size;
int huge_pages_status = HUGE_PAGES_UNKNOWN;
/* /*
* These variables are all dummies that don't do anything, except in some * These variables are all dummies that don't do anything, except in some
@ -4876,6 +4884,17 @@ struct config_enum ConfigureNamesEnum[] =
NULL, NULL, NULL NULL, NULL, NULL
}, },
{
{"huge_pages_status", PGC_INTERNAL, PRESET_OPTIONS,
gettext_noop("Indicates the status of huge pages."),
NULL,
GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
},
&huge_pages_status,
HUGE_PAGES_UNKNOWN, huge_pages_status_options,
NULL, NULL, NULL
},
{ {
{"recovery_prefetch", PGC_SIGHUP, WAL_RECOVERY, {"recovery_prefetch", PGC_SIGHUP, WAL_RECOVERY,
gettext_noop("Prefetch referenced blocks during recovery."), gettext_noop("Prefetch referenced blocks during recovery."),

View File

@ -46,12 +46,13 @@ extern PGDLLIMPORT int shared_memory_type;
extern PGDLLIMPORT int huge_pages; extern PGDLLIMPORT int huge_pages;
extern PGDLLIMPORT int huge_page_size; extern PGDLLIMPORT int huge_page_size;
/* Possible values for huge_pages */ /* Possible values for huge_pages and huge_pages_status */
typedef enum typedef enum
{ {
HUGE_PAGES_OFF, HUGE_PAGES_OFF,
HUGE_PAGES_ON, HUGE_PAGES_ON,
HUGE_PAGES_TRY HUGE_PAGES_TRY, /* only for huge_pages */
HUGE_PAGES_UNKNOWN /* only for huge_pages_status */
} HugePagesType; } HugePagesType;
/* Possible values for shared_memory_type */ /* Possible values for shared_memory_type */

View File

@ -100,6 +100,12 @@ my $system_user =
$node->safe_psql('postgres', $node->safe_psql('postgres',
q(select (string_to_array(SYSTEM_USER, ':'))[2])); q(select (string_to_array(SYSTEM_USER, ':'))[2]));
# While on it, check the status of huge pages, that can be either on
# or off, but never unknown.
my $huge_pages_status =
$node->safe_psql('postgres', q(SHOW huge_pages_status;));
isnt($huge_pages_status, 'unknown', "check huge_pages_status");
# Tests without the user name map. # Tests without the user name map.
# Failure as connection is attempted with a database role not mapping # Failure as connection is attempted with a database role not mapping
# to an authorized system user. # to an authorized system user.

View File

@ -21,6 +21,10 @@ $node->init;
$node->append_conf('postgresql.conf', "log_connections = on\n"); $node->append_conf('postgresql.conf', "log_connections = on\n");
$node->start; $node->start;
my $huge_pages_status =
$node->safe_psql('postgres', q(SHOW huge_pages_status;));
isnt($huge_pages_status, 'unknown', "check huge_pages_status");
# SSPI is set up by default. Make sure it interacts correctly with # SSPI is set up by default. Make sure it interacts correctly with
# require_auth. # require_auth.
$node->connect_ok("require_auth=sspi", $node->connect_ok("require_auth=sspi",