summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorAnas Nashif <anas.nashif@intel.com>2012-10-11 12:38:04 -0700
committerAnas Nashif <anas.nashif@intel.com>2013-02-02 16:44:15 -0800
commitcd10f180b09bd91d4d720c66a0835b757d7f944f (patch)
treec2134ff9c2ff07e707fb9f972cc315bcaa31577d /lib
parent76bb342f9ae2c3e5a902fc9f66af03d072d523d7 (diff)
downloadrpm-cd10f180b09bd91d4d720c66a0835b757d7f944f.tar.gz
rpm-cd10f180b09bd91d4d720c66a0835b757d7f944f.tar.bz2
rpm-cd10f180b09bd91d4d720c66a0835b757d7f944f.zip
Suspend exclusive database lock when scriptlets get called
Suspend exclusive database lock when scriptlets get called, allowing read access in scriptlets. Only needed for DB_PRIVATE (aka global) locking.
Diffstat (limited to 'lib')
-rw-r--r--lib/backend/db3.c56
-rw-r--r--lib/backend/dbi.h18
-rw-r--r--lib/psm.c2
-rw-r--r--lib/rpmdb.c6
-rw-r--r--lib/rpmts.c5
-rw-r--r--lib/rpmts.h2
6 files changed, 89 insertions, 0 deletions
diff --git a/lib/backend/db3.c b/lib/backend/db3.c
index a47d08b78..a55a608cf 100644
--- a/lib/backend/db3.c
+++ b/lib/backend/db3.c
@@ -632,3 +632,59 @@ int dbiOpen(rpmdb rdb, rpmDbiTagVal rpmtag, dbiIndex * dbip, int flags)
return rc;
}
+
+int dbiSuspendDBLock(dbiIndex dbi, unsigned int flags)
+{
+ struct flock l;
+ int rc = 0;
+ int fdno = -1;
+
+ if (!dbi->dbi_lockdbfd)
+ return 0;
+ if (!(dbi->dbi_rpmdb->db_mode & (O_RDWR|O_WRONLY)))
+ return 0;
+ if (_lockdbfd == 0)
+ return 0;
+ if (!(dbi->dbi_db->fd(dbi->dbi_db, &fdno) == 0 && fdno >= 0))
+ return 1;
+ 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"));
+ return rc;
+}
+
+int dbiResumeDBLock(dbiIndex dbi, unsigned int flags)
+{
+ struct flock l;
+ int rc = 0;
+ int tries;
+ int fdno = -1;
+
+ if (!dbi->dbi_lockdbfd)
+ return 0;
+ if (!(dbi->dbi_rpmdb->db_mode & (O_RDWR|O_WRONLY)))
+ return 0;
+ if (_lockdbfd == 0)
+ return 0;
+ if (!(dbi->dbi_db->fd(dbi->dbi_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 = 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;
+}
+
diff --git a/lib/backend/dbi.h b/lib/backend/dbi.h
index 49fa1f1f2..3d848a8a0 100644
--- a/lib/backend/dbi.h
+++ b/lib/backend/dbi.h
@@ -81,6 +81,24 @@ struct dbiIndex_s {
extern "C" {
#endif
+/** \ingroup dbi
+ * Suspend the exclusive lock on the dbi
+ * @param dbi index database handle
+ * @param flags (unused)
+ * @return 0 on success
+ */
+RPM_GNUC_INTERNAL
+int dbiSuspendDBLock(dbiIndex dbi, unsigned int flags);
+
+/** \ingroup dbi
+ * Reacquire an exclusive lock on the dbi
+ * @param dbi index database handle
+ * @param flags (unused)
+ * @return 0 on success
+ */
+RPM_GNUC_INTERNAL
+int dbiResumeDBLock(dbiIndex dbi, unsigned int flags);
+
RPM_GNUC_INTERNAL
/* Globally enable/disable fsync in the backend */
diff --git a/lib/psm.c b/lib/psm.c
index c786f1e37..aad047fcf 100644
--- a/lib/psm.c
+++ b/lib/psm.c
@@ -419,10 +419,12 @@ static rpmRC runScript(rpmpsm psm, ARGV_const_t prefixes,
if (sfd == NULL)
sfd = rpmtsScriptFd(psm->ts);
+ rpmtsSuspendResumeDBLock(psm->ts, 0);
rpmswEnter(rpmtsOp(psm->ts, RPMTS_OP_SCRIPTLETS), 0);
rc = rpmScriptRun(script, arg1, arg2, sfd,
prefixes, warn_only, selinux);
rpmswExit(rpmtsOp(psm->ts, RPMTS_OP_SCRIPTLETS), 0);
+ rpmtsSuspendResumeDBLock(psm->ts, 1);
/* Map warn-only errors to "notfound" for script stop callback */
stoprc = (rc != RPMRC_OK && warn_only) ? RPMRC_NOTFOUND : rc;
diff --git a/lib/rpmdb.c b/lib/rpmdb.c
index 1a2fda504..c17dcbfc6 100644
--- a/lib/rpmdb.c
+++ b/lib/rpmdb.c
@@ -781,6 +781,12 @@ int rpmdbSync(rpmdb db)
return dbiForeach(db->_dbi, dbiSync, 0);
}
+int rpmdbSuspendResumeDBLock(rpmdb db, int mode)
+{
+ if (db == NULL) return 0;
+ return dbiForeach(db->_dbi, mode ? dbiResumeDBLock : dbiSuspendDBLock, 0);
+}
+
static rpmdb newRpmdb(const char * root, const char * home,
int mode, int perms, int flags)
{
diff --git a/lib/rpmts.c b/lib/rpmts.c
index 964273473..d3b893a1d 100644
--- a/lib/rpmts.c
+++ b/lib/rpmts.c
@@ -95,6 +95,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)
{
rpmlock lock = rpmtsAcquireLock(ts);
diff --git a/lib/rpmts.h b/lib/rpmts.h
index 0b8d970e7..059f46d24 100644
--- a/lib/rpmts.h
+++ b/lib/rpmts.h
@@ -423,6 +423,8 @@ rpmdb rpmtsGetRdb(rpmts ts);
void * rpmtsNotify(rpmts ts, rpmte te,
rpmCallbackType what, rpm_loff_t amount, rpm_loff_t total);
+int rpmtsSuspendResumeDBLock(rpmts ts, int mode);
+
/** \ingroup rpmts
* Return number of (ordered) transaction set elements.
* @param ts transaction set