static int ldb_kv_dn_list_load(struct ldb_module *module,
			       struct ldb_kv_private *ldb_kv,
			       struct ldb_dn *dn,
			       struct dn_list *list,
			       enum dn_list_will_be_read_only read_only)
{
	struct ldb_message *msg;
	int ret, version;
	struct ldb_message_element *el;
	TDB_DATA rec = {0};
	struct dn_list *list2;
	bool from_primary_cache = false;
	TDB_DATA key = {0};

	list->dn = NULL;
	list->count = 0;
	list->strict = false;

	/*
	 * See if we have an in memory index cache
	 */
	if (ldb_kv->idxptr == NULL) {
		goto normal_index;
	}

	key.dptr = discard_const_p(unsigned char, ldb_dn_get_linearized(dn));
	key.dsize = strlen((char *)key.dptr);

	/*
	 * Have we cached this index record?
	 * If we have a nested transaction cache try that first.
	 * then try the transaction cache.
	 * if the record is not cached it will need to be read from disk.
	 */
	if (ldb_kv->nested_idx_ptr != NULL) {
		rec = tdb_fetch(ldb_kv->nested_idx_ptr->itdb, key);
	}
	if (rec.dptr == NULL) {
		from_primary_cache = true;
		rec = tdb_fetch(ldb_kv->idxptr->itdb, key);
	}
	if (rec.dptr == NULL) {
		goto normal_index;
	}

	/* we've found an in-memory index entry */
	list2 = ldb_kv_index_idxptr(module, rec);
	if (list2 == NULL) {
		free(rec.dptr);
		return LDB_ERR_OPERATIONS_ERROR;
	}
	free(rec.dptr);

	/*
	 * If this is a read only transaction the indexes will not be
	 * changed so we don't need a copy in the event of a rollback
	 *
	 * In this case make an early return
	 */
	if (read_only == DN_LIST_WILL_BE_READ_ONLY) {
		*list = *list2;
		return LDB_SUCCESS;
	}

	/*
	 * record was read from the sub transaction cache, so we have
	 * already copied the primary cache record
	 */
	if (!from_primary_cache) {
		*list = *list2;
		return LDB_SUCCESS;
	}

	/*
	 * No index sub transaction active, so no need to cache a copy
	 */
	if (ldb_kv->nested_idx_ptr == NULL) {
		*list = *list2;
		return LDB_SUCCESS;
	}

	/*
	 * There is an active index sub transaction, and the record was
	 * found in the primary index transaction cache.  A copy of the
	 * record needs be taken to prevent the original entry being
	 * altered, until the index sub transaction is committed.
	 */

	{
		struct ldb_val *dns = NULL;
		size_t x = 0;

		dns = talloc_array(
			list,
			struct ldb_val,
			list2->count);
		if (dns == NULL) {
			return LDB_ERR_OPERATIONS_ERROR;
		}
		for (x = 0; x < list2->count; x++) {
			dns[x].length = list2->dn[x].length;
			dns[x].data = talloc_memdup(
				dns,
				list2->dn[x].data,
				list2->dn[x].length);
			if (dns[x].data == NULL) {
				TALLOC_FREE(dns);
				return LDB_ERR_OPERATIONS_ERROR;
			}
		}
		list->dn = dns;
		list->count = list2->count;
	}
	return LDB_SUCCESS;

	/*
	 * Index record not found in the caches, read it from the
	 * database.
	 */
normal_index:
	msg = ldb_msg_new(list);
	if (msg == NULL) {
		return LDB_ERR_OPERATIONS_ERROR;
	}

	ret = ldb_kv_search_dn1(module,
				dn,
				msg,
				LDB_UNPACK_DATA_FLAG_NO_DN |
				/*
				 * The entry point ldb_kv_search_indexed is
				 * only called from the read-locked
				 * ldb_kv_search.
				 */
				LDB_UNPACK_DATA_FLAG_READ_LOCKED);
	if (ret != LDB_SUCCESS) {
		talloc_free(msg);
		return ret;
	}

	el = ldb_msg_find_element(msg, LDB_KV_IDX);
	if (!el) {
		talloc_free(msg);
		return LDB_SUCCESS;
	}

	version = ldb_msg_find_attr_as_int(msg, LDB_KV_IDXVERSION, 0);

	/*
	 * we avoid copying the strings by stealing the list.  We have
	 * to steal msg onto el->values (which looks odd) because
	 * the memory is allocated on msg, not on each value.
	 */
	if (ldb_kv->cache->GUID_index_attribute == NULL) {
		/* check indexing version number */
		if (version != LDB_KV_INDEXING_VERSION) {
			ldb_debug_set(ldb_module_get_ctx(module),
				      LDB_DEBUG_ERROR,
				      "Wrong DN index version %d "
				      "expected %d for %s",
				      version, LDB_KV_INDEXING_VERSION,
				      ldb_dn_get_linearized(dn));
			talloc_free(msg);
			return LDB_ERR_OPERATIONS_ERROR;
		}

		talloc_steal(el->values, msg);
		list->dn = talloc_steal(list, el->values);
		list->count = el->num_values;
	} else {
		unsigned int i;
		if (version != LDB_KV_GUID_INDEXING_VERSION) {
			/* This is quite likely during the DB startup
			   on first upgrade to using a GUID index */
			ldb_debug_set(ldb_module_get_ctx(module),
				      LDB_DEBUG_ERROR,
				      "Wrong GUID index version %d "
				      "expected %d for %s",
				      version, LDB_KV_GUID_INDEXING_VERSION,
				      ldb_dn_get_linearized(dn));
			talloc_free(msg);
			return LDB_ERR_OPERATIONS_ERROR;
		}

		if (el->num_values == 0) {
			talloc_free(msg);
			return LDB_ERR_OPERATIONS_ERROR;
		}

		if ((el->values[0].length % LDB_KV_GUID_SIZE) != 0) {
			talloc_free(msg);
			return LDB_ERR_OPERATIONS_ERROR;
		}

		list->count = el->values[0].length / LDB_KV_GUID_SIZE;
		list->dn = talloc_array(list, struct ldb_val, list->count);
		if (list->dn == NULL) {
			talloc_free(msg);
			return LDB_ERR_OPERATIONS_ERROR;
		}

		/*
		 * The actual data is on msg.
		 */
		talloc_steal(list->dn, msg);
		for (i = 0; i < list->count; i++) {
			list->dn[i].data
				= &el->values[0].data[i * LDB_KV_GUID_SIZE];
			list->dn[i].length = LDB_KV_GUID_SIZE;
		}
	}

	/* We don't need msg->elements any more */
	talloc_free(msg->elements);
	return LDB_SUCCESS;
}