From 56deeba7514f9e3e8d91c9d0e5f56d206f1ec663 Mon Sep 17 00:00:00 2001
From: Florents Tselai <florents.tselai@gmail.com>
Date: Tue, 8 Jul 2025 14:06:57 +0300
Subject: [PATCH v5] Update pg_dsm_registry_allocations to include stuff added
 in fe07100

---
 doc/src/sgml/system-views.sgml                | 84 +++++++++++++++++++
 src/backend/catalog/system_views.sql          |  8 ++
 src/backend/storage/ipc/dsm_registry.c        | 66 +++++++++++++++
 src/include/catalog/pg_proc.dat               |  6 ++
 .../expected/test_dsm_registry.out            |  9 ++
 .../sql/test_dsm_registry.sql                 |  2 +
 src/test/regress/expected/rules.out           |  4 +
 7 files changed, 179 insertions(+)

diff --git a/doc/src/sgml/system-views.sgml b/doc/src/sgml/system-views.sgml
index e1ac544ee40..c61c6f6b2a7 100644
--- a/doc/src/sgml/system-views.sgml
+++ b/doc/src/sgml/system-views.sgml
@@ -186,6 +186,11 @@
       <entry>NUMA node mappings for shared memory allocations</entry>
      </row>
 
+     <row>
+      <entry><link linkend="view-pg-dsm-registry-allocations"><structname>pg_dsm_registry_allocations</structname></link></entry>
+      <entry>DSM segment allocations registered via the DSM registry</entry>
+     </row>
+
      <row>
       <entry><link linkend="view-pg-stats"><structname>pg_stats</structname></link></entry>
       <entry>planner statistics</entry>
@@ -4143,6 +4148,85 @@ SELECT * FROM pg_locks pl LEFT JOIN pg_prepared_xacts ppx
   </para>
  </sect1>
 
+ <sect1 id="view-pg-dsm-registry-allocations">
+  <title><structname>pg_dsm_registry_allocations</structname></title>
+
+  <indexterm zone="view-pg-dsm-registry-allocations">
+   <primary>pg_dsm_registry_allocations</primary>
+  </indexterm>
+
+  <para>
+     The <structname>pg_dsm_registry_allocations</structname> view shows current
+     allocations registered in the dynamic shared memory (DSM) registry. This
+     includes all entries that have been registered and tracked by
+     <productname>PostgreSQL</productname> during the server's operation. Entries
+     may represent a raw dynamic shared memory (DSM) segment, a dynamic shared
+     memory area (DSA), or a shared hash table (dshash) built on top of a DSA.
+  </para>
+
+  <para>
+   This view is useful for monitoring DSM usage by extensions or internal
+   components using dynamic shared memory segments.
+  </para>
+
+  <table>
+     <title><structname>pg_dsm_registry_allocations</structname> Columns</title>
+     <tgroup cols="1">
+      <thead>
+       <row>
+        <entry role="catalog_table_entry"><para role="column_definition">
+         Column Type
+        </para>
+         <para>
+          Description
+         </para></entry>
+       </row>
+      </thead>
+
+      <tbody>
+       <row>
+        <entry role="catalog_table_entry"><para role="column_definition">
+         <structfield>name</structfield> <type>text</type>
+        </para>
+         <para>
+          The name of the allocation as registered in the DSM registry.
+         </para></entry>
+       </row>
+
+       <row>
+        <entry role="catalog_table_entry"><para role="column_definition">
+         <structfield>type</structfield> <type>text</type>
+        </para>
+         <para>
+          The type of allocation. Possible values are <literal>dsm</literal> for a
+          raw dynamic shared memory segment, <literal>dsa</literal> for a dynamic
+          shared memory area, and <literal>dsh</literal> for a dynamic shared hash table.
+         </para></entry>
+       </row>
+
+       <row>
+        <entry role="catalog_table_entry"><para role="column_definition">
+         <structfield>size</structfield> <type>int8</type>
+        </para>
+         <para>
+          The size of the allocation in bytes. For entries of type <literal>dsm</literal>,
+          this reflects the actual size of the allocated DSM segment. For <literal>dsa</literal>
+          and <literal>dsh</literal> entries, the size is reported as <literal>NULL</literal>
+          because the server does not attach to these areas in order to retrieve their size.
+         </para></entry>
+       </row>
+      </tbody>
+     </tgroup>
+    </table>
+
+  <para>
+   By default, access to the <structname>pg_dsm_registry_allocations</structname>
+   view is restricted to superusers or roles granted the
+   <literal>pg_read_all_stats</literal> role due to the sensitive nature
+   of dynamic shared memory usage information.
+  </para>
+ </sect1>
+
  <sect1 id="view-pg-stats">
   <title><structname>pg_stats</structname></title>
 
