From f66d63613d8db0974c79a83a67184efa1dddfd93 Mon Sep 17 00:00:00 2001
From: Florents Tselai <florents.tselai@gmail.com>
Date: Wed, 4 Jun 2025 21:02:01 +0300
Subject: [PATCH v4] Add pg_dsm_registry_allocations system view

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

diff --git a/doc/src/sgml/system-views.sgml b/doc/src/sgml/system-views.sgml
index b58c52ea50f..e41a7b5745f 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>
@@ -4146,6 +4151,69 @@ 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 DSM segments that have been allocated and tracked by
+   <productname>PostgreSQL</productname> during the server's operation.
+  </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 DSM allocation as registered in the DSM registry.
+       </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 allocated dynamic shared memory segment in bytes.
+       </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 08f780a2e63..64e62732f18 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 1d4fd31ffed..0650c70e173 100644
--- a/src/backend/storage/ipc/dsm_registry.c
+++ b/src/backend/storage/ipc/dsm_registry.c
@@ -26,10 +26,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"
 
 typedef struct DSMRegistryCtxStruct
@@ -198,3 +200,35 @@ GetNamedDSMSegment(const char *name, size_t size,
 
 	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)
+	{
+		Datum values[2];
+		bool nulls[2] = {false, false};
+
+		values[0] = CStringGetTextDatum(entry->name);
+		values[1] = Int64GetDatum(entry->size);
+
+		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 d3d28a263fa..bef92be8250 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8541,6 +8541,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,int8}', proargmodes => '{o,o}',
+  proargnames => '{name,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 8ffbd343a05..3c279378b5b 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
@@ -12,3 +12,9 @@ SELECT get_val_in_shmem();
              1236
 (1 row)
 
+SELECT size > 0 FROM pg_dsm_registry_allocations WHERE name = 'test_dsm_registry';
+ ?column? 
+----------
+ t
+(1 row)
+
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 b3351be0a16..d27ee2e6a1a 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
@@ -2,3 +2,5 @@ CREATE EXTENSION test_dsm_registry;
 SELECT set_val_in_shmem(1236);
 \c
 SELECT get_val_in_shmem();
+
+SELECT size > 0 FROM pg_dsm_registry_allocations WHERE name = 'test_dsm_registry';
diff --git a/src/test/regress/expected/rules.out b/src/test/regress/expected/rules.out
index 6cf828ca8d0..893c5b2b933 100644
--- a/src/test/regress/expected/rules.out
+++ b/src/test/regress/expected/rules.out
@@ -1340,6 +1340,9 @@ 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,
+    size
+   FROM pg_get_dsm_registry_allocations() pg_get_dsm_registry_allocations(name, size);
 pg_file_settings| SELECT sourcefile,
     sourceline,
     seqno,
-- 
2.49.0

