| From: | Mingwei Jia <i(at)nayishan(dot)top> |
|---|---|
| To: | pgsql-hackers(at)lists(dot)postgresql(dot)org |
| Subject: | [RFC PATCH v2 RESEND 02/10] umbra: add patch 1 smgr implementation boundary |
| Date: | 2026-06-01 23:33:32 |
| Message-ID: | 20260601233340.67949-1-i@nayishan.top |
| Views: | Whole Thread | Raw Message | Download mbox | Resend email |
| Thread: | |
| Lists: | pgsql-hackers |
---
configure | 38 ++++++
configure.ac | 10 ++
meson.build | 1 +
meson_options.txt | 3 +
src/Makefile.global.in | 1 +
src/backend/storage/smgr/Makefile | 8 ++
src/backend/storage/smgr/meson.build | 6 +
src/backend/storage/smgr/smgr.c | 52 ++++++++-
src/backend/storage/smgr/umbra.c | 167 +++++++++++++++++++++++++++
src/include/pg_config.h.in | 3 +
src/include/storage/smgr.h | 11 +-
src/include/storage/umbra.h | 54 +++++++++
12 files changed, 345 insertions(+), 9 deletions(-)
create mode 100644 src/backend/storage/smgr/umbra.c
create mode 100644 src/include/storage/umbra.h
diff --git a/configure b/configure
index f66c1054a7..a63ecb3745 100755
--- a/configure
+++ b/configure
@@ -723,6 +723,7 @@ LIBURING_LIBS
LIBURING_CFLAGS
with_liburing
with_readline
+with_umbra
with_systemd
with_selinux
with_ldap
@@ -872,6 +873,7 @@ with_ldap
with_bonjour
with_selinux
with_systemd
+with_umbra
with_readline
with_libedit_preferred
with_liburing
@@ -1590,6 +1592,7 @@ Optional Packages:
--with-bonjour build with Bonjour support
--with-selinux build with SELinux support
--with-systemd build with systemd support
+ --with-umbra build with Umbra storage manager (experimental)
--without-readline do not use GNU Readline nor BSD Libedit for editing
--with-libedit-preferred
prefer BSD Libedit over GNU Readline
@@ -8635,6 +8638,41 @@ fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $with_systemd" >&5
$as_echo "$with_systemd" >&6; }
+#
+# Umbra storage manager (experimental)
+#
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build with Umbra storage manager" >&5
+$as_echo_n "checking whether to build with Umbra storage manager... " >&6; }
+
+
+
+# Check whether --with-umbra was given.
+if test "${with_umbra+set}" = set; then :
+ withval=$with_umbra;
+ case $withval in
+ yes)
+
+$as_echo "#define USE_UMBRA 1" >>confdefs.h
+
+ ;;
+ no)
+ :
+ ;;
+ *)
+ as_fn_error $? "no argument expected for --with-umbra option" "$LINENO" 5
+ ;;
+ esac
+
+else
+ with_umbra=no
+
+fi
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $with_umbra" >&5
+$as_echo "$with_umbra" >&6; }
+
+
#
# Readline
#
diff --git a/configure.ac b/configure.ac
index 8d176bd346..43006a5284 100644
--- a/configure.ac
+++ b/configure.ac
@@ -992,6 +992,16 @@ PGAC_ARG_BOOL(with, systemd, no, [build with systemd support],
AC_SUBST(with_systemd)
AC_MSG_RESULT([$with_systemd])
+#
+# Umbra storage manager (experimental)
+#
+AC_MSG_CHECKING([whether to build with Umbra storage manager])
+PGAC_ARG_BOOL(with, umbra, no,
+ [build with Umbra storage manager (experimental)],
+ [AC_DEFINE([USE_UMBRA], 1, [Define to build with Umbra storage manager. (--with-umbra)])])
+AC_MSG_RESULT([$with_umbra])
+AC_SUBST(with_umbra)
+
#
# Readline
#
diff --git a/meson.build b/meson.build
index be97e986e5..016ba9fc0c 100644
--- a/meson.build
+++ b/meson.build
@@ -505,6 +505,7 @@ meson_bin = find_program(meson_binpath, native: true)
cdata.set('USE_ASSERT_CHECKING', get_option('cassert') ? 1 : false)
cdata.set('USE_INJECTION_POINTS', get_option('injection_points') ? 1 : false)
+cdata.set('USE_UMBRA', get_option('umbra').enabled() ? 1 : false)
blocksize = get_option('blocksize').to_int() * 1024
diff --git a/meson_options.txt b/meson_options.txt
index 6a793f3e47..469239543c 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -46,6 +46,9 @@ option('tap_tests', type: 'feature', value: 'auto',
option('injection_points', type: 'boolean', value: false,
description: 'Enable injection points')
+option('umbra', type: 'feature', value: 'disabled',
+ description: 'Enable experimental Umbra storage manager')
+
option('PG_TEST_EXTRA', type: 'string', value: '',
description: 'Enable selected extra tests. Overridden by PG_TEST_EXTRA environment variable.')
diff --git a/src/Makefile.global.in b/src/Makefile.global.in
index a7699b026b..4e2815218a 100644
--- a/src/Makefile.global.in
+++ b/src/Makefile.global.in
@@ -201,6 +201,7 @@ with_liburing = @with_liburing@
with_libxml = @with_libxml@
with_libxslt = @with_libxslt@
with_llvm = @with_llvm@
+with_umbra = @with_umbra@
with_system_tzdata = @with_system_tzdata@
with_uuid = @with_uuid@
with_zlib = @with_zlib@
diff --git a/src/backend/storage/smgr/Makefile b/src/backend/storage/smgr/Makefile
index 1d0b98764f..537e7b65f4 100644
--- a/src/backend/storage/smgr/Makefile
+++ b/src/backend/storage/smgr/Makefile
@@ -17,4 +17,12 @@ OBJS = \
md.o \
smgr.o
+ifeq ($(with_umbra), yes)
+OBJS += \
+ umbra.o
+endif
+
+# Reconfiguration can change both OBJS and the default smgr implementation.
+objfiles.txt smgr.o: $(top_builddir)/src/Makefile.global
+
include $(top_srcdir)/src/backend/common.mk
diff --git a/src/backend/storage/smgr/meson.build b/src/backend/storage/smgr/meson.build
index 3785c40385..ba28e59f2f 100644
--- a/src/backend/storage/smgr/meson.build
+++ b/src/backend/storage/smgr/meson.build
@@ -5,3 +5,9 @@ backend_sources += files(
'md.c',
'smgr.c',
)
+
+if get_option('umbra').enabled()
+ backend_sources += files(
+ 'umbra.c',
+ )
+endif
diff --git a/src/backend/storage/smgr/smgr.c b/src/backend/storage/smgr/smgr.c
index 5391640d86..a7b70d856c 100644
--- a/src/backend/storage/smgr/smgr.c
+++ b/src/backend/storage/smgr/smgr.c
@@ -4,8 +4,9 @@
* public interface routines to storage manager switch.
*
* All file system operations on relations dispatch through these routines.
- * An SMgrRelation represents physical on-disk relation files that are open
- * for reading and writing.
+ * An SMgrRelation represents storage-manager state for a relation. The
+ * selected storage manager implementation owns any implementation-specific
+ * state needed to service those operations.
*
* When a relation is first accessed through the relation cache, the
* corresponding SMgrRelation entry is opened by calling smgropen(), and the
@@ -71,6 +72,9 @@
#include "storage/ipc.h"
#include "storage/md.h"
#include "storage/smgr.h"
+#ifdef USE_UMBRA
+#include "storage/umbra.h"
+#endif
#include "utils/hsearch.h"
#include "utils/inval.h"
@@ -91,6 +95,7 @@ typedef struct f_smgr
void (*smgr_shutdown) (void); /* may be NULL */
void (*smgr_open) (SMgrRelation reln);
void (*smgr_close) (SMgrRelation reln, ForkNumber forknum);
+ void (*smgr_destroy) (SMgrRelation reln); /* may be NULL */
void (*smgr_create) (SMgrRelation reln, ForkNumber forknum,
bool isRedo);
bool (*smgr_exists) (SMgrRelation reln, ForkNumber forknum);
@@ -125,6 +130,14 @@ typedef struct f_smgr
int (*smgr_fd) (SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, uint32 *off);
} f_smgr;
+#define SMGR_MD 0
+#ifdef USE_UMBRA
+#define SMGR_UMBRA 1
+#define SMGR_DEFAULT SMGR_UMBRA
+#else
+#define SMGR_DEFAULT SMGR_MD
+#endif
+
static const f_smgr smgrsw[] = {
/* magnetic disk */
{
@@ -132,6 +145,7 @@ static const f_smgr smgrsw[] = {
.smgr_shutdown = NULL,
.smgr_open = mdopen,
.smgr_close = mdclose,
+ .smgr_destroy = NULL,
.smgr_create = mdcreate,
.smgr_exists = mdexists,
.smgr_unlink = mdunlink,
@@ -148,7 +162,33 @@ static const f_smgr smgrsw[] = {
.smgr_immedsync = mdimmedsync,
.smgr_registersync = mdregistersync,
.smgr_fd = mdfd,
- }
+ },
+#ifdef USE_UMBRA
+ /* Umbra storage manager */
+ {
+ .smgr_init = uminit,
+ .smgr_shutdown = NULL,
+ .smgr_open = umopen,
+ .smgr_close = umclose,
+ .smgr_destroy = umdestroy,
+ .smgr_create = umcreate,
+ .smgr_exists = umexists,
+ .smgr_unlink = umunlink,
+ .smgr_extend = umextend,
+ .smgr_zeroextend = umzeroextend,
+ .smgr_prefetch = umprefetch,
+ .smgr_maxcombine = ummaxcombine,
+ .smgr_readv = umreadv,
+ .smgr_startreadv = umstartreadv,
+ .smgr_writev = umwritev,
+ .smgr_writeback = umwriteback,
+ .smgr_nblocks = umnblocks,
+ .smgr_truncate = umtruncate,
+ .smgr_immedsync = umimmedsync,
+ .smgr_registersync = umregistersync,
+ .smgr_fd = umfd,
+ },
+#endif
};
static const int NSmgr = lengthof(smgrsw);
@@ -273,7 +313,8 @@ smgropen(RelFileLocator rlocator, ProcNumber backend)
reln->smgr_targblock = InvalidBlockNumber;
for (int i = 0; i <= MAX_FORKNUM; ++i)
reln->smgr_cached_nblocks[i] = InvalidBlockNumber;
- reln->smgr_which = 0; /* we only have md.c at present */
+ reln->smgr_which = SMGR_DEFAULT;
+ reln->smgr_private = NULL;
/* it is not pinned yet */
reln->pincount = 0;
@@ -331,6 +372,9 @@ smgrdestroy(SMgrRelation reln)
for (forknum = 0; forknum <= MAX_FORKNUM; forknum++)
smgrsw[reln->smgr_which].smgr_close(reln, forknum);
+ if (smgrsw[reln->smgr_which].smgr_destroy != NULL)
+ smgrsw[reln->smgr_which].smgr_destroy(reln);
+
dlist_delete(&reln->node);
if (hash_search(SMgrRelationHash,
diff --git a/src/backend/storage/smgr/umbra.c b/src/backend/storage/smgr/umbra.c
new file mode 100644
index 0000000000..4c4fd28dbf
--- /dev/null
+++ b/src/backend/storage/smgr/umbra.c
@@ -0,0 +1,167 @@
+/*-------------------------------------------------------------------------
+ *
+ * umbra.c
+ * Umbra storage manager skeleton.
+ *
+ * This file establishes Umbra as a separate smgr implementation from md.c.
+ * The initial implementation preserves md semantics by forwarding relation
+ * file operations to md.c.
+ *
+ * src/backend/storage/smgr/umbra.c
+ *
+ *-------------------------------------------------------------------------
+ */
+#include "postgres.h"
+
+#include "storage/md.h"
+#include "storage/smgr.h"
+#include "storage/umbra.h"
+#include "utils/memutils.h"
+
+typedef struct UmbraSmgrRelationState
+{
+ bool initialized;
+} UmbraSmgrRelationState;
+
+void
+uminit(void)
+{
+}
+
+void
+umopen(SMgrRelation reln)
+{
+ UmbraSmgrRelationState *state;
+
+ Assert(reln->smgr_private == NULL);
+
+ state = MemoryContextAllocZero(TopMemoryContext,
+ sizeof(UmbraSmgrRelationState));
+ state->initialized = true;
+ reln->smgr_private = state;
+
+ mdopen(reln);
+}
+
+void
+umclose(SMgrRelation reln, ForkNumber forknum)
+{
+ mdclose(reln, forknum);
+}
+
+void
+umdestroy(SMgrRelation reln)
+{
+ UmbraSmgrRelationState *state = reln->smgr_private;
+
+ if (state != NULL)
+ {
+ Assert(state->initialized);
+ pfree(state);
+ reln->smgr_private = NULL;
+ }
+}
+
+void
+umcreate(SMgrRelation reln, ForkNumber forknum, bool isRedo)
+{
+ mdcreate(reln, forknum, isRedo);
+}
+
+bool
+umexists(SMgrRelation reln, ForkNumber forknum)
+{
+ return mdexists(reln, forknum);
+}
+
+void
+umunlink(RelFileLocatorBackend rlocator, ForkNumber forknum, bool isRedo)
+{
+ mdunlink(rlocator, forknum, isRedo);
+}
+
+void
+umextend(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum,
+ const void *buffer, bool skipFsync)
+{
+ mdextend(reln, forknum, blocknum, buffer, skipFsync);
+}
+
+void
+umzeroextend(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum,
+ int nblocks, bool skipFsync)
+{
+ mdzeroextend(reln, forknum, blocknum, nblocks, skipFsync);
+}
+
+bool
+umprefetch(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum,
+ int nblocks)
+{
+ return mdprefetch(reln, forknum, blocknum, nblocks);
+}
+
+uint32
+ummaxcombine(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum)
+{
+ return mdmaxcombine(reln, forknum, blocknum);
+}
+
+void
+umreadv(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum,
+ void **buffers, BlockNumber nblocks)
+{
+ mdreadv(reln, forknum, blocknum, buffers, nblocks);
+}
+
+void
+umstartreadv(PgAioHandle *ioh, SMgrRelation reln, ForkNumber forknum,
+ BlockNumber blocknum, void **buffers, BlockNumber nblocks)
+{
+ mdstartreadv(ioh, reln, forknum, blocknum, buffers, nblocks);
+}
+
+void
+umwritev(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum,
+ const void **buffers, BlockNumber nblocks, bool skipFsync)
+{
+ mdwritev(reln, forknum, blocknum, buffers, nblocks, skipFsync);
+}
+
+void
+umwriteback(SMgrRelation reln, ForkNumber forknum,
+ BlockNumber blocknum, BlockNumber nblocks)
+{
+ mdwriteback(reln, forknum, blocknum, nblocks);
+}
+
+BlockNumber
+umnblocks(SMgrRelation reln, ForkNumber forknum)
+{
+ return mdnblocks(reln, forknum);
+}
+
+void
+umtruncate(SMgrRelation reln, ForkNumber forknum,
+ BlockNumber old_blocks, BlockNumber nblocks)
+{
+ mdtruncate(reln, forknum, old_blocks, nblocks);
+}
+
+void
+umimmedsync(SMgrRelation reln, ForkNumber forknum)
+{
+ mdimmedsync(reln, forknum);
+}
+
+void
+umregistersync(SMgrRelation reln, ForkNumber forknum)
+{
+ mdregistersync(reln, forknum);
+}
+
+int
+umfd(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, uint32 *off)
+{
+ return mdfd(reln, forknum, blocknum, off);
+}
diff --git a/src/include/pg_config.h.in b/src/include/pg_config.h.in
index 4f8113c144..2bd28af842 100644
--- a/src/include/pg_config.h.in
+++ b/src/include/pg_config.h.in
@@ -698,6 +698,9 @@
/* Define to 1 to build with injection points. (--enable-injection-points) */
#undef USE_INJECTION_POINTS
+/* Define to build with Umbra storage manager. (--with-umbra) */
+#undef USE_UMBRA
+
/* Define to 1 to build with LDAP support. (--with-ldap) */
#undef USE_LDAP
diff --git a/src/include/storage/smgr.h b/src/include/storage/smgr.h
index 09bd42fcf4..1076717b92 100644
--- a/src/include/storage/smgr.h
+++ b/src/include/storage/smgr.h
@@ -21,11 +21,11 @@
/*
* smgr.c maintains a table of SMgrRelation objects, which are essentially
- * cached file handles. An SMgrRelation is created (if not already present)
- * by smgropen(), and destroyed by smgrdestroy(). Note that neither of these
- * operations imply I/O, they just create or destroy a hashtable entry. (But
- * smgrdestroy() may release associated resources, such as OS-level file
- * descriptors.)
+ * cached storage-manager handles for a relation. An SMgrRelation is created
+ * (if not already present) by smgropen(), and destroyed by smgrdestroy().
+ * Note that neither of these operations imply I/O, they just create or destroy
+ * a hashtable entry. (But smgrdestroy() may release associated resources,
+ * such as OS-level file descriptors.)
*
* An SMgrRelation may be "pinned", to prevent it from being destroyed while
* it's in use. We use this to prevent pointers in relcache to smgr from being
@@ -53,6 +53,7 @@ typedef struct SMgrRelationData
* submodules. Do not touch them from elsewhere.
*/
int smgr_which; /* storage manager selector */
+ void *smgr_private; /* implementation-private state */
/*
* for md.c; per-fork arrays of the number of open segments
diff --git a/src/include/storage/umbra.h b/src/include/storage/umbra.h
new file mode 100644
index 0000000000..9a2873f96d
--- /dev/null
+++ b/src/include/storage/umbra.h
@@ -0,0 +1,54 @@
+/*-------------------------------------------------------------------------
+ *
+ * umbra.h
+ * Umbra storage manager public interface declarations.
+ *
+ * This header declares the Umbra smgr callback surface used by smgr.c when
+ * the build is configured with --with-umbra.
+ *
+ * src/include/storage/umbra.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef UMBRA_H
+#define UMBRA_H
+
+#include "storage/aio_types.h"
+#include "storage/block.h"
+#include "storage/relfilelocator.h"
+#include "storage/smgr.h"
+
+extern void uminit(void);
+extern void umopen(SMgrRelation reln);
+extern void umclose(SMgrRelation reln, ForkNumber forknum);
+extern void umdestroy(SMgrRelation reln);
+extern void umcreate(SMgrRelation reln, ForkNumber forknum, bool isRedo);
+extern bool umexists(SMgrRelation reln, ForkNumber forknum);
+extern void umunlink(RelFileLocatorBackend rlocator, ForkNumber forknum, bool isRedo);
+extern void umextend(SMgrRelation reln, ForkNumber forknum,
+ BlockNumber blocknum, const void *buffer, bool skipFsync);
+extern void umzeroextend(SMgrRelation reln, ForkNumber forknum,
+ BlockNumber blocknum, int nblocks, bool skipFsync);
+extern bool umprefetch(SMgrRelation reln, ForkNumber forknum,
+ BlockNumber blocknum, int nblocks);
+extern uint32 ummaxcombine(SMgrRelation reln, ForkNumber forknum,
+ BlockNumber blocknum);
+extern void umreadv(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum,
+ void **buffers, BlockNumber nblocks);
+extern void umstartreadv(PgAioHandle *ioh,
+ SMgrRelation reln, ForkNumber forknum,
+ BlockNumber blocknum,
+ void **buffers, BlockNumber nblocks);
+extern void umwritev(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum,
+ const void **buffers, BlockNumber nblocks, bool skipFsync);
+extern void umwriteback(SMgrRelation reln, ForkNumber forknum,
+ BlockNumber blocknum, BlockNumber nblocks);
+extern BlockNumber umnblocks(SMgrRelation reln, ForkNumber forknum);
+extern void umtruncate(SMgrRelation reln, ForkNumber forknum,
+ BlockNumber old_blocks, BlockNumber nblocks);
+extern void umimmedsync(SMgrRelation reln, ForkNumber forknum);
+extern void umregistersync(SMgrRelation reln, ForkNumber forknum);
+extern int umfd(SMgrRelation reln, ForkNumber forknum,
+ BlockNumber blocknum, uint32 *off);
+
+#endif /* UMBRA_H */
--
2.50.1 (Apple Git-155)
| From | Date | Subject | |
|---|---|---|---|
| Next Message | Mingwei Jia | 2026-06-01 23:33:33 | [RFC PATCH v2 RESEND 03/10] umbra: add patch 2 umfile physical file manager and metadata storage primitives |
| Previous Message | Mingwei Jia | 2026-06-01 23:29:20 | [RFC PATCH v2 RESEND 01/10] umbra: add patch 0 design notes and repository navigation |