Index | Thread | Search

From:
Pascal Stumpf <pascal@stumpf.co>
Subject:
Re: Update: prometheus to 3.5.1
To:
ports@openbsd.org
Date:
Wed, 25 Mar 2026 21:02:18 +0100

Download raw body.

Thread
On Wed, 25 Mar 2026 10:50:46 +0100, Claudio Jeker wrote:
> I spent the last few days improving the mmap_openbsd diff to also cover
> the chunks. This should fix a frequent panic like this one:
> 	panic: corruption in head chunk file /var/prometheus/chunks_head/001099: checksum mismatch expected:0, actual:d096d996
> 
> I had to fiddle a lot in tsdb/chunks to make this work and the MmapWriter
> code had to be seriously adjusted so that performance did not tank.
> One of the main issues is mmap.resize which does munmap / mmap dances that
> very much show how horribly inefficent munmap is on OpenBSD. To prevent
> excess resize calls I preallocate the mmaps to the maximum size.
> Also the number of msync(2) calls has been reduced as much as possible
> since those trigger similarly inefficent code paths as munmap.
> In most cases there is no need to msync(2) since all mmaps use the same
> backing uvm_object and so the read-only mappings will see the changes
> without msync(2).
> 
> This seems to be stable on my "production" system and the performance
> seems to be ok for my case.


>> Fetch https://www.zyd.ch/distfiles/prometheus-vendor-3.5.1.tar.gz
prometheus-vendor-3.5.... 100% |************************| 16126 KB
00:01    
>> Size does not match for prometheus-vendor-3.5.1.tar.g


