struct ldif_info {
struct berval li_base_path; /* database directory */
struct ldif_tool li_tool; /* for slap tools */
+ /*
+ * Read-only LDAP requests readlock li_rdwr for filesystem input.
+ * Update requests first lock li_modop_mutex for filesystem I/O,
+ * and then writelock li_rdwr as well for filesystem output.
+ * This allows update requests to do callbacks that acquire
+ * read locks, e.g. access controls that inspect entries.
+ * (An alternative would be recursive read/write locks.)
+ */
+ ldap_pvt_thread_mutex_t li_modop_mutex; /* serialize update requests */
ldap_pvt_thread_rdwr_t li_rdwr; /* no other I/O when writing */
};
if ( rc != LDAP_SUCCESS )
goto send_res;
- ldap_pvt_thread_rdwr_wlock(&li->li_rdwr);
+ ldap_pvt_thread_mutex_lock( &li->li_modop_mutex );
rc = ldif_prepare_create( op, e, &path, &parentdir, &rs->sr_text );
if ( rc == LDAP_SUCCESS ) {
+ ldap_pvt_thread_rdwr_wlock( &li->li_rdwr );
rc = ldif_write_entry( op, e, &path, parentdir, &rs->sr_text );
+ ldap_pvt_thread_rdwr_wunlock( &li->li_rdwr );
+
SLAP_FREE( path.bv_val );
if ( parentdir != NULL )
SLAP_FREE( parentdir );
}
- ldap_pvt_thread_rdwr_wunlock(&li->li_rdwr);
+ ldap_pvt_thread_mutex_unlock( &li->li_modop_mutex );
send_res:
rs->sr_err = rc;
slap_mods_opattrs( op, &op->orm_modlist, 1 );
- ldap_pvt_thread_rdwr_wlock(&li->li_rdwr);
+ ldap_pvt_thread_mutex_lock( &li->li_modop_mutex );
rc = get_entry( op, &entry, &path, &rs->sr_text );
if ( rc == LDAP_SUCCESS ) {
rc = apply_modify_to_entry( entry, modlst, op, rs );
if ( rc == LDAP_SUCCESS ) {
+ ldap_pvt_thread_rdwr_wlock( &li->li_rdwr );
rc = ldif_write_entry( op, entry, &path, NULL, &rs->sr_text );
+ ldap_pvt_thread_rdwr_wunlock( &li->li_rdwr );
}
entry_free( entry );
SLAP_FREE( path.bv_val );
}
- ldap_pvt_thread_rdwr_wunlock(&li->li_rdwr);
+ ldap_pvt_thread_mutex_unlock( &li->li_modop_mutex );
rs->sr_err = rc;
send_ldap_result( op, rs );
slap_get_csn( op, &csn, 1 );
}
- ldap_pvt_thread_rdwr_wlock(&li->li_rdwr);
+ ldap_pvt_thread_mutex_lock( &li->li_modop_mutex );
+ ldap_pvt_thread_rdwr_wlock( &li->li_rdwr );
if ( op->o_abandon ) {
rc = SLAPD_ABANDON;
goto done;
SLAP_FREE(path.bv_val);
done:
- ldap_pvt_thread_rdwr_wunlock(&li->li_rdwr);
+ ldap_pvt_thread_rdwr_wunlock( &li->li_rdwr );
+ ldap_pvt_thread_mutex_unlock( &li->li_modop_mutex );
rs->sr_err = rc;
send_ldap_result( op, rs );
slap_graduate_commit_csn( op );
struct berval *oldpath,
const char **text )
{
+ struct ldif_info *li = (struct ldif_info *) op->o_bd->be_private;
struct berval newpath;
char *parentdir = NULL, *trash;
int rc, rename_res;
}
if ( rc == LDAP_SUCCESS ) {
+ ldap_pvt_thread_rdwr_wlock( &li->li_rdwr );
+
rc = ldif_write_entry( op, entry, &newpath, parentdir, text );
if ( rc == LDAP_SUCCESS && !same_ndn ) {
trash = oldpath->bv_val; /* will be .ldif file to delete */
}
}
+ ldap_pvt_thread_rdwr_wunlock( &li->li_rdwr );
if ( !same_ndn )
SLAP_FREE( newpath.bv_val );
if ( parentdir != NULL )
slap_mods_opattrs( op, &op->orr_modlist, 1 );
- ldap_pvt_thread_rdwr_wlock( &li->li_rdwr );
+ ldap_pvt_thread_mutex_lock( &li->li_modop_mutex );
rc = get_entry( op, &entry, &old_path, &rs->sr_text );
if ( rc == LDAP_SUCCESS ) {
SLAP_FREE( old_path.bv_val );
}
- ldap_pvt_thread_rdwr_wunlock( &li->li_rdwr );
+ ldap_pvt_thread_mutex_unlock( &li->li_modop_mutex );
rs->sr_err = rc;
send_ldap_result( op, rs );
slap_graduate_commit_csn( op );
li = ch_calloc( 1, sizeof(struct ldif_info) );
be->be_private = li;
be->be_cf_ocs = ldifocs;
- ldap_pvt_thread_rdwr_init(&li->li_rdwr);
+ ldap_pvt_thread_mutex_init( &li->li_modop_mutex );
+ ldap_pvt_thread_rdwr_init( &li->li_rdwr );
SLAP_DBFLAGS( be ) |= SLAP_DBFLAG_ONE_SUFFIX;
return 0;
}
struct ldif_info *li = be->be_private;
ch_free(li->li_base_path.bv_val);
- ldap_pvt_thread_rdwr_destroy(&li->li_rdwr);
+ ldap_pvt_thread_rdwr_destroy( &li->li_rdwr );
+ ldap_pvt_thread_mutex_destroy( &li->li_modop_mutex );
free( be->be_private );
return 0;
}