rpm/suspendlock.diff

161 lines
4.1 KiB
Diff
Raw Normal View History

Suspend exclusive database lock when scriptlets get called, allowing
read access in scriptlets. Only needed for DB_PRIVATE (aka global)
locking.
I hijacked the dbiSync function for this because I did not want
to change the ABI.
Index: lib/psm.c
===================================================================
--- lib/psm.c.orig
+++ lib/psm.c
@@ -756,6 +756,8 @@ static rpmRC runScript(rpmpsm psm, Heade
goto exit;
}
+ rpmtsSuspendResumeDBLock(psm->ts, 0);
+
xx = rpmsqFork(&psm->sq);
if (psm->sq.child == 0) {
rpmlog(RPMLOG_DEBUG, "%s: %s\texecv(%s) pid %d\n",
@@ -770,6 +772,8 @@ static rpmRC runScript(rpmpsm psm, Heade
(void) psmWait(psm);
+ rpmtsSuspendResumeDBLock(psm->ts, 1);
+
if (psm->sq.reaped < 0) {
rpmlog(RPMLOG_ERR, _("%s scriptlet failed, waitpid(%d) rc %d: %s\n"),
sname, psm->sq.child, psm->sq.reaped, strerror(errno));
Index: lib/rpmts.c
===================================================================
--- lib/rpmts.c.orig
+++ lib/rpmts.c
@@ -108,6 +108,11 @@ int rpmtsOpenDB(rpmts ts, int dbmode)
return rc;
}
+int rpmtsSuspendResumeDBLock(rpmts ts, int mode)
+{
+ return rpmdbSuspendResumeDBLock(ts->rdb, mode);
+}
+
int rpmtsInitDB(rpmts ts, int dbmode)
{
void *lock = rpmtsAcquireLock(ts);
Index: lib/rpmts.h
===================================================================
--- lib/rpmts.h.orig
+++ lib/rpmts.h
@@ -472,6 +472,10 @@ rpmdb rpmtsGetRdb(rpmts ts);
*/
int rpmtsInitDSI(const rpmts ts);
+int rpmtsSuspendResumeDBLock(rpmts ts, int mode)
+ /*@globals fileSystem @*/
+ /*@modifies fileSystem @*/;
+
/** \ingroup rpmts
* Update disk space info for a file.
* @param ts transaction set
Index: lib/backend/db3.c
===================================================================
--- lib/backend/db3.c.orig
+++ lib/backend/db3.c
@@ -398,12 +398,18 @@ errxit:
return rc;
}
+static int db3SuspendResumeLock(dbiIndex dbi, int mode);
+
static int db3sync(dbiIndex dbi, unsigned int flags)
{
DB * db = dbi->dbi_db;
int rc = 0;
int _printit;
+ if (flags == (unsigned int)-1)
+ return db3SuspendResumeLock(dbi, 0);
+ if (flags == (unsigned int)-2)
+ return db3SuspendResumeLock(dbi, 1);
if (db != NULL)
rc = db->sync(db, flags);
/* XXX DB_INCOMPLETE is returned occaisionally with multiple access. */
@@ -1122,6 +1128,50 @@ static int db3open(rpmdb rpmdb, rpmTag r
return rc;
}
+static int
+db3SuspendResumeLock(dbiIndex dbi, int mode)
+{
+ struct flock l;
+ int rc = 0;
+ int tries;
+ int fdno = -1;
+
+ if (!dbi->dbi_lockdbfd)
+ return 0;
+ if (!(dbi->dbi_mode & (O_RDWR|O_WRONLY)))
+ return 0;
+ if ((dbi->dbi_ecflags & DB_CLIENT) && dbi->dbi_host)
+ return 0;
+ if (dbi->dbi_use_dbenv && _lockdbfd == 0)
+ return 0;
+ if (!(dbi->dbi_db->fd(dbi->dbi_db, &fdno) == 0 && fdno >= 0))
+ return 1;
+ if (mode == 0) {
+ memset(&l, 0, sizeof(l));
+ l.l_whence = 0;
+ l.l_start = 0;
+ l.l_len = 0;
+ l.l_type = F_RDLCK;
+ rc = fcntl(fdno, F_SETLK, (void *) &l);
+ if (rc)
+ rpmlog(RPMLOG_WARNING, _("could not suspend database lock\n"));
+ } else {
+ 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 = F_WRLCK;
+ rc = fcntl(fdno, tries ? F_SETLKW : F_SETLK, (void *) &l);
+ if (!rc)
+ break;
+ if (tries == 0)
+ rpmlog(RPMLOG_WARNING, _("waiting to reestablish exclusive database lock\n"));
+ }
+ }
+ return rc;
+}
+
/** \ingroup db3
*/
RPM_GNUC_INTERNAL
Index: lib/rpmdb.c
===================================================================
--- lib/rpmdb.c.orig
+++ lib/rpmdb.c
@@ -886,6 +886,21 @@ int rpmdbSync(rpmdb db)
return rc;
}
+int rpmdbSuspendResumeDBLock(rpmdb db, int mode)
+{
+ int dbix;
+ int rc = 0;
+ if (db == NULL) return 0;
+ for (dbix = 0; dbix < db->db_ndbi; dbix++) {
+ int xx;
+ if (db->_dbi[dbix] == NULL)
+ continue;
+ xx = dbiSync(db->_dbi[dbix], mode ? -2 : -1);
+ if (xx && rc == 0) rc = xx;
+ }
+ return rc;
+}
+
/* FIX: dbTemplate structure assignment */
static
rpmdb newRpmdb(const char * root,