summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPanu Matilainen <pmatilai@redhat.com>2017-08-28 18:56:04 +0300
committerPanu Matilainen <pmatilai@redhat.com>2017-10-26 10:40:47 +0300
commit61ca9299669ef990bd835f78ae0c454445ca4de6 (patch)
tree5fdc3c4d1ca4b6fe0713783e28580e5fa6a9b975
parent96b610f53b73fb096138f70454c5e5d4d35e4cd4 (diff)
downloadrpm-61ca9299669ef990bd835f78ae0c454445ca4de6.tar.gz
Limit automatic fallback to DB_PRIVATE to read-only operations
Only permit automatic fallback to the essentially lockless operation of DB_PRIVATE when read-only database is requested. This isn't exactly correct, as readers need locks for correct operation just like writers do, but at least in the readonly case the database wont be damaged. The exception to the rule is systems which don't support the shared mapping at all so we don't have much choice. Explicitly configured I-know-what-I'm-doing DB_PRIVATE is not affected either. (cherry picked from commit 70a1efa52b2c442308fd1ddfd706770b6515a2c5)
-rw-r--r--lib/backend/db3.c8
1 files changed, 6 insertions, 2 deletions
diff --git a/lib/backend/db3.c b/lib/backend/db3.c
index 7f302a71a..bbf10bc85 100644
--- a/lib/backend/db3.c
+++ b/lib/backend/db3.c
@@ -401,6 +401,7 @@ static int db_init(rpmdb rdb, const char * dbhome)
int rc, xx;
int retry_open = 2;
int lockfd = -1;
+ int rdonly = ((rdb->db_mode & O_ACCMODE) == O_RDONLY);
struct dbConfig_s * cfg = &rdb->cfg;
/* This is our setup, thou shall not have other setups before us */
uint32_t eflags = (DB_CREATE|DB_INIT_MPOOL|DB_INIT_CDB);
@@ -469,7 +470,7 @@ static int db_init(rpmdb rdb, const char * dbhome)
*/
if (!(eflags & DB_PRIVATE)) {
lockfd = serialize_env(dbhome);
- if (lockfd < 0) {
+ if (lockfd < 0 && rdonly) {
eflags |= DB_PRIVATE;
retry_open--;
rpmlog(RPMLOG_DEBUG, "serialize failed, using private dbenv\n");
@@ -487,7 +488,10 @@ static int db_init(rpmdb rdb, const char * dbhome)
free(fstr);
rc = (dbenv->open)(dbenv, dbhome, eflags, rdb->db_perms);
- if ((rc == EACCES || rc == EROFS) || (rc == EINVAL && errno == rc)) {
+ if (rc == EINVAL && errno == rc) {
+ eflags |= DB_PRIVATE;
+ retry_open--;
+ } else if (rdonly && (rc == EACCES || rc == EROFS)) {
eflags |= DB_PRIVATE;
retry_open--;
} else {