]> git.sur5r.net Git - openldap/commitdiff
ITS#5262 must protect dn2id between the time it's read from the DB
authorHoward Chu <hyc@openldap.org>
Thu, 6 Dec 2007 05:48:02 +0000 (05:48 +0000)
committerHoward Chu <hyc@openldap.org>
Thu, 6 Dec 2007 05:48:02 +0000 (05:48 +0000)
and it's inserted into EntryInfo cache.

servers/slapd/back-bdb/back-bdb.h
servers/slapd/back-bdb/cache.c
servers/slapd/back-bdb/dn2id.c
servers/slapd/back-bdb/proto-bdb.h

index 6e49d132a20ac0bbfece965a15c5a4ca36e279b1..c83ddf0764f0417b9ba9d941a49cf52c37d00cc9 100644 (file)
@@ -70,13 +70,15 @@ typedef struct __db_locker * BDB_LOCKER;
 extern int __lock_getlocker(DB_LOCKTAB *lt, u_int32_t locker, int create, DB_LOCKER **ret);
 
 #define CURSOR_SETLOCKER(cursor, id)   cursor->locker = id
-#define        CURSOR_GETLOCKER(cursor)        cursor->locker
+#define CURSOR_GETLOCKER(cursor)       cursor->locker
+#define BDB_LOCKID(locker)     locker->id
 #else
 
 typedef u_int32_t BDB_LOCKER;
 
 #define CURSOR_SETLOCKER(cursor, id)   cursor->locker = id
 #define CURSOR_GETLOCKER(cursor)       cursor->locker
+#define BDB_LOCKID(locker)     locker
 
 #endif
 
index 93be806635a00b9cbe4341897c8bfad572db7ff0..ffe8580cfcd0b5ae427ae053fe9b9f61bde18642 100644 (file)
@@ -155,12 +155,6 @@ bdb_cache_lru_link( struct bdb_info *bdb, EntryInfo *ei )
  * alternatives though.
  */
 
