int crypt_deactivate_by_name(struct crypt_device *cd, const char *name, uint32_t flags)
{
	struct crypt_device *fake_cd = NULL;
	struct luks2_hdr *hdr2 = NULL;
	struct crypt_dm_active_device dmd = {};
	int r;
	uint32_t get_flags = DM_ACTIVE_DEVICE | DM_ACTIVE_UUID | DM_ACTIVE_HOLDERS;

	if (!name)
		return -EINVAL;

	if ((flags & CRYPT_DEACTIVATE_DEFERRED) && (flags & CRYPT_DEACTIVATE_DEFERRED_CANCEL))
		return -EINVAL;

	log_dbg(cd, "Deactivating volume %s.", name);

	if (!cd) {
		r = crypt_init_by_name(&fake_cd, name);
		if (r < 0)
			return r;
		cd = fake_cd;
	}

	/* skip holders detection and early abort when some flags raised */
	if (flags & (CRYPT_DEACTIVATE_FORCE | CRYPT_DEACTIVATE_DEFERRED | CRYPT_DEACTIVATE_DEFERRED_CANCEL))
		get_flags &= ~DM_ACTIVE_HOLDERS;

	switch (crypt_status(cd, name)) {
		case CRYPT_ACTIVE:
		case CRYPT_BUSY:
			if (flags & CRYPT_DEACTIVATE_DEFERRED_CANCEL) {
				r = dm_cancel_deferred_removal(name);
				if (r < 0)
					log_err(cd, _("Could not cancel deferred remove from device %s."), name);
				break;
			}

			r = dm_query_device(cd, name, get_flags, &dmd);
			if (r >= 0) {
				if (dmd.holders) {
					log_err(cd, _("Device %s is still in use."), name);
					r = -EBUSY;
					break;
				}
			}

			if (isLUKS2(cd->type))
				hdr2 = crypt_get_hdr(cd, CRYPT_LUKS2);

			if ((dmd.uuid && !strncmp(CRYPT_LUKS2, dmd.uuid, sizeof(CRYPT_LUKS2)-1)) || hdr2)
				r = LUKS2_deactivate(cd, name, hdr2, &dmd, flags);
			else if (isTCRYPT(cd->type))
				r = TCRYPT_deactivate(cd, name, flags);
			else
				r = dm_remove_device(cd, name, flags);
			if (r < 0 && crypt_status(cd, name) == CRYPT_BUSY) {
				log_err(cd, _("Device %s is still in use."), name);
				r = -EBUSY;
			}
			break;
		case CRYPT_INACTIVE:
			log_err(cd, _("Device %s is not active."), name);
			r = -ENODEV;
			break;
		default:
			log_err(cd, _("Invalid device %s."), name);
			r = -EINVAL;
	}

	dm_targets_free(cd, &dmd);
	free(CONST_CAST(void*)dmd.uuid);
	crypt_free(fake_cd);

	return r;
}
int crypt_deactivate_by_name(struct crypt_device *cd, const char *name, uint32_t flags)
{
	struct crypt_device *fake_cd = NULL;
	struct luks2_hdr *hdr2 = NULL;
	struct crypt_dm_active_device dmd = {};
	int r;
	uint32_t get_flags = DM_ACTIVE_DEVICE | DM_ACTIVE_UUID | DM_ACTIVE_HOLDERS;

	if (!name)
		return -EINVAL;

	if ((flags & CRYPT_DEACTIVATE_DEFERRED) && (flags & CRYPT_DEACTIVATE_DEFERRED_CANCEL))
		return -EINVAL;

	log_dbg(cd, "Deactivating volume %s.", name);

	if (!cd) {
		r = crypt_init_by_name(&fake_cd, name);
		if (r < 0)
			return r;
		cd = fake_cd;
	}

	 
	if (flags & (CRYPT_DEACTIVATE_FORCE | CRYPT_DEACTIVATE_DEFERRED | CRYPT_DEACTIVATE_DEFERRED_CANCEL))
		get_flags &= ~DM_ACTIVE_HOLDERS;

	switch (crypt_status(cd, name)) {
		case CRYPT_ACTIVE:
		case CRYPT_BUSY:
			if (flags & CRYPT_DEACTIVATE_DEFERRED_CANCEL) {
				r = dm_cancel_deferred_removal(name);
				if (r < 0)
					log_err(cd, _("Could not cancel deferred remove from device %s."), name);
				break;
			}

			r = dm_query_device(cd, name, get_flags, &dmd);
			if (r >= 0) {
				if (dmd.holders) {
					log_err(cd, _("Device %s is still in use."), name);
					r = -EBUSY;
					break;
				}
			}

			if (isLUKS2(cd->type))
				hdr2 = crypt_get_hdr(cd, CRYPT_LUKS2);

			if ((dmd.uuid && !strncmp(CRYPT_LUKS2, dmd.uuid, sizeof(CRYPT_LUKS2)-1)) || hdr2)
				r = LUKS2_deactivate(cd, name, hdr2, &dmd, flags);
			else if (isTCRYPT(cd->type))
				r = TCRYPT_deactivate(cd, name, flags);
			else
				r = dm_remove_device(cd, name, flags);
			if (r < 0 && crypt_status(cd, name) == CRYPT_BUSY) {
				log_err(cd, _("Device %s is still in use."), name);
				r = -EBUSY;
			}
			break;
		case CRYPT_INACTIVE:
			log_err(cd, _("Device %s is not active."), name);
			r = -ENODEV;
			break;
		default:
			log_err(cd, _("Invalid device %s."), name);
			r = -EINVAL;
	}

	dm_targets_free(cd, &dmd);
	free(CONST_CAST(void*)dmd.uuid);
	crypt_free(fake_cd);

	return r;
}