diff --git a/db-5.3.28-condition-variable-ppc.patch b/db-5.3.28-condition-variable-ppc.patch new file mode 100644 index 0000000..13b2b8f --- /dev/null +++ b/db-5.3.28-condition-variable-ppc.patch @@ -0,0 +1,111 @@ +diff -up db-5.3.28/src/env/env_region.c.pthreads db-5.3.28/src/env/env_region.c +--- db-5.3.28/src/env/env_region.c.pthreads 2017-06-19 08:48:19.362325045 +0200 ++++ db-5.3.28/src/env/env_region.c 2017-06-19 08:49:38.910773653 +0200 +@@ -305,15 +305,7 @@ user_map_functions: + goto creation; + } + +- /* We have an old environment but cannot rebuild it safely. */ +- if (ret == DB_OLD_VERSION) { +- __db_errx(env, DB_STR("1539", +- "Build signature doesn't match environment")); +- ret = DB_VERSION_MISMATCH; +- goto err; +- } +- + if (renv->majver != DB_VERSION_MAJOR || + renv->minver != DB_VERSION_MINOR) { + /* + * Special case a region that's all nul bytes, just treat it +@@ -337,6 +329,20 @@ user_map_functions: + goto err; + } + ++ /* ++ * We have an old environment but cannot rebuild it safely. ++ * The environment might still be readable by the current process ++ * (only the libpthread timestamp changed) if this process is the one ++ * that is holding the lock on the region file as we can be sure ++ * the environment did not get rebuilt under our feet. ++ */ ++ if (ret == DB_OLD_VERSION && __check_lock_fn(env->lockfhp->name, getpid()) ) { ++ __db_errx(env, DB_STR("1539", ++ "Build signature doesn't match environment")); ++ ret = DB_VERSION_MISMATCH; ++ goto err; ++ } ++ + /* + * Check if the environment has had a catastrophic failure. + * +diff -up db-5.3.28/src/os/os_flock.c.pthreads db-5.3.28/src/os/os_flock.c +--- db-5.3.28/src/os/os_flock.c.pthreads 2017-06-19 08:48:19.362325045 +0200 ++++ db-5.3.28/src/os/os_flock.c 2017-06-19 08:48:19.364325006 +0200 +@@ -15,6 +15,67 @@ static int __os_filelocking_notsup __P(( + #endif + + /* ++ * __check_lock_fn -- ++ * Parse /proc/locks to see if the file described by 'fn' is locked. ++ * Additionally (if 'pid' is not 0) check if the process holding ++ * the lock has the same pid value as 'pid'. ++ * ++ * Returns 0 if a lock on fn is found, 1 if it is not found and -1 on error. ++ */ ++ ++int __check_lock_fn(fn, pid) ++ char *fn; ++ pid_t pid; ++{ ++ FILE* fp; ++ char buffer[PATH_MAX]; ++ char *token; ++ int i, fd, inode; ++ struct stat st; ++ pid_t lpid = 0; ++ ++ if (!fn) ++ return -1; ++ ++ fp = fopen("/proc/locks", "r"); ++ if (!fp) ++ return -1; ++ ++ /* Get the file's inode */ ++ if (stat(fn, &st)) ++ return -1; ++ ++ while (fgets(buffer, sizeof(buffer), fp)) ++ for (token = strtok(buffer, " "), i = 0; token; token = strtok(NULL, " "), i++) { ++ /* Do not parse any other fields */ ++ if (i > 5) ++ break; ++ /* Save the PID */ ++ if (i == 4) ++ lpid = atoi(token); ++ /* Check the inode */ ++ else if (i == 5) { ++ inode = 0; ++ sscanf(token, "%*02x:%*02x:%d", &inode); ++ /* Not the inode we are looking for */ ++ if (inode != st.st_ino) ++ continue; ++ /* ++ * We have the correct file. ++ * We are either looking for a specific process or we do not care at all. ++ */ ++ if (!pid || lpid == pid) { ++ fclose(fp); ++ return 0; ++ } ++ /* Not the lock we are looking for */ ++ } ++ } ++ fclose(fp); ++ return 1; ++} ++ ++/* + * __os_fdlock -- + * Acquire/release a lock on a byte in a file. + * diff --git a/db-5.3.28-rpm-lock-check.patch b/db-5.3.28-rpm-lock-check.patch index e9da60e..3fad092 100644 --- a/db-5.3.28-rpm-lock-check.patch +++ b/db-5.3.28-rpm-lock-check.patch @@ -1,67 +1,73 @@ diff -up db-5.3.28/src/env/env_region.c.rpmlock db-5.3.28/src/env/env_region.c ---- db-5.3.28/src/env/env_region.c.rpmlock 2017-06-13 11:17:13.750899154 +0200 -+++ db-5.3.28/src/env/env_region.c 2017-06-13 11:18:22.221560122 +0200 -@@ -290,7 +290,8 @@ user_map_functions: - +--- db-5.3.28/src/env/env_region.c.rpmlock 2017-06-19 09:53:42.727715374 +0200 ++++ db-5.3.28/src/env/env_region.c 2017-06-19 09:55:28.195688220 +0200 +@@ -291,18 +291,23 @@ user_map_functions: if (create_ok && ret == DB_OLD_VERSION && -- ENV_PRIMARY_LOCK(env, DB_LOCK_WRITE, 1) == 0) { -+ ENV_PRIMARY_LOCK(env, DB_LOCK_WRITE, 1) == 0 && -+ __rpm_lock_check(env) == 0) { - if (FLD_ISSET(dbenv->verbose, DB_VERB_RECOVERY)) - __db_msg(env, "Recreating idle environment"); - F_SET(infop, REGION_CREATE_OK); + ENV_PRIMARY_LOCK(env, DB_LOCK_WRITE, 1) == 0) { +- if (FLD_ISSET(dbenv->verbose, DB_VERB_RECOVERY)) +- __db_msg(env, "Recreating idle environment"); +- F_SET(infop, REGION_CREATE_OK); ++ /* If the rpm transaction lock is taken we cannot safely rebuild */ ++ if (!__rpm_lock_free(env)) ++ ENV_PRIMARY_UNLOCK(env); ++ else { ++ if (FLD_ISSET(dbenv->verbose, DB_VERB_RECOVERY)) ++ __db_msg(env, "Recreating idle environment"); ++ F_SET(infop, REGION_CREATE_OK); + +- /* +- * Detach from the environment region; we need to unmap it (and +- * close any file handle) so that we don't leak memory or files. +- */ +- DB_ASSERT(env, infop->rp == NULL); +- infop->rp = &tregion; +- (void)__env_sys_detach(env, infop, 0); +- goto creation; ++ /* ++ * Detach from the environment region; we need to unmap it (and ++ * close any file handle) so that we don't leak memory or files. ++ */ ++ DB_ASSERT(env, infop->rp == NULL); ++ infop->rp = &tregion; ++ (void)__env_sys_detach(env, infop, 0); ++ goto creation; ++ } + } + + if (renv->majver != DB_VERSION_MAJOR || diff -up db-5.3.28/src/os/os_flock.c.rpmlock db-5.3.28/src/os/os_flock.c ---- db-5.3.28/src/os/os_flock.c.rpmlock 2017-06-13 11:17:13.748899193 +0200 -+++ db-5.3.28/src/os/os_flock.c 2017-06-13 11:17:13.750899154 +0200 -@@ -15,6 +15,53 @@ static int __os_filelocking_notsup __P(( - #endif +--- db-5.3.28/src/os/os_flock.c.rpmlock 2017-06-19 09:52:49.418740004 +0200 ++++ db-5.3.28/src/os/os_flock.c 2017-06-19 09:53:16.428220866 +0200 +@@ -70,6 +70,34 @@ int __check_lock_fn(fn, pid) + } /* -+ * __rpm_lock_check -- -+ * Try to acquire and release a lock used by rpm to see -+ * if libdb is being updated and it is safe to access -+ * its environment files. -+ * -+ * FIXME: This function leaks the file descriptor on purpose -+ * so that rpm's transaction lock is not dropped due to -+ * how fcntl locks interact with close(2). ++ * __rpm_lock_free -- ++ * Try to look at a lock used by rpm to see if libdb is being ++ * updated and it is safe to access its environment files. + */ + +#define RPM_PATH SHAREDSTATEDIR "/rpm" +#define RPMLOCK_PATH RPM_PATH "/.rpm.lock" + -+int __rpm_lock_check(env) ++int __rpm_lock_free(env) + ENV *env; +{ -+#ifdef HAVE_FCNTL -+ struct flock info; -+ int fd; + int ret; + ++ /* No need to check the transaction lock if not in rpm */ + if (strstr(env->db_home, RPM_PATH) == NULL) -+ /* No need to check the transaction lock if not in rpm */ -+ return 0; ++ return 1; + -+ fd = open(RPMLOCK_PATH, O_RDWR); -+ if (fd == -1) ++ /* Assume it is safe to rebuild if the lock file does not exist */ ++ if (access(RPMLOCK_PATH, F_OK) && errno == ENOENT) + return 1; -+ /* Try to get an exclusive lock on rpm's lock file */ -+ info.l_type = F_WRLCK; -+ info.l_whence = SEEK_SET; -+ info.l_start = 0; -+ info.l_len = 0; -+ info.l_pid = 0; -+ /* We do not want to hold so just check if we can get it */ -+ if ((ret = fcntl(fd, F_GETLK, &info)) != -1 && info.l_type == F_UNLCK) -+ /* Lock is not taken, the environment can be rebuilt */ -+ return 0; -+ else -+ return 1; -+#else -+ /* fcntl not supported, fail with error message */ -+ return __os_filelocking_notsup(env); -+#endif ++ ++ ret = __check_lock_fn(RPMLOCK_PATH, 0); ++ /* __check_lock_fn can return -1 on failure - return 0 (taken) instead */ ++ return ret == -1 ? 0: ret; ++ +} + +/* diff --git a/libdb.spec b/libdb.spec index 0dd9ccf..eb49b4f 100644 --- a/libdb.spec +++ b/libdb.spec @@ -35,9 +35,11 @@ Patch29: db-5.3.28-lemon_hash.patch # upstream patch adding the ability to recreate libdb's environment on version mismatch # or when libpthread.so is modified (rhbz#1394862) Patch30: db-5.3.28-condition_variable.patch -# downstream patch to check whether there is a rpm transaction going on when rpm's environment needs to be rebuilt -# TODO: remove this patch as soon as we can afford to -Patch31: db-5.3.28-rpm-lock-check.patch +# additional changes to the upstream patch to address rhbz#1460003 +Patch31: db-5.3.28-condition-variable-ppc.patch +# downstream patch that adds a check for rpm transaction lock in order to be able to update libdb +# FIXME: remove when able +Patch32: db-5.3.28-rpm-lock-check.patch URL: http://www.oracle.com/database/berkeley-db/ License: BSD and LGPLv2 and Sleepycat @@ -232,6 +234,7 @@ popd %patch29 -p1 %patch30 -p1 %patch31 -p1 +%patch32 -p1 cd dist ./s_config