-#if DB_VERSION_FULL >= 0x04060012
-#define BDB_LOCKID(locker)     locker->id
-#else
-#define BDB_LOCKID(locker)     locker
-#endif
-
 /* Atomically release and reacquire a lock */
 int
 bdb_cache_entry_db_relock(
@@ -426,6 +420,7 @@ bdb_cache_find_ndn(
                ei.bei_parent = eip;
                ei2 = (EntryInfo *)avl_find( eip->bei_kids, &ei, bdb_rdn_cmp );
                if ( !ei2 ) {
+                       DB_LOCK lock;
                        int len = ei.bei_nrdn.bv_len;
                                
                        if ( BER_BVISEMPTY( ndn )) {
@@ -442,9 +437,11 @@ bdb_cache_find_ndn(
                                ei.bei_nrdn.bv_val );
 #endif
 
-                       rc = bdb_dn2id( op, locker, &ei.bei_nrdn, &ei );
+                       lock.mode = DB_LOCK_NG;
+                       rc = bdb_dn2id( op, &ei.bei_nrdn, &ei, locker, &lock );
                        if (rc) {
                                bdb_cache_entryinfo_lock( eip );
+                               bdb_cache_entry_db_unlock( bdb, &lock );
                                *res = eip;
                                return rc;
                        }
@@ -461,6 +458,7 @@ bdb_cache_find_ndn(
                                ei.bei_nrdn.bv_val, ei.bei_id, 0 );
                        /* add_internal left eip and c_rwlock locked */
                        ldap_pvt_thread_rdwr_wunlock( &bdb->bi_cache.c_rwlock );
+                       bdb_cache_entry_db_unlock( bdb, &lock );
                        if ( rc ) {
                                *res = eip;
                                return rc;
index 0f6b1927bbfeadabdb3aa5e95167c00274be248c..33234ceaa005c21d17a6e094eb0ffc509ece8517 100644 (file)
 #include "idl.h"
 #include "lutil.h"
 
+#define bdb_dn2id_lock                                 BDB_SYMBOL(dn2id_lock)
+
+static int
+bdb_dn2id_lock( struct bdb_info *bdb, struct berval *dn,
+       int rw, BDB_LOCKER locker, DB_LOCK *lock )
+{
+       int       rc;
+       DBT       lockobj;
+       int       db_rw;
+
+       if (rw)
+               db_rw = DB_LOCK_WRITE;
+       else
+               db_rw = DB_LOCK_READ;
+
+       lockobj.data = dn->bv_val;
+       lockobj.size = dn->bv_len;
+
+       rc = LOCK_GET(bdb->bi_dbenv, BDB_LOCKID(locker), DB_LOCK_NOWAIT,
+                                       &lockobj, db_rw, lock);
+       return rc;
+}
+
 #ifndef BDB_HIER
 int
 bdb_dn2id_add(
@@ -146,10 +169,11 @@ bdb_dn2id_delete(
 {
        struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
        DB *db = bdb->bi_dn2id->bdi_db;
-       int             rc;
-       DBT             key;
        char            *buf;
+       DBT             key;
+       DB_LOCK lock;
        struct berval   pdn, ptr;
+       int             rc;
 
        Debug( LDAP_DEBUG_TRACE, "=> bdb_dn2id_delete( \"%s\", 0x%08lx )\n",
                e->e_ndn, e->e_id, 0 );
@@ -165,6 +189,10 @@ bdb_dn2id_delete(
        AC_MEMCPY( ptr.bv_val, e->e_nname.bv_val, e->e_nname.bv_len );
        ptr.bv_val[ptr.bv_len] = '\0';
 
+       /* We hold this lock until the TXN completes */
+       rc = bdb_dn2id_lock( bdb, &e->e_nname, 1, TXN_ID( txn ), &lock );
+       if ( rc ) return rc;
+
        /* delete it */
        rc = db->del( db, txn, &key, 0 );
        if( rc != 0 ) {
@@ -244,9 +272,10 @@ done:
 int
 bdb_dn2id(
        Operation *op,
-       BDB_LOCKER locker,
        struct berval   *dn,
-       EntryInfo *ei )
+       EntryInfo *ei,
+       BDB_LOCKER locker,
+       DB_LOCK *lock )
 {
        struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
        DB *db = bdb->bi_dn2id->bdi_db;
@@ -268,6 +297,9 @@ bdb_dn2id(
        data.ulen = sizeof(ID);
        data.flags = DB_DBT_USERMEM;
 
+       rc = bdb_dn2id_lock( bdb, dn, 0, locker, lock );
+       if ( rc ) return rc;
+
        rc = db->cursor( db, NULL, &cursor, bdb->bi_db_opflags );
        if ( rc ) return rc;
        if ( locker ) {
@@ -576,6 +608,7 @@ hdb_dn2id_delete(
        int rc;
        ID      nid;
        unsigned char dlen[2];
+       DB_LOCK lock;
 
        DBTzero(&key);
        key.size = sizeof(ID);
@@ -589,6 +622,10 @@ hdb_dn2id_delete(
        data.dlen = data.size;
        data.flags = DB_DBT_USERMEM | DB_DBT_PARTIAL;
 
+       /* We hold this lock until the TXN completes */
+       rc = bdb_dn2id_lock( bdb, &e->e_nname, 1, TXN_ID( txn ), &lock );
+       if ( rc ) return rc;
+
        key.data = &nid;
        rc = db->cursor( db, txn, &cursor, bdb->bi_db_opflags );
        if ( rc ) return rc;
@@ -646,9 +683,10 @@ hdb_dn2id_delete(
 int
 hdb_dn2id(
        Operation       *op,
-       BDB_LOCKER locker,
        struct berval   *in,
-       EntryInfo       *ei )
+       EntryInfo       *ei,
+       BDB_LOCKER locker,
+       DB_LOCK *lock )
 {
        struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
        DB *db = bdb->bi_dn2id->bdi_db;
@@ -677,6 +715,9 @@ hdb_dn2id(
        data.dlen = data.ulen;
        data.flags = DB_DBT_USERMEM | DB_DBT_PARTIAL;
 
+       rc = bdb_dn2id_lock( bdb, in, 0, locker, lock );
+       if ( rc ) return rc;
+
        rc = db->cursor( db, NULL, &cursor, bdb->bi_db_opflags );
        if ( rc ) return rc;
        if ( locker ) {
index d0f01989ad79be20c36ff43ad84037942b9ee7d4..d1691b0808d0269de28b2289337d06f017b9031f 100644 (file)
@@ -97,9 +97,10 @@ int bdb_dn2entry LDAP_P(( Operation *op, DB_TXN *tid,
 
 int bdb_dn2id(
        Operation *op,
-       BDB_LOCKER locker,
        struct berval *dn,
-       EntryInfo *ei );
+       EntryInfo *ei,
+       BDB_LOCKER locker,
+       DB_LOCK *lock );
 
 int bdb_dn2id_add(
        Operation *op,