File suspendlock.diff of Package rpm.22276
Suspend exclusive database lock when scriptlets get called, allowing
read access in scriptlets. Only needed for DB_PRIVATE (aka global)
locking.
--- ./lib/backend/db3.c.orig 2017-12-01 14:27:03.193486711 +0000
+++ ./lib/backend/db3.c 2017-12-01 14:27:23.747426200 +0000
@@ -552,6 +552,46 @@ static void db3_dbSetFSync(rpmdb rdb, in
static int db3_Ctrl(rpmdb rdb, dbCtrlOp ctrl)
{
+ struct flock l;
+ int tries;
+ int fdno = -1;
+ dbiIndex dbi;
+ DB * db;
+
+ switch (ctrl) {
+ case DB_CTRL_SUSPEND_DBLOCK:
+ case DB_CTRL_RESUME_DBLOCK:
+ dbi = rdb->db_pkgs; /* packages db only */
+ if (!dbi)
+ return 1;
+ if (!dbi->cfg.dbi_lockdbfd || (dbi->dbi_flags & DBI_VERIFYONLY) != 0)
+ return 0;
+ if (!(dbi->dbi_rpmdb->db_mode & (O_RDWR|O_WRONLY)))
+ return 0;
+ if (_lockdbfd == 0)
+ return 0;
+ db = dbi->dbi_db;
+ if (!(db->fd(db, &fdno) == 0 && fdno >= 0))
+ return 1;
+ for (tries = 0; tries < 2; tries++) {
+ memset(&l, 0, sizeof(l));
+ l.l_whence = 0;
+ l.l_start = 0;
+ l.l_len = 0;
+ l.l_type = ctrl == DB_CTRL_SUSPEND_DBLOCK ? F_RDLCK : F_WRLCK;
+ if (!fcntl(fdno, tries ? F_SETLKW : F_SETLK, (void *)&l))
+ return 0;
+ if (ctrl == DB_CTRL_SUSPEND_DBLOCK) {
+ rpmlog(RPMLOG_WARNING, _("could not suspend database lock\n"));
+ return 1;
+ }
+ if (tries == 0)
+ rpmlog(RPMLOG_WARNING, _("waiting to reestablish exclusive database lock\n"));
+ }
+ return 1;
+ default:
+ break;
+ }
return 0;
}
--- ./lib/backend/dbi.h.orig 2017-12-01 14:27:03.193486711 +0000
+++ ./lib/backend/dbi.h 2017-12-01 14:27:23.747426200 +0000
@@ -17,7 +17,9 @@ typedef enum dbCtrlOp_e {
DB_CTRL_UNLOCK_RO = 2,
DB_CTRL_LOCK_RW = 3,
DB_CTRL_UNLOCK_RW = 4,
- DB_CTRL_INDEXSYNC = 5
+ DB_CTRL_INDEXSYNC = 5,
+ DB_CTRL_SUSPEND_DBLOCK = 100,
+ DB_CTRL_RESUME_DBLOCK = 101
} dbCtrlOp;
typedef struct dbiIndex_s * dbiIndex;
--- ./lib/rpmdb.c.orig 2017-12-01 14:27:03.190486720 +0000
+++ ./lib/rpmdb.c 2017-12-01 14:27:23.748426197 +0000
@@ -2639,6 +2639,12 @@ int rpmdbCtrl(rpmdb db, rpmdbCtrlOp ctrl
case RPMDB_CTRL_INDEXSYNC:
dbctrl = DB_CTRL_INDEXSYNC;
break;
+ case RPMDB_CTRL_SUSPEND_DBLOCK:
+ dbctrl = DB_CTRL_SUSPEND_DBLOCK;
+ break;
+ case RPMDB_CTRL_RESUME_DBLOCK:
+ dbctrl = DB_CTRL_RESUME_DBLOCK;
+ break;
}
return dbctrl ? dbCtrl(db, dbctrl) : 1;
}
--- ./lib/rpmdb.h.orig 2017-10-05 10:04:57.035602138 +0000
+++ ./lib/rpmdb.h 2017-12-01 14:27:23.748426197 +0000
@@ -35,7 +35,9 @@ typedef enum rpmdbCtrlOp_e {
RPMDB_CTRL_UNLOCK_RO = 2,
RPMDB_CTRL_LOCK_RW = 3,
RPMDB_CTRL_UNLOCK_RW = 4,
- RPMDB_CTRL_INDEXSYNC = 5
+ RPMDB_CTRL_INDEXSYNC = 5,
+ RPMDB_CTRL_SUSPEND_DBLOCK = 100,
+ RPMDB_CTRL_RESUME_DBLOCK = 101
} rpmdbCtrlOp;
/** \ingroup rpmdb
--- ./lib/transaction.c.orig 2017-12-01 14:27:23.750426192 +0000
+++ ./lib/transaction.c 2017-12-01 14:28:43.232192224 +0000
@@ -1457,6 +1457,7 @@ rpmRC runScript(rpmts ts, rpmte te, Head
stag != RPMTAG_PREUN &&
stag != RPMTAG_PRETRANS &&
stag != RPMTAG_VERIFYSCRIPT);
+ rpmdb rdb = rpmtsGetRdb(ts);
/* Fake up a transaction element for triggers from rpmdb */
if (te == NULL) {
@@ -1468,10 +1469,12 @@ rpmRC runScript(rpmts ts, rpmte te, Head
if (sfd == NULL)
sfd = rpmtsScriptFd(ts);
+ rpmdbCtrl(rdb, RPMDB_CTRL_SUSPEND_DBLOCK);
rpmswEnter(rpmtsOp(ts, RPMTS_OP_SCRIPTLETS), 0);
rc = rpmScriptRun(script, arg1, arg2, sfd,
prefixes, warn_only, rpmtsPlugins(ts));
rpmswExit(rpmtsOp(ts, RPMTS_OP_SCRIPTLETS), 0);
+ rpmdbCtrl(rdb, RPMDB_CTRL_RESUME_DBLOCK);
/* Map warn-only errors to "notfound" for script stop callback */
stoprc = (rc != RPMRC_OK && warn_only) ? RPMRC_NOTFOUND : rc;