diff --git a/src/backend/catalog/system_views.sql b/src/backend/catalog/system_views.sql
index e5dbbe61b81..e637f080a37 100644
--- a/src/backend/catalog/system_views.sql
+++ b/src/backend/catalog/system_views.sql
@@ -666,6 +666,14 @@ GRANT SELECT ON pg_shmem_allocations_numa TO pg_read_all_stats;
 REVOKE EXECUTE ON FUNCTION pg_get_shmem_allocations_numa() FROM PUBLIC;
 GRANT EXECUTE ON FUNCTION pg_get_shmem_allocations_numa() TO pg_read_all_stats;
 
+CREATE VIEW pg_dsm_registry_allocations AS
+SELECT * FROM pg_get_dsm_registry_allocations();
+
+REVOKE ALL ON pg_dsm_registry_allocations FROM PUBLIC;
+GRANT SELECT ON pg_dsm_registry_allocations TO pg_read_all_stats;
+REVOKE EXECUTE ON FUNCTION pg_get_dsm_registry_allocations() FROM PUBLIC;
+GRANT EXECUTE ON FUNCTION pg_get_dsm_registry_allocations() TO pg_read_all_stats;
+
 CREATE VIEW pg_backend_memory_contexts AS
     SELECT * FROM pg_get_backend_memory_contexts();
 
diff --git a/src/backend/storage/ipc/dsm_registry.c b/src/backend/storage/ipc/dsm_registry.c
index 828c2ff0c7f..1934e086b0a 100644
--- a/src/backend/storage/ipc/dsm_registry.c
+++ b/src/backend/storage/ipc/dsm_registry.c
@@ -40,10 +40,12 @@
 
 #include "postgres.h"
 
+#include "funcapi.h"
 #include "lib/dshash.h"
 #include "storage/dsm_registry.h"
 #include "storage/lwlock.h"
 #include "storage/shmem.h"
+#include "utils/builtins.h"
 #include "utils/memutils.h"
 
 #define DSMR_NAME_LEN				128
@@ -435,3 +437,67 @@ GetNamedDSHash(const char *name, const dshash_parameters *params, bool *found)
 
 	return ret;
 }
+
+Datum
+pg_get_dsm_registry_allocations(PG_FUNCTION_ARGS)
+{
+	ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
+	DSMRegistryEntry *entry;
+	dshash_seq_status status;
+
+	InitMaterializedSRF(fcinfo, MAT_SRF_USE_EXPECTED_DESC);
+
+	/* Ensure DSM registry initialized */
+	init_dsm_registry();
+
+	/* Use non-exclusive access to avoid blocking other backends */
+	dshash_seq_init(&status, dsm_registry_table, false);
+
+	while ((entry = dshash_seq_next(&status)) != NULL)
+	{
+		/* name, type, size */
+		Datum values[3];
+		bool nulls[3] = {false, false, false};
+
+		/* 0: name */
+		values[0] = CStringGetTextDatum(entry->name);
+
+		/* 1: type */
+		switch (entry->type) {
+			case DSMR_ENTRY_TYPE_DSM:
+				values[1] = CStringGetTextDatum("dsm");
+				break;
+			case DSMR_ENTRY_TYPE_DSA:
+				values[1] = CStringGetTextDatum("dsa");
+				break;
+			case DSMR_ENTRY_TYPE_DSH:
+				values[1] = CStringGetTextDatum("dsh");
+				break;
+			default:
+				values[1] = CStringGetTextDatum("unknown");
+				break;
+		}
+
+		/* 2: size */
+		switch (entry->type)
+		{
+			case DSMR_ENTRY_TYPE_DSM:
+				values[2] = Int64GetDatum(entry->data.dsm.size);
+				break;
+
+			/* in case of dsa or dsh we return NULL */
+			case DSMR_ENTRY_TYPE_DSA:
+			case DSMR_ENTRY_TYPE_DSH:
+			default:
+				nulls[2] = true;
+				break;
+		}
+
+		tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc,
+							 values, nulls);
+	}
+
+	dshash_seq_term(&status);
+
+	return (Datum) 0;
+}
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index d4650947c63..2f5df3affae 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8559,6 +8559,12 @@
   proallargtypes => '{text,int8,int8,int8}', proargmodes => '{o,o,o,o}',
   proargnames => '{name,off,size,allocated_size}',
   prosrc => 'pg_get_shmem_allocations' },
