int crypt_get_active_device(struct crypt_device *cd, const char *name,
			    struct crypt_active_device *cad)
{
	int r;
	struct crypt_dm_active_device dmd, dmdi = {};
	const char *namei = NULL;
	struct dm_target *tgt = &dmd.segment;
	uint64_t min_offset = UINT64_MAX;

	if (!cd || !name || !cad)
		return -EINVAL;

	r = dm_query_device(cd, name, DM_ACTIVE_DEVICE, &dmd);
	if (r < 0)
		return r;

	/* For LUKS2 with integrity we need flags from underlying dm-integrity */
	if (isLUKS2(cd->type) && crypt_get_integrity_tag_size(cd) && single_segment(&dmd)) {
		namei = device_dm_name(tgt->data_device);
		if (namei && dm_query_device(cd, namei, 0, &dmdi) >= 0)
			dmd.flags |= dmdi.flags;
	}

	if (cd && isTCRYPT(cd->type)) {
		cad->offset	= TCRYPT_get_data_offset(cd, &cd->u.tcrypt.hdr, &cd->u.tcrypt.params);
		cad->iv_offset	= TCRYPT_get_iv_offset(cd, &cd->u.tcrypt.hdr, &cd->u.tcrypt.params);
	} else {
		while (tgt) {
			if (tgt->type == DM_CRYPT && (min_offset > tgt->u.crypt.offset)) {
				min_offset = tgt->u.crypt.offset;
				cad->iv_offset = tgt->u.crypt.iv_offset;
			} else if (tgt->type == DM_INTEGRITY && (min_offset > tgt->u.integrity.offset)) {
				min_offset = tgt->u.integrity.offset;
				cad->iv_offset = 0;
			} else if (tgt->type == DM_LINEAR && (min_offset > tgt->u.linear.offset)) {
				min_offset = tgt->u.linear.offset;
				cad->iv_offset = 0;
			}
			tgt = tgt->next;
		}
	}

	if (min_offset != UINT64_MAX)
		cad->offset = min_offset;

	cad->size	= dmd.size;
	cad->flags	= dmd.flags;

	r = 0;
	dm_targets_free(cd, &dmd);
	dm_targets_free(cd, &dmdi);

	return r;
}
int crypt_get_active_device(struct crypt_device *cd, const char *name,
			    struct crypt_active_device *cad)
{
	int r;
	struct crypt_dm_active_device dmd, dmdi = {};
	const char *namei = NULL;
	struct dm_target *tgt = &dmd.segment;
	uint64_t min_offset = UINT64_MAX;

	if (!cd || !name || !cad)
		return -EINVAL;

	r = dm_query_device(cd, name, DM_ACTIVE_DEVICE, &dmd);
	if (r < 0)
		return r;

	 
	if (isLUKS2(cd->type) && crypt_get_integrity_tag_size(cd) && single_segment(&dmd)) {
		namei = device_dm_name(tgt->data_device);
		if (namei && dm_query_device(cd, namei, 0, &dmdi) >= 0)
			dmd.flags |= dmdi.flags;
	}

	if (cd && isTCRYPT(cd->type)) {
		cad->offset	= TCRYPT_get_data_offset(cd, &cd->u.tcrypt.hdr, &cd->u.tcrypt.params);
		cad->iv_offset	= TCRYPT_get_iv_offset(cd, &cd->u.tcrypt.hdr, &cd->u.tcrypt.params);
	} else {
		while (tgt) {
			if (tgt->type == DM_CRYPT && (min_offset > tgt->u.crypt.offset)) {
				min_offset = tgt->u.crypt.offset;
				cad->iv_offset = tgt->u.crypt.iv_offset;
			} else if (tgt->type == DM_INTEGRITY && (min_offset > tgt->u.integrity.offset)) {
				min_offset = tgt->u.integrity.offset;
				cad->iv_offset = 0;
			} else if (tgt->type == DM_LINEAR && (min_offset > tgt->u.linear.offset)) {
				min_offset = tgt->u.linear.offset;
				cad->iv_offset = 0;
			}
			tgt = tgt->next;
		}
	}

	if (min_offset != UINT64_MAX)
		cad->offset = min_offset;

	cad->size	= dmd.size;
	cad->flags	= dmd.flags;

	r = 0;
	dm_targets_free(cd, &dmd);
	dm_targets_free(cd, &dmdi);

	return r;
}