Teach autoprewarm to use the dynamic shared memory registry.
authorNathan Bossart <[email protected]>
Fri, 19 Jan 2024 20:43:59 +0000 (14:43 -0600)
committerNathan Bossart <[email protected]>
Fri, 19 Jan 2024 20:43:59 +0000 (14:43 -0600)
Besides showcasing the DSM registry, this prevents pg_prewarm from
stealing from the main shared memory segment's extra buffer space
when autoprewarm_start_worker() and autoprewarm_dump_now() are used
without loading the module via shared_preload_libraries.

Suggested-by: Michael Paquier
Reviewed-by: Bharath Rupireddy
Discussion: https://postgr.es/m/20231205034647.GA2705267%40nathanxps13

contrib/pg_prewarm/autoprewarm.c

index 9085a409db7d8b53d04bda32e929a6cc1080935a..9ea6c2252ad9231cec5721f955dd3042a9c11c6b 100644 (file)
 #include "access/xact.h"
 #include "catalog/pg_class.h"
 #include "catalog/pg_type.h"
-#include "miscadmin.h"
 #include "pgstat.h"
 #include "postmaster/bgworker.h"
 #include "postmaster/interrupt.h"
 #include "storage/buf_internals.h"
 #include "storage/dsm.h"
+#include "storage/dsm_registry.h"
 #include "storage/fd.h"
 #include "storage/ipc.h"
 #include "storage/latch.h"
@@ -95,8 +95,6 @@ static void apw_start_database_worker(void);
 static bool apw_init_shmem(void);
 static void apw_detach_shmem(int code, Datum arg);
 static int apw_compare_blockinfo(const void *p, const void *q);
-static void autoprewarm_shmem_request(void);
-static shmem_request_hook_type prev_shmem_request_hook = NULL;
 
 /* Pointer to shared-memory state. */
 static AutoPrewarmSharedState *apw_state = NULL;
@@ -140,26 +138,11 @@ _PG_init(void)
 
    MarkGUCPrefixReserved("pg_prewarm");
 
-   prev_shmem_request_hook = shmem_request_hook;
-   shmem_request_hook = autoprewarm_shmem_request;
-
    /* Register autoprewarm worker, if enabled. */
    if (autoprewarm)
        apw_start_leader_worker();
 }
 
-/*
- * Requests any additional shared memory required for autoprewarm.
- */
-static void
-autoprewarm_shmem_request(void)
-{
-   if (prev_shmem_request_hook)
-       prev_shmem_request_hook();
-
-   RequestAddinShmemSpace(MAXALIGN(sizeof(AutoPrewarmSharedState)));
-}
-
 /*
  * Main entry point for the leader autoprewarm process.  Per-database workers
  * have a separate entry point.
@@ -767,6 +750,16 @@ autoprewarm_dump_now(PG_FUNCTION_ARGS)
    PG_RETURN_INT64((int64) num_blocks);
 }
 
+static void
+apw_init_state(void *ptr)
+{
+   AutoPrewarmSharedState *state = (AutoPrewarmSharedState *) ptr;
+
+   LWLockInitialize(&state->lock, LWLockNewTrancheId());
+   state->bgworker_pid = InvalidPid;
+   state->pid_using_dumpfile = InvalidPid;
+}
+
 /*
  * Allocate and initialize autoprewarm related shared memory, if not already
  * done, and set up backend-local pointer to that state.  Returns true if an
@@ -777,19 +770,10 @@ apw_init_shmem(void)
 {
    bool        found;
 
-   LWLockAcquire(AddinShmemInitLock, LW_EXCLUSIVE);
-   apw_state = ShmemInitStruct("autoprewarm",
-                               sizeof(AutoPrewarmSharedState),
-                               &found);
-   if (!found)
-   {
-       /* First time through ... */
-       LWLockInitialize(&apw_state->lock, LWLockNewTrancheId());
-       apw_state->bgworker_pid = InvalidPid;
-       apw_state->pid_using_dumpfile = InvalidPid;
-   }
-   LWLockRelease(AddinShmemInitLock);
-
+   apw_state = GetNamedDSMSegment("autoprewarm",
+                                  sizeof(AutoPrewarmSharedState),
+                                  apw_init_state,
+                                  &found);
    LWLockRegisterTranche(apw_state->lock.tranche, "autoprewarm");
 
    return found;