浏览代码

Merge pull request #47460 from thaJeztah/bump_bolt

vendor: go.etcd.io/bbolt v1.3.9
Sebastiaan van Stijn 1 年之前
父节点
当前提交
b37f8c8070
共有 6 个文件被更改,包括 62 次插入37 次删除
  1. 1 1
      vendor.mod
  2. 2 2
      vendor.sum
  3. 2 13
      vendor/go.etcd.io/bbolt/bolt_openbsd.go
  4. 19 11
      vendor/go.etcd.io/bbolt/bucket.go
  5. 37 9
      vendor/go.etcd.io/bbolt/db.go
  6. 1 1
      vendor/modules.txt

+ 1 - 1
vendor.mod

@@ -92,7 +92,7 @@ require (
 	github.com/vbatts/tar-split v0.11.5
 	github.com/vishvananda/netlink v1.2.1-beta.2
 	github.com/vishvananda/netns v0.0.4
-	go.etcd.io/bbolt v1.3.7
+	go.etcd.io/bbolt v1.3.9
 	go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.46.1
 	go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.46.1
 	go.opentelemetry.io/otel v1.21.0

+ 2 - 2
vendor.sum

@@ -1322,8 +1322,8 @@ go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
 go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
 go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ=
 go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4=
-go.etcd.io/bbolt v1.3.7 h1:j+zJOnnEjF/kyHlDDgGnVL/AIqIJPq8UoB2GSNfkUfQ=
-go.etcd.io/bbolt v1.3.7/go.mod h1:N9Mkw9X8x5fupy0IKsmuqVtoGDyxsaDlbk4Rd05IAQw=
+go.etcd.io/bbolt v1.3.9 h1:8x7aARPEXiXbHmtUwAIv7eV2fQFHrLLavdiJ3uzJXoI=
+go.etcd.io/bbolt v1.3.9/go.mod h1:zaO32+Ti0PK1ivdPtgMESzuzL2VPoIG1PCQNvOdo/dE=
 go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg=
 go.etcd.io/etcd/api/v3 v3.5.6/go.mod h1:KFtNaxGDw4Yx/BA4iPPwevUTAuqcsPxzyX8PHydchN8=
 go.etcd.io/etcd/client/pkg/v3 v3.5.6 h1:TXQWYceBKqLp4sa87rcPs11SXxUA/mHwH975v+BDvLU=

+ 2 - 13
vendor/go.etcd.io/bbolt/bolt_openbsd.go

@@ -1,22 +1,11 @@
 package bbolt
 
 import (
-	"syscall"
-	"unsafe"
-)
-
-const (
-	msAsync      = 1 << iota // perform asynchronous writes
-	msSync                   // perform synchronous writes
-	msInvalidate             // invalidate cached data
+	"golang.org/x/sys/unix"
 )
 
 func msync(db *DB) error {
-	_, _, errno := syscall.Syscall(syscall.SYS_MSYNC, uintptr(unsafe.Pointer(db.data)), uintptr(db.datasz), msInvalidate)
-	if errno != 0 {
-		return errno
-	}
-	return nil
+	return unix.Msync(db.data[:db.datasz], unix.MS_INVALIDATE)
 }
 
 func fdatasync(db *DB) error {

+ 19 - 11
vendor/go.etcd.io/bbolt/bucket.go

@@ -162,12 +162,17 @@ func (b *Bucket) CreateBucket(key []byte) (*Bucket, error) {
 		return nil, ErrBucketNameRequired
 	}
 
+	// Insert into node.
+	// Tip: Use a new variable `newKey` instead of reusing the existing `key` to prevent
+	// it from being marked as leaking, and accordingly cannot be allocated on stack.
+	newKey := cloneBytes(key)
+
 	// Move cursor to correct position.
 	c := b.Cursor()
-	k, _, flags := c.seek(key)
+	k, _, flags := c.seek(newKey)
 
 	// Return an error if there is an existing key.
-	if bytes.Equal(key, k) {
+	if bytes.Equal(newKey, k) {
 		if (flags & bucketLeafFlag) != 0 {
 			return nil, ErrBucketExists
 		}
@@ -182,16 +187,14 @@ func (b *Bucket) CreateBucket(key []byte) (*Bucket, error) {
 	}
 	var value = bucket.write()
 
-	// Insert into node.
-	key = cloneBytes(key)
-	c.node().put(key, key, value, 0, bucketLeafFlag)
+	c.node().put(newKey, newKey, value, 0, bucketLeafFlag)
 
 	// Since subbuckets are not allowed on inline buckets, we need to
 	// dereference the inline page, if it exists. This will cause the bucket
 	// to be treated as a regular, non-inline bucket for the rest of the tx.
 	b.page = nil
 
-	return b.Bucket(key), nil
+	return b.Bucket(newKey), nil
 }
 
 // CreateBucketIfNotExists creates a new bucket if it doesn't already exist and returns a reference to it.
@@ -288,18 +291,23 @@ func (b *Bucket) Put(key []byte, value []byte) error {
 		return ErrValueTooLarge
 	}
 
+	// Insert into node.
+	// Tip: Use a new variable `newKey` instead of reusing the existing `key` to prevent
+	// it from being marked as leaking, and accordingly cannot be allocated on stack.
+	newKey := cloneBytes(key)
+
 	// Move cursor to correct position.
 	c := b.Cursor()
-	k, _, flags := c.seek(key)
+	k, _, flags := c.seek(newKey)
 
 	// Return an error if there is an existing key with a bucket value.
-	if bytes.Equal(key, k) && (flags&bucketLeafFlag) != 0 {
+	if bytes.Equal(newKey, k) && (flags&bucketLeafFlag) != 0 {
 		return ErrIncompatibleValue
 	}
 
-	// Insert into node.
-	key = cloneBytes(key)
-	c.node().put(key, key, value, 0, 0)
+	// gofail: var beforeBucketPut struct{}
+
+	c.node().put(newKey, newKey, value, 0, 0)
 
 	return nil
 }

+ 37 - 9
vendor/go.etcd.io/bbolt/db.go

@@ -57,6 +57,12 @@ const (
 // All data access is performed through transactions which can be obtained through the DB.
 // All the functions on DB will return a ErrDatabaseNotOpen if accessed before Open() is called.
 type DB struct {
+	// Put `stats` at the first field to ensure it's 64-bit aligned. Note that
+	// the first word in an allocated struct can be relied upon to be 64-bit
+	// aligned. Refer to https://pkg.go.dev/sync/atomic#pkg-note-BUG. Also
+	// refer to discussion in https://github.com/etcd-io/bbolt/issues/577.
+	stats Stats
+
 	// When enabled, the database will perform a Check() after every commit.
 	// A panic is issued if the database is in an inconsistent state. This
 	// flag has a large performance impact so it should only be used for
@@ -147,7 +153,6 @@ type DB struct {
 	opened   bool
 	rwtx     *Tx
 	txs      []*Tx
-	stats    Stats
 
 	freelist     *freelist
 	freelistLoad sync.Once
@@ -424,7 +429,7 @@ func (db *DB) hasSyncedFreelist() bool {
 
 // mmap opens the underlying memory-mapped file and initializes the meta references.
 // minsz is the minimum size that the new mmap can be.
-func (db *DB) mmap(minsz int) error {
+func (db *DB) mmap(minsz int) (err error) {
 	db.mmaplock.Lock()
 	defer db.mmaplock.Unlock()
 
@@ -459,17 +464,27 @@ func (db *DB) mmap(minsz int) error {
 	}
 
 	// Unmap existing data before continuing.
-	if err := db.munmap(); err != nil {
+	if err = db.munmap(); err != nil {
 		return err
 	}
 
 	// Memory-map the data file as a byte slice.
 	// gofail: var mapError string
 	// return errors.New(mapError)
-	if err := mmap(db, size); err != nil {
+	if err = mmap(db, size); err != nil {
 		return err
 	}
 
+	// Perform unmmap on any error to reset all data fields:
+	// dataref, data, datasz, meta0 and meta1.
+	defer func() {
+		if err != nil {
+			if unmapErr := db.munmap(); unmapErr != nil {
+				err = fmt.Errorf("%w; rollback unmap also failed: %v", err, unmapErr)
+			}
+		}
+	}()
+
 	if db.Mlock {
 		// Don't allow swapping of data file
 		if err := db.mlock(fileSize); err != nil {
@@ -553,6 +568,8 @@ func (db *DB) mmapSize(size int) (int, error) {
 }
 
 func (db *DB) munlock(fileSize int) error {
+	// gofail: var munlockError string
+	// return errors.New(munlockError)
 	if err := munlock(db, fileSize); err != nil {
 		return fmt.Errorf("munlock error: " + err.Error())
 	}
@@ -560,6 +577,8 @@ func (db *DB) munlock(fileSize int) error {
 }
 
 func (db *DB) mlock(fileSize int) error {
+	// gofail: var mlockError string
+	// return errors.New(mlockError)
 	if err := mlock(db, fileSize); err != nil {
 		return fmt.Errorf("mlock error: " + err.Error())
 	}
@@ -649,9 +668,10 @@ func (db *DB) close() error {
 	// Clear ops.
 	db.ops.writeAt = nil
 
+	var errs []error
 	// Close the mmap.
 	if err := db.munmap(); err != nil {
-		return err
+		errs = append(errs, err)
 	}
 
 	// Close file handles.
@@ -660,18 +680,22 @@ func (db *DB) close() error {
 		if !db.readOnly {
 			// Unlock the file.
 			if err := funlock(db); err != nil {
-				return fmt.Errorf("bolt.Close(): funlock error: %w", err)
+				errs = append(errs, fmt.Errorf("bolt.Close(): funlock error: %w", err))
 			}
 		}
 
 		// Close the file descriptor.
 		if err := db.file.Close(); err != nil {
-			return fmt.Errorf("db file close: %s", err)
+			errs = append(errs, fmt.Errorf("db file close: %w", err))
 		}
 		db.file = nil
 	}
 
 	db.path = ""
+
+	if len(errs) > 0 {
+		return errs[0]
+	}
 	return nil
 }
 
@@ -1263,6 +1287,12 @@ var DefaultOptions = &Options{
 
 // Stats represents statistics about the database.
 type Stats struct {
+	// Put `TxStats` at the first field to ensure it's 64-bit aligned. Note
+	// that the first word in an allocated struct can be relied upon to be
+	// 64-bit aligned. Refer to https://pkg.go.dev/sync/atomic#pkg-note-BUG.
+	// Also refer to discussion in https://github.com/etcd-io/bbolt/issues/577.
+	TxStats TxStats // global, ongoing stats.
+
 	// Freelist stats
 	FreePageN     int // total number of free pages on the freelist
 	PendingPageN  int // total number of pending pages on the freelist
@@ -1272,8 +1302,6 @@ type Stats struct {
 	// Transaction stats
 	TxN     int // total number of started read transactions
 	OpenTxN int // number of currently open read transactions
-
-	TxStats TxStats // global, ongoing stats.
 }
 
 // Sub calculates and returns the difference between two sets of database stats.

+ 1 - 1
vendor/modules.txt

@@ -1120,7 +1120,7 @@ github.com/zmap/zlint/v3/lints/etsi
 github.com/zmap/zlint/v3/lints/mozilla
 github.com/zmap/zlint/v3/lints/rfc
 github.com/zmap/zlint/v3/util
-# go.etcd.io/bbolt v1.3.7
+# go.etcd.io/bbolt v1.3.9
 ## explicit; go 1.17
 go.etcd.io/bbolt
 # go.etcd.io/etcd/client/pkg/v3 v3.5.6