+{ oid => '6062', descr => 'dsm registry allocations',
+  proname => 'pg_get_dsm_registry_allocations', prorows => '50', proretset => 't',
+  provolatile => 'v', prorettype => 'record', proargtypes => '',
+  proallargtypes => '{text,text,int8}', proargmodes => '{o,o,o}',
+  proargnames => '{name,type,size}',
+  prosrc => 'pg_get_dsm_registry_allocations' },
 
 { oid => '4099', descr => 'Is NUMA support available?',
   proname => 'pg_numa_available', provolatile => 's', prorettype => 'bool',
diff --git a/src/test/modules/test_dsm_registry/expected/test_dsm_registry.out b/src/test/modules/test_dsm_registry/expected/test_dsm_registry.out
index 8ded82e59d6..90f0a888a16 100644
--- a/src/test/modules/test_dsm_registry/expected/test_dsm_registry.out
+++ b/src/test/modules/test_dsm_registry/expected/test_dsm_registry.out
@@ -24,3 +24,12 @@ SELECT get_val_in_hash('test');
  1414
 (1 row)
 
+\c
+SELECT name, type, size > 0 OR size ISNULL as size FROM pg_dsm_registry_allocations WHERE name like 'test_dsm_registry%';
+          name          | type | size 
+------------------------+------+------
+ test_dsm_registry_dsa  | dsa  | t
+ test_dsm_registry_hash | dsh  | t
+ test_dsm_registry_dsm  | dsm  | t
+(3 rows)
+
diff --git a/src/test/modules/test_dsm_registry/sql/test_dsm_registry.sql b/src/test/modules/test_dsm_registry/sql/test_dsm_registry.sql
index c2e25cddaae..a84beaec6c5 100644
--- a/src/test/modules/test_dsm_registry/sql/test_dsm_registry.sql
+++ b/src/test/modules/test_dsm_registry/sql/test_dsm_registry.sql
@@ -4,3 +4,5 @@ SELECT set_val_in_hash('test', '1414');
 \c
 SELECT get_val_in_shmem();
 SELECT get_val_in_hash('test');
+\c
+SELECT name, type, size > 0 OR size ISNULL as size FROM pg_dsm_registry_allocations WHERE name like 'test_dsm_registry%';
diff --git a/src/test/regress/expected/rules.out b/src/test/regress/expected/rules.out
index 6cf828ca8d0..dce8c672b40 100644
--- a/src/test/regress/expected/rules.out
+++ b/src/test/regress/expected/rules.out
@@ -1340,6 +1340,10 @@ pg_cursors| SELECT name,
     is_scrollable,
     creation_time
    FROM pg_cursor() c(name, statement, is_holdable, is_binary, is_scrollable, creation_time);
+pg_dsm_registry_allocations| SELECT name,
+    type,
+    size
+   FROM pg_get_dsm_registry_allocations() pg_get_dsm_registry_allocations(name, type, size);
 pg_file_settings| SELECT sourcefile,
     sourceline,
     seqno,
-- 
2.49.0

