diff --git a/servers/slapd/back-mdb/attr.c b/servers/slapd/back-mdb/attr.c index 63b5552792..aec9446652 100644 --- a/servers/slapd/back-mdb/attr.c +++ b/servers/slapd/back-mdb/attr.c @@ -811,3 +811,14 @@ int mdb_ad_get( struct mdb_info *mdb, MDB_txn *txn, AttributeDescription *ad ) return rc; } + +void mdb_ad_unwind( struct mdb_info *mdb, int prev_ads ) +{ + int i; + + for (i=mdb->mi_numads; i>prev_ads; i--) { + mdb->mi_adxs[mdb->mi_ads[i]->ad_index] = 0; + mdb->mi_ads[i] = NULL; + } + mdb->mi_numads = i; +} diff --git a/servers/slapd/back-mdb/id2entry.c b/servers/slapd/back-mdb/id2entry.c index 0d5f4e17ea..508652803d 100644 --- a/servers/slapd/back-mdb/id2entry.c +++ b/servers/slapd/back-mdb/id2entry.c @@ -272,7 +272,7 @@ static int mdb_id2entry_put( struct mdb_info *mdb = (struct mdb_info *) op->o_bd->be_private; Ecount ec; MDB_val key, data; - int rc, adding = flag; + int rc, adding = flag, prev_ads = mdb->mi_numads; /* We only store rdns, and they go in the dn2id database. */ @@ -280,16 +280,20 @@ static int mdb_id2entry_put( key.mv_size = sizeof(ID); rc = mdb_entry_partsize( mdb, txn, e, &ec ); - if (rc) - return LDAP_OTHER; + if (rc) { + rc = LDAP_OTHER; + goto fail; + } flag |= MDB_RESERVE; if (e->e_id < mdb->mi_nextid) flag &= ~MDB_APPEND; - if (mdb->mi_maxentrysize && ec.len > mdb->mi_maxentrysize) - return LDAP_ADMINLIMIT_EXCEEDED; + if (mdb->mi_maxentrysize && ec.len > mdb->mi_maxentrysize) { + rc = LDAP_ADMINLIMIT_EXCEEDED; + goto fail; + } again: data.mv_size = ec.dlen; @@ -300,7 +304,7 @@ again: if (rc == MDB_SUCCESS) { rc = mdb_entry_encode( op, e, &data, &ec ); if( rc != LDAP_SUCCESS ) - return rc; + goto fail; /* Handle adds of large multi-valued attrs here. * Modifies handle them directly. */ @@ -323,7 +327,8 @@ again: "mdb_id2entry_put: mdb_mval_put failed: %s(%d) \"%s\"\n", mdb_strerror(rc), rc, e->e_nname.bv_val ); - return LDAP_OTHER; + rc = LDAP_OTHER; + goto fail; } } } @@ -340,6 +345,10 @@ again: if ( rc != MDB_KEYEXIST ) rc = LDAP_OTHER; } +fail: + if (rc) { + mdb_ad_unwind( mdb, prev_ads ); + } return rc; } diff --git a/servers/slapd/back-mdb/proto-mdb.h b/servers/slapd/back-mdb/proto-mdb.h index 8025fdb8c5..05c85175ef 100644 --- a/servers/slapd/back-mdb/proto-mdb.h +++ b/servers/slapd/back-mdb/proto-mdb.h @@ -57,6 +57,7 @@ void mdb_attr_info_free( AttrInfo *ai ); int mdb_ad_read( struct mdb_info *mdb, MDB_txn *txn ); int mdb_ad_get( struct mdb_info *mdb, MDB_txn *txn, AttributeDescription *ad ); +void mdb_ad_unwind( struct mdb_info *mdb, int prev_ads ); /* * config.c