[Rpm-maint] [Suse patch] Suspend exclusive database lock for scriptlets

Panu Matilainen pmatilai at redhat.com
Fri May 25 11:05:00 UTC 2007


More locking-related tweaks - is the private locking a leftover from the 
4.1-4.2 days of locking horrors (which I can certainly understand ;), 
never since revisited or decision based on current experiences?

 	- Panu -
---

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
@@ -799,6 +799,8 @@ static rpmRC runScript(rpmpsm psm, Heade
      }
      if (out == NULL) return RPMRC_FAIL;	/* XXX can't happen */

+    rpmtsSuspendResumeDBLock(psm->ts, 0);
+
      /*@-branchstate@*/
      xx = rpmsqFork(&psm->sq);
      if (psm->sq.child == 0) {
@@ -924,6 +926,8 @@ static rpmRC runScript(rpmpsm psm, Heade

      (void) psmWait(psm);

+    rpmtsSuspendResumeDBLock(psm->ts, 1);
+
    /* XXX filter order dependent multilib "other" arch helper error. */
    if (!(psm->sq.reaped >= 0 && !strcmp(argv[0], "/usr/sbin/glibc_post_upgrade") && WEXITSTATUS(psm->sq.status) == 110)) {
      if (psm->sq.reaped < 0) {
Index: lib/rpmts.c
===================================================================
--- lib/rpmts.c.orig
+++ lib/rpmts.c
@@ -190,6 +190,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
@@ -470,6 +470,10 @@ int rpmtsRebuildDB(rpmts ts)
  	/*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
  	/*@modifies ts, rpmGlobalMacroContext, fileSystem, internalState @*/;

+int rpmtsSuspendResumeDBLock(rpmts ts, int mode)
+	/*@globals fileSystem @*/
+	/*@modifies fileSystem @*/;
+
  /** \ingroup rpmts
   * Verify the database used by the transaction.
   * @param ts		transaction set
Index: rpmdb/db3.c
===================================================================
--- rpmdb/db3.c.orig
+++ rpmdb/db3.c
@@ -458,6 +458,8 @@ errxit:
  }
  /*@=moduncon@*/

+static int db3SuspendResumeLock(dbiIndex dbi, int mode);
+
  static int db3sync(dbiIndex dbi, unsigned int flags)
  	/*@globals fileSystem @*/
  	/*@modifies fileSystem @*/
@@ -466,6 +468,10 @@ static int db3sync(dbiIndex dbi, unsigne
      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. */
@@ -1412,6 +1418,50 @@ static int db3open(rpmdb rpmdb, rpmTag r
      /*@=nullstate =compmempass@*/
  }

+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)
+	    rpmMessage(RPMMESS_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)
+		rpmMessage(RPMMESS_WARNING, _("waiting to reestablish exclusive database lock\n"));
+	}
+    }
+    return rc;
+}
+
  /** \ingroup db3
   */
  /*@-exportheadervar@*/
Index: rpmdb/rpmdb.c
===================================================================
--- rpmdb/rpmdb.c.orig
+++ rpmdb/rpmdb.c
@@ -945,6 +945,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;
+}
+
  /*@-mods@*/	/* FIX: dbTemplate structure assignment */
  static /*@only@*/ /*@null@*/
  rpmdb newRpmdb(/*@kept@*/ /*@null@*/ const char * root,



More information about the Rpm-maint mailing list