> -- 
> :wq Claudio
> 
> Index: Makefile
> ===================================================================
> RCS file: /cvs/ports/sysutils/prometheus/Makefile,v
> diff -u -p -r1.23 Makefile
> --- Makefile	25 Sep 2023 17:07:36 -0000	1.23
> +++ Makefile	23 Mar 2026 21:46:40 -0000
> @@ -1,6 +1,6 @@
>  COMMENT =		systems monitoring and alerting toolkit
>  
> -V =			2.37.9
> +V =			3.5.1
>  GH_ACCOUNT =		prometheus
>  GH_PROJECT =		prometheus
>  GH_TAGNAME =		v${V}
> @@ -29,27 +29,20 @@ USE_GMAKE =		Yes
>  MODULES =		lang/go
>  MODGO_GOPATH =		${MODGO_WORKSPACE}
>  
> -post-extract:
> -	mv ${WRKDIR}/static/react ${WRKDIST}/web/ui/static/
> -
>  # promu doesn't like the default PREFIX
>  do-build:
>  	cd ${WRKSRC} && \
>  	${MAKE_ENV} GOMAXPROCS=${MAKE_JOBS} PREFIX=. ${MAKE_PROGRAM} \
> +	    PREBUILT_ASSETS_STATIC_DIR=${WRKDIR}/static \
>  	    PROMU="${LOCALBASE}/bin/promu -v" build
>  
>  do-install:
>  	${INSTALL_DATA_DIR} ${WRKINST}/${SYSCONFDIR}/prometheus
>  	${INSTALL_DATA_DIR} ${WRKINST}/${LOCALSTATEDIR}/prometheus
>  	${INSTALL_DATA_DIR} ${PREFIX}/share/doc/prometheus
> -	${INSTALL_DATA_DIR} ${PREFIX}/share/examples/prometheus/consoles
> -	${INSTALL_DATA_DIR} ${PREFIX}/share/examples/prometheus/console_libraries
> +	${INSTALL_DATA_DIR} ${PREFIX}/share/examples/prometheus
>  	${INSTALL_PROGRAM} ${WRKSRC}/prometheus ${PREFIX}/bin
>  	${INSTALL_PROGRAM} ${WRKSRC}/promtool ${PREFIX}/bin
> -	${INSTALL_DATA} ${WRKSRC}/consoles/* \
> -		${PREFIX}/share/examples/prometheus/consoles/
> -	${INSTALL_DATA} ${WRKSRC}/console_libraries/{menu.lib,prom.lib} \
> -		${PREFIX}/share/examples/prometheus/console_libraries
>  	${INSTALL_DATA} ${WRKSRC}/documentation/examples/prometheus.yml \
>  		${PREFIX}/share/examples/prometheus/prometheus.yml
>  	${INSTALL_DATA} ${WRKSRC}/LICENSE ${PREFIX}/share/doc/prometheus/
> Index: distinfo
> ===================================================================
> RCS file: /cvs/ports/sysutils/prometheus/distinfo,v
> diff -u -p -r1.12 distinfo
> --- distinfo	6 Sep 2023 10:28:49 -0000	1.12
> +++ distinfo	18 Mar 2026 16:33:34 -0000
> @@ -1,6 +1,6 @@
> -SHA256 (prometheus-2.37.9.tar.gz) = gSoQplOidWqzAzS9TPBmH5TepeWUw3LTPRNwQHRgpGo=
> -SHA256 (prometheus-vendor-2.37.9.tar.gz) = ea+tEdN2yBEMBYY78U6tPOLI7uorbEhNL3o5/JTxaPI=
> -SHA256 (prometheus-web-ui-2.37.9.tar.gz) = 2z6Ohg/dUEwQ5NxTn1wfxwVrKOPJGAWgSXNxb2lX4MA=
> -SIZE (prometheus-2.37.9.tar.gz) = 6048911
> -SIZE (prometheus-vendor-2.37.9.tar.gz) = 11758451
> -SIZE (prometheus-web-ui-2.37.9.tar.gz) = 2390133
> +SHA256 (prometheus-3.5.1.tar.gz) = rdZ3162GT87UPBS6CNooIT7+ibHje6WSnu9D1bgvaS8=
> +SHA256 (prometheus-vendor-3.5.1.tar.gz) = SfhHWwxq4/bzMvTfN9dn9IgxqNpXpzkL+0YczqKvp0E=
> +SHA256 (prometheus-web-ui-3.5.1.tar.gz) = 1Cvm4TYLCadGMAKBj6uviDRzawIm6S7guO0SUQwIsgY=
> +SIZE (prometheus-3.5.1.tar.gz) = 5129927
> +SIZE (prometheus-vendor-3.5.1.tar.gz) = 16523299
> +SIZE (prometheus-web-ui-3.5.1.tar.gz) = 3487629
> Index: patches/patch-Makefile
> ===================================================================
> RCS file: patches/patch-Makefile
> diff -N patches/patch-Makefile
> --- patches/patch-Makefile	28 Feb 2023 17:54:21 -0000	1.7
> +++ /dev/null	1 Jan 1970 00:00:00 -0000
> @@ -1,23 +0,0 @@
> -The react build is provided via extra distfile
> -
> -Index: Makefile
> ---- Makefile.orig
> -+++ Makefile
> -@@ -83,7 +83,7 @@ ui-lint:
> - 	cd $(UI_PATH) && npm run lint
> - 
> - .PHONY: assets
> --assets: ui-install ui-build
> -+assets:
> - 
> - .PHONY: assets-compress
> - assets-compress: assets
> -@@ -124,7 +124,7 @@ plugins/plugins.go: plugins.yml plugins/generate.go
> - plugins: plugins/plugins.go
> - 
> - .PHONY: build
> --build: assets npm_licenses assets-compress common-build plugins
> -+build: assets-compress common-build plugins
> - 
> - .PHONY: bench_tsdb
> - bench_tsdb: $(PROMU)
> Index: patches/patch-Makefile_common
> ===================================================================
> RCS file: /cvs/ports/sysutils/prometheus/patches/patch-Makefile_common,v
> diff -u -p -r1.7 patch-Makefile_common
> --- patches/patch-Makefile_common	28 Feb 2023 17:54:21 -0000	1.7
> +++ patches/patch-Makefile_common	18 Mar 2026 15:27:52 -0000
> @@ -3,7 +3,7 @@ Don't fetch promu form internet. This is
>  Index: Makefile.common
>  --- Makefile.common.orig
>  +++ Makefile.common
> -@@ -232,11 +232,7 @@ common-docker-manifest:
> +@@ -247,11 +247,7 @@ common-docker-manifest:
>   promu: $(PROMU)
>   
>   $(PROMU):
> @@ -14,5 +14,5 @@ Index: Makefile.common
>  -	rm -r $(PROMU_TMP)
>  +	@true
>   
> - .PHONY: proto
> - proto:
> + .PHONY: common-proto
> + common-proto:
> Index: patches/patch-_promu_yml
> ===================================================================
> RCS file: /cvs/ports/sysutils/prometheus/patches/patch-_promu_yml,v
> diff -u -p -r1.6 patch-_promu_yml
> --- patches/patch-_promu_yml	6 Sep 2023 10:28:49 -0000	1.6
> +++ patches/patch-_promu_yml	18 Mar 2026 15:52:51 -0000
> @@ -3,12 +3,11 @@ Don't include user and hostname into bui
>  Index: .promu.yml
>  --- .promu.yml.orig
>  +++ .promu.yml
> -@@ -16,13 +16,13 @@ build:
> +@@ -16,12 +16,13 @@ build:
>               - builtinassets
>           windows:
>               - builtinassets
> --    flags: -a
> -+    flags: -v -a
> ++    flags: -v
>       ldflags: |
>  -        -X github.com/prometheus/common/version.Version={{.Version}}
>  -        -X github.com/prometheus/common/version.Revision={{.Revision}}
> Index: patches/patch-mmap_openbsd
> ===================================================================
> RCS file: /cvs/ports/sysutils/prometheus/patches/patch-mmap_openbsd,v
> diff -u -p -r1.3 patch-mmap_openbsd
> --- patches/patch-mmap_openbsd	15 Jun 2023 08:52:07 -0000	1.3
> +++ patches/patch-mmap_openbsd	25 Mar 2026 09:38:59 -0000
> @@ -1,89 +1,106 @@
> -Diff from https://github.com/prometheus/prometheus/issues/8799
> +Diff from https://github.com/cjeker/prometheus/tree/mmap_openbsd_v351
> +Based on work from https://github.com/prometheus/prometheus/issues/8799
>  and https://github.com/prometheus/prometheus/pull/9085
>  to make tsdb only use mmap and work around missing UBC support.
>  
>  diff --git go.mod go.mod
> -index 39c3fcb5b..760b39a8b 100644
> +index 7a27951ac..eee4405dd 100644
>  --- go.mod
>  +++ go.mod
> -@@ -13,7 +13,6 @@ require (
> - 	github.com/dgryski/go-sip13 v0.0.0-20200911182023-62edffca9245
> - 	github.com/digitalocean/godo v1.81.0
> - 	github.com/docker/docker v20.10.24+incompatible
> --	github.com/edsrzf/mmap-go v1.1.0
> - 	github.com/envoyproxy/go-control-plane v0.10.3
> - 	github.com/envoyproxy/protoc-gen-validate v0.6.7
> - 	github.com/fsnotify/fsnotify v1.5.4
> +@@ -17,7 +17,6 @@ require (
> + 	github.com/dennwc/varint v1.0.0
> + 	github.com/digitalocean/godo v1.152.0
> + 	github.com/docker/docker v28.5.2+incompatible
> +-	github.com/edsrzf/mmap-go v1.2.0
> + 	github.com/envoyproxy/go-control-plane/envoy v1.32.4
> + 	github.com/envoyproxy/protoc-gen-validate v1.2.1
> + 	github.com/facette/natsort v0.0.0-20181210072756-2cd4dd1e2dcb
>  diff --git go.sum go.sum
> -index e7aee4a9b..6b323945d 100644
> +index 8ed834bcf..00ff455ac 100644
>  --- go.sum
>  +++ go.sum
> -@@ -202,8 +202,6 @@ github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5m
> - github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU=
> - github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I=
> - github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M=
> --github.com/edsrzf/mmap-go v1.1.0 h1:6EUwBLQ/Mcr1EYLE4Tn1VdW1A4ckqCQWZBw8Hr0kjpQ=
> --github.com/edsrzf/mmap-go v1.1.0/go.mod h1:19H/e8pUPLicwkyNgOykDXkJ9F0MHE+Z52B8EIth78Q=
> - github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc=
> - github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs=
> - github.com/emicklei/go-restful v2.9.5+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs=
> +@@ -122,8 +122,6 @@ github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKoh
> + github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=
> + github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4=
> + github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
> +-github.com/edsrzf/mmap-go v1.2.0 h1:hXLYlkbaPzt1SaQk+anYwKSRNhufIDCchSPkUD6dD84=
> +-github.com/edsrzf/mmap-go v1.2.0/go.mod h1:19H/e8pUPLicwkyNgOykDXkJ9F0MHE+Z52B8EIth78Q=
> + github.com/emicklei/go-restful/v3 v3.11.0 h1:rAQeMHw1c7zTmncogyy8VvRZwtkmkZ4FxERmMY4rD+g=
> + github.com/emicklei/go-restful/v3 v3.11.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=
> + github.com/envoyproxy/go-control-plane/envoy v1.32.4 h1:jb83lalDRZSpPWW2Z7Mck/8kXZ5CQAFYVjQcdVIr83A=
>  diff --git promql/query_logger.go promql/query_logger.go
> -index 716e7749b..8eb1afce0 100644
> +index c0a70b66d..8aac517e2 100644
>  --- promql/query_logger.go
>  +++ promql/query_logger.go
> -@@ -22,13 +22,13 @@ import (
> +@@ -26,11 +26,11 @@ import (
>   	"time"
>   	"unicode/utf8"
>   
>  -	"github.com/edsrzf/mmap-go"
> - 	"github.com/go-kit/log"
> - 	"github.com/go-kit/log/level"
>  +	"github.com/prometheus/prometheus/tsdb/fileutil"
>   )
>   
>   type ActiveQueryTracker struct {
> --	mmapedFile    []byte
> +-	mmappedFile   []byte
>  +	mw            *fileutil.MmapWriter
>   	getNextIndex  chan int
> - 	logger        log.Logger
> - 	maxConcurrent int
> -@@ -81,7 +81,7 @@ func logUnfinishedQueries(filename string, filesize int, logger log.Logger) {
> + 	logger        *slog.Logger
> + 	closer        io.Closer
> +@@ -87,12 +87,12 @@ func logUnfinishedQueries(filename string, filesize int, logger *slog.Logger) {
> + }
> + 
> + type mmappedFile struct {
> +-	f io.Closer
> +-	m mmap.MMap
> ++	f  io.Closer
> ++	mw *fileutil.MmapWriter
> + }
> + 
> + func (f *mmappedFile) Close() error {
> +-	err := f.m.Unmap()
> ++	err := f.mw.Close()
> + 	if err != nil {
> + 		err = fmt.Errorf("mmappedFile: unmapping: %w", err)
>   	}
> +@@ -103,7 +103,7 @@ func (f *mmappedFile) Close() error {
> + 	return err
>   }
>   
> --func getMMapedFile(filename string, filesize int, logger log.Logger) ([]byte, error) {
> -+func getMMapedFile(filename string, filesize int, logger log.Logger) (*fileutil.MmapWriter, error) {
> +-func getMMappedFile(filename string, filesize int, logger *slog.Logger) ([]byte, io.Closer, error) {
> ++func getMMappedFile(filename string, filesize int, logger *slog.Logger) (*fileutil.MmapWriter, io.Closer, error) {
>   	file, err := os.OpenFile(filename, os.O_CREATE|os.O_RDWR|os.O_TRUNC, 0o666)
>   	if err != nil {
>   		absPath, pathErr := filepath.Abs(filename)
> -@@ -92,19 +92,13 @@ func getMMapedFile(filename string, filesize int, logger log.Logger) ([]byte, er
> - 		return nil, err
> +@@ -114,21 +114,14 @@ func getMMappedFile(filename string, filesize int, logger *slog.Logger) ([]byte,
> + 		return nil, nil, err
>   	}
>   
>  -	err = file.Truncate(int64(filesize))
>  -	if err != nil {
> --		level.Error(logger).Log("msg", "Error setting filesize.", "filesize", filesize, "err", err)
> --		return nil, err
> +-		file.Close()
> +-		logger.Error("Error setting filesize.", "filesize", filesize, "err", err)
> +-		return nil, nil, err
>  -	}
>  -
>  -	fileAsBytes, err := mmap.Map(file, mmap.RDWR, 0)
>  +	mw, err := fileutil.NewMmapWriterWithSize(file, filesize)
>   	if err != nil {
> - 		level.Error(logger).Log("msg", "Failed to mmap", "file", filename, "Attempted size", filesize, "err", err)
> - 		return nil, err
> + 		file.Close()
> + 		logger.Error("Failed to mmap", "file", filename, "Attempted size", filesize, "err", err)
> + 		return nil, nil, err
>   	}
>   
> --	return fileAsBytes, err
> -+	return mw, err
> +-	return fileAsBytes, &mmappedFile{f: file, m: fileAsBytes}, err
> ++	return mw, &mmappedFile{f: file, mw: mw}, err
>   }
>   
> - func NewActiveQueryTracker(localStoragePath string, maxConcurrent int, logger log.Logger) *ActiveQueryTracker {
> -@@ -116,14 +110,17 @@ func NewActiveQueryTracker(localStoragePath string, maxConcurrent int, logger lo
> + func NewActiveQueryTracker(localStoragePath string, maxConcurrent int, logger *slog.Logger) *ActiveQueryTracker {
> +@@ -140,15 +133,18 @@ func NewActiveQueryTracker(localStoragePath string, maxConcurrent int, logger *s
>   	filename, filesize := filepath.Join(localStoragePath, "queries.active"), 1+maxConcurrent*entrySize
>   	logUnfinishedQueries(filename, filesize, logger)
>   
> --	fileAsBytes, err := getMMapedFile(filename, filesize, logger)
> -+	mw, err := getMMapedFile(filename, filesize, logger)
> +-	fileAsBytes, closer, err := getMMappedFile(filename, filesize, logger)
> ++	mw, closer, err := getMMappedFile(filename, filesize, logger)
>   	if err != nil {
>   		panic("Unable to create mmap-ed active query log")
>   	}
> @@ -94,16 +111,19 @@ index 716e7749b..8eb1afce0 100644
>  +		panic("Unable to write mmap-ed active query log")
>  +	}
>   	activeQueryTracker := ActiveQueryTracker{
> --		mmapedFile:    fileAsBytes,
> +-		mmappedFile:   fileAsBytes,
> + 		closer:        closer,
>  +		mw:            mw,
>   		getNextIndex:  make(chan int, maxConcurrent),
>   		logger:        logger,
>   		maxConcurrent: maxConcurrent,
> -@@ -180,19 +177,27 @@ func (tracker ActiveQueryTracker) GetMaxConcurrent() int {
> +@@ -205,19 +201,29 @@ func (tracker ActiveQueryTracker) GetMaxConcurrent() int {
>   }
>   
>   func (tracker ActiveQueryTracker) Delete(insertIndex int) {
> --	copy(tracker.mmapedFile[insertIndex:], strings.Repeat("\x00", entrySize))
> +-	copy(tracker.mmappedFile[insertIndex:], strings.Repeat("\x00", entrySize))
> ++	buf := tracker.mw.Bytes()
> ++	copy(buf[insertIndex:], strings.Repeat("\x00", entrySize))
>  +	_, err := tracker.mw.WriteAt([]byte(strings.Repeat("\x00", entrySize)), int64(insertIndex))
>  +	if err != nil {
>  +		panic("Unable to write mmap-ed active query log")
> @@ -114,7 +134,7 @@ index 716e7749b..8eb1afce0 100644
>   func (tracker ActiveQueryTracker) Insert(ctx context.Context, query string) (int, error) {
>   	select {
>   	case i := <-tracker.getNextIndex:
> --		fileBytes := tracker.mmapedFile
> +-		fileBytes := tracker.mmappedFile
>   		entry := newJSONEntry(query, tracker.logger)
>   		start, end := i, i+entrySize
>   
> @@ -132,20 +152,20 @@ index 716e7749b..8eb1afce0 100644
>   	case <-ctx.Done():
>   		return 0, ctx.Err()
>  diff --git promql/query_logger_test.go promql/query_logger_test.go
> -index ad76fb992..bd92b81af 100644
> +index eb06e513e..ef2f85cfd 100644
>  --- promql/query_logger_test.go
>  +++ promql/query_logger_test.go
> -@@ -19,13 +19,22 @@ import (
> - 	"testing"
> +@@ -21,12 +21,22 @@ import (
>   
>   	"github.com/grafana/regexp"
> -+	"github.com/prometheus/prometheus/tsdb/fileutil"
>   	"github.com/stretchr/testify/require"
> ++
> ++	"github.com/prometheus/prometheus/tsdb/fileutil"
>   )
>   
>   func TestQueryLogging(t *testing.T) {
>  -	fileAsBytes := make([]byte, 4096)
> -+	file, err := ioutil.TempFile("", "mmapedFile")
> ++	file, err := os.CreateTemp("", "mmapedFile")
>  +	require.NoError(t, err)
>  +
>  +	filename := file.Name()
> @@ -155,12 +175,12 @@ index ad76fb992..bd92b81af 100644
>  +	require.NoError(t, err)
>  +
>   	queryLogger := ActiveQueryTracker{
> --		mmapedFile:   fileAsBytes,
> +-		mmappedFile:  fileAsBytes,
>  +		mw:           mw,
>   		logger:       nil,
>   		getNextIndex: make(chan int, 4),
>   	}
> -@@ -45,6 +54,7 @@ func TestQueryLogging(t *testing.T) {
> +@@ -46,6 +56,7 @@ func TestQueryLogging(t *testing.T) {
>   		`^{"query":"","timestamp_sec":\d+}\x00*,$`,
>   		`^{"query":"SpecialCharQuery{host=\\"2132132\\", id=123123}","timestamp_sec":\d+}\x00*,$`,
>   	}
> @@ -168,12 +188,12 @@ index ad76fb992..bd92b81af 100644
>   
>   	// Check for inserts of queries.
>   	for i := 0; i < 4; i++ {
> -@@ -67,9 +77,17 @@ func TestQueryLogging(t *testing.T) {
> +@@ -68,9 +79,17 @@ func TestQueryLogging(t *testing.T) {
>   }
>   
>   func TestIndexReuse(t *testing.T) {
>  -	queryBytes := make([]byte, 1+3*entrySize)
> -+	file, err := ioutil.TempFile("", "mmapedFile")
> ++	file, err := os.CreateTemp("", "mmapedFile")
>  +	require.NoError(t, err)
>  +
>  +	filename := file.Name()
> @@ -183,12 +203,12 @@ index ad76fb992..bd92b81af 100644
>  +	require.NoError(t, err)
>  +
>   	queryLogger := ActiveQueryTracker{
> --		mmapedFile:   queryBytes,
> +-		mmappedFile:  queryBytes,
>  +		mw:           mw,
>   		logger:       nil,
>   		getNextIndex: make(chan int, 3),
>   	}
> -@@ -91,6 +109,7 @@ func TestIndexReuse(t *testing.T) {
> +@@ -92,6 +111,7 @@ func TestIndexReuse(t *testing.T) {
>   		`^{"query":"ThisShouldBeInsertedAtIndex2","timestamp_sec":\d+}\x00*,$`,
>   		`^{"query":"TestQuery3","timestamp_sec":\d+}\x00*,$`,
>   	}
> @@ -196,26 +216,367 @@ index ad76fb992..bd92b81af 100644
>   
>   	// Check all bytes and verify new query was inserted at index 2
>   	for i := 0; i < 3; i++ {
> -@@ -110,10 +129,12 @@ func TestMMapFile(t *testing.T) {
> - 	filename := file.Name()
> - 	defer os.Remove(filename)
> +@@ -109,9 +129,10 @@ func TestMMapFile(t *testing.T) {
> + 	fpath := filepath.Join(dir, "mmappedFile")
> + 	const data = "ab"
>   
> --	fileAsBytes, err := getMMapedFile(filename, 2, nil)
> -+	mw, err := getMMapedFile(filename, 2, nil)
> -+	require.NoError(t, err)
> - 
> -+	fileAsBytes := mw.Bytes()
> -+	_, err = mw.Write([]byte("ab"))
> +-	fileAsBytes, closer, err := getMMappedFile(fpath, 2, nil)
> ++	mw, closer, err := getMMappedFile(fpath, 2, nil)
>   	require.NoError(t, err)
> --	copy(fileAsBytes, "ab")
> +-	copy(fileAsBytes, data)
> ++	buf := mw.Bytes()
> ++	copy(buf, data)
> + 	require.NoError(t, closer.Close())
> + 
> + 	f, err := os.Open(fpath)
> +diff --git tsdb/chunks/chunks.go tsdb/chunks/chunks.go
> +index 034106238..9d9606512 100644
> +--- tsdb/chunks/chunks.go
> ++++ tsdb/chunks/chunks.go
> +@@ -280,7 +280,7 @@ func checkCRC32(data, sum []byte) error {
> + type Writer struct {
> + 	dirFile *os.File
> + 	files   []*os.File
> +-	wbuf    fileutil.BufWriter
> ++	wbuf    fileutil.MmapBufWriter
> + 	n       int64
> + 	crc32   hash.Hash
> + 	buf     [binary.MaxVarintLen32]byte
> +@@ -361,19 +361,18 @@ func (w *Writer) finalizeTail() error {
> + 		return nil
> + 	}
> + 
> ++	off := int64(SegmentHeaderSize)
> ++
> + 	if w.wbuf != nil {
> +-		if err := w.wbuf.Flush(); err != nil {
> ++		// As the file was pre-allocated, we truncate any superfluous zero bytes.
> ++		off = w.wbuf.Offset()
> ++		if err := w.wbuf.Close(); err != nil {
> + 			return err
> + 		}
> + 	}
> + 	if err := tf.Sync(); err != nil {
> + 		return err
> + 	}
> +-	// As the file was pre-allocated, we truncate any superfluous zero bytes.
> +-	off, err := tf.Seek(0, io.SeekCurrent)
> +-	if err != nil {
> +-		return err
> +-	}
> + 	if err := tf.Truncate(off); err != nil {
> + 		return err
> + 	}
> +@@ -387,7 +386,7 @@ func (w *Writer) cut() error {
> + 		return err
> + 	}
> + 
> +-	n, f, _, err := cutSegmentFile(w.dirFile, MagicChunks, chunksFormatV1, w.segmentSize)
> ++	n, f, mw, _, err := cutSegmentFile(w.dirFile, MagicChunks, chunksFormatV1, w.segmentSize)
> + 	if err != nil {
> + 		return err
> + 	}
> +@@ -395,21 +394,11 @@ func (w *Writer) cut() error {
> + 
> + 	w.files = append(w.files, f)
> + 	if w.wbuf != nil {
> +-		if err := w.wbuf.Reset(f); err != nil {
> ++		if err := w.wbuf.Reset(mw); err != nil {
> + 			return err
> + 		}
> + 	} else {
> +-		var (
> +-			wbuf fileutil.BufWriter
> +-			err  error
> +-		)
> +-		size := 8 * 1024 * 1024
> +-		if w.useUncachedIO {
> +-			// Uncached IO is implemented using direct I/O for now.
> +-			wbuf, err = fileutil.NewDirectIOWriter(f, size)
> +-		} else {
> +-			wbuf, err = fileutil.NewBufioWriterWithSeek(f, size)
> +-		}
> ++		wbuf, err := fileutil.NewBufioMmapWriter(mw)
> + 		if err != nil {
> + 			return err
> + 		}
> +@@ -419,20 +408,22 @@ func (w *Writer) cut() error {
> + 	return nil
> + }
> + 
> +-func cutSegmentFile(dirFile *os.File, magicNumber uint32, chunksFormat byte, allocSize int64) (headerSize int, newFile *os.File, seq int, returnErr error) {
> ++func cutSegmentFile(dirFile *os.File, magicNumber uint32, chunksFormat byte, allocSize int64) (headerSize int, newFile *os.File, newMw *fileutil.MmapWriter, seq int, returnErr error) {
> + 	p, seq, err := nextSequenceFile(dirFile.Name())
> + 	if err != nil {
> +-		return 0, nil, 0, fmt.Errorf("next sequence file: %w", err)
> ++		return 0, nil, nil, 0, fmt.Errorf("next sequence file: %w", err)
> + 	}
> + 	ptmp := p + ".tmp"
> +-	f, err := os.OpenFile(ptmp, os.O_WRONLY|os.O_CREATE, 0o666)
> ++	f, err := os.OpenFile(ptmp, os.O_RDWR|os.O_CREATE, 0o666)
> + 	if err != nil {
> +-		return 0, nil, 0, fmt.Errorf("open temp file: %w", err)
> ++		return 0, nil, nil, 0, fmt.Errorf("open temp file: %w", err)
> + 	}
> ++	mw := fileutil.NewMmapWriter(f)
> + 	defer func() {
> + 		if returnErr != nil {
> + 			errs := tsdb_errors.NewMulti(returnErr)
> + 			if f != nil {
> ++				mw.Close()
> + 				errs.Add(f.Close())
> + 			}
> + 			// Calling RemoveAll on a non-existent file does not return error.
> +@@ -442,11 +433,11 @@ func cutSegmentFile(dirFile *os.File, magicNumber uint32, chunksFormat byte, all
> + 	}()
> + 	if allocSize > 0 {
> + 		if err = fileutil.Preallocate(f, allocSize, true); err != nil {
> +-			return 0, nil, 0, fmt.Errorf("preallocate: %w", err)
> ++			return 0, nil, nil, 0, fmt.Errorf("preallocate: %w", err)
> + 		}
> + 	}
> + 	if err = dirFile.Sync(); err != nil {
> +-		return 0, nil, 0, fmt.Errorf("sync directory: %w", err)
> ++		return 0, nil, nil, 0, fmt.Errorf("sync directory: %w", err)
> + 	}
> + 
> + 	// Write header metadata for new file.
> +@@ -454,29 +445,35 @@ func cutSegmentFile(dirFile *os.File, magicNumber uint32, chunksFormat byte, all
> + 	binary.BigEndian.PutUint32(metab[:MagicChunksSize], magicNumber)
> + 	metab[4] = chunksFormat
> + 
> +-	n, err := f.Write(metab)
> ++	n, err := mw.Write(metab)
> + 	if err != nil {
> +-		return 0, nil, 0, fmt.Errorf("write header: %w", err)
> ++		return 0, nil, nil, 0, fmt.Errorf("write header: %w", err)
> ++	}
> ++	if err := mw.Close(); err != nil {
> ++		return 0, nil, nil, 0, fmt.Errorf("close temp mmap: %w", err)
> + 	}
> ++	mw = nil
> + 	if err := f.Close(); err != nil {
> +-		return 0, nil, 0, fmt.Errorf("close temp file: %w", err)
> ++		return 0, nil, nil, 0, fmt.Errorf("close temp file: %w", err)
> + 	}
> + 	f = nil
> + 
> + 	if err := fileutil.Rename(ptmp, p); err != nil {
> +-		return 0, nil, 0, fmt.Errorf("replace file: %w", err)
> ++		return 0, nil, nil, 0, fmt.Errorf("replace file: %w", err)
> + 	}
> + 
> +-	f, err = os.OpenFile(p, os.O_WRONLY, 0o666)
> ++	f, err = os.OpenFile(p, os.O_RDWR, 0o666)
> + 	if err != nil {
> +-		return 0, nil, 0, fmt.Errorf("open final file: %w", err)
> ++		return 0, nil, nil, 0, fmt.Errorf("open final file: %w", err)
> + 	}
> ++	mw, err = fileutil.NewMmapWriterWithSize(f, int(allocSize))
> ++
> + 	// Skip header for further writes.
> + 	offset := int64(n)
> +-	if _, err := f.Seek(offset, 0); err != nil {
> +-		return 0, nil, 0, fmt.Errorf("seek to %d in final file: %w", offset, err)
> ++	if _, err := mw.Seek(offset, 0); err != nil {
> ++		return 0, nil, nil, 0, fmt.Errorf("seek to %d in final file: %w", offset, err)
> + 	}
> +-	return n, f, seq, nil
> ++	return n, f, mw, seq, nil
> + }
> + 
> + func (w *Writer) write(b []byte) error {
> +diff --git tsdb/chunks/head_chunks.go tsdb/chunks/head_chunks.go
> +index 876b42cb2..14fc84af3 100644
> +--- tsdb/chunks/head_chunks.go
> ++++ tsdb/chunks/head_chunks.go
> +@@ -61,6 +61,7 @@ const (
> + 	// MaxHeadChunkMetaSize is the max size of an mmapped chunks minus the chunks data.
> + 	// Max because the uvarint size can be smaller.
> + 	MaxHeadChunkMetaSize = SeriesRefSize + 2*MintMaxtSize + ChunkEncodingSize + MaxChunkLengthFieldSize + CRCSize
> ++	MinHeadChunkMetaSize = SeriesRefSize + 2*MintMaxtSize + ChunkEncodingSize + 1 + CRCSize
> + 	// MinWriteBufferSize is the minimum write buffer size allowed.
> + 	MinWriteBufferSize = 64 * 1024 // 64KB.
> + 	// MaxWriteBufferSize is the maximum write buffer size allowed.
> +@@ -191,14 +192,16 @@ func (f *chunkPos) bytesToWriteForChunk(chkLen uint64) uint64 {
> + // ChunkDiskMapper is for writing the Head block chunks to disk
> + // and access chunks via mmapped files.
> + type ChunkDiskMapper struct {
> ++	// needs to be correctly aligned
> ++	curFileOffset atomic.Uint64 // Bytes written in current open file.
> + 	// Writer.
> + 	dir             *os.File
> + 	writeBufferSize int
> + 
> +-	curFile         *os.File      // File being written to.
> +-	curFileSequence int           // Index of current open file being appended to. 0 if no file is active.
> +-	curFileOffset   atomic.Uint64 // Bytes written in current open file.
> +-	curFileMaxt     int64         // Used for the size retention.
> ++	curFile         *os.File // File being written to.
> ++	curMw           *fileutil.MmapWriter
> ++	curFileSequence int   // Index of current open file being appended to. 0 if no file is active.
> ++	curFileMaxt     int64 // Used for the size retention.
> + 
> + 	// The values in evtlPos represent the file position which will eventually be
> + 	// reached once the content of the write queue has been fully processed.
> +@@ -604,7 +607,7 @@ func (cdm *ChunkDiskMapper) cut() (seq, offset int, returnErr error) {
> + 		return 0, 0, err
> + 	}
> + 
> +-	offset, newFile, seq, err := cutSegmentFile(cdm.dir, MagicHeadChunks, headChunksFormatV1, HeadChunkFilePreallocationSize)
> ++	offset, newFile, newMw, seq, err := cutSegmentFile(cdm.dir, MagicHeadChunks, headChunksFormatV1, HeadChunkFilePreallocationSize)
> + 	if err != nil {
> + 		return 0, 0, err
> + 	}
> +@@ -613,6 +616,7 @@ func (cdm *ChunkDiskMapper) cut() (seq, offset int, returnErr error) {
> + 		// The file should not be closed if there is no error,
> + 		// its kept open in the ChunkDiskMapper.
> + 		if returnErr != nil {
> ++			returnErr = tsdb_errors.NewMulti(returnErr, newMw.Close()).Err()
> + 			returnErr = tsdb_errors.NewMulti(returnErr, newFile.Close()).Err()
> + 		}
> + 	}()
> +@@ -633,10 +637,11 @@ func (cdm *ChunkDiskMapper) cut() (seq, offset int, returnErr error) {
> + 	cdm.readPathMtx.Lock()
> + 	cdm.curFileSequence = seq
> + 	cdm.curFile = newFile
> ++	cdm.curMw = newMw
> + 	if cdm.chkWriter != nil {
> +-		cdm.chkWriter.Reset(newFile)
> ++		cdm.chkWriter.Reset(cdm.curMw)
> + 	} else {
> +-		cdm.chkWriter = bufio.NewWriterSize(newFile, cdm.writeBufferSize)
> ++		cdm.chkWriter = bufio.NewWriterSize(cdm.curMw, cdm.writeBufferSize)
> + 	}
> + 
> + 	cdm.closers[cdm.curFileSequence] = mmapFile
> +@@ -659,10 +664,9 @@ func (cdm *ChunkDiskMapper) finalizeCurFile() error {
> + 		return err
> + 	}
>   
> - 	f, err := os.Open(filename)
> +-	if err := cdm.curFile.Sync(); err != nil {
> ++	if err := cdm.curMw.Close(); err != nil {
> + 		return err
> + 	}
> +-
> + 	return cdm.curFile.Close()
> + }
> + 
> +@@ -774,7 +778,7 @@ func (cdm *ChunkDiskMapper) Chunk(ref ChunkDiskMapperRef) (chunkenc.Chunk, error
> + 		return nil, &CorruptionErr{
> + 			Dir:       cdm.dir.Name(),
> + 			FileIndex: sgmIndex,
> +-			Err:       fmt.Errorf("head chunk file doesn't include enough bytes to read the chunk - required:%v, available:%v", chkDataEnd, mmapFile.byteSlice.Len()),
> ++			Err:       fmt.Errorf("head chunk file doesn't Include enough bytes to read the chunk - required:%v, available:%v", chkDataEnd, mmapFile.byteSlice.Len()),
> + 		}
> + 	}
> + 
> +@@ -834,7 +838,7 @@ func (cdm *ChunkDiskMapper) IterateAllChunks(f func(seriesRef HeadSeriesRef, chu
> + 		}
> + 		idx := HeadChunkFileHeaderSize
> + 		for idx < fileEnd {
> +-			if fileEnd-idx < MaxHeadChunkMetaSize {
> ++			if fileEnd-idx < MinHeadChunkMetaSize {
> + 				// Check for all 0s which marks the end of the file.
> + 				allZeros := true
> + 				for _, b := range mmapFile.byteSlice.Range(idx, fileEnd) {
> +@@ -851,7 +855,7 @@ func (cdm *ChunkDiskMapper) IterateAllChunks(f func(seriesRef HeadSeriesRef, chu
> + 					Dir:       cdm.dir.Name(),
> + 					FileIndex: segID,
> + 					Err: fmt.Errorf("head chunk file has some unread data, but doesn't include enough bytes to read the chunk header"+
> +-						" - required:%v, available:%v, file:%d", idx+MaxHeadChunkMetaSize, fileEnd, segID),
> ++						" - required:%v, available:%v, file:%d cur %d", idx+MinHeadChunkMetaSize, fileEnd, segID, cdm.curFileSequence),
> + 				}
> + 			}
> + 			chunkRef := newChunkDiskMapperRef(uint64(segID), uint64(idx))
> +@@ -886,7 +890,7 @@ func (cdm *ChunkDiskMapper) IterateAllChunks(f func(seriesRef HeadSeriesRef, chu
> + 				return &CorruptionErr{
> + 					Dir:       cdm.dir.Name(),
> + 					FileIndex: segID,
> +-					Err:       fmt.Errorf("head chunk file doesn't include enough bytes to read the chunk header - required:%v, available:%v, file:%d", idx+CRCSize, fileEnd, segID),
> ++					Err:       fmt.Errorf("head chunk file doesn't include enough bytes to read the crc32 sum - required:%v, available:%v, hcf: %v, srs: %v, mms: %v, ces: %v, n: %v dataLen: %v, numSamples: %v, file:%d cur:%d", idx+CRCSize, fileEnd, HeadChunkFileHeaderSize, SeriesRefSize, MintMaxtSize, ChunkEncodingSize, n, dataLen, numSamples, segID, cdm.curFileSequence),
> + 				}
> + 			}
> + 
> +diff --git tsdb/chunks/head_chunks_openbsd.go tsdb/chunks/head_chunks_openbsd.go
> +new file mode 100644
> +index 000000000..05e308427
> +--- /dev/null
> ++++ tsdb/chunks/head_chunks_openbsd.go
> +@@ -0,0 +1,18 @@
> ++// Copyright 2020 The Prometheus Authors
> ++// Licensed under the Apache License, Version 2.0 (the "License");
> ++// you may not use this file except in compliance with the License.
> ++// You may obtain a copy of the License at
> ++//
> ++// http://www.apache.org/licenses/LICENSE-2.0
> ++//
> ++// Unless required by applicable law or agreed to in writing, software
> ++// distributed under the License is distributed on an "AS IS" BASIS,
> ++// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
> ++// See the License for the specific language governing permissions and
> ++// limitations under the License.
> ++
> ++package chunks
> ++
> ++// HeadChunkFilePreallocationSize is the size to which the m-map file should be preallocated when a new file is cut.
> ++// For OpenBSD use the MaxHeadChunkFileSize for performance reasons
> ++var HeadChunkFilePreallocationSize int64 = MaxHeadChunkFileSize
> +diff --git tsdb/chunks/head_chunks_other.go tsdb/chunks/head_chunks_other.go
> +index f30c5e55e..6e82d73f4 100644
> +--- tsdb/chunks/head_chunks_other.go
> ++++ tsdb/chunks/head_chunks_other.go
> +@@ -11,7 +11,7 @@
> + // See the License for the specific language governing permissions and
> + // limitations under the License.
> + 
> +-//go:build !windows
> ++//go:build !windows && !openbsd
> + 
> + package chunks
> + 
> +diff --git tsdb/chunks/head_chunks_test.go tsdb/chunks/head_chunks_test.go
> +index 68742471e..a3dda8b0e 100644
> +--- tsdb/chunks/head_chunks_test.go
> ++++ tsdb/chunks/head_chunks_test.go
> +@@ -26,6 +26,7 @@ import (
> + 	"github.com/stretchr/testify/require"
> + 
> + 	"github.com/prometheus/prometheus/tsdb/chunkenc"
> ++	"github.com/prometheus/prometheus/tsdb/fileutil"
> + )
> + 
> + var writeQueueSize int
> +@@ -131,7 +132,7 @@ func TestChunkDiskMapper_WriteChunk_Chunk_IterateChunks(t *testing.T) {
> + 	require.Len(t, hrw.mmappedChunkFiles, 3, "expected 3 mmapped files, got %d", len(hrw.mmappedChunkFiles))
> + 	require.Len(t, hrw.closers, len(hrw.mmappedChunkFiles))
> + 
> +-	actualBytes, err := os.ReadFile(firstFileName)
> ++	actualBytes, err := mmapReadFile(firstFileName)
>   	require.NoError(t, err)
> + 
> + 	// Check header of the segment file.
> +@@ -581,3 +582,15 @@ func createChunk(t *testing.T, idx int, hrw *ChunkDiskMapper) (seriesRef HeadSer
> + 	<-awaitCb
> + 	return
> + }
> ++
> ++func mmapReadFile(path string) ([]byte, error) {
> ++	var b []byte
> ++	m, err := fileutil.OpenMmapFile(path)
> ++	if err != nil {
> ++		return nil, err
> ++	}
> ++	bb := m.Bytes()
> ++	b = append(b, bb...)
> ++	m.Close()
> ++	return b, nil
> ++}
>  diff --git tsdb/fileutil/mmap.go tsdb/fileutil/mmap.go
> -index 4dbca4f97..e1c522472 100644
> +index 782ff27ec..15590e2e3 100644
>  --- tsdb/fileutil/mmap.go
>  +++ tsdb/fileutil/mmap.go
> -@@ -20,8 +20,31 @@ import (
> +@@ -19,8 +19,31 @@ import (
>   )
>   
>   type MmapFile struct {
> @@ -236,40 +597,36 @@ index 4dbca4f97..e1c522472 100644
>  +	if size <= 0 {
>  +		info, err := f.Stat()
>  +		if err != nil {
> -+			return nil, errors.Wrap(err, "stat")
> ++			return nil, fmt.Errorf("stat: %w", err)
>  +		}
>  +		size = int(info.Size())
>  +	}
>  +
>  +	b, err := mmapRw(f, size)
>  +	if err != nil {
> -+		return nil, errors.Wrapf(err, "mmap, size %d", size)
> ++		return nil, fmt.Errorf("mmap, size %d: %w", size, err)
>  +	}
>  +	return &MmapFile{f: f, b: b, rw: true}, nil
>   }
>   
>   func OpenMmapFile(path string) (*MmapFile, error) {
> -@@ -46,22 +69,53 @@ func OpenMmapFileWithSize(path string, size int) (mf *MmapFile, retErr error) {
> +@@ -45,22 +68,49 @@ func OpenMmapFileWithSize(path string, size int) (mf *MmapFile, retErr error) {
>   		size = int(info.Size())
>   	}
>   
>  -	b, err := mmap(f, size)
>  +	b, err := mmapRo(f, size)
>   	if err != nil {
> - 		return nil, errors.Wrapf(err, "mmap, size %d", size)
> + 		return nil, fmt.Errorf("mmap, size %d: %w", size, err)
>   	}
>  +	return &MmapFile{f: f, b: b, closeFile: true}, nil
>  +}
>   
>  -	return &MmapFile{f: f, b: b}, nil
>  +func (f *MmapFile) resize(size int) error {
> -+	err := f.Sync()
> ++	err := munmap(f.b)
>  +	if err != nil {
> -+		return errors.Wrap(err, "resize sync")
> -+	}
> -+	err = munmap(f.b)
> -+	if err != nil {
> -+		return errors.Wrap(err, "resize munmap")
> ++		return fmt.Errorf("resize munmap: %w", err)
>  +	}
>  +	var b []byte
>  +	if f.rw {
> @@ -278,7 +635,7 @@ index 4dbca4f97..e1c522472 100644
>  +		b, err = mmapRo(f.f, size)
>  +	}
>  +	if err != nil {
> -+		return errors.Wrap(err, "resize mmap")
> ++		return fmt.Errorf("resize mmap: %w", err)
>  +	}
>  +	f.b = b
>  +	return nil
> @@ -296,13 +653,13 @@ index 4dbca4f97..e1c522472 100644
>   
>   	if err0 != nil {
>  -		return err0
> -+		return errors.Wrap(err0, "close sync")
> ++		return fmt.Errorf("close sync: %w", err0)
>  +	}
>  +	if err1 != nil {
> -+		return errors.Wrap(err1, "close munmap")
> ++		return fmt.Errorf("close munmap: %w", err1)
>  +	}
>  +	if err2 != nil {
> -+		return errors.Wrap(err2, "close file")
> ++		return fmt.Errorf("close file: %w", err2)
>   	}
>  -	return err1
>  +	return nil
> @@ -368,10 +725,10 @@ index 000000000..31fd98e6d
>  +	return nil
>  +}
>  diff --git tsdb/fileutil/mmap_unix.go tsdb/fileutil/mmap_unix.go
> -index 1fd7f48ff..c83a32011 100644
> +index 3d15e1a8c..9a7c62816 100644
>  --- tsdb/fileutil/mmap_unix.go
>  +++ tsdb/fileutil/mmap_unix.go
> -@@ -22,10 +22,14 @@ import (
> +@@ -21,10 +21,14 @@ import (
>   	"golang.org/x/sys/unix"
>   )
>   
> @@ -421,10 +778,10 @@ index b94226412..9caf36622 100644
>   	if h == 0 {
>  diff --git tsdb/fileutil/writer.go tsdb/fileutil/writer.go
>  new file mode 100644
> -index 000000000..86c1504e4
> +index 000000000..f50a2fa84
>  --- /dev/null
>  +++ tsdb/fileutil/writer.go
> -@@ -0,0 +1,156 @@
> +@@ -0,0 +1,203 @@
>  +// Copyright 2021 The Prometheus Authors
>  +// Licensed under the Apache License, Version 2.0 (the "License");
>  +// you may not use this file except in compliance with the License.
> @@ -456,6 +813,50 @@ index 000000000..86c1504e4
>  +	rpos int
>  +}
>  +
> ++type MmapBufWriter interface {
> ++	Write([]byte) (int, error)
> ++	Close() error
> ++	Offset() int64
> ++	Reset(mw *MmapWriter) error
> ++}
> ++
> ++type mmapBufioWriter struct {
> ++	mw *MmapWriter
> ++}
> ++
> ++func (m *mmapBufioWriter) Write(b []byte) (int, error) {
> ++	return m.mw.Write(b)
> ++}
> ++
> ++func (m *mmapBufioWriter) Close() error {
> ++	return m.mw.Close()
> ++}
> ++
> ++func (m *mmapBufioWriter) Offset() int64 {
> ++	off, _ := m.mw.Seek(0, io.SeekCurrent)
> ++	return off
> ++}
> ++
> ++func (m *mmapBufioWriter) Reset(mw *MmapWriter) error {
> ++	if err := m.mw.Close(); err != nil {
> ++		return err
> ++	}
> ++	m.mw = mw
> ++	return nil
> ++}
> ++
> ++func NewBufioMmapWriter(mw *MmapWriter) (MmapBufWriter, error) {
> ++	if mw.mf == nil {
> ++		mf, err := OpenRwMmapFromFile(mw.f, 0)
> ++		if err != nil {
> ++			return nil, err
> ++		}
> ++		mw.mf = mf
> ++		mw.buf = mf.Bytes()
> ++	}
> ++	return &mmapBufioWriter{mw}, nil
> ++}
> ++
>  +func NewMmapWriter(f *os.File) *MmapWriter {
>  +	return &MmapWriter{f: f}
>  +}
> @@ -480,7 +881,9 @@ index 000000000..86c1504e4
>  +func (mw *MmapWriter) Close() error {
>  +	mw.buf = nil
>  +	if mw.mf != nil {
> -+		return mw.mf.Close()
> ++		err := mw.mf.Close()
> ++		mw.mf = nil
> ++		return err
>  +	}
>  +	return nil
>  +}
> @@ -513,20 +916,23 @@ index 000000000..86c1504e4
>  +}
>  +
>  +func (mw *MmapWriter) Seek(offset int64, whence int) (ret int64, err error) {
> -+	var abs int
> ++	var abs int64
> ++	mw.Lock()
> ++	defer mw.Unlock()
>  +	switch whence {
>  +	case io.SeekStart:
> -+		abs = int(offset)
> ++		abs = offset
> ++	case io.SeekCurrent:
> ++		abs = int64(mw.wpos) + offset
>  +	default:
>  +		return 0, errors.New("invalid whence")
>  +	}
>  +	if abs < 0 {
>  +		return 0, errors.New("negative position")
>  +	}
> -+	mw.Lock()
> -+	defer mw.Unlock()
> -+	mw.rpos = abs
> -+	return offset, nil
> ++	mw.wpos = int(abs)
> ++	mw.rpos = int(abs)
> ++	return abs, nil
>  +}
>  +
>  +func (mw *MmapWriter) Read(p []byte) (n int, err error) {
> @@ -544,12 +950,12 @@ index 000000000..86c1504e4
>  +	mw.Lock()
>  +	defer mw.Unlock()
>  +	if mw.mf == nil {
> -+		err = mw.mmap(len(p))
> ++		err = mw.mmap(mw.wpos + len(p))
>  +		if err != nil {
>  +			return
>  +		}
>  +	}
> -+	if len(p) > len(mw.buf)-mw.wpos {
> ++	if mw.wpos+len(p) > len(mw.buf) {
>  +		err = mw.resize(mw.wpos + len(p))
>  +		if err != nil {
>  +			return
> @@ -558,7 +964,6 @@ index 000000000..86c1504e4
>  +
>  +	n = copy(mw.buf[mw.wpos:], p)
>  +	mw.wpos += n
> -+	err = mw.Sync()
>  +	return
>  +}
>  +
> @@ -578,14 +983,13 @@ index 000000000..86c1504e4
>  +		}
>  +	}
>  +	n = copy(mw.buf[pos:], p)
> -+	err = mw.Sync()
>  +	return
>  +}
>  diff --git tsdb/index/index.go tsdb/index/index.go
> -index 29295c45f..451c80582 100644
> +index edcb92a71..36ba9d291 100644
>  --- tsdb/index/index.go
>  +++ tsdb/index/index.go
> -@@ -257,6 +257,7 @@ func (w *Writer) addPadding(size int) error {
> +@@ -272,6 +272,7 @@ func (w *Writer) addPadding(size int) error {
>   type FileWriter struct {
>   	f    *os.File
>   	fbuf *bufio.Writer
> @@ -593,7 +997,7 @@ index 29295c45f..451c80582 100644
>   	pos  uint64
>   	name string
>   }
> -@@ -266,14 +267,20 @@ func NewFileWriter(name string) (*FileWriter, error) {
> +@@ -281,14 +282,20 @@ func NewFileWriter(name string) (*FileWriter, error) {
>   	if err != nil {
>   		return nil, err
>   	}
> @@ -615,7 +1019,7 @@ index 29295c45f..451c80582 100644
>   func (fw *FileWriter) Pos() uint64 {
>   	return fw.pos
>   }
> -@@ -304,7 +311,7 @@ func (fw *FileWriter) WriteAt(buf []byte, pos uint64) error {
> +@@ -319,7 +326,7 @@ func (fw *FileWriter) WriteAt(buf []byte, pos uint64) error {
>   	if err := fw.Flush(); err != nil {
>   		return err
>   	}
> @@ -624,7 +1028,7 @@ index 29295c45f..451c80582 100644
>   	return err
>   }
>   
> -@@ -326,7 +333,7 @@ func (fw *FileWriter) Close() error {
> +@@ -341,7 +348,7 @@ func (fw *FileWriter) Close() error {
>   	if err := fw.Flush(); err != nil {
>   		return err
>   	}
> @@ -633,7 +1037,7 @@ index 29295c45f..451c80582 100644
>   		return err
>   	}
>   	return fw.f.Close()
> -@@ -987,11 +994,11 @@ func (w *Writer) writePostings() error {
> +@@ -1026,11 +1033,11 @@ func (w *Writer) writePostings() error {
>   	if err := w.fP.Flush(); err != nil {
>   		return err
>   	}
> Index: pkg/PLIST
> ===================================================================
> RCS file: /cvs/ports/sysutils/prometheus/pkg/PLIST,v
> diff -u -p -r1.7 PLIST
> --- pkg/PLIST	8 Nov 2022 11:17:11 -0000	1.7
> +++ pkg/PLIST	18 Mar 2026 15:48:34 -0000
> @@ -8,17 +8,6 @@ share/doc/prometheus/
>  share/doc/prometheus/LICENSE
>  share/doc/prometheus/NOTICE
>  share/examples/prometheus/
> -share/examples/prometheus/console_libraries/
> -share/examples/prometheus/console_libraries/menu.lib
> -share/examples/prometheus/console_libraries/prom.lib
> -share/examples/prometheus/consoles/
> -share/examples/prometheus/consoles/index.html.example
> -share/examples/prometheus/consoles/node-cpu.html
> -share/examples/prometheus/consoles/node-disk.html
> -share/examples/prometheus/consoles/node-overview.html
> -share/examples/prometheus/consoles/node.html
> -share/examples/prometheus/consoles/prometheus-overview.html
> -share/examples/prometheus/consoles/prometheus.html
>  share/examples/prometheus/prometheus.yml
>  @sample ${SYSCONFDIR}/prometheus/prometheus.yml
>  @mode 0755
>