From: Pascal Stumpf Subject: Re: Update: prometheus to 3.5.1 To: ports@openbsd.org Date: Wed, 25 Mar 2026 21:02:18 +0100 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 >