diff options
author | Anas Nashif <anas.nashif@intel.com> | 2012-10-11 12:38:04 -0700 |
---|---|---|
committer | Anas Nashif <anas.nashif@intel.com> | 2013-02-02 16:44:15 -0800 |
commit | cd10f180b09bd91d4d720c66a0835b757d7f944f (patch) | |
tree | c2134ff9c2ff07e707fb9f972cc315bcaa31577d /lib | |
parent | 76bb342f9ae2c3e5a902fc9f66af03d072d523d7 (diff) | |
download | rpm-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.c | 56 | ||||
-rw-r--r-- | lib/backend/dbi.h | 18 | ||||
-rw-r--r-- | lib/psm.c | 2 | ||||
-rw-r--r-- | lib/rpmdb.c | 6 | ||||
-rw-r--r-- | lib/rpmts.c | 5 | ||||
-rw-r--r-- | lib/rpmts.h | 2 |
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 */ @@ -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 |