mirror of
https://github.com/openwrt/packages.git
synced 2025-12-21 21:24:31 +04:00
db47: replace with db
There's no need to maintain an old version. Removed all patches as they are all upstream. Import new ones from Arch, Debian, and OpenEmbedded. Signed-off-by: Rosen Penev <rosenp@gmail.com>
This commit is contained in:
@@ -7,24 +7,20 @@
|
||||
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
BASE_VERSION:=4.7.25
|
||||
PKG_NAME:=db
|
||||
PKG_VERSION:=5.3.28
|
||||
PKG_RELEASE:=1
|
||||
|
||||
PKG_NAME:=db47
|
||||
PKG_VERSION:=$(BASE_VERSION).4.NC
|
||||
PKG_RELEASE:=7
|
||||
|
||||
PKG_BUILD_DIR:=$(BUILD_DIR)/db-$(BASE_VERSION).NC
|
||||
PKG_SOURCE:=db-$(BASE_VERSION).NC.tar.gz
|
||||
PKG_SOURCE_URL:=http://download.oracle.com/berkeley-db/
|
||||
PKG_HASH:=cd39c711023ff44c01d3c8ff0323eef7318660772b24f287556e6bf676a12535
|
||||
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
|
||||
PKG_SOURCE_URL:=https://download.oracle.com/berkeley-db/
|
||||
PKG_HASH:=e0a992d740709892e81f9d93f06daf305cf73fb81b545afe72478043172c3628
|
||||
|
||||
PKG_MAINTAINER:=Marcel Denia <naoir@gmx.net>
|
||||
PKG_LICENSE:=Sleepycat
|
||||
PKG_LICENSE_FILES:=LICENSE
|
||||
|
||||
PKG_BUILD_DEPENDS:=libxml2
|
||||
PKG_FIXUP:=autoreconf
|
||||
PKG_LIBTOOL_PATHS:=. build_unix
|
||||
PKG_BUILD_DEPENDS:=libxml2
|
||||
PKG_BUILD_PARALLEL:=1
|
||||
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
@@ -32,26 +28,28 @@ include $(INCLUDE_DIR)/package.mk
|
||||
define Package/libdb47
|
||||
SECTION:=libs
|
||||
CATEGORY:=Libraries
|
||||
TITLE:=Berkeley DB library (4.7)
|
||||
TITLE:=Berkeley DB library
|
||||
URL:=http://www.oracle.com/us/products/database/berkeley-db
|
||||
PROVIDES:=libdb47-full
|
||||
ABI_VERSION:=5
|
||||
endef
|
||||
|
||||
define Package/libdb47/description
|
||||
Berkeley DB library (4.7).
|
||||
Berkeley DB library.
|
||||
endef
|
||||
|
||||
define Package/libdb47xx
|
||||
SECTION:=libs
|
||||
CATEGORY:=Libraries
|
||||
DEPENDS:=+libdb47 +libstdcpp
|
||||
TITLE:=Berkeley DB library (4.7) for C++
|
||||
TITLE:=Berkeley DB library for C++
|
||||
URL:=http://www.oracle.com/us/products/database/berkeley-db
|
||||
PROVIDES:=libdb47xx-full
|
||||
ABI_VERSION:=5
|
||||
endef
|
||||
|
||||
define Package/libdb47xx/description
|
||||
Berkeley DB library (4.7). C++ wrapper.
|
||||
Berkeley DB library C++ wrapper.
|
||||
endef
|
||||
|
||||
CONFIGURE_PATH = build_unix
|
||||
@@ -63,7 +61,6 @@ CONFIGURE_ARGS += \
|
||||
--disable-java \
|
||||
--with-mutex=POSIX/pthreads/library \
|
||||
--disable-tcl \
|
||||
--disable-rpc \
|
||||
--enable-compat185 \
|
||||
--disable-debug \
|
||||
$(if $(CONFIG_PACKAGE_libdb47xx),--enable-cxx,--disable-cxx)
|
||||
19
libs/db/patches/010-fix-parallel-build.patch
Normal file
19
libs/db/patches/010-fix-parallel-build.patch
Normal file
@@ -0,0 +1,19 @@
|
||||
With higher paralelism it sometimes fails with:
|
||||
libtool: link: `util_log.lo' is not a valid libtool object
|
||||
make: *** [db_replicate] Error 1
|
||||
|
||||
Upstream-Status: Inappropriate [as far as open source community is concerned, upstream is dead]
|
||||
|
||||
Signed-off-by: Martin Jansa <Martin.Jansa@gmail.com>
|
||||
|
||||
--- a/dist/Makefile.in
|
||||
+++ b/dist/Makefile.in
|
||||
@@ -1034,7 +1034,7 @@ db_recover: db_recover@o@ util_sig@o@ $(
|
||||
db_recover@o@ util_sig@o@ $(DEF_LIB) $(LIBS)
|
||||
$(POSTLINK) $@
|
||||
|
||||
-db_replicate: db_replicate@o@ util_sig@o@ $(DEF_LIB)
|
||||
+db_replicate: db_replicate@o@ util_log@o@ util_sig@o@ $(DEF_LIB)
|
||||
$(CCLINK) -o $@ $(LDFLAGS) \
|
||||
db_replicate@o@ util_log@o@ util_sig@o@ $(DEF_LIB) $(LIBS)
|
||||
$(POSTLINK) $@
|
||||
@@ -0,0 +1,40 @@
|
||||
From 29621d637e30982489693f2e207ce6a1790e3337 Mon Sep 17 00:00:00 2001
|
||||
From: Khem Raj <raj.khem@gmail.com>
|
||||
Date: Wed, 22 Mar 2017 15:32:26 +0000
|
||||
Subject: [PATCH] atomic: Rename local __atomic_compare_exchange to avoid clash
|
||||
with builtins
|
||||
|
||||
Helps building with clang
|
||||
|
||||
Fixes
|
||||
|
||||
../db-5.3.28/src/dbinc/atomic.h:179:19: error: definition of builtin function '__atomic_compare_exchange'
|
||||
static inline int __atomic_compare_exchange(
|
||||
|
||||
Upstream-Status: Inappropriate [as far as open source community is concerned, upstream is dead]
|
||||
|
||||
Signed-off-by: Khem Raj <raj.khem@gmail.com>
|
||||
---
|
||||
src/dbinc/atomic.h | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
--- a/src/dbinc/atomic.h
|
||||
+++ b/src/dbinc/atomic.h
|
||||
@@ -144,7 +144,7 @@ typedef LONG volatile *interlocked_val;
|
||||
#define atomic_inc(env, p) __atomic_inc(p)
|
||||
#define atomic_dec(env, p) __atomic_dec(p)
|
||||
#define atomic_compare_exchange(env, p, o, n) \
|
||||
- __atomic_compare_exchange((p), (o), (n))
|
||||
+ __db_atomic_compare_exchange((p), (o), (n))
|
||||
static inline int __atomic_inc(db_atomic_t *p)
|
||||
{
|
||||
int temp;
|
||||
@@ -176,7 +176,7 @@ static inline int __atomic_dec(db_atomic
|
||||
* http://gcc.gnu.org/onlinedocs/gcc-4.1.0/gcc/Atomic-Builtins.html
|
||||
* which configure could be changed to use.
|
||||
*/
|
||||
-static inline int __atomic_compare_exchange(
|
||||
+static inline int __db_atomic_compare_exchange(
|
||||
db_atomic_t *p, atomic_value_t oldval, atomic_value_t newval)
|
||||
{
|
||||
atomic_value_t was;
|
||||
@@ -0,0 +1,37 @@
|
||||
From 32e5943a3c4637d39e4d65b544dcb99e280210e3 Mon Sep 17 00:00:00 2001
|
||||
From: Khem Raj <raj.khem@gmail.com>
|
||||
Date: Sun, 23 Jul 2017 10:54:26 -0700
|
||||
Subject: [PATCH] configure: Add explicit tag options to libtool invocation
|
||||
|
||||
This helps cross compile when tag inference via heuristics
|
||||
fail because CC variable is having -fPIE -pie and libtool
|
||||
smartly removes it when building libraries
|
||||
|
||||
Upstream-Status: Inappropriate [as far as open source community is concerned, upstream is dead]
|
||||
|
||||
Signed-off-by: Khem Raj <raj.khem@gmail.com>
|
||||
---
|
||||
dist/configure.ac | 12 ++++++------
|
||||
1 file changed, 6 insertions(+), 6 deletions(-)
|
||||
|
||||
--- a/dist/configure.ac
|
||||
+++ b/dist/configure.ac
|
||||
@@ -366,12 +366,12 @@ LIBTOOL="./libtool"
|
||||
|
||||
INSTALLER="\$(LIBTOOL) --mode=install cp -p"
|
||||
|
||||
-MAKEFILE_CC="\$(LIBTOOL) --mode=compile ${MAKEFILE_CC}"
|
||||
-MAKEFILE_SOLINK="\$(LIBTOOL) --mode=link ${MAKEFILE_CCLINK} -avoid-version"
|
||||
-MAKEFILE_CCLINK="\$(LIBTOOL) --mode=link ${MAKEFILE_CCLINK}"
|
||||
-MAKEFILE_CXX="\$(LIBTOOL) --mode=compile ${MAKEFILE_CXX}"
|
||||
-MAKEFILE_XSOLINK="\$(LIBTOOL) --mode=link ${MAKEFILE_CXXLINK} -avoid-version"
|
||||
-MAKEFILE_CXXLINK="\$(LIBTOOL) --mode=link ${MAKEFILE_CXXLINK}"
|
||||
+MAKEFILE_CC="\$(LIBTOOL) --tag=CC --mode=compile ${MAKEFILE_CC}"
|
||||
+MAKEFILE_SOLINK="\$(LIBTOOL) --tag=CC --mode=link ${MAKEFILE_CCLINK} -avoid-version"
|
||||
+MAKEFILE_CCLINK="\$(LIBTOOL) --tag=CC --mode=link ${MAKEFILE_CCLINK}"
|
||||
+MAKEFILE_CXX="\$(LIBTOOL) --tag=CXX --mode=compile ${MAKEFILE_CXX}"
|
||||
+MAKEFILE_XSOLINK="\$(LIBTOOL) --tag=CXX --mode=link ${MAKEFILE_CXXLINK} -avoid-version"
|
||||
+MAKEFILE_CXXLINK="\$(LIBTOOL) --tag=CXX --mode=link ${MAKEFILE_CXXLINK}"
|
||||
|
||||
|
||||
case "$host_os" in
|
||||
76
libs/db/patches/040-sequence-type.patch
Normal file
76
libs/db/patches/040-sequence-type.patch
Normal file
@@ -0,0 +1,76 @@
|
||||
configure wants to use host-specific types to get a 64-bit integer in db.h
|
||||
instead of using an alias such as int64_t. This means that the header differs
|
||||
in multilib environments for no good reason, so replace the type with the alias
|
||||
in stdint.h.
|
||||
|
||||
This then breaks the overly complicated type check but as we know that int64_t
|
||||
exists and works, we can just delete that.
|
||||
|
||||
Upstream-Status: Inappropriate [as far as open source community is concerned, upstream is dead]
|
||||
Signed-off-by: Ross Burton <ross.burton@intel.com>
|
||||
|
||||
--- a/dist/aclocal/sequence.m4
|
||||
+++ b/dist/aclocal/sequence.m4
|
||||
@@ -21,14 +21,14 @@ AC_DEFUN(AM_SEQUENCE_CONFIGURE, [
|
||||
db_cv_seq_type="no"
|
||||
if test "$db_cv_build_sequence" = "yes" -a\
|
||||
"$ac_cv_sizeof_long" -eq "8"; then
|
||||
- db_cv_seq_type="long"
|
||||
+ db_cv_seq_type="int64_t"
|
||||
db_cv_seq_fmt='"%ld"'
|
||||
db_cv_seq_ufmt='"%lu"'
|
||||
INT64_FMT='#define INT64_FMT "%ld"'
|
||||
UINT64_FMT='#define UINT64_FMT "%lu"'
|
||||
else if test "$db_cv_build_sequence" = "yes" -a\
|
||||
"$ac_cv_sizeof_long_long" -eq "8"; then
|
||||
- db_cv_seq_type="long long"
|
||||
+ db_cv_seq_type="int64_t"
|
||||
db_cv_seq_fmt='"%lld"'
|
||||
db_cv_seq_ufmt='"%llu"'
|
||||
INT64_FMT='#define INT64_FMT "%lld"'
|
||||
@@ -38,44 +38,7 @@ AC_DEFUN(AM_SEQUENCE_CONFIGURE, [
|
||||
fi
|
||||
fi
|
||||
|
||||
- # Test to see if we can declare variables of the appropriate size
|
||||
- # and format them. If we're cross-compiling, all we get is a link
|
||||
- # test, which won't test for the appropriate printf format strings.
|
||||
- if test "$db_cv_build_sequence" = "yes"; then
|
||||
- AC_TRY_RUN([
|
||||
- main() {
|
||||
- $db_cv_seq_type l;
|
||||
- unsigned $db_cv_seq_type u;
|
||||
- char buf@<:@100@:>@;
|
||||
-
|
||||
- buf@<:@0@:>@ = 'a';
|
||||
- l = 9223372036854775807LL;
|
||||
- (void)snprintf(buf, sizeof(buf), $db_cv_seq_fmt, l);
|
||||
- if (strcmp(buf, "9223372036854775807"))
|
||||
- return (1);
|
||||
- u = 18446744073709551615ULL;
|
||||
- (void)snprintf(buf, sizeof(buf), $db_cv_seq_ufmt, u);
|
||||
- if (strcmp(buf, "18446744073709551615"))
|
||||
- return (1);
|
||||
- return (0);
|
||||
- }],, [db_cv_build_sequence="no"],
|
||||
- AC_TRY_LINK(,[
|
||||
- $db_cv_seq_type l;
|
||||
- unsigned $db_cv_seq_type u;
|
||||
- char buf@<:@100@:>@;
|
||||
-
|
||||
- buf@<:@0@:>@ = 'a';
|
||||
- l = 9223372036854775807LL;
|
||||
- (void)snprintf(buf, sizeof(buf), $db_cv_seq_fmt, l);
|
||||
- if (strcmp(buf, "9223372036854775807"))
|
||||
- return (1);
|
||||
- u = 18446744073709551615ULL;
|
||||
- (void)snprintf(buf, sizeof(buf), $db_cv_seq_ufmt, u);
|
||||
- if (strcmp(buf, "18446744073709551615"))
|
||||
- return (1);
|
||||
- return (0);
|
||||
- ],, [db_cv_build_sequence="no"]))
|
||||
- fi
|
||||
+ db_cv_build_sequence="yes"
|
||||
if test "$db_cv_build_sequence" = "yes"; then
|
||||
AC_SUBST(db_seq_decl)
|
||||
db_seq_decl="typedef $db_cv_seq_type db_seq_t;";
|
||||
@@ -0,0 +1,132 @@
|
||||
From a3569f118fd95b7ad41e1a1128e17c0b8928556d Mon Sep 17 00:00:00 2001
|
||||
From: Khem Raj <raj.khem@gmail.com>
|
||||
Date: Sun, 20 Jan 2019 18:30:23 -0800
|
||||
Subject: [PATCH] Fix libc++ compatibility by renaming atomic_init API
|
||||
|
||||
db5 does not build because it is redefining a C++11 standard
|
||||
library identifier, atomic_init(). Therefore prefix all
|
||||
its internal defines with '__db_', to avoid collisions.
|
||||
|
||||
Upstream-Status: Inappropriate [as far as open source community is concerned, upstream is dead]
|
||||
|
||||
Signed-off-by: Khem Raj <raj.khem@gmail.com>
|
||||
---
|
||||
src/dbinc/atomic.h | 4 ++--
|
||||
src/mp/mp_fget.c | 4 ++--
|
||||
src/mp/mp_mvcc.c | 4 ++--
|
||||
src/mp/mp_region.c | 4 ++--
|
||||
src/mutex/mut_method.c | 2 +-
|
||||
src/mutex/mut_tas.c | 4 ++--
|
||||
6 files changed, 11 insertions(+), 11 deletions(-)
|
||||
|
||||
--- a/src/dbinc/atomic.h
|
||||
+++ b/src/dbinc/atomic.h
|
||||
@@ -70,7 +70,7 @@ typedef struct {
|
||||
* These have no memory barriers; the caller must include them when necessary.
|
||||
*/
|
||||
#define atomic_read(p) ((p)->value)
|
||||
-#define atomic_init(p, val) ((p)->value = (val))
|
||||
+#define __db_atomic_init(p, val) ((p)->value = (val))
|
||||
|
||||
#ifdef HAVE_ATOMIC_SUPPORT
|
||||
|
||||
@@ -206,7 +206,7 @@ static inline int __db_atomic_compare_ex
|
||||
#define atomic_dec(env, p) (--(p)->value)
|
||||
#define atomic_compare_exchange(env, p, oldval, newval) \
|
||||
(DB_ASSERT(env, atomic_read(p) == (oldval)), \
|
||||
- atomic_init(p, (newval)), 1)
|
||||
+ __db_atomic_init(p, (newval)), 1)
|
||||
#else
|
||||
#define atomic_inc(env, p) __atomic_inc(env, p)
|
||||
#define atomic_dec(env, p) __atomic_dec(env, p)
|
||||
--- a/src/mp/mp_fget.c
|
||||
+++ b/src/mp/mp_fget.c
|
||||
@@ -649,7 +649,7 @@ alloc: /* Allocate a new buffer header
|
||||
|
||||
/* Initialize enough so we can call __memp_bhfree. */
|
||||
alloc_bhp->flags = 0;
|
||||
- atomic_init(&alloc_bhp->ref, 1);
|
||||
+ __db_atomic_init(&alloc_bhp->ref, 1);
|
||||
#ifdef DIAGNOSTIC
|
||||
if ((uintptr_t)alloc_bhp->buf & (sizeof(size_t) - 1)) {
|
||||
__db_errx(env, DB_STR("3025",
|
||||
@@ -955,7 +955,7 @@ alloc: /* Allocate a new buffer header
|
||||
MVCC_MPROTECT(bhp->buf, mfp->pagesize,
|
||||
PROT_READ);
|
||||
|
||||
- atomic_init(&alloc_bhp->ref, 1);
|
||||
+ __db_atomic_init(&alloc_bhp->ref, 1);
|
||||
MUTEX_LOCK(env, alloc_bhp->mtx_buf);
|
||||
alloc_bhp->priority = bhp->priority;
|
||||
alloc_bhp->pgno = bhp->pgno;
|
||||
--- a/src/mp/mp_mvcc.c
|
||||
+++ b/src/mp/mp_mvcc.c
|
||||
@@ -276,7 +276,7 @@ __memp_bh_freeze(dbmp, infop, hp, bhp, n
|
||||
#else
|
||||
memcpy(frozen_bhp, bhp, SSZA(BH, buf));
|
||||
#endif
|
||||
- atomic_init(&frozen_bhp->ref, 0);
|
||||
+ __db_atomic_init(&frozen_bhp->ref, 0);
|
||||
if (mutex != MUTEX_INVALID)
|
||||
frozen_bhp->mtx_buf = mutex;
|
||||
else if ((ret = __mutex_alloc(env, MTX_MPOOL_BH,
|
||||
@@ -428,7 +428,7 @@ __memp_bh_thaw(dbmp, infop, hp, frozen_b
|
||||
#endif
|
||||
alloc_bhp->mtx_buf = mutex;
|
||||
MUTEX_LOCK(env, alloc_bhp->mtx_buf);
|
||||
- atomic_init(&alloc_bhp->ref, 1);
|
||||
+ __db_atomic_init(&alloc_bhp->ref, 1);
|
||||
F_CLR(alloc_bhp, BH_FROZEN);
|
||||
}
|
||||
|
||||
--- a/src/mp/mp_region.c
|
||||
+++ b/src/mp/mp_region.c
|
||||
@@ -245,7 +245,7 @@ __memp_init(env, dbmp, reginfo_off, htab
|
||||
MTX_MPOOL_FILE_BUCKET, 0, &htab[i].mtx_hash)) != 0)
|
||||
return (ret);
|
||||
SH_TAILQ_INIT(&htab[i].hash_bucket);
|
||||
- atomic_init(&htab[i].hash_page_dirty, 0);
|
||||
+ __db_atomic_init(&htab[i].hash_page_dirty, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -302,7 +302,7 @@ no_prealloc:
|
||||
} else
|
||||
hp->mtx_hash = mtx_base + (i % dbenv->mp_mtxcount);
|
||||
SH_TAILQ_INIT(&hp->hash_bucket);
|
||||
- atomic_init(&hp->hash_page_dirty, 0);
|
||||
+ __db_atomic_init(&hp->hash_page_dirty, 0);
|
||||
#ifdef HAVE_STATISTICS
|
||||
hp->hash_io_wait = 0;
|
||||
hp->hash_frozen = hp->hash_thawed = hp->hash_frozen_freed = 0;
|
||||
--- a/src/mutex/mut_method.c
|
||||
+++ b/src/mutex/mut_method.c
|
||||
@@ -474,7 +474,7 @@ atomic_compare_exchange(env, v, oldval,
|
||||
MUTEX_LOCK(env, mtx);
|
||||
ret = atomic_read(v) == oldval;
|
||||
if (ret)
|
||||
- atomic_init(v, newval);
|
||||
+ __db_atomic_init(v, newval);
|
||||
MUTEX_UNLOCK(env, mtx);
|
||||
|
||||
return (ret);
|
||||
--- a/src/mutex/mut_tas.c
|
||||
+++ b/src/mutex/mut_tas.c
|
||||
@@ -47,7 +47,7 @@ __db_tas_mutex_init(env, mutex, flags)
|
||||
|
||||
#ifdef HAVE_SHARED_LATCHES
|
||||
if (F_ISSET(mutexp, DB_MUTEX_SHARED))
|
||||
- atomic_init(&mutexp->sharecount, 0);
|
||||
+ __db_atomic_init(&mutexp->sharecount, 0);
|
||||
else
|
||||
#endif
|
||||
if (MUTEX_INIT(&mutexp->tas)) {
|
||||
@@ -536,7 +536,7 @@ __db_tas_mutex_unlock(env, mutex)
|
||||
F_CLR(mutexp, DB_MUTEX_LOCKED);
|
||||
/* Flush flag update before zeroing count */
|
||||
MEMBAR_EXIT();
|
||||
- atomic_init(&mutexp->sharecount, 0);
|
||||
+ __db_atomic_init(&mutexp->sharecount, 0);
|
||||
} else {
|
||||
DB_ASSERT(env, sharecount > 0);
|
||||
MEMBAR_EXIT();
|
||||
45
libs/db/patches/060-clock-Do-not-define-own-timespec.patch
Normal file
45
libs/db/patches/060-clock-Do-not-define-own-timespec.patch
Normal file
@@ -0,0 +1,45 @@
|
||||
From 96b303caf70a7635953c36e5bfb9ad6e75cb7637 Mon Sep 17 00:00:00 2001
|
||||
From: Khem Raj <raj.khem@gmail.com>
|
||||
Date: Fri, 14 Feb 2020 14:12:59 -0800
|
||||
Subject: [PATCH] clock: Do not define own timespec
|
||||
|
||||
timespec is provided by libc and its best left to libc
|
||||
os_gettime takes a db_timespec and passed its address to clock_gettime
|
||||
which assumes that db_timespec and timespec are same but actually
|
||||
its 12-bytes here and libc has 16-bytes
|
||||
|
||||
This can cause problems especially with 64bit time_t
|
||||
|
||||
Upstream-Status: Inappropriate [as far as open source community is concerned, upstream is dead]
|
||||
Signed-off-by: Khem Raj <raj.khem@gmail.com>
|
||||
---
|
||||
src/dbinc/clock.h | 17 +----------------
|
||||
1 file changed, 1 insertion(+), 16 deletions(-)
|
||||
|
||||
--- a/src/dbinc/clock.h
|
||||
+++ b/src/dbinc/clock.h
|
||||
@@ -44,22 +44,8 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
-/*
|
||||
- * This declaration is POSIX-compatible. Because there are lots of different
|
||||
- * time.h include file patterns out there, it's easier to declare our own name
|
||||
- * in all cases than to try and discover if a system has a struct timespec.
|
||||
- * For the same reason, and because we'd have to #include <sys/time.h> in db.h,
|
||||
- * we don't export any timespec structures in the DB API, even in places where
|
||||
- * it would make sense, like the replication statistics information.
|
||||
- */
|
||||
-typedef struct {
|
||||
- time_t tv_sec; /* seconds */
|
||||
-#ifdef HAVE_MIXED_SIZE_ADDRESSING
|
||||
- int32_t tv_nsec;
|
||||
-#else
|
||||
- long tv_nsec; /* nanoseconds */
|
||||
-#endif
|
||||
-} db_timespec;
|
||||
+#include <time.h>
|
||||
+#define db_timespec struct timespec
|
||||
|
||||
/* Operations on timespecs */
|
||||
#undef timespecclear
|
||||
181
libs/db/patches/070-memp-stat-upstream-fix.patch
Normal file
181
libs/db/patches/070-memp-stat-upstream-fix.patch
Normal file
@@ -0,0 +1,181 @@
|
||||
--- a/src/mp/mp_stat.c
|
||||
+++ b/src/mp/mp_stat.c
|
||||
@@ -87,6 +87,13 @@ __memp_stat(env, gspp, fspp, flags)
|
||||
u_int32_t i;
|
||||
uintmax_t tmp_wait, tmp_nowait;
|
||||
|
||||
+ /*
|
||||
+ * The array holding the lengths related to the buffer allocated for *fspp.
|
||||
+ * The first element of the array holds the number of entries allocated.
|
||||
+ * The second element of the array holds the total number of bytes allocated.
|
||||
+ */
|
||||
+ u_int32_t fsp_len[2];
|
||||
+
|
||||
dbmp = env->mp_handle;
|
||||
mp = dbmp->reginfo[0].primary;
|
||||
|
||||
@@ -193,32 +200,53 @@ __memp_stat(env, gspp, fspp, flags)
|
||||
if (fspp != NULL) {
|
||||
*fspp = NULL;
|
||||
|
||||
- /* Count the MPOOLFILE structures. */
|
||||
- i = 0;
|
||||
- len = 0;
|
||||
- if ((ret = __memp_walk_files(env,
|
||||
- mp, __memp_count_files, &len, &i, flags)) != 0)
|
||||
- return (ret);
|
||||
-
|
||||
- if (i == 0)
|
||||
- return (0);
|
||||
- len += sizeof(DB_MPOOL_FSTAT *); /* Trailing NULL */
|
||||
+ while (*fspp == NULL) {
|
||||
+ /* Count the MPOOLFILE structures. */
|
||||
+ i = 0;
|
||||
+ /*
|
||||
+ * Allow space for the first __memp_get_files() to align the
|
||||
+ * structure array to uintmax_t, DB_MPOOL_STAT's most
|
||||
+ * restrictive field. [#23150]
|
||||
+ */
|
||||
+ len = sizeof(uintmax_t);
|
||||
+ if ((ret = __memp_walk_files(env,
|
||||
+ mp, __memp_count_files, &len, &i, flags)) != 0)
|
||||
+ return (ret);
|
||||
+
|
||||
+ if (i == 0)
|
||||
+ return (0);
|
||||
+
|
||||
+ /*
|
||||
+ * Copy the number of DB_MPOOL_FSTAT entries and the number of
|
||||
+ * bytes allocated for them into fsp_len. Do not count the space
|
||||
+ * reserved for allignment.
|
||||
+ */
|
||||
+ fsp_len[0] = i;
|
||||
+ fsp_len[1] = len - sizeof(uintmax_t);
|
||||
|
||||
- /* Allocate space */
|
||||
- if ((ret = __os_umalloc(env, len, fspp)) != 0)
|
||||
- return (ret);
|
||||
+ len += sizeof(DB_MPOOL_FSTAT *); /* Trailing NULL */
|
||||
|
||||
- tfsp = *fspp;
|
||||
- *tfsp = NULL;
|
||||
+ /* Allocate space */
|
||||
+ if ((ret = __os_umalloc(env, len, fspp)) != 0)
|
||||
+ return (ret);
|
||||
|
||||
- /*
|
||||
- * Files may have been opened since we counted, don't walk
|
||||
- * off the end of the allocated space.
|
||||
- */
|
||||
- if ((ret = __memp_walk_files(env,
|
||||
- mp, __memp_get_files, &tfsp, &i, flags)) != 0)
|
||||
- return (ret);
|
||||
+ tfsp = *fspp;
|
||||
+ *tfsp = NULL;
|
||||
|
||||
+ /*
|
||||
+ * Files may have been opened since we counted, if we walk off
|
||||
+ * the end of the allocated space specified in fsp_len, retry.
|
||||
+ */
|
||||
+ if ((ret = __memp_walk_files(env,
|
||||
+ mp, __memp_get_files, &tfsp, fsp_len, flags)) != 0) {
|
||||
+ if (ret == DB_BUFFER_SMALL) {
|
||||
+ __os_ufree(env, *fspp);
|
||||
+ *fspp = NULL;
|
||||
+ tfsp = NULL;
|
||||
+ } else
|
||||
+ return (ret);
|
||||
+ }
|
||||
+ }
|
||||
*++tfsp = NULL;
|
||||
}
|
||||
|
||||
@@ -286,28 +314,35 @@ __memp_count_files(env, mfp, argp, count
|
||||
* for the text file names.
|
||||
*/
|
||||
static int
|
||||
-__memp_get_files(env, mfp, argp, countp, flags)
|
||||
+__memp_get_files(env, mfp, argp, fsp_len, flags)
|
||||
ENV *env;
|
||||
MPOOLFILE *mfp;
|
||||
void *argp;
|
||||
- u_int32_t *countp;
|
||||
+ u_int32_t fsp_len[];
|
||||
u_int32_t flags;
|
||||
{
|
||||
DB_MPOOL *dbmp;
|
||||
DB_MPOOL_FSTAT **tfsp, *tstruct;
|
||||
char *name, *tname;
|
||||
- size_t nlen;
|
||||
+ size_t nlen, tlen;
|
||||
|
||||
- if (*countp == 0)
|
||||
- return (0);
|
||||
+ /* We walked through more files than argp was allocated for. */
|
||||
+ if (fsp_len[0] == 0)
|
||||
+ return DB_BUFFER_SMALL;
|
||||
|
||||
dbmp = env->mp_handle;
|
||||
tfsp = *(DB_MPOOL_FSTAT ***)argp;
|
||||
|
||||
if (*tfsp == NULL) {
|
||||
- /* Add 1 to count because we need to skip over the NULL. */
|
||||
- tstruct = (DB_MPOOL_FSTAT *)(tfsp + *countp + 1);
|
||||
- tname = (char *)(tstruct + *countp);
|
||||
+ /*
|
||||
+ * Add 1 to count because to skip over the NULL end marker.
|
||||
+ * Align it further for DB_MPOOL_STAT's most restrictive field
|
||||
+ * because uintmax_t might require stricter alignment than
|
||||
+ * pointers; e.g., IP32 LL64 SPARC. [#23150]
|
||||
+ */
|
||||
+ tstruct = (DB_MPOOL_FSTAT *)&tfsp[fsp_len[0] + 1];
|
||||
+ tstruct = ALIGNP_INC(tstruct, sizeof(uintmax_t));
|
||||
+ tname = (char *)&tstruct[fsp_len[0]];
|
||||
*tfsp = tstruct;
|
||||
} else {
|
||||
tstruct = *tfsp + 1;
|
||||
@@ -317,6 +352,15 @@ __memp_get_files(env, mfp, argp, countp,
|
||||
|
||||
name = __memp_fns(dbmp, mfp);
|
||||
nlen = strlen(name) + 1;
|
||||
+
|
||||
+ /* The space required for file names is larger than argp was allocated for. */
|
||||
+ tlen = sizeof(DB_MPOOL_FSTAT *) + sizeof(DB_MPOOL_FSTAT) + nlen;
|
||||
+ if (fsp_len[1] < tlen)
|
||||
+ return DB_BUFFER_SMALL;
|
||||
+ else
|
||||
+ /* Count down the number of bytes left in argp. */
|
||||
+ fsp_len[1] -= tlen;
|
||||
+
|
||||
memcpy(tname, name, nlen);
|
||||
memcpy(tstruct, &mfp->stat, sizeof(mfp->stat));
|
||||
tstruct->file_name = tname;
|
||||
@@ -325,7 +369,9 @@ __memp_get_files(env, mfp, argp, countp,
|
||||
tstruct->st_pagesize = mfp->pagesize;
|
||||
|
||||
*(DB_MPOOL_FSTAT ***)argp = tfsp;
|
||||
- (*countp)--;
|
||||
+
|
||||
+ /* Count down the number of entries left in argp. */
|
||||
+ fsp_len[0]--;
|
||||
|
||||
if (LF_ISSET(DB_STAT_CLEAR))
|
||||
memset(&mfp->stat, 0, sizeof(mfp->stat));
|
||||
--- a/src/mp/mp_sync.c
|
||||
+++ b/src/mp/mp_sync.c
|
||||
@@ -57,11 +57,13 @@ __memp_walk_files(env, mp, func, arg, co
|
||||
if ((t_ret = func(env,
|
||||
mfp, arg, countp, flags)) != 0 && ret == 0)
|
||||
ret = t_ret;
|
||||
- if (ret != 0 && !LF_ISSET(DB_STAT_MEMP_NOERROR))
|
||||
+ if (ret != 0 &&
|
||||
+ (!LF_ISSET(DB_STAT_MEMP_NOERROR) || ret == DB_BUFFER_SMALL))
|
||||
break;
|
||||
}
|
||||
MUTEX_UNLOCK(env, hp->mtx_hash);
|
||||
- if (ret != 0 && !LF_ISSET(DB_STAT_MEMP_NOERROR))
|
||||
+ if (ret != 0 &&
|
||||
+ (!LF_ISSET(DB_STAT_MEMP_NOERROR) || ret == DB_BUFFER_SMALL))
|
||||
break;
|
||||
}
|
||||
return (ret);
|
||||
600
libs/db/patches/080-mutex-leak.patch
Normal file
600
libs/db/patches/080-mutex-leak.patch
Normal file
@@ -0,0 +1,600 @@
|
||||
--- a/src/dbinc_auto/int_def.in
|
||||
+++ b/src/dbinc_auto/int_def.in
|
||||
@@ -1373,6 +1373,7 @@
|
||||
#define __memp_pgread __memp_pgread@DB_VERSION_UNIQUE_NAME@
|
||||
#define __memp_pg __memp_pg@DB_VERSION_UNIQUE_NAME@
|
||||
#define __memp_bhfree __memp_bhfree@DB_VERSION_UNIQUE_NAME@
|
||||
+#define __memp_bh_clear_dirty __memp_bh_clear_dirty@DB_VERSION_UNIQUE_NAME@
|
||||
#define __memp_fget_pp __memp_fget_pp@DB_VERSION_UNIQUE_NAME@
|
||||
#define __memp_fget __memp_fget@DB_VERSION_UNIQUE_NAME@
|
||||
#define __memp_fcreate_pp __memp_fcreate_pp@DB_VERSION_UNIQUE_NAME@
|
||||
@@ -1397,6 +1398,7 @@
|
||||
#define __memp_fclose __memp_fclose@DB_VERSION_UNIQUE_NAME@
|
||||
#define __memp_mf_discard __memp_mf_discard@DB_VERSION_UNIQUE_NAME@
|
||||
#define __memp_inmemlist __memp_inmemlist@DB_VERSION_UNIQUE_NAME@
|
||||
+#define __memp_mf_mark_dead __memp_mf_mark_dead@DB_VERSION_UNIQUE_NAME@
|
||||
#define __memp_fput_pp __memp_fput_pp@DB_VERSION_UNIQUE_NAME@
|
||||
#define __memp_fput __memp_fput@DB_VERSION_UNIQUE_NAME@
|
||||
#define __memp_unpin_buffers __memp_unpin_buffers@DB_VERSION_UNIQUE_NAME@
|
||||
@@ -1455,6 +1457,7 @@
|
||||
#define __mp_xxx_fh __mp_xxx_fh@DB_VERSION_UNIQUE_NAME@
|
||||
#define __memp_sync_int __memp_sync_int@DB_VERSION_UNIQUE_NAME@
|
||||
#define __memp_mf_sync __memp_mf_sync@DB_VERSION_UNIQUE_NAME@
|
||||
+#define __memp_purge_dead_files __memp_purge_dead_files@DB_VERSION_UNIQUE_NAME@
|
||||
#define __memp_trickle_pp __memp_trickle_pp@DB_VERSION_UNIQUE_NAME@
|
||||
#define __mutex_alloc __mutex_alloc@DB_VERSION_UNIQUE_NAME@
|
||||
#define __mutex_alloc_int __mutex_alloc_int@DB_VERSION_UNIQUE_NAME@
|
||||
--- a/src/dbinc_auto/mp_ext.h
|
||||
+++ b/src/dbinc_auto/mp_ext.h
|
||||
@@ -16,6 +16,7 @@ int __memp_bhwrite __P((DB_MPOOL *, DB_M
|
||||
int __memp_pgread __P((DB_MPOOLFILE *, BH *, int));
|
||||
int __memp_pg __P((DB_MPOOLFILE *, db_pgno_t, void *, int));
|
||||
int __memp_bhfree __P((DB_MPOOL *, REGINFO *, MPOOLFILE *, DB_MPOOL_HASH *, BH *, u_int32_t));
|
||||
+void __memp_bh_clear_dirty __P((ENV*, DB_MPOOL_HASH *, BH *));
|
||||
int __memp_fget_pp __P((DB_MPOOLFILE *, db_pgno_t *, DB_TXN *, u_int32_t, void *));
|
||||
int __memp_fget __P((DB_MPOOLFILE *, db_pgno_t *, DB_THREAD_INFO *, DB_TXN *, u_int32_t, void *));
|
||||
int __memp_fcreate_pp __P((DB_ENV *, DB_MPOOLFILE **, u_int32_t));
|
||||
@@ -40,6 +41,7 @@ int __memp_fclose_pp __P((DB_MPOOLFILE *
|
||||
int __memp_fclose __P((DB_MPOOLFILE *, u_int32_t));
|
||||
int __memp_mf_discard __P((DB_MPOOL *, MPOOLFILE *, int));
|
||||
int __memp_inmemlist __P((ENV *, char ***, int *));
|
||||
+void __memp_mf_mark_dead __P((DB_MPOOL *, MPOOLFILE *, int*));
|
||||
int __memp_fput_pp __P((DB_MPOOLFILE *, void *, DB_CACHE_PRIORITY, u_int32_t));
|
||||
int __memp_fput __P((DB_MPOOLFILE *, DB_THREAD_INFO *, void *, DB_CACHE_PRIORITY));
|
||||
int __memp_unpin_buffers __P((ENV *, DB_THREAD_INFO *));
|
||||
@@ -98,6 +100,7 @@ int __memp_fsync __P((DB_MPOOLFILE *));
|
||||
int __mp_xxx_fh __P((DB_MPOOLFILE *, DB_FH **));
|
||||
int __memp_sync_int __P((ENV *, DB_MPOOLFILE *, u_int32_t, u_int32_t, u_int32_t *, int *));
|
||||
int __memp_mf_sync __P((DB_MPOOL *, MPOOLFILE *, int));
|
||||
+int __memp_purge_dead_files __P((ENV *));
|
||||
int __memp_trickle_pp __P((DB_ENV *, int, int *));
|
||||
|
||||
#if defined(__cplusplus)
|
||||
--- a/src/mp/mp_bh.c
|
||||
+++ b/src/mp/mp_bh.c
|
||||
@@ -474,11 +474,8 @@ file_dead:
|
||||
if (F_ISSET(bhp, BH_DIRTY | BH_TRASH)) {
|
||||
MUTEX_LOCK(env, hp->mtx_hash);
|
||||
DB_ASSERT(env, !SH_CHAIN_HASNEXT(bhp, vc));
|
||||
- if (ret == 0 && F_ISSET(bhp, BH_DIRTY)) {
|
||||
- F_CLR(bhp, BH_DIRTY | BH_DIRTY_CREATE);
|
||||
- DB_ASSERT(env, atomic_read(&hp->hash_page_dirty) > 0);
|
||||
- atomic_dec(env, &hp->hash_page_dirty);
|
||||
- }
|
||||
+ if (ret == 0)
|
||||
+ __memp_bh_clear_dirty(env, hp, bhp);
|
||||
|
||||
/* put the page back if necessary. */
|
||||
if ((ret != 0 || BH_REFCOUNT(bhp) > 1) &&
|
||||
@@ -688,3 +685,29 @@ no_hp: if (mfp != NULL)
|
||||
|
||||
return (ret);
|
||||
}
|
||||
+
|
||||
+/*
|
||||
+ * __memp_bh_clear_dirty --
|
||||
+ * Clear the dirty flag of of a buffer. Calls on the same buffer must be
|
||||
+ * serialized to get the accounting correct. This can be achieved by
|
||||
+ * acquiring an exclusive lock on the buffer, a shared lock on the
|
||||
+ * buffer plus an exclusive lock on the hash bucket, or some other
|
||||
+ * mechanism that guarantees single-thread access to the entire region
|
||||
+ * (e.g. during __memp_region_bhfree()).
|
||||
+ *
|
||||
+ * PUBLIC: void __memp_bh_clear_dirty __P((ENV*, DB_MPOOL_HASH *, BH *));
|
||||
+ */
|
||||
+void
|
||||
+__memp_bh_clear_dirty(env, hp, bhp)
|
||||
+ ENV *env;
|
||||
+ DB_MPOOL_HASH *hp;
|
||||
+ BH *bhp;
|
||||
+{
|
||||
+ COMPQUIET(env, env);
|
||||
+ if (F_ISSET(bhp, BH_DIRTY)) {
|
||||
+ F_CLR(bhp, BH_DIRTY | BH_DIRTY_CREATE);
|
||||
+ DB_ASSERT(env, atomic_read(&hp->hash_page_dirty) > 0);
|
||||
+ (void)atomic_dec(env, &hp->hash_page_dirty);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
--- a/src/mp/mp_fget.c
|
||||
+++ b/src/mp/mp_fget.c
|
||||
@@ -439,12 +439,7 @@ thawed: need_free = (atomic_dec(env, &
|
||||
if (flags == DB_MPOOL_FREE) {
|
||||
freebuf: MUTEX_LOCK(env, hp->mtx_hash);
|
||||
h_locked = 1;
|
||||
- if (F_ISSET(bhp, BH_DIRTY)) {
|
||||
- F_CLR(bhp, BH_DIRTY | BH_DIRTY_CREATE);
|
||||
- DB_ASSERT(env,
|
||||
- atomic_read(&hp->hash_page_dirty) > 0);
|
||||
- atomic_dec(env, &hp->hash_page_dirty);
|
||||
- }
|
||||
+ __memp_bh_clear_dirty(env, hp, bhp);
|
||||
|
||||
/*
|
||||
* If the buffer we found is already freed, we're done.
|
||||
--- a/src/mp/mp_fopen.c
|
||||
+++ b/src/mp/mp_fopen.c
|
||||
@@ -14,6 +14,7 @@
|
||||
#include "dbinc/db_page.h"
|
||||
#include "dbinc/hash.h"
|
||||
|
||||
+static int __memp_count_dead_mutex __P((DB_MPOOL *, u_int32_t *));
|
||||
static int __memp_mpf_alloc __P((DB_MPOOL *,
|
||||
DB_MPOOLFILE *, const char *, u_int32_t, u_int32_t, MPOOLFILE **));
|
||||
static int __memp_mpf_find __P((ENV *,
|
||||
@@ -711,7 +712,11 @@ __memp_mpf_find(env, dbmfp, hp, path, fl
|
||||
*/
|
||||
if (LF_ISSET(DB_TRUNCATE)) {
|
||||
MUTEX_LOCK(env, mfp->mutex);
|
||||
- mfp->deadfile = 1;
|
||||
+ /*
|
||||
+ * We cannot purge dead files here, because the caller
|
||||
+ * is holding the mutex of the hash bucket of mfp.
|
||||
+ */
|
||||
+ __memp_mf_mark_dead(dbmp, mfp, NULL);
|
||||
MUTEX_UNLOCK(env, mfp->mutex);
|
||||
continue;
|
||||
}
|
||||
@@ -909,10 +914,11 @@ __memp_fclose(dbmfp, flags)
|
||||
MPOOLFILE *mfp;
|
||||
char *rpath;
|
||||
u_int32_t ref;
|
||||
- int deleted, ret, t_ret;
|
||||
+ int deleted, purge_dead, ret, t_ret;
|
||||
|
||||
env = dbmfp->env;
|
||||
dbmp = env->mp_handle;
|
||||
+ purge_dead = 0;
|
||||
ret = 0;
|
||||
|
||||
/*
|
||||
@@ -1006,7 +1012,7 @@ __memp_fclose(dbmfp, flags)
|
||||
if (--mfp->mpf_cnt == 0 || LF_ISSET(DB_MPOOL_DISCARD)) {
|
||||
if (LF_ISSET(DB_MPOOL_DISCARD) ||
|
||||
F_ISSET(mfp, MP_TEMP) || mfp->unlink_on_close) {
|
||||
- mfp->deadfile = 1;
|
||||
+ __memp_mf_mark_dead(dbmp, mfp, &purge_dead);
|
||||
}
|
||||
if (mfp->unlink_on_close) {
|
||||
if ((t_ret = __db_appname(dbmp->env, DB_APP_DATA,
|
||||
@@ -1039,6 +1045,8 @@ __memp_fclose(dbmfp, flags)
|
||||
}
|
||||
if (!deleted && !LF_ISSET(DB_MPOOL_NOLOCK))
|
||||
MUTEX_UNLOCK(env, mfp->mutex);
|
||||
+ if (purge_dead)
|
||||
+ (void)__memp_purge_dead_files(env);
|
||||
|
||||
done: /* Discard the DB_MPOOLFILE structure. */
|
||||
if (dbmfp->pgcookie != NULL) {
|
||||
@@ -1093,7 +1101,7 @@ __memp_mf_discard(dbmp, mfp, hp_locked)
|
||||
* mutex so we don't deadlock. Make sure nobody ever looks at this
|
||||
* structure again.
|
||||
*/
|
||||
- mfp->deadfile = 1;
|
||||
+ __memp_mf_mark_dead(dbmp, mfp, NULL);
|
||||
|
||||
/* Discard the mutex we're holding and return it too the pool. */
|
||||
MUTEX_UNLOCK(env, mfp->mutex);
|
||||
@@ -1218,3 +1226,104 @@ nomem: MUTEX_UNLOCK(env, hp->mtx_hash);
|
||||
*namesp = NULL;
|
||||
return (ret);
|
||||
}
|
||||
+
|
||||
+/*
|
||||
+ * __memp_mf_mark_dead --
|
||||
+ * Mark an MPOOLFILE as dead because its contents are no longer necessary.
|
||||
+ * This happens when removing, truncation, or closing an unnamed in-memory
|
||||
+ * database. Return, in the purgep parameter, whether the caller should
|
||||
+ * call __memp_purge_dead_files() after the lock on mfp is released. The
|
||||
+ * caller must hold an exclusive lock on the mfp handle.
|
||||
+ *
|
||||
+ * PUBLIC: void __memp_mf_mark_dead __P((DB_MPOOL *, MPOOLFILE *, int*));
|
||||
+ */
|
||||
+void
|
||||
+__memp_mf_mark_dead(dbmp, mfp, purgep)
|
||||
+ DB_MPOOL *dbmp;
|
||||
+ MPOOLFILE *mfp;
|
||||
+ int *purgep;
|
||||
+{
|
||||
+ ENV *env;
|
||||
+#ifdef HAVE_MUTEX_SUPPORT
|
||||
+ REGINFO *infop;
|
||||
+ DB_MUTEXREGION *mtxregion;
|
||||
+ u_int32_t mutex_max, mutex_inuse, dead_mutex;
|
||||
+#endif
|
||||
+
|
||||
+ if (purgep != NULL)
|
||||
+ *purgep = 0;
|
||||
+
|
||||
+ env = dbmp->env;
|
||||
+
|
||||
+#ifdef HAVE_MUTEX_SUPPORT
|
||||
+ MUTEX_REQUIRED(env, mfp->mutex);
|
||||
+
|
||||
+ if (MUTEX_ON(env) && mfp->deadfile == 0) {
|
||||
+ infop = &env->mutex_handle->reginfo;
|
||||
+ mtxregion = infop->primary;
|
||||
+
|
||||
+ mutex_inuse = mtxregion->stat.st_mutex_inuse;
|
||||
+ if ((mutex_max = env->dbenv->mutex_max) == 0)
|
||||
+ mutex_max = infop->rp->max / mtxregion->mutex_size;
|
||||
+
|
||||
+ /*
|
||||
+ * Purging dead pages requires a full scan of the entire cache
|
||||
+ * buffer, so it is a slow operation. We only want to do it
|
||||
+ * when it is necessary and provides enough benefits. Below is
|
||||
+ * a simple heuristic that determines when to purge all dead
|
||||
+ * pages.
|
||||
+ */
|
||||
+ if (purgep != NULL && mutex_inuse > mutex_max - 200) {
|
||||
+ /*
|
||||
+ * If the mutex region is almost full and there are
|
||||
+ * many mutexes held by dead files, purge dead files.
|
||||
+ */
|
||||
+ (void)__memp_count_dead_mutex(dbmp, &dead_mutex);
|
||||
+ dead_mutex += mfp->block_cnt + 1;
|
||||
+
|
||||
+ if (dead_mutex > mutex_inuse / 20)
|
||||
+ *purgep = 1;
|
||||
+ }
|
||||
+ }
|
||||
+#endif
|
||||
+
|
||||
+ mfp->deadfile = 1;
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * __memp_count_dead_mutex --
|
||||
+ * Estimate the number of mutexes held by dead files.
|
||||
+ */
|
||||
+static int
|
||||
+__memp_count_dead_mutex(dbmp, dead_mutex)
|
||||
+ DB_MPOOL *dbmp;
|
||||
+ u_int32_t *dead_mutex;
|
||||
+{
|
||||
+ ENV *env;
|
||||
+ DB_MPOOL_HASH *hp;
|
||||
+ MPOOL *mp;
|
||||
+ MPOOLFILE *mfp;
|
||||
+ u_int32_t mutex_per_file;
|
||||
+ int busy, i;
|
||||
+
|
||||
+ env = dbmp->env;
|
||||
+ *dead_mutex = 0;
|
||||
+ mutex_per_file = 1;
|
||||
+#ifndef HAVE_ATOMICFILEREAD
|
||||
+ mutex_per_file = 2;
|
||||
+#endif
|
||||
+ mp = dbmp->reginfo[0].primary;
|
||||
+ hp = R_ADDR(dbmp->reginfo, mp->ftab);
|
||||
+ for (i = 0; i < MPOOL_FILE_BUCKETS; i++, hp++) {
|
||||
+ busy = MUTEX_TRYLOCK(env, hp->mtx_hash);
|
||||
+ if (busy)
|
||||
+ continue;
|
||||
+ SH_TAILQ_FOREACH(mfp, &hp->hash_bucket, q, __mpoolfile) {
|
||||
+ if (mfp->deadfile)
|
||||
+ *dead_mutex += mfp->block_cnt + mutex_per_file;
|
||||
+ }
|
||||
+ MUTEX_UNLOCK(env, hp->mtx_hash);
|
||||
+ }
|
||||
+
|
||||
+ return (0);
|
||||
+}
|
||||
--- a/src/mp/mp_method.c
|
||||
+++ b/src/mp/mp_method.c
|
||||
@@ -640,7 +640,7 @@ __memp_nameop(env, fileid, newname, full
|
||||
MPOOLFILE *mfp;
|
||||
roff_t newname_off;
|
||||
u_int32_t bucket;
|
||||
- int locked, ret;
|
||||
+ int locked, purge_dead, ret;
|
||||
size_t nlen;
|
||||
void *p;
|
||||
|
||||
@@ -657,6 +657,7 @@ __memp_nameop(env, fileid, newname, full
|
||||
nhp = NULL;
|
||||
p = NULL;
|
||||
locked = ret = 0;
|
||||
+ purge_dead = 0;
|
||||
|
||||
if (!MPOOL_ON(env))
|
||||
goto fsop;
|
||||
@@ -749,7 +750,7 @@ __memp_nameop(env, fileid, newname, full
|
||||
*/
|
||||
if (mfp->no_backing_file)
|
||||
mfp->mpf_cnt--;
|
||||
- mfp->deadfile = 1;
|
||||
+ __memp_mf_mark_dead(dbmp, mfp, &purge_dead);
|
||||
MUTEX_UNLOCK(env, mfp->mutex);
|
||||
} else {
|
||||
/*
|
||||
@@ -808,6 +809,12 @@ err: if (p != NULL) {
|
||||
if (nhp != NULL && nhp != hp)
|
||||
MUTEX_UNLOCK(env, nhp->mtx_hash);
|
||||
}
|
||||
+ /*
|
||||
+ * __memp_purge_dead_files() must be called when the hash bucket is
|
||||
+ * unlocked.
|
||||
+ */
|
||||
+ if (purge_dead)
|
||||
+ (void)__memp_purge_dead_files(env);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
--- a/src/mp/mp_sync.c
|
||||
+++ b/src/mp/mp_sync.c
|
||||
@@ -26,6 +26,7 @@ static int __memp_close_flush_files __P(
|
||||
static int __memp_sync_files __P((ENV *));
|
||||
static int __memp_sync_file __P((ENV *,
|
||||
MPOOLFILE *, void *, u_int32_t *, u_int32_t));
|
||||
+static inline void __update_err_ret(int, int*);
|
||||
|
||||
/*
|
||||
* __memp_walk_files --
|
||||
@@ -965,3 +966,123 @@ __bhcmp(p1, p2)
|
||||
return (1);
|
||||
return (0);
|
||||
}
|
||||
+
|
||||
+/*
|
||||
+ * __memp_purge_dead_files --
|
||||
+ * Remove all dead files and their buffers from the mpool. The caller
|
||||
+ * cannot hold any lock on the dead MPOOLFILE handles, their buffers
|
||||
+ * or their hash buckets.
|
||||
+ *
|
||||
+ * PUBLIC: int __memp_purge_dead_files __P((ENV *));
|
||||
+ */
|
||||
+int
|
||||
+__memp_purge_dead_files(env)
|
||||
+ ENV *env;
|
||||
+{
|
||||
+ BH *bhp;
|
||||
+ DB_MPOOL *dbmp;
|
||||
+ DB_MPOOL_HASH *hp, *hp_end;
|
||||
+ REGINFO *infop;
|
||||
+ MPOOL *c_mp, *mp;
|
||||
+ MPOOLFILE *mfp;
|
||||
+ u_int32_t i_cache;
|
||||
+ int ret, t_ret, h_lock;
|
||||
+
|
||||
+ if (!MPOOL_ON(env))
|
||||
+ return (0);
|
||||
+
|
||||
+ dbmp = env->mp_handle;
|
||||
+ mp = dbmp->reginfo[0].primary;
|
||||
+ ret = t_ret = h_lock = 0;
|
||||
+
|
||||
+ /*
|
||||
+ * Walk each cache's list of buffers and free all buffers whose
|
||||
+ * MPOOLFILE is marked as dead.
|
||||
+ */
|
||||
+ for (i_cache = 0; i_cache < mp->nreg; i_cache++) {
|
||||
+ infop = &dbmp->reginfo[i_cache];
|
||||
+ c_mp = infop->primary;
|
||||
+
|
||||
+ hp = R_ADDR(infop, c_mp->htab);
|
||||
+ hp_end = &hp[c_mp->htab_buckets];
|
||||
+ for (; hp < hp_end; hp++) {
|
||||
+ /* Skip empty buckets. */
|
||||
+ if (SH_TAILQ_FIRST(&hp->hash_bucket, __bh) == NULL)
|
||||
+ continue;
|
||||
+
|
||||
+ /*
|
||||
+ * Search for a dead buffer. Other places that call
|
||||
+ * __memp_bhfree() acquire the buffer lock before the
|
||||
+ * hash bucket lock. Even though we acquire the two
|
||||
+ * locks in reverse order, we cannot deadlock here
|
||||
+ * because we don't block waiting for the locks.
|
||||
+ */
|
||||
+ t_ret = MUTEX_TRYLOCK(env, hp->mtx_hash);
|
||||
+ if (t_ret != 0) {
|
||||
+ __update_err_ret(t_ret, &ret);
|
||||
+ continue;
|
||||
+ }
|
||||
+ h_lock = 1;
|
||||
+ SH_TAILQ_FOREACH(bhp, &hp->hash_bucket, hq, __bh) {
|
||||
+ /* Skip buffers that are being used. */
|
||||
+ if (BH_REFCOUNT(bhp) > 0)
|
||||
+ continue;
|
||||
+
|
||||
+ mfp = R_ADDR(dbmp->reginfo, bhp->mf_offset);
|
||||
+ if (!mfp->deadfile)
|
||||
+ continue;
|
||||
+
|
||||
+ /* Found a dead buffer. Prepare to free it. */
|
||||
+ t_ret = MUTEX_TRYLOCK(env, bhp->mtx_buf);
|
||||
+ if (t_ret != 0) {
|
||||
+ __update_err_ret(t_ret, &ret);
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ DB_ASSERT(env, (!F_ISSET(bhp, BH_EXCLUSIVE) &&
|
||||
+ BH_REFCOUNT(bhp) == 0));
|
||||
+ F_SET(bhp, BH_EXCLUSIVE);
|
||||
+ (void)atomic_inc(env, &bhp->ref);
|
||||
+
|
||||
+ __memp_bh_clear_dirty(env, hp, bhp);
|
||||
+
|
||||
+ /*
|
||||
+ * Free the buffer. The buffer and hash bucket
|
||||
+ * are unlocked by __memp_bhfree.
|
||||
+ */
|
||||
+ if ((t_ret = __memp_bhfree(dbmp, infop, mfp,
|
||||
+ hp, bhp, BH_FREE_FREEMEM)) == 0)
|
||||
+ /*
|
||||
+ * Decrement hp, so the next turn will
|
||||
+ * search the same bucket again.
|
||||
+ */
|
||||
+ hp--;
|
||||
+ else
|
||||
+ __update_err_ret(t_ret, &ret);
|
||||
+
|
||||
+ /*
|
||||
+ * The hash bucket is unlocked, we need to
|
||||
+ * start over again.
|
||||
+ */
|
||||
+ h_lock = 0;
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ if (h_lock) {
|
||||
+ MUTEX_UNLOCK(env, hp->mtx_hash);
|
||||
+ h_lock = 0;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return (ret);
|
||||
+}
|
||||
+
|
||||
+static inline void
|
||||
+__update_err_ret(t_ret, retp)
|
||||
+ int t_ret;
|
||||
+ int *retp;
|
||||
+{
|
||||
+ if (t_ret != 0 && t_ret != DB_LOCK_NOTGRANTED && *retp == 0)
|
||||
+ *retp = t_ret;
|
||||
+}
|
||||
--- a/src/mp/mp_trickle.c
|
||||
+++ b/src/mp/mp_trickle.c
|
||||
@@ -67,6 +67,10 @@ __memp_trickle(env, pct, nwrotep)
|
||||
return (EINVAL);
|
||||
}
|
||||
|
||||
+ /* First we purge all dead files and their buffers. */
|
||||
+ if ((ret = __memp_purge_dead_files(env)) != 0)
|
||||
+ return (ret);
|
||||
+
|
||||
/*
|
||||
* Loop through the caches counting total/dirty buffers.
|
||||
*
|
||||
--- a/src/mutex/mut_region.c
|
||||
+++ b/src/mutex/mut_region.c
|
||||
@@ -17,7 +17,7 @@
|
||||
static db_size_t __mutex_align_size __P((ENV *));
|
||||
static int __mutex_region_init __P((ENV *, DB_MUTEXMGR *));
|
||||
static size_t __mutex_region_size __P((ENV *));
|
||||
-static size_t __mutex_region_max __P((ENV *));
|
||||
+static size_t __mutex_region_max __P((ENV *, u_int32_t));
|
||||
|
||||
/*
|
||||
* __mutex_open --
|
||||
@@ -34,7 +34,7 @@ __mutex_open(env, create_ok)
|
||||
DB_MUTEXMGR *mtxmgr;
|
||||
DB_MUTEXREGION *mtxregion;
|
||||
size_t size;
|
||||
- u_int32_t cpu_count;
|
||||
+ u_int32_t cpu_count, mutex_needed;
|
||||
int ret;
|
||||
#ifndef HAVE_ATOMIC_SUPPORT
|
||||
u_int i;
|
||||
@@ -61,19 +61,20 @@ __mutex_open(env, create_ok)
|
||||
}
|
||||
|
||||
/*
|
||||
- * If the user didn't set an absolute value on the number of mutexes
|
||||
- * we'll need, figure it out. We're conservative in our allocation,
|
||||
- * we need mutexes for DB handles, group-commit queues and other things
|
||||
- * applications allocate at run-time. The application may have kicked
|
||||
- * up our count to allocate its own mutexes, add that in.
|
||||
+ * Figure out the number of mutexes we'll need. We're conservative in
|
||||
+ * our allocation, we need mutexes for DB handles, group-commit queues
|
||||
+ * and other things applications allocate at run-time. The application
|
||||
+ * may have kicked up our count to allocate its own mutexes, add that
|
||||
+ * in.
|
||||
*/
|
||||
+ mutex_needed =
|
||||
+ __lock_region_mutex_count(env) +
|
||||
+ __log_region_mutex_count(env) +
|
||||
+ __memp_region_mutex_count(env) +
|
||||
+ __txn_region_mutex_count(env);
|
||||
if (dbenv->mutex_cnt == 0 &&
|
||||
F_ISSET(env, ENV_PRIVATE | ENV_THREAD) != ENV_PRIVATE)
|
||||
- dbenv->mutex_cnt =
|
||||
- __lock_region_mutex_count(env) +
|
||||
- __log_region_mutex_count(env) +
|
||||
- __memp_region_mutex_count(env) +
|
||||
- __txn_region_mutex_count(env);
|
||||
+ dbenv->mutex_cnt = mutex_needed;
|
||||
|
||||
if (dbenv->mutex_max != 0 && dbenv->mutex_cnt > dbenv->mutex_max)
|
||||
dbenv->mutex_cnt = dbenv->mutex_max;
|
||||
@@ -90,8 +91,8 @@ __mutex_open(env, create_ok)
|
||||
size = __mutex_region_size(env);
|
||||
if (create_ok)
|
||||
F_SET(&mtxmgr->reginfo, REGION_CREATE_OK);
|
||||
- if ((ret = __env_region_attach(env,
|
||||
- &mtxmgr->reginfo, size, size + __mutex_region_max(env))) != 0)
|
||||
+ if ((ret = __env_region_attach(env, &mtxmgr->reginfo,
|
||||
+ size, size + __mutex_region_max(env, mutex_needed))) != 0)
|
||||
goto err;
|
||||
|
||||
/* If we created the region, initialize it. */
|
||||
@@ -352,9 +353,13 @@ __mutex_region_size(env)
|
||||
|
||||
s = sizeof(DB_MUTEXMGR) + 1024;
|
||||
|
||||
- /* We discard one mutex for the OOB slot. */
|
||||
+ /*
|
||||
+ * We discard one mutex for the OOB slot. Make sure mutex_cnt doesn't
|
||||
+ * overflow.
|
||||
+ */
|
||||
s += __env_alloc_size(
|
||||
- (dbenv->mutex_cnt + 1) *__mutex_align_size(env));
|
||||
+ (dbenv->mutex_cnt + (dbenv->mutex_cnt == UINT32_MAX ? 0 : 1)) *
|
||||
+ __mutex_align_size(env));
|
||||
|
||||
return (s);
|
||||
}
|
||||
@@ -364,28 +369,42 @@ __mutex_region_size(env)
|
||||
* Return the amount of space needed to reach the maximum size.
|
||||
*/
|
||||
static size_t
|
||||
-__mutex_region_max(env)
|
||||
+__mutex_region_max(env, mutex_needed)
|
||||
ENV *env;
|
||||
+ u_int32_t mutex_needed;
|
||||
{
|
||||
DB_ENV *dbenv;
|
||||
- u_int32_t max;
|
||||
+ u_int32_t max, mutex_cnt;
|
||||
|
||||
dbenv = env->dbenv;
|
||||
+ mutex_cnt = dbenv->mutex_cnt;
|
||||
|
||||
- if ((max = dbenv->mutex_max) == 0) {
|
||||
+ /*
|
||||
+ * We want to limit the region size to accommodate at most UINT32_MAX
|
||||
+ * mutexes. If mutex_cnt is UINT32_MAX, no more space is allowed.
|
||||
+ */
|
||||
+ if ((max = dbenv->mutex_max) == 0 && mutex_cnt != UINT32_MAX)
|
||||
if (F_ISSET(env, ENV_PRIVATE | ENV_THREAD) == ENV_PRIVATE)
|
||||
- max = dbenv->mutex_inc + 1;
|
||||
- else
|
||||
+ if (dbenv->mutex_inc + 1 < UINT32_MAX - mutex_cnt)
|
||||
+ max = dbenv->mutex_inc + 1 + mutex_cnt;
|
||||
+ else
|
||||
+ max = UINT32_MAX;
|
||||
+ else {
|
||||
max = __lock_region_mutex_max(env) +
|
||||
__txn_region_mutex_max(env) +
|
||||
__log_region_mutex_max(env) +
|
||||
dbenv->mutex_inc + 100;
|
||||
- } else if (max <= dbenv->mutex_cnt)
|
||||
+ if (max < UINT32_MAX - mutex_needed)
|
||||
+ max += mutex_needed;
|
||||
+ else
|
||||
+ max = UINT32_MAX;
|
||||
+ }
|
||||
+
|
||||
+ if (max <= mutex_cnt)
|
||||
return (0);
|
||||
else
|
||||
- max -= dbenv->mutex_cnt;
|
||||
-
|
||||
- return ( __env_alloc_size(max * __mutex_align_size(env)));
|
||||
+ return (__env_alloc_size(
|
||||
+ (max - mutex_cnt) * __mutex_align_size(env)));
|
||||
}
|
||||
|
||||
#ifdef HAVE_MUTEX_SYSTEM_RESOURCES
|
||||
20
libs/db/patches/090-lemon-hash.patch
Normal file
20
libs/db/patches/090-lemon-hash.patch
Normal file
@@ -0,0 +1,20 @@
|
||||
--- a/lang/sql/sqlite/tool/lemon.c
|
||||
+++ b/lang/sql/sqlite/tool/lemon.c
|
||||
@@ -3428,7 +3428,7 @@ void print_stack_union(
|
||||
int maxdtlength; /* Maximum length of any ".datatype" field. */
|
||||
char *stddt; /* Standardized name for a datatype */
|
||||
int i,j; /* Loop counters */
|
||||
- int hash; /* For hashing the name of a type */
|
||||
+ unsigned hash; /* For hashing the name of a type */
|
||||
const char *name; /* Name of the parser */
|
||||
|
||||
/* Allocate and initialize types[] and allocate stddt[] */
|
||||
@@ -3491,7 +3491,7 @@ void print_stack_union(
|
||||
break;
|
||||
}
|
||||
hash++;
|
||||
- if( hash>=arraysize ) hash = 0;
|
||||
+ if( hash>=(unsigned)arraysize ) hash = 0;
|
||||
}
|
||||
if( types[hash]==0 ){
|
||||
sp->dtnum = hash + 1;
|
||||
18
libs/db/patches/100-mmap-high-cpu-usage.patch
Normal file
18
libs/db/patches/100-mmap-high-cpu-usage.patch
Normal file
@@ -0,0 +1,18 @@
|
||||
Author: Filip Januš <fjanus@redhat.com>
|
||||
Date: 6 Sep 2021
|
||||
Related: https://bugzilla.redhat.com/show_bug.cgi?id=1992402
|
||||
Patch was created based on the discussion in the previous link
|
||||
--- a/src/os/os_map.c
|
||||
+++ b/src/os/os_map.c
|
||||
@@ -213,7 +213,10 @@ __os_attach(env, infop, rp)
|
||||
if (rp->max < rp->size)
|
||||
rp->max = rp->size;
|
||||
if (ret == 0 && F_ISSET(infop, REGION_CREATE)) {
|
||||
- if (F_ISSET(dbenv, DB_ENV_REGION_INIT))
|
||||
+
|
||||
+ rp->size = rp->max;
|
||||
+
|
||||
+ if (F_ISSET(dbenv, DB_ENV_REGION_INIT))
|
||||
ret = __db_file_write(env, infop->fhp,
|
||||
rp->size / MEGABYTE, rp->size % MEGABYTE, 0x00);
|
||||
else
|
||||
693
libs/db/patches/110-CVE-2019-2708.patch
Normal file
693
libs/db/patches/110-CVE-2019-2708.patch
Normal file
@@ -0,0 +1,693 @@
|
||||
--- a/src/btree/bt_cursor.c
|
||||
+++ b/src/btree/bt_cursor.c
|
||||
@@ -282,6 +282,8 @@ __bamc_refresh(dbc)
|
||||
*
|
||||
* Recno uses the btree bt_ovflsize value -- it's close enough.
|
||||
*/
|
||||
+ if (t->bt_minkey == 0)
|
||||
+ return (DB_RECOVER);
|
||||
cp->ovflsize = B_MINKEY_TO_OVFLSIZE(
|
||||
dbp, F_ISSET(dbc, DBC_OPD) ? 2 : t->bt_minkey, dbp->pgsize);
|
||||
|
||||
--- a/src/btree/bt_verify.c
|
||||
+++ b/src/btree/bt_verify.c
|
||||
@@ -611,7 +611,11 @@ __bam_vrfy_inp(dbp, vdp, h, pgno, nentri
|
||||
isbad = 1;
|
||||
goto err;
|
||||
default:
|
||||
- DB_ASSERT(env, ret != 0);
|
||||
+ if (ret == 0) {
|
||||
+ isbad = 1;
|
||||
+ ret = DB_VERIFY_FATAL;
|
||||
+ goto err;
|
||||
+ }
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -922,7 +926,7 @@ __bam_vrfy_itemorder(dbp, vdp, ip, h, pg
|
||||
DBT dbta, dbtb, dup_1, dup_2, *p1, *p2, *tmp;
|
||||
ENV *env;
|
||||
PAGE *child;
|
||||
- db_pgno_t cpgno;
|
||||
+ db_pgno_t cpgno, grandparent;
|
||||
VRFY_PAGEINFO *pip;
|
||||
db_indx_t i, *inp;
|
||||
int adj, cmp, freedup_1, freedup_2, isbad, ret, t_ret;
|
||||
@@ -954,7 +958,8 @@ __bam_vrfy_itemorder(dbp, vdp, ip, h, pg
|
||||
|
||||
buf1 = buf2 = NULL;
|
||||
|
||||
- DB_ASSERT(env, !LF_ISSET(DB_NOORDERCHK));
|
||||
+ if (LF_ISSET(DB_NOORDERCHK))
|
||||
+ return (EINVAL);
|
||||
|
||||
dupfunc = (dbp->dup_compare == NULL) ? __bam_defcmp : dbp->dup_compare;
|
||||
if (TYPE(h) == P_LDUP)
|
||||
@@ -963,6 +968,7 @@ __bam_vrfy_itemorder(dbp, vdp, ip, h, pg
|
||||
func = __bam_defcmp;
|
||||
if (dbp->bt_internal != NULL) {
|
||||
bt = (BTREE *)dbp->bt_internal;
|
||||
+ grandparent = bt->bt_root;
|
||||
if (TYPE(h) == P_IBTREE && (bt->bt_compare != NULL ||
|
||||
dupfunc != __bam_defcmp)) {
|
||||
/*
|
||||
@@ -974,8 +980,24 @@ __bam_vrfy_itemorder(dbp, vdp, ip, h, pg
|
||||
*/
|
||||
mpf = dbp->mpf;
|
||||
child = h;
|
||||
+ cpgno = pgno;
|
||||
while (TYPE(child) == P_IBTREE) {
|
||||
+ if (NUM_ENT(child) == 0) {
|
||||
+ EPRINT((env, DB_STR_A("1088",
|
||||
+ "Page %lu: internal page is empty and should not be",
|
||||
+ "%lu"), (u_long)cpgno));
|
||||
+ ret = DB_VERIFY_BAD;
|
||||
+ goto err;
|
||||
+ }
|
||||
bi = GET_BINTERNAL(dbp, child, 0);
|
||||
+ if (grandparent == bi->pgno) {
|
||||
+ EPRINT((env, DB_STR_A("5552",
|
||||
+ "Page %lu: found twice in the btree",
|
||||
+ "%lu"), (u_long)grandparent));
|
||||
+ ret = DB_VERIFY_FATAL;
|
||||
+ goto err;
|
||||
+ } else
|
||||
+ grandparent = cpgno;
|
||||
cpgno = bi->pgno;
|
||||
if (child != h &&
|
||||
(ret = __memp_fput(mpf,
|
||||
@@ -1231,7 +1253,10 @@ overflow: if (!ovflok) {
|
||||
*/
|
||||
if (dup_1.data == NULL ||
|
||||
dup_2.data == NULL) {
|
||||
- DB_ASSERT(env, !ovflok);
|
||||
+ if (ovflok) {
|
||||
+ isbad = 1;
|
||||
+ goto err;
|
||||
+ }
|
||||
if (pip != NULL)
|
||||
F_SET(pip,
|
||||
VRFY_INCOMPLETE);
|
||||
@@ -1569,9 +1594,10 @@ bad_prev: isbad = 1;
|
||||
(ret = __db_vrfy_ovfl_structure(dbp, vdp,
|
||||
child->pgno, child->tlen,
|
||||
flags | DB_ST_OVFL_LEAF)) != 0) {
|
||||
- if (ret == DB_VERIFY_BAD)
|
||||
+ if (ret == DB_VERIFY_BAD) {
|
||||
isbad = 1;
|
||||
- else
|
||||
+ break;
|
||||
+ } else
|
||||
goto done;
|
||||
}
|
||||
|
||||
@@ -1645,9 +1671,10 @@ bad_prev: isbad = 1;
|
||||
stflags | DB_ST_TOPLEVEL,
|
||||
NULL, NULL, NULL)) != 0) {
|
||||
if (ret ==
|
||||
- DB_VERIFY_BAD)
|
||||
+ DB_VERIFY_BAD) {
|
||||
isbad = 1;
|
||||
- else
|
||||
+ break;
|
||||
+ } else
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
@@ -1790,7 +1817,10 @@ bad_prev: isbad = 1;
|
||||
*/
|
||||
|
||||
/* Otherwise, __db_vrfy_childput would be broken. */
|
||||
- DB_ASSERT(env, child->refcnt >= 1);
|
||||
+ if (child->refcnt < 1) {
|
||||
+ isbad = 1;
|
||||
+ goto err;
|
||||
+ }
|
||||
|
||||
/*
|
||||
* An overflow referenced more than twice here
|
||||
@@ -1807,9 +1837,10 @@ bad_prev: isbad = 1;
|
||||
if ((ret = __db_vrfy_ovfl_structure(dbp,
|
||||
vdp, child->pgno, child->tlen,
|
||||
flags)) != 0) {
|
||||
- if (ret == DB_VERIFY_BAD)
|
||||
+ if (ret == DB_VERIFY_BAD) {
|
||||
isbad = 1;
|
||||
- else
|
||||
+ break;
|
||||
+ } else
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
@@ -1847,9 +1878,10 @@ bad_prev: isbad = 1;
|
||||
if ((ret = __bam_vrfy_subtree(dbp, vdp, li->pgno,
|
||||
i == 0 ? NULL : li, ri, flags, &child_level,
|
||||
&child_nrecs, NULL)) != 0) {
|
||||
- if (ret == DB_VERIFY_BAD)
|
||||
+ if (ret == DB_VERIFY_BAD) {
|
||||
isbad = 1;
|
||||
- else
|
||||
+ break;
|
||||
+ } else
|
||||
goto done;
|
||||
}
|
||||
|
||||
@@ -2675,7 +2707,11 @@ __bam_meta2pgset(dbp, vdp, btmeta, flags
|
||||
db_pgno_t current, p;
|
||||
int err_ret, ret;
|
||||
|
||||
- DB_ASSERT(dbp->env, pgset != NULL);
|
||||
+ if (pgset == NULL) {
|
||||
+ EPRINT((dbp->env, DB_STR("5542",
|
||||
+ "Error, database contains no visible pages.")));
|
||||
+ return (DB_RUNRECOVERY);
|
||||
+ }
|
||||
|
||||
mpf = dbp->mpf;
|
||||
h = NULL;
|
||||
--- a/src/db/db_conv.c
|
||||
+++ b/src/db/db_conv.c
|
||||
@@ -493,8 +493,11 @@ __db_byteswap(dbp, pg, h, pagesize, pgin
|
||||
db_indx_t i, *inp, len, tmp;
|
||||
u_int8_t *end, *p, *pgend;
|
||||
|
||||
- if (pagesize == 0)
|
||||
- return (0);
|
||||
+ /* This function is also used to byteswap logs, so
|
||||
+ * the pagesize might not be an actual page size.
|
||||
+ */
|
||||
+ if (!(pagesize >= 24 && pagesize <= DB_MAX_PGSIZE))
|
||||
+ return (EINVAL);
|
||||
|
||||
if (pgin) {
|
||||
M_32_SWAP(h->lsn.file);
|
||||
@@ -513,26 +516,41 @@ __db_byteswap(dbp, pg, h, pagesize, pgin
|
||||
pgend = (u_int8_t *)h + pagesize;
|
||||
|
||||
inp = P_INP(dbp, h);
|
||||
- if ((u_int8_t *)inp >= pgend)
|
||||
- goto out;
|
||||
+ if ((u_int8_t *)inp > pgend)
|
||||
+ return (__db_pgfmt(env, pg));
|
||||
|
||||
switch (TYPE(h)) {
|
||||
case P_HASH_UNSORTED:
|
||||
case P_HASH:
|
||||
for (i = 0; i < NUM_ENT(h); i++) {
|
||||
+ if ((u_int8_t*)(inp + i) >= pgend)
|
||||
+ return (__db_pgfmt(env, pg));
|
||||
+ if (inp[i] == 0)
|
||||
+ continue;
|
||||
if (pgin)
|
||||
M_16_SWAP(inp[i]);
|
||||
+ if (inp[i] >= pagesize)
|
||||
+ return (__db_pgfmt(env, pg));
|
||||
|
||||
- if (P_ENTRY(dbp, h, i) >= pgend)
|
||||
- continue;
|
||||
+ if (P_ENTRY(dbp, h, i) >= pgend)
|
||||
+ return (__db_pgfmt(env, pg));
|
||||
|
||||
switch (HPAGE_TYPE(dbp, h, i)) {
|
||||
case H_KEYDATA:
|
||||
break;
|
||||
case H_DUPLICATE:
|
||||
+ if (LEN_HITEM(dbp, h, pagesize, i) <
|
||||
+ HKEYDATA_SIZE(0))
|
||||
+ return (__db_pgfmt(env, pg));
|
||||
+
|
||||
len = LEN_HKEYDATA(dbp, h, pagesize, i);
|
||||
p = HKEYDATA_DATA(P_ENTRY(dbp, h, i));
|
||||
- for (end = p + len; p < end;) {
|
||||
+
|
||||
+ end = p + len;
|
||||
+ if (end > pgend)
|
||||
+ return (__db_pgfmt(env, pg));
|
||||
+
|
||||
+ while (p < end) {
|
||||
if (pgin) {
|
||||
P_16_SWAP(p);
|
||||
memcpy(&tmp,
|
||||
@@ -544,14 +562,20 @@ __db_byteswap(dbp, pg, h, pagesize, pgin
|
||||
SWAP16(p);
|
||||
}
|
||||
p += tmp;
|
||||
+ if (p >= end)
|
||||
+ return (__db_pgfmt(env, pg));
|
||||
SWAP16(p);
|
||||
}
|
||||
break;
|
||||
case H_OFFDUP:
|
||||
+ if ((inp[i] + HOFFDUP_SIZE) > pagesize)
|
||||
+ return (__db_pgfmt(env, pg));
|
||||
p = HOFFPAGE_PGNO(P_ENTRY(dbp, h, i));
|
||||
SWAP32(p); /* pgno */
|
||||
break;
|
||||
case H_OFFPAGE:
|
||||
+ if ((inp[i] + HOFFPAGE_SIZE) > pagesize)
|
||||
+ return (__db_pgfmt(env, pg));
|
||||
p = HOFFPAGE_PGNO(P_ENTRY(dbp, h, i));
|
||||
SWAP32(p); /* pgno */
|
||||
SWAP32(p); /* tlen */
|
||||
@@ -559,7 +583,6 @@ __db_byteswap(dbp, pg, h, pagesize, pgin
|
||||
default:
|
||||
return (__db_pgfmt(env, pg));
|
||||
}
|
||||
-
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -576,8 +599,12 @@ __db_byteswap(dbp, pg, h, pagesize, pgin
|
||||
case P_LDUP:
|
||||
case P_LRECNO:
|
||||
for (i = 0; i < NUM_ENT(h); i++) {
|
||||
+ if ((u_int8_t *)(inp + i) >= pgend)
|
||||
+ return (__db_pgfmt(env, pg));
|
||||
if (pgin)
|
||||
M_16_SWAP(inp[i]);
|
||||
+ if (inp[i] >= pagesize)
|
||||
+ return (__db_pgfmt(env, pg));
|
||||
|
||||
/*
|
||||
* In the case of on-page duplicates, key information
|
||||
@@ -597,7 +624,7 @@ __db_byteswap(dbp, pg, h, pagesize, pgin
|
||||
|
||||
bk = GET_BKEYDATA(dbp, h, i);
|
||||
if ((u_int8_t *)bk >= pgend)
|
||||
- continue;
|
||||
+ return (__db_pgfmt(env, pg));
|
||||
switch (B_TYPE(bk->type)) {
|
||||
case B_KEYDATA:
|
||||
M_16_SWAP(bk->len);
|
||||
@@ -605,6 +632,8 @@ __db_byteswap(dbp, pg, h, pagesize, pgin
|
||||
case B_DUPLICATE:
|
||||
case B_OVERFLOW:
|
||||
bo = (BOVERFLOW *)bk;
|
||||
+ if (((u_int8_t *)bo + BOVERFLOW_SIZE) > pgend)
|
||||
+ return (__db_pgfmt(env, pg));
|
||||
M_32_SWAP(bo->pgno);
|
||||
M_32_SWAP(bo->tlen);
|
||||
break;
|
||||
@@ -618,12 +647,17 @@ __db_byteswap(dbp, pg, h, pagesize, pgin
|
||||
break;
|
||||
case P_IBTREE:
|
||||
for (i = 0; i < NUM_ENT(h); i++) {
|
||||
+ if ((u_int8_t *)(inp + i) > pgend)
|
||||
+ return (__db_pgfmt(env, pg));
|
||||
if (pgin)
|
||||
M_16_SWAP(inp[i]);
|
||||
+ if ((u_int16_t)(inp[i] +
|
||||
+ BINTERNAL_SIZE(0) - 1) > pagesize)
|
||||
+ break;
|
||||
|
||||
bi = GET_BINTERNAL(dbp, h, i);
|
||||
- if ((u_int8_t *)bi >= pgend)
|
||||
- continue;
|
||||
+ if (((u_int8_t *)bi + BINTERNAL_SIZE(0)) > pgend)
|
||||
+ return (__db_pgfmt(env, pg));
|
||||
|
||||
M_16_SWAP(bi->len);
|
||||
M_32_SWAP(bi->pgno);
|
||||
@@ -634,6 +668,10 @@ __db_byteswap(dbp, pg, h, pagesize, pgin
|
||||
break;
|
||||
case B_DUPLICATE:
|
||||
case B_OVERFLOW:
|
||||
+ if ((u_int16_t)(inp[i] +
|
||||
+ BINTERNAL_SIZE(BOVERFLOW_SIZE) - 1) >
|
||||
+ pagesize)
|
||||
+ goto out;
|
||||
bo = (BOVERFLOW *)bi->data;
|
||||
M_32_SWAP(bo->pgno);
|
||||
M_32_SWAP(bo->tlen);
|
||||
@@ -648,12 +686,16 @@ __db_byteswap(dbp, pg, h, pagesize, pgin
|
||||
break;
|
||||
case P_IRECNO:
|
||||
for (i = 0; i < NUM_ENT(h); i++) {
|
||||
+ if ((u_int8_t *)(inp + i) >= pgend)
|
||||
+ return (__db_pgfmt(env, pg));
|
||||
if (pgin)
|
||||
M_16_SWAP(inp[i]);
|
||||
+ if (inp[i] >= pagesize)
|
||||
+ return (__db_pgfmt(env, pg));
|
||||
|
||||
ri = GET_RINTERNAL(dbp, h, i);
|
||||
- if ((u_int8_t *)ri >= pgend)
|
||||
- continue;
|
||||
+ if ((((u_int8_t *)ri) + RINTERNAL_SIZE) > pgend)
|
||||
+ return (__db_pgfmt(env, pg));
|
||||
|
||||
M_32_SWAP(ri->pgno);
|
||||
M_32_SWAP(ri->nrecs);
|
||||
--- a/src/db/db_vrfy.c
|
||||
+++ b/src/db/db_vrfy.c
|
||||
@@ -375,8 +375,10 @@ __db_verify(dbp, ip, name, subdb, handle
|
||||
vdp, name, 0, lp, rp, flags)) != 0) {
|
||||
if (t_ret == DB_VERIFY_BAD)
|
||||
isbad = 1;
|
||||
- else
|
||||
- goto err;
|
||||
+ else {
|
||||
+ ret = t_ret;
|
||||
+ goto err;
|
||||
+ }
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -764,9 +766,10 @@ __db_vrfy_walkpages(dbp, vdp, handle, ca
|
||||
*/
|
||||
if ((t_ret = __memp_fget(mpf, &i,
|
||||
vdp->thread_info, NULL, 0, &h)) != 0) {
|
||||
- if (dbp->type == DB_HASH ||
|
||||
+ if ((dbp->type == DB_HASH ||
|
||||
(dbp->type == DB_QUEUE &&
|
||||
- F_ISSET(dbp, DB_AM_INMEM))) {
|
||||
+ F_ISSET(dbp, DB_AM_INMEM))) &&
|
||||
+ t_ret != DB_RUNRECOVERY) {
|
||||
if ((t_ret =
|
||||
__db_vrfy_getpageinfo(vdp, i, &pip)) != 0)
|
||||
goto err1;
|
||||
@@ -936,6 +939,8 @@ err: if (h != NULL && (t_ret = __memp_f
|
||||
return (ret == 0 ? t_ret : ret);
|
||||
}
|
||||
|
||||
+ if (ret == DB_PAGE_NOTFOUND && isbad == 1)
|
||||
+ ret = 0;
|
||||
return ((isbad == 1 && ret == 0) ? DB_VERIFY_BAD : ret);
|
||||
}
|
||||
|
||||
@@ -1567,7 +1572,7 @@ __db_vrfy_meta(dbp, vdp, meta, pgno, fla
|
||||
if (pgno == PGNO_BASE_MD &&
|
||||
dbtype != DB_QUEUE && meta->last_pgno != vdp->last_pgno) {
|
||||
#ifdef HAVE_FTRUNCATE
|
||||
- isbad = 1;
|
||||
+ ret = DB_VERIFY_FATAL;
|
||||
EPRINT((env, DB_STR_A("0552",
|
||||
"Page %lu: last_pgno is not correct: %lu != %lu",
|
||||
"%lu %lu %lu"), (u_long)pgno,
|
||||
@@ -1608,7 +1613,11 @@ __db_vrfy_freelist(dbp, vdp, meta, flags
|
||||
|
||||
env = dbp->env;
|
||||
pgset = vdp->pgset;
|
||||
- DB_ASSERT(env, pgset != NULL);
|
||||
+ if (pgset == NULL) {
|
||||
+ EPRINT((env, DB_STR("5543",
|
||||
+ "Error, database contains no visible pages.")));
|
||||
+ return (DB_RUNRECOVERY);
|
||||
+ }
|
||||
|
||||
if ((ret = __db_vrfy_getpageinfo(vdp, meta, &pip)) != 0)
|
||||
return (ret);
|
||||
@@ -1993,7 +2002,8 @@ __db_salvage_pg(dbp, vdp, pgno, h, handl
|
||||
int keyflag, ret, t_ret;
|
||||
|
||||
env = dbp->env;
|
||||
- DB_ASSERT(env, LF_ISSET(DB_SALVAGE));
|
||||
+ if (!LF_ISSET(DB_SALVAGE))
|
||||
+ return (EINVAL);
|
||||
|
||||
/*
|
||||
* !!!
|
||||
@@ -2126,10 +2136,8 @@ __db_salvage_leaf(dbp, vdp, pgno, h, han
|
||||
int (*callback) __P((void *, const void *));
|
||||
u_int32_t flags;
|
||||
{
|
||||
- ENV *env;
|
||||
-
|
||||
- env = dbp->env;
|
||||
- DB_ASSERT(env, LF_ISSET(DB_SALVAGE));
|
||||
+ if (!LF_ISSET(DB_SALVAGE))
|
||||
+ return (EINVAL);
|
||||
|
||||
/* If we got this page in the subdb pass, we can safely skip it. */
|
||||
if (__db_salvage_isdone(vdp, pgno))
|
||||
@@ -2223,8 +2231,8 @@ __db_salvage_unknowns(dbp, vdp, handle,
|
||||
ret = t_ret;
|
||||
break;
|
||||
case SALVAGE_OVERFLOW:
|
||||
- DB_ASSERT(env, 0); /* Shouldn't ever happen. */
|
||||
- break;
|
||||
+ EPRINT((env, DB_STR("5544", "Invalid page type to salvage.")));
|
||||
+ return (EINVAL);
|
||||
case SALVAGE_HASH:
|
||||
if ((t_ret = __ham_salvage(dbp, vdp,
|
||||
pgno, h, handle, callback, flags)) != 0 && ret == 0)
|
||||
@@ -2237,8 +2245,8 @@ __db_salvage_unknowns(dbp, vdp, handle,
|
||||
* Shouldn't happen, but if it does, just do what the
|
||||
* nice man says.
|
||||
*/
|
||||
- DB_ASSERT(env, 0);
|
||||
- break;
|
||||
+ EPRINT((env, DB_STR("5545", "Invalid page type to salvage.")));
|
||||
+ return (EINVAL);
|
||||
}
|
||||
if ((t_ret = __memp_fput(mpf,
|
||||
vdp->thread_info, h, dbp->priority)) != 0 && ret == 0)
|
||||
@@ -2284,8 +2292,8 @@ __db_salvage_unknowns(dbp, vdp, handle,
|
||||
ret = t_ret;
|
||||
break;
|
||||
default:
|
||||
- DB_ASSERT(env, 0); /* Shouldn't ever happen. */
|
||||
- break;
|
||||
+ EPRINT((env, DB_STR("5546", "Invalid page type to salvage.")));
|
||||
+ return (EINVAL);
|
||||
}
|
||||
if ((t_ret = __memp_fput(mpf,
|
||||
vdp->thread_info, h, dbp->priority)) != 0 && ret == 0)
|
||||
@@ -2342,7 +2350,10 @@ __db_vrfy_inpitem(dbp, h, pgno, i, is_bt
|
||||
|
||||
env = dbp->env;
|
||||
|
||||
- DB_ASSERT(env, himarkp != NULL);
|
||||
+ if (himarkp == NULL) {
|
||||
+ __db_msg(env, "Page %lu index has no end.", (u_long)pgno);
|
||||
+ return (DB_VERIFY_FATAL);
|
||||
+ }
|
||||
inp = P_INP(dbp, h);
|
||||
|
||||
/*
|
||||
@@ -2755,7 +2766,11 @@ __db_salvage_subdbpg(dbp, vdp, master, h
|
||||
goto err;
|
||||
ovfl_bufsz = bkkey->len + 1;
|
||||
}
|
||||
- DB_ASSERT(env, subdbname != NULL);
|
||||
+ if (subdbname == NULL) {
|
||||
+ EPRINT((env, DB_STR("5547", "Subdatabase cannot be null.")));
|
||||
+ ret = EINVAL;
|
||||
+ goto err;
|
||||
+ }
|
||||
memcpy(subdbname, bkkey->data, bkkey->len);
|
||||
subdbname[bkkey->len] = '\0';
|
||||
}
|
||||
--- a/src/db/db_vrfyutil.c
|
||||
+++ b/src/db/db_vrfyutil.c
|
||||
@@ -208,7 +208,8 @@ __db_vrfy_getpageinfo(vdp, pgno, pipp)
|
||||
if ((ret = __db_get(pgdbp,
|
||||
vdp->thread_info, vdp->txn, &key, &data, 0)) == 0) {
|
||||
/* Found it. */
|
||||
- DB_ASSERT(env, data.size == sizeof(VRFY_PAGEINFO));
|
||||
+ if (data.size != sizeof(VRFY_PAGEINFO))
|
||||
+ return (DB_VERIFY_FATAL);
|
||||
pip = data.data;
|
||||
LIST_INSERT_HEAD(&vdp->activepips, pip, links);
|
||||
goto found;
|
||||
@@ -336,7 +337,8 @@ __db_vrfy_pgset_get(dbp, ip, txn, pgno,
|
||||
F_SET(&data, DB_DBT_USERMEM);
|
||||
|
||||
if ((ret = __db_get(dbp, ip, txn, &key, &data, 0)) == 0) {
|
||||
- DB_ASSERT(dbp->env, data.size == sizeof(int));
|
||||
+ if (data.size != sizeof(int))
|
||||
+ return (EINVAL);
|
||||
} else if (ret == DB_NOTFOUND)
|
||||
val = 0;
|
||||
else
|
||||
@@ -376,7 +378,8 @@ __db_vrfy_pgset_inc(dbp, ip, txn, pgno)
|
||||
F_SET(&data, DB_DBT_USERMEM);
|
||||
|
||||
if ((ret = __db_get(dbp, ip, txn, &key, &data, 0)) == 0) {
|
||||
- DB_ASSERT(dbp->env, data.size == sizeof(int));
|
||||
+ if (data.size != sizeof(int))
|
||||
+ return (DB_VERIFY_FATAL);
|
||||
} else if (ret != DB_NOTFOUND)
|
||||
return (ret);
|
||||
|
||||
@@ -413,7 +416,8 @@ __db_vrfy_pgset_next(dbc, pgnop)
|
||||
if ((ret = __dbc_get(dbc, &key, &data, DB_NEXT)) != 0)
|
||||
return (ret);
|
||||
|
||||
- DB_ASSERT(dbc->env, key.size == sizeof(db_pgno_t));
|
||||
+ if (key.size != sizeof(db_pgno_t))
|
||||
+ return (DB_VERIFY_FATAL);
|
||||
*pgnop = pgno;
|
||||
|
||||
return (0);
|
||||
@@ -560,7 +564,8 @@ __db_vrfy_ccset(dbc, pgno, cipp)
|
||||
if ((ret = __dbc_get(dbc, &key, &data, DB_SET)) != 0)
|
||||
return (ret);
|
||||
|
||||
- DB_ASSERT(dbc->env, data.size == sizeof(VRFY_CHILDINFO));
|
||||
+ if (data.size != sizeof(VRFY_CHILDINFO))
|
||||
+ return (DB_VERIFY_FATAL);
|
||||
*cipp = (VRFY_CHILDINFO *)data.data;
|
||||
|
||||
return (0);
|
||||
@@ -588,7 +593,8 @@ __db_vrfy_ccnext(dbc, cipp)
|
||||
if ((ret = __dbc_get(dbc, &key, &data, DB_NEXT_DUP)) != 0)
|
||||
return (ret);
|
||||
|
||||
- DB_ASSERT(dbc->env, data.size == sizeof(VRFY_CHILDINFO));
|
||||
+ if (data.size != sizeof(VRFY_CHILDINFO))
|
||||
+ return (DB_VERIFY_FATAL);
|
||||
*cipp = (VRFY_CHILDINFO *)data.data;
|
||||
|
||||
return (0);
|
||||
@@ -715,7 +721,8 @@ __db_salvage_getnext(vdp, dbcp, pgnop, p
|
||||
return (ret);
|
||||
|
||||
while ((ret = __dbc_get(*dbcp, &key, &data, DB_NEXT)) == 0) {
|
||||
- DB_ASSERT(dbp->env, data.size == sizeof(u_int32_t));
|
||||
+ if (data.size != sizeof(u_int32_t))
|
||||
+ return (DB_VERIFY_FATAL);
|
||||
memcpy(&pgtype, data.data, sizeof(pgtype));
|
||||
|
||||
if (skip_overflow && pgtype == SALVAGE_OVERFLOW)
|
||||
@@ -724,8 +731,9 @@ __db_salvage_getnext(vdp, dbcp, pgnop, p
|
||||
if ((ret = __dbc_del(*dbcp, 0)) != 0)
|
||||
return (ret);
|
||||
if (pgtype != SALVAGE_IGNORE) {
|
||||
- DB_ASSERT(dbp->env, key.size == sizeof(db_pgno_t));
|
||||
- DB_ASSERT(dbp->env, data.size == sizeof(u_int32_t));
|
||||
+ if (key.size != sizeof(db_pgno_t)
|
||||
+ || data.size != sizeof(u_int32_t))
|
||||
+ return (DB_VERIFY_FATAL);
|
||||
|
||||
*pgnop = *(db_pgno_t *)key.data;
|
||||
*pgtypep = *(u_int32_t *)data.data;
|
||||
--- a/src/db/partition.c
|
||||
+++ b/src/db/partition.c
|
||||
@@ -461,9 +461,19 @@ __partition_chk_meta(dbp, ip, txn, flags
|
||||
} else
|
||||
part->nparts = meta->nparts;
|
||||
} else if (meta->nparts != 0 && part->nparts != meta->nparts) {
|
||||
+ ret = EINVAL;
|
||||
__db_errx(env, DB_STR("0656",
|
||||
"Number of partitions does not match."));
|
||||
+ goto err;
|
||||
+ }
|
||||
+ /*
|
||||
+ * There is no limit on the number of partitions, but I cannot imagine a real
|
||||
+ * database having more than 10000.
|
||||
+ */
|
||||
+ if (meta->nparts > 10000) {
|
||||
ret = EINVAL;
|
||||
+ __db_errx(env, DB_STR_A("5553",
|
||||
+ "Too many partitions %lu", "%lu"), (u_long)(meta->nparts));
|
||||
goto err;
|
||||
}
|
||||
|
||||
@@ -1874,10 +1884,13 @@ __part_verify(dbp, vdp, fname, handle, c
|
||||
memcpy(rp->data, key->data, key->size);
|
||||
B_TSET(rp->type, B_KEYDATA);
|
||||
}
|
||||
-vrfy: if ((t_ret = __db_verify(*pdbp, ip, (*pdbp)->fname,
|
||||
- NULL, handle, callback,
|
||||
- lp, rp, flags | DB_VERIFY_PARTITION)) != 0 && ret == 0)
|
||||
- ret = t_ret;
|
||||
+vrfy: if ((t_ret = __db_verify(*pdbp, ip, (*pdbp)->fname,
|
||||
+ NULL, handle, callback,
|
||||
+ lp, rp, flags | DB_VERIFY_PARTITION)) != 0 && ret == 0) {
|
||||
+ ret = t_ret;
|
||||
+ if (ret == ENOENT)
|
||||
+ break;
|
||||
+ }
|
||||
}
|
||||
|
||||
err: if (lp != NULL)
|
||||
--- a/src/hash/hash_page.c
|
||||
+++ b/src/hash/hash_page.c
|
||||
@@ -865,7 +865,11 @@ __ham_verify_sorted_page (dbc, p)
|
||||
/* Validate that next, prev pointers are OK */
|
||||
n = NUM_ENT(p);
|
||||
dbp = dbc->dbp;
|
||||
- DB_ASSERT(dbp->env, n%2 == 0 );
|
||||
+ if (n % 2 != 0) {
|
||||
+ __db_errx(dbp->env, DB_STR_A("5549",
|
||||
+ "Odd number of entries on page: %lu", "%lu"), (u_long)(p->pgno));
|
||||
+ return (DB_VERIFY_FATAL);
|
||||
+ }
|
||||
|
||||
env = dbp->env;
|
||||
t = dbp->h_internal;
|
||||
@@ -936,7 +940,12 @@ __ham_verify_sorted_page (dbc, p)
|
||||
if ((ret = __db_prpage(dbp, p, DB_PR_PAGE)) != 0)
|
||||
return (ret);
|
||||
#endif
|
||||
- DB_ASSERT(dbp->env, res < 0);
|
||||
+ if (res >= 0) {
|
||||
+ __db_errx(env, DB_STR_A("5550",
|
||||
+ "Odd number of entries on page: %lu", "%lu"),
|
||||
+ (u_long)p->pgno);
|
||||
+ return (DB_VERIFY_FATAL);
|
||||
+ }
|
||||
}
|
||||
|
||||
prev = curr;
|
||||
--- a/src/hash/hash_verify.c
|
||||
+++ b/src/hash/hash_verify.c
|
||||
@@ -443,7 +443,7 @@ __ham_vrfy_structure(dbp, vdp, meta_pgno
|
||||
isbad = 1;
|
||||
else
|
||||
goto err;
|
||||
- }
|
||||
+ }
|
||||
|
||||
/*
|
||||
* There may be unused hash pages corresponding to buckets
|
||||
@@ -574,7 +574,7 @@ __ham_vrfy_bucket(dbp, vdp, m, bucket, f
|
||||
"Page %lu: impossible first page in bucket %lu", "%lu %lu"),
|
||||
(u_long)pgno, (u_long)bucket));
|
||||
/* Unsafe to continue. */
|
||||
- isbad = 1;
|
||||
+ ret = DB_VERIFY_FATAL;
|
||||
goto err;
|
||||
}
|
||||
|
||||
@@ -604,7 +604,7 @@ __ham_vrfy_bucket(dbp, vdp, m, bucket, f
|
||||
EPRINT((env, DB_STR_A("1116",
|
||||
"Page %lu: hash page referenced twice", "%lu"),
|
||||
(u_long)pgno));
|
||||
- isbad = 1;
|
||||
+ ret = DB_VERIFY_FATAL;
|
||||
/* Unsafe to continue. */
|
||||
goto err;
|
||||
} else if ((ret = __db_vrfy_pgset_inc(vdp->pgset,
|
||||
@@ -1049,7 +1049,11 @@ __ham_meta2pgset(dbp, vdp, hmeta, flags,
|
||||
COMPQUIET(flags, 0);
|
||||
ip = vdp->thread_info;
|
||||
|
||||
- DB_ASSERT(dbp->env, pgset != NULL);
|
||||
+ if (pgset == NULL) {
|
||||
+ EPRINT((dbp->env, DB_STR("5548",
|
||||
+ "Error, database contains no visible pages.")));
|
||||
+ return (DB_VERIFY_FATAL);
|
||||
+ }
|
||||
|
||||
mpf = dbp->mpf;
|
||||
totpgs = 0;
|
||||
--- a/src/qam/qam_verify.c
|
||||
+++ b/src/qam/qam_verify.c
|
||||
@@ -465,7 +465,14 @@ __qam_vrfy_walkqueue(dbp, vdp, handle, c
|
||||
/* Verify/salvage each page. */
|
||||
if ((ret = __db_cursor(dbp, vdp->thread_info, NULL, &dbc, 0)) != 0)
|
||||
return (ret);
|
||||
-begin: for (; i <= stop; i++) {
|
||||
+begin: if ((stop - i) > 100000) {
|
||||
+ EPRINT((env, DB_STR_A("5551",
|
||||
+"Warning, many possible extends files (%lu), will take a long time to verify",
|
||||
+ "%lu"), (u_long)(stop - i)));
|
||||
+ }
|
||||
+ for (; i <= stop; i++) {
|
||||
+ if (i == UINT32_MAX)
|
||||
+ break;
|
||||
/*
|
||||
* If DB_SALVAGE is set, we inspect our database of completed
|
||||
* pages, and skip any we've already printed in the subdb pass.
|
||||
67
libs/db/patches/120-CVE-2019-8457.patch
Normal file
67
libs/db/patches/120-CVE-2019-8457.patch
Normal file
@@ -0,0 +1,67 @@
|
||||
Description: Enhance the rtreenode function in order to avoid a heap out-of-bounds read
|
||||
Origin: https://www.sqlite.org/src/info/90acdbfce9c08858
|
||||
Bug-Debian: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=929775
|
||||
|
||||
--- a/lang/sql/sqlite/ext/rtree/rtree.c
|
||||
+++ b/lang/sql/sqlite/ext/rtree/rtree.c
|
||||
@@ -3089,38 +3089,45 @@ static void rtreenode(sqlite3_context *c
|
||||
RtreeNode node;
|
||||
Rtree tree;
|
||||
int ii;
|
||||
+ int nData;
|
||||
+ int errCode;
|
||||
+ sqlite3_str *pOut;
|
||||
|
||||
UNUSED_PARAMETER(nArg);
|
||||
memset(&node, 0, sizeof(RtreeNode));
|
||||
memset(&tree, 0, sizeof(Rtree));
|
||||
tree.nDim = sqlite3_value_int(apArg[0]);
|
||||
+ if( tree.nDim<1 || tree.nDim>5 ) return;
|
||||
tree.nBytesPerCell = 8 + 8 * tree.nDim;
|
||||
node.zData = (u8 *)sqlite3_value_blob(apArg[1]);
|
||||
+ nData = sqlite3_value_bytes(apArg[1]);
|
||||
+ if( nData<4 ) return;
|
||||
+ if( nData<NCELL(&node)*tree.nBytesPerCell ) return;
|
||||
|
||||
+ pOut = sqlite3_str_new(0);
|
||||
for(ii=0; ii<NCELL(&node); ii++){
|
||||
- char zCell[512];
|
||||
- int nCell = 0;
|
||||
RtreeCell cell;
|
||||
int jj;
|
||||
|
||||
nodeGetCell(&tree, &node, ii, &cell);
|
||||
- sqlite3_snprintf(512-nCell,&zCell[nCell],"%lld", cell.iRowid);
|
||||
- nCell = strlen(zCell);
|
||||
+ if( ii>0 ) sqlite3_str_append(pOut, " ", 1);
|
||||
+ sqlite3_str_appendf(pOut, "{%lld", cell.iRowid);
|
||||
for(jj=0; jj<tree.nDim*2; jj++){
|
||||
- sqlite3_snprintf(512-nCell,&zCell[nCell]," %f",(double)cell.aCoord[jj].f);
|
||||
- nCell = strlen(zCell);
|
||||
+#ifndef SQLITE_RTREE_INT_ONLY
|
||||
+ sqlite3_str_appendf(pOut, " %g", (double)cell.aCoord[jj].f);
|
||||
+#else
|
||||
+ sqlite3_str_appendf(pOut, " %d", cell.aCoord[jj].i);
|
||||
+#endif
|
||||
}
|
||||
|
||||
- if( zText ){
|
||||
- char *zTextNew = sqlite3_mprintf("%s {%s}", zText, zCell);
|
||||
- sqlite3_free(zText);
|
||||
- zText = zTextNew;
|
||||
- }else{
|
||||
- zText = sqlite3_mprintf("{%s}", zCell);
|
||||
- }
|
||||
+
|
||||
+ sqlite3_str_append(pOut, "}", 1);
|
||||
+
|
||||
}
|
||||
-
|
||||
- sqlite3_result_text(ctx, zText, -1, sqlite3_free);
|
||||
+ errCode = sqlite3_str_errcode(pOut);
|
||||
+ sqlite3_result_text(ctx, sqlite3_str_finish(pOut), -1, sqlite3_free);
|
||||
+ sqlite3_result_error_code(ctx, errCode);
|
||||
+
|
||||
}
|
||||
|
||||
static void rtreedepth(sqlite3_context *ctx, int nArg, sqlite3_value **apArg){
|
||||
22
libs/db/patches/130-CVE-2017-10140-cwd-db_config.patch
Normal file
22
libs/db/patches/130-CVE-2017-10140-cwd-db_config.patch
Normal file
@@ -0,0 +1,22 @@
|
||||
Description: CVE-2017-10140: Reads DB_CONFIG from the current working directory
|
||||
Do not access DB_CONFIG when db_home is not set.
|
||||
Origin: vendor, https://src.fedoraproject.org/rpms/libdb/raw/8047fa8580659fcae740c25e91b490539b8453eb/f/db-5.3.28-cwd-db_config.patch
|
||||
Bug-Debian: https://bugs.debian.org/872436
|
||||
Bug-RedHat: https://bugzilla.redhat.com/show_bug.cgi?id=1464032
|
||||
Bug-SuSE: https://bugzilla.novell.com/show_bug.cgi?id=1043886
|
||||
Forwarded: no
|
||||
Author: Petr Kubat <pkubat@redhat.com>
|
||||
Reviewed-by: Salvatore Bonaccorso <carnil@debian.org>
|
||||
Last-Update: 2017-08-17
|
||||
|
||||
--- a/src/env/env_open.c
|
||||
+++ b/src/env/env_open.c
|
||||
@@ -473,7 +473,7 @@ __env_config(dbenv, db_home, flagsp, mod
|
||||
env->db_mode = mode == 0 ? DB_MODE_660 : mode;
|
||||
|
||||
/* Read the DB_CONFIG file. */
|
||||
- if ((ret = __env_read_db_config(env)) != 0)
|
||||
+ if (env->db_home != NULL && (ret = __env_read_db_config(env)) != 0)
|
||||
return (ret);
|
||||
|
||||
/*
|
||||
@@ -0,0 +1,34 @@
|
||||
From: Andy Whitcroft <apw@canonical.com>
|
||||
Subject: [PATCH] MMAP_EXTEND mode requires we extend in full system page increments
|
||||
Date: Wed, 12 Mar 2014 11:58:31 +0100
|
||||
|
||||
When extending a mmap file we must ensure we extend by full system pages,
|
||||
otherwise there is a risk (when the filesystem page size is smaller than
|
||||
the system page size) that we will not allocate disk extents to store
|
||||
the memory and it will be lost resulting in data loss.
|
||||
|
||||
Signed-off-by: Andy Whitcroft <apw@canonical.com>
|
||||
Signed-off-by: Cédric Le Goater <clg@fr.ibm.com>
|
||||
|
||||
---
|
||||
env_file.c | 9 +++++++++
|
||||
1 file changed, 9 insertions(+)
|
||||
|
||||
--- a/src/env/env_file.c
|
||||
+++ b/src/env/env_file.c
|
||||
@@ -28,6 +28,15 @@ __db_file_extend(env, fhp, size)
|
||||
int ret;
|
||||
char buf;
|
||||
|
||||
+#ifdef HAVE_MMAP_EXTEND
|
||||
+ /*
|
||||
+ * We have to ensure we extend a mmap'd segment a full memory page at
|
||||
+ * a time or risk the end of the page not having any filesystem blocks
|
||||
+ * associated resulting in the data loss.
|
||||
+ */
|
||||
+ size = DB_ALIGN(size, getpagesize()) - 1;
|
||||
+#endif
|
||||
+
|
||||
buf = '\0';
|
||||
/*
|
||||
* Extend the file by writing the last page. If the region is >4Gb,
|
||||
15
libs/db/patches/150-mutex-alignment.patch
Normal file
15
libs/db/patches/150-mutex-alignment.patch
Normal file
@@ -0,0 +1,15 @@
|
||||
--- a/src/dbinc/mutex_int.h
|
||||
+++ b/src/dbinc/mutex_int.h
|
||||
@@ -850,7 +850,11 @@ typedef volatile unsigned char tsl_t;
|
||||
* alignment locally.
|
||||
*/
|
||||
#ifndef MUTEX_ALIGN
|
||||
-#define MUTEX_ALIGN sizeof(unsigned int)
|
||||
+# if defined(__linux__) && defined(__sparc__)
|
||||
+# define MUTEX_ALIGN 8
|
||||
+# else
|
||||
+# define MUTEX_ALIGN sizeof(unsigned int)
|
||||
+# endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
29
libs/db/patches/160-pg_crypt_size.patch
Normal file
29
libs/db/patches/160-pg_crypt_size.patch
Normal file
@@ -0,0 +1,29 @@
|
||||
--- a/src/dbinc/db_page.h
|
||||
+++ b/src/dbinc/db_page.h
|
||||
@@ -256,6 +256,17 @@ typedef struct __pg_crypto {
|
||||
*/
|
||||
} PG_CRYPTO;
|
||||
|
||||
+/*
|
||||
+ * With most compilers sizeof(PG_CRYPTO) == 38. However some ABIs
|
||||
+ * require it to be padded to 40 bytes. The padding must be excluded
|
||||
+ * from our size calculations due to the 16-byte alignment requirement
|
||||
+ * for crypto.
|
||||
+ *
|
||||
+ * A similar problem applies to PG_CHKSUM, but it's too late to change
|
||||
+ * that.
|
||||
+ */
|
||||
+#define SIZEOF_PG_CRYPTO 38
|
||||
+
|
||||
typedef struct _db_page {
|
||||
DB_LSN lsn; /* 00-07: Log sequence number. */
|
||||
db_pgno_t pgno; /* 08-11: Current page number. */
|
||||
@@ -291,7 +302,7 @@ typedef struct _db_page {
|
||||
*/
|
||||
#define P_INP(dbp, pg) \
|
||||
((db_indx_t *)((u_int8_t *)(pg) + SIZEOF_PAGE + \
|
||||
- (F_ISSET((dbp), DB_AM_ENCRYPT) ? sizeof(PG_CRYPTO) : \
|
||||
+ (F_ISSET((dbp), DB_AM_ENCRYPT) ? SIZEOF_PG_CRYPTO : \
|
||||
(F_ISSET((dbp), DB_AM_CHKSUM) ? sizeof(PG_CHKSUM) : 0))))
|
||||
|
||||
#define P_IV(dbp, pg) \
|
||||
@@ -1,55 +0,0 @@
|
||||
--- a/sequence/sequence.c
|
||||
+++ b/sequence/sequence.c
|
||||
@@ -187,7 +187,11 @@ __seq_open_pp(seq, txn, keyp, flags)
|
||||
if ((ret = __db_get_flags(dbp, &tflags)) != 0)
|
||||
goto err;
|
||||
|
||||
- if (DB_IS_READONLY(dbp)) {
|
||||
+ /*
|
||||
+ * We can let replication clients open sequences, but must
|
||||
+ * check later that they do not update them.
|
||||
+ */
|
||||
+ if (F_ISSET(dbp, DB_AM_RDONLY)) {
|
||||
ret = __db_rdonly(dbp->env, "DB_SEQUENCE->open");
|
||||
goto err;
|
||||
}
|
||||
@@ -244,6 +248,11 @@ retry: if ((ret = __db_get(dbp, ip,
|
||||
if ((ret != DB_NOTFOUND && ret != DB_KEYEMPTY) ||
|
||||
!LF_ISSET(DB_CREATE))
|
||||
goto err;
|
||||
+ if (IS_REP_CLIENT(env) &&
|
||||
+ !F_ISSET(dbp, DB_AM_NOT_DURABLE)) {
|
||||
+ ret = __db_rdonly(env, "DB_SEQUENCE->open");
|
||||
+ goto err;
|
||||
+ }
|
||||
ret = 0;
|
||||
|
||||
rp = &seq->seq_record;
|
||||
@@ -296,7 +305,12 @@ retry: if ((ret = __db_get(dbp, ip,
|
||||
*/
|
||||
rp = seq->seq_data.data;
|
||||
if (rp->seq_version == DB_SEQUENCE_OLDVER) {
|
||||
-oldver: rp->seq_version = DB_SEQUENCE_VERSION;
|
||||
+oldver: if (IS_REP_CLIENT(env) &&
|
||||
+ !F_ISSET(dbp, DB_AM_NOT_DURABLE)) {
|
||||
+ ret = __db_rdonly(env, "DB_SEQUENCE->open");
|
||||
+ goto err;
|
||||
+ }
|
||||
+ rp->seq_version = DB_SEQUENCE_VERSION;
|
||||
if (!F_ISSET(env, ENV_LITTLEENDIAN)) {
|
||||
if (IS_DB_AUTO_COMMIT(dbp, txn)) {
|
||||
if ((ret =
|
||||
@@ -707,6 +721,13 @@ __seq_get(seq, txn, delta, retp, flags)
|
||||
|
||||
MUTEX_LOCK(env, seq->mtx_seq);
|
||||
|
||||
+ if (handle_check && IS_REP_CLIENT(env) &&
|
||||
+ !F_ISSET(dbp, DB_AM_NOT_DURABLE)) {
|
||||
+ ret = __db_rdonly(env, "DB_SEQUENCE->get");
|
||||
+ goto err;
|
||||
+ }
|
||||
+
|
||||
+
|
||||
if (rp->seq_min + delta > rp->seq_max) {
|
||||
__db_errx(env, "Sequence overflow");
|
||||
ret = EINVAL;
|
||||
@@ -1,42 +0,0 @@
|
||||
--- a/lock/lock.c
|
||||
+++ b/lock/lock.c
|
||||
@@ -1274,10 +1274,12 @@ __lock_put_internal(lt, lockp, obj_ndx,
|
||||
SH_TAILQ_REMOVE(
|
||||
<->obj_tab[obj_ndx], sh_obj, links, __db_lockobj);
|
||||
if (sh_obj->lockobj.size > sizeof(sh_obj->objdata)) {
|
||||
- LOCK_REGION_LOCK(env);
|
||||
+ if (region->part_t_size != 1)
|
||||
+ LOCK_REGION_LOCK(env);
|
||||
__env_alloc_free(<->reginfo,
|
||||
SH_DBT_PTR(&sh_obj->lockobj));
|
||||
- LOCK_REGION_UNLOCK(env);
|
||||
+ if (region->part_t_size != 1)
|
||||
+ LOCK_REGION_UNLOCK(env);
|
||||
}
|
||||
SH_TAILQ_INSERT_HEAD(
|
||||
&FREE_OBJS(lt, part_id), sh_obj, links, __db_lockobj);
|
||||
@@ -1467,15 +1469,21 @@ retry: SH_TAILQ_FOREACH(sh_obj, <->obj
|
||||
if (obj->size <= sizeof(sh_obj->objdata))
|
||||
p = sh_obj->objdata;
|
||||
else {
|
||||
- LOCK_REGION_LOCK(env);
|
||||
+ /*
|
||||
+ * If we have only one partition, the region is locked.
|
||||
+ */
|
||||
+ if (region->part_t_size != 1)
|
||||
+ LOCK_REGION_LOCK(env);
|
||||
if ((ret =
|
||||
__env_alloc(<->reginfo, obj->size, &p)) != 0) {
|
||||
__db_errx(env,
|
||||
"No space for lock object storage");
|
||||
- LOCK_REGION_UNLOCK(env);
|
||||
+ if (region->part_t_size != 1)
|
||||
+ LOCK_REGION_UNLOCK(env);
|
||||
goto err;
|
||||
}
|
||||
- LOCK_REGION_UNLOCK(env);
|
||||
+ if (region->part_t_size != 1)
|
||||
+ LOCK_REGION_UNLOCK(env);
|
||||
}
|
||||
|
||||
memcpy(p, obj->data, obj->size);
|
||||
@@ -1,211 +0,0 @@
|
||||
--- a/lock/lock_deadlock.c
|
||||
+++ b/lock/lock_deadlock.c
|
||||
@@ -121,7 +121,7 @@ __lock_detect(env, atype, rejectp)
|
||||
DB_LOCKTAB *lt;
|
||||
db_timespec now;
|
||||
locker_info *idmap;
|
||||
- u_int32_t *bitmap, *copymap, **deadp, **free_me, *tmpmap;
|
||||
+ u_int32_t *bitmap, *copymap, **deadp, **deadlist, *tmpmap;
|
||||
u_int32_t i, cid, keeper, killid, limit, nalloc, nlockers;
|
||||
u_int32_t lock_max, txn_max;
|
||||
int ret, status;
|
||||
@@ -133,7 +133,8 @@ __lock_detect(env, atype, rejectp)
|
||||
if (IS_REP_CLIENT(env))
|
||||
atype = DB_LOCK_MINWRITE;
|
||||
|
||||
- free_me = NULL;
|
||||
+ copymap = tmpmap = NULL;
|
||||
+ deadlist = NULL;
|
||||
|
||||
lt = env->lk_handle;
|
||||
if (rejectp != NULL)
|
||||
@@ -179,11 +180,11 @@ __lock_detect(env, atype, rejectp)
|
||||
memcpy(copymap, bitmap, nlockers * sizeof(u_int32_t) * nalloc);
|
||||
|
||||
if ((ret = __os_calloc(env, sizeof(u_int32_t), nalloc, &tmpmap)) != 0)
|
||||
- goto err1;
|
||||
+ goto err;
|
||||
|
||||
/* Find a deadlock. */
|
||||
if ((ret =
|
||||
- __dd_find(env, bitmap, idmap, nlockers, nalloc, &deadp)) != 0)
|
||||
+ __dd_find(env, bitmap, idmap, nlockers, nalloc, &deadlist)) != 0)
|
||||
return (ret);
|
||||
|
||||
/*
|
||||
@@ -204,8 +205,7 @@ __lock_detect(env, atype, rejectp)
|
||||
txn_max = TXN_MAXIMUM;
|
||||
|
||||
killid = BAD_KILLID;
|
||||
- free_me = deadp;
|
||||
- for (; *deadp != NULL; deadp++) {
|
||||
+ for (deadp = deadlist; *deadp != NULL; deadp++) {
|
||||
if (rejectp != NULL)
|
||||
++*rejectp;
|
||||
killid = (u_int32_t)(*deadp - bitmap) / nalloc;
|
||||
@@ -342,11 +342,12 @@ dokill: if (killid == BAD_KILLID) {
|
||||
__db_msg(env,
|
||||
"Aborting locker %lx", (u_long)idmap[killid].id);
|
||||
}
|
||||
- __os_free(env, tmpmap);
|
||||
-err1: __os_free(env, copymap);
|
||||
-
|
||||
-err: if (free_me != NULL)
|
||||
- __os_free(env, free_me);
|
||||
+err: if(copymap != NULL)
|
||||
+ __os_free(env, copymap);
|
||||
+ if (deadlist != NULL)
|
||||
+ __os_free(env, deadlist);
|
||||
+ if(tmpmap != NULL)
|
||||
+ __os_free(env, tmpmap);
|
||||
__os_free(env, bitmap);
|
||||
__os_free(env, idmap);
|
||||
|
||||
@@ -360,6 +361,17 @@ err: if (free_me != NULL)
|
||||
|
||||
#define DD_INVALID_ID ((u_int32_t) -1)
|
||||
|
||||
+/*
|
||||
+ * __dd_build --
|
||||
+ * Build the lock dependency bit maps.
|
||||
+ * Notes on synchronization:
|
||||
+ * LOCK_SYSTEM_LOCK is used to hold objects locked when we have
|
||||
+ * a single partition.
|
||||
+ * LOCK_LOCKERS is held while we are walking the lockers list and
|
||||
+ * to single thread the use of lockerp->dd_id.
|
||||
+ * LOCK_DD protects the DD list of objects.
|
||||
+ */
|
||||
+
|
||||
static int
|
||||
__dd_build(env, atype, bmp, nlockers, allocp, idmap, rejectp)
|
||||
ENV *env;
|
||||
@@ -393,6 +405,7 @@ __dd_build(env, atype, bmp, nlockers, al
|
||||
* In particular we do not build the conflict array and our caller
|
||||
* needs to expect this.
|
||||
*/
|
||||
+ LOCK_SYSTEM_LOCK(lt, region);
|
||||
if (atype == DB_LOCK_EXPIRE) {
|
||||
skip: LOCK_DD(env, region);
|
||||
op = SH_TAILQ_FIRST(®ion->dd_objs, __db_lockobj);
|
||||
@@ -430,17 +443,18 @@ skip: LOCK_DD(env, region);
|
||||
OBJECT_UNLOCK(lt, region, indx);
|
||||
}
|
||||
UNLOCK_DD(env, region);
|
||||
+ LOCK_SYSTEM_UNLOCK(lt, region);
|
||||
goto done;
|
||||
}
|
||||
|
||||
/*
|
||||
- * We'll check how many lockers there are, add a few more in for
|
||||
- * good measure and then allocate all the structures. Then we'll
|
||||
- * verify that we have enough room when we go back in and get the
|
||||
- * mutex the second time.
|
||||
+ * Allocate after locking the region
|
||||
+ * to make sure the structures are large enough.
|
||||
*/
|
||||
-retry: count = region->stat.st_nlockers;
|
||||
+ LOCK_LOCKERS(env, region);
|
||||
+ count = region->stat.st_nlockers;
|
||||
if (count == 0) {
|
||||
+ UNLOCK_LOCKERS(env, region);
|
||||
*nlockers = 0;
|
||||
return (0);
|
||||
}
|
||||
@@ -448,50 +462,37 @@ retry: count = region->stat.st_nlockers;
|
||||
if (FLD_ISSET(env->dbenv->verbose, DB_VERB_DEADLOCK))
|
||||
__db_msg(env, "%lu lockers", (u_long)count);
|
||||
|
||||
- count += 20;
|
||||
nentries = (u_int32_t)DB_ALIGN(count, 32) / 32;
|
||||
|
||||
- /*
|
||||
- * Allocate enough space for a count by count bitmap matrix.
|
||||
- *
|
||||
- * XXX
|
||||
- * We can probably save the malloc's between iterations just
|
||||
- * reallocing if necessary because count grew by too much.
|
||||
- */
|
||||
+ /* Allocate enough space for a count by count bitmap matrix. */
|
||||
if ((ret = __os_calloc(env, (size_t)count,
|
||||
- sizeof(u_int32_t) * nentries, &bitmap)) != 0)
|
||||
+ sizeof(u_int32_t) * nentries, &bitmap)) != 0) {
|
||||
+ UNLOCK_LOCKERS(env, region);
|
||||
return (ret);
|
||||
+ }
|
||||
|
||||
if ((ret = __os_calloc(env,
|
||||
sizeof(u_int32_t), nentries, &tmpmap)) != 0) {
|
||||
+ UNLOCK_LOCKERS(env, region);
|
||||
__os_free(env, bitmap);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
if ((ret = __os_calloc(env,
|
||||
(size_t)count, sizeof(locker_info), &id_array)) != 0) {
|
||||
+ UNLOCK_LOCKERS(env, region);
|
||||
__os_free(env, bitmap);
|
||||
__os_free(env, tmpmap);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
/*
|
||||
- * Now go back in and actually fill in the matrix.
|
||||
- */
|
||||
- if (region->stat.st_nlockers > count) {
|
||||
- __os_free(env, bitmap);
|
||||
- __os_free(env, tmpmap);
|
||||
- __os_free(env, id_array);
|
||||
- goto retry;
|
||||
- }
|
||||
-
|
||||
- /*
|
||||
* First we go through and assign each locker a deadlock detector id.
|
||||
*/
|
||||
id = 0;
|
||||
- LOCK_LOCKERS(env, region);
|
||||
SH_TAILQ_FOREACH(lip, ®ion->lockers, ulinks, __db_locker) {
|
||||
if (lip->master_locker == INVALID_ROFF) {
|
||||
+ DB_ASSERT(env, id < count);
|
||||
lip->dd_id = id++;
|
||||
id_array[lip->dd_id].id = lip->id;
|
||||
switch (atype) {
|
||||
@@ -510,7 +511,6 @@ retry: count = region->stat.st_nlockers;
|
||||
lip->dd_id = DD_INVALID_ID;
|
||||
|
||||
}
|
||||
- UNLOCK_LOCKERS(env, region);
|
||||
|
||||
/*
|
||||
* We only need consider objects that have waiters, so we use
|
||||
@@ -669,7 +669,6 @@ again: memset(bitmap, 0, count * sizeof
|
||||
* status after building the bit maps so that we will not detect
|
||||
* a blocked transaction without noting that it is already aborting.
|
||||
*/
|
||||
- LOCK_LOCKERS(env, region);
|
||||
for (id = 0; id < count; id++) {
|
||||
if (!id_array[id].valid)
|
||||
continue;
|
||||
@@ -738,6 +737,7 @@ get_lock: id_array[id].last_lock = R_OF
|
||||
id_array[id].in_abort = 1;
|
||||
}
|
||||
UNLOCK_LOCKERS(env, region);
|
||||
+ LOCK_SYSTEM_UNLOCK(lt, region);
|
||||
|
||||
/*
|
||||
* Now we can release everything except the bitmap matrix that we
|
||||
@@ -839,6 +839,7 @@ __dd_abort(env, info, statusp)
|
||||
ret = 0;
|
||||
|
||||
/* We must lock so this locker cannot go away while we abort it. */
|
||||
+ LOCK_SYSTEM_LOCK(lt, region);
|
||||
LOCK_LOCKERS(env, region);
|
||||
|
||||
/*
|
||||
@@ -895,6 +896,7 @@ __dd_abort(env, info, statusp)
|
||||
done: OBJECT_UNLOCK(lt, region, info->last_ndx);
|
||||
err:
|
||||
out: UNLOCK_LOCKERS(env, region);
|
||||
+ LOCK_SYSTEM_UNLOCK(lt, region);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
@@ -1,118 +0,0 @@
|
||||
--- a/dbinc/repmgr.h
|
||||
+++ b/dbinc/repmgr.h
|
||||
@@ -374,6 +374,7 @@ typedef struct {
|
||||
#define SITE_FROM_EID(eid) (&db_rep->sites[eid])
|
||||
#define EID_FROM_SITE(s) ((int)((s) - (&db_rep->sites[0])))
|
||||
#define IS_VALID_EID(e) ((e) >= 0)
|
||||
+#define IS_KNOWN_REMOTE_SITE(e) ((e) >= 0 && ((u_int)(e)) < db_rep->site_cnt)
|
||||
#define SELF_EID INT_MAX
|
||||
|
||||
#define IS_PEER_POLICY(p) ((p) == DB_REPMGR_ACKS_ALL_PEERS || \
|
||||
--- a/rep/rep_elect.c
|
||||
+++ b/rep/rep_elect.c
|
||||
@@ -33,7 +33,7 @@ static int __rep_elect_init
|
||||
static int __rep_fire_elected __P((ENV *, REP *, u_int32_t));
|
||||
static void __rep_elect_master __P((ENV *, REP *));
|
||||
static int __rep_tally __P((ENV *, REP *, int, u_int32_t *, u_int32_t, roff_t));
|
||||
-static int __rep_wait __P((ENV *, db_timeout_t *, int *, int, u_int32_t));
|
||||
+static int __rep_wait __P((ENV *, db_timeout_t *, int, u_int32_t));
|
||||
|
||||
/*
|
||||
* __rep_elect --
|
||||
@@ -55,7 +55,7 @@ __rep_elect(dbenv, given_nsites, nvotes,
|
||||
ENV *env;
|
||||
LOG *lp;
|
||||
REP *rep;
|
||||
- int done, eid, elected, full_elect, locked, in_progress, need_req;
|
||||
+ int done, elected, full_elect, locked, in_progress, need_req;
|
||||
int ret, send_vote, t_ret;
|
||||
u_int32_t ack, ctlflags, egen, nsites, orig_tally, priority, realpri;
|
||||
u_int32_t tiebreaker;
|
||||
@@ -181,8 +181,7 @@ __rep_elect(dbenv, given_nsites, nvotes,
|
||||
REP_SYSTEM_UNLOCK(env);
|
||||
(void)__rep_send_message(env, DB_EID_BROADCAST,
|
||||
REP_MASTER_REQ, NULL, NULL, 0, 0);
|
||||
- ret = __rep_wait(env, &to, &eid,
|
||||
- 0, REP_F_EPHASE0);
|
||||
+ ret = __rep_wait(env, &to, 0, REP_F_EPHASE0);
|
||||
REP_SYSTEM_LOCK(env);
|
||||
F_CLR(rep, REP_F_EPHASE0);
|
||||
switch (ret) {
|
||||
@@ -286,11 +285,11 @@ restart:
|
||||
REP_SYSTEM_LOCK(env);
|
||||
goto vote;
|
||||
}
|
||||
- ret = __rep_wait(env, &to, &eid, full_elect, REP_F_EPHASE1);
|
||||
+ ret = __rep_wait(env, &to, full_elect, REP_F_EPHASE1);
|
||||
switch (ret) {
|
||||
case 0:
|
||||
/* Check if election complete or phase complete. */
|
||||
- if (eid != DB_EID_INVALID && !IN_ELECTION(rep)) {
|
||||
+ if (!IN_ELECTION(rep)) {
|
||||
RPRINT(env, DB_VERB_REP_ELECT,
|
||||
(env, "Ended election phase 1"));
|
||||
goto edone;
|
||||
@@ -398,15 +397,12 @@ phase2:
|
||||
REP_SYSTEM_LOCK(env);
|
||||
goto i_won;
|
||||
}
|
||||
- ret = __rep_wait(env, &to, &eid, full_elect, REP_F_EPHASE2);
|
||||
+ ret = __rep_wait(env, &to, full_elect, REP_F_EPHASE2);
|
||||
RPRINT(env, DB_VERB_REP_ELECT,
|
||||
(env, "Ended election phase 2 %d", ret));
|
||||
switch (ret) {
|
||||
case 0:
|
||||
- if (eid != DB_EID_INVALID)
|
||||
- goto edone;
|
||||
- ret = DB_REP_UNAVAIL;
|
||||
- break;
|
||||
+ goto edone;
|
||||
case DB_REP_EGENCHG:
|
||||
if (to > timeout)
|
||||
to = timeout;
|
||||
@@ -1050,13 +1046,6 @@ __rep_elect_master(env, rep)
|
||||
ENV *env;
|
||||
REP *rep;
|
||||
{
|
||||
- /*
|
||||
- * We often come through here twice, sometimes even more. We mustn't
|
||||
- * let the redundant calls affect stats counting. But rep_elect relies
|
||||
- * on this first part for setting eidp.
|
||||
- */
|
||||
- rep->master_id = rep->eid;
|
||||
-
|
||||
if (F_ISSET(rep, REP_F_MASTERELECT | REP_F_MASTER)) {
|
||||
/* We've been through here already; avoid double counting. */
|
||||
return;
|
||||
@@ -1093,10 +1082,10 @@ __rep_fire_elected(env, rep, egen)
|
||||
(timeout > 5000000) ? 500000 : ((timeout >= 10) ? timeout / 10 : 1);
|
||||
|
||||
static int
|
||||
-__rep_wait(env, timeoutp, eidp, full_elect, flags)
|
||||
+__rep_wait(env, timeoutp, full_elect, flags)
|
||||
ENV *env;
|
||||
db_timeout_t *timeoutp;
|
||||
- int *eidp, full_elect;
|
||||
+ int full_elect;
|
||||
u_int32_t flags;
|
||||
{
|
||||
DB_REP *db_rep;
|
||||
@@ -1174,7 +1163,6 @@ __rep_wait(env, timeoutp, eidp, full_ele
|
||||
F_CLR(rep, REP_F_EGENUPDATE);
|
||||
ret = DB_REP_EGENCHG;
|
||||
} else if (phase_over) {
|
||||
- *eidp = rep->master_id;
|
||||
done = 1;
|
||||
ret = 0;
|
||||
}
|
||||
--- a/repmgr/repmgr_net.c
|
||||
+++ b/repmgr/repmgr_net.c
|
||||
@@ -100,6 +100,8 @@ __repmgr_send(dbenv, control, rec, lsnp,
|
||||
control, rec, &nsites_sent, &npeers_sent)) != 0)
|
||||
goto out;
|
||||
} else {
|
||||
+ DB_ASSERT(env, IS_KNOWN_REMOTE_SITE(eid));
|
||||
+
|
||||
/*
|
||||
* If this is a request that can be sent anywhere, then see if
|
||||
* we can send it to our peer (to save load on the master), but
|
||||
@@ -1,11 +0,0 @@
|
||||
--- a/repmgr/repmgr_net.c
|
||||
+++ b/repmgr/repmgr_net.c
|
||||
@@ -1136,7 +1136,7 @@ __repmgr_listen(env)
|
||||
}
|
||||
|
||||
ret = net_errno;
|
||||
- __db_err(env, ret, why);
|
||||
+ __db_err(env, ret, "%s", why);
|
||||
clean: if (s != INVALID_SOCKET)
|
||||
(void)closesocket(s);
|
||||
return (ret);
|
||||
Reference in New Issue
Block a user