int crypt_resize(struct crypt_device *cd, const char *name, uint64_t new_size)
{
	struct crypt_dm_active_device dmdq, dmd = {};
	struct dm_target *tgt = &dmdq.segment;
	int r;

	/*
	 * FIXME: Also with LUKS2 we must not allow resize when there's
	 *	  explicit size stored in metadata (length != "dynamic")
	 */

	/* Device context type must be initialized */
	if (!cd || !cd->type || !name)
		return -EINVAL;

	if (isTCRYPT(cd->type) || isBITLK(cd->type)) {
		log_err(cd, _("This operation is not supported for this device type."));
		return -ENOTSUP;
	}

	log_dbg(cd, "Resizing device %s to %" PRIu64 " sectors.", name, new_size);

	r = dm_query_device(cd, name, DM_ACTIVE_CRYPT_KEYSIZE | DM_ACTIVE_CRYPT_KEY, &dmdq);
	if (r < 0) {
		log_err(cd, _("Device %s is not active."), name);
		return -EINVAL;
	}
	if (!single_segment(&dmdq) || tgt->type != DM_CRYPT) {
		log_dbg(cd, "Unsupported device table detected in %s.", name);
		r = -EINVAL;
		goto out;
	}

	if ((dmdq.flags & CRYPT_ACTIVATE_KEYRING_KEY) && !crypt_key_in_keyring(cd)) {
		r = -EPERM;
		goto out;
	}

	if (crypt_key_in_keyring(cd)) {
		if (!isLUKS2(cd->type)) {
			r = -EINVAL;
			goto out;
		}
		r = LUKS2_key_description_by_segment(cd, &cd->u.luks2.hdr,
					tgt->u.crypt.vk, CRYPT_DEFAULT_SEGMENT);
		if (r)
			goto out;

		dmdq.flags |= CRYPT_ACTIVATE_KEYRING_KEY;
	}

	if (crypt_loop_device(crypt_get_device_name(cd))) {
		log_dbg(cd, "Trying to resize underlying loop device %s.",
			crypt_get_device_name(cd));
		/* Here we always use default size not new_size */
		if (crypt_loop_resize(crypt_get_device_name(cd)))
			log_err(cd, _("Cannot resize loop device."));
	}

	r = device_block_adjust(cd, crypt_data_device(cd), DEV_OK,
				crypt_get_data_offset(cd), &new_size, &dmdq.flags);
	if (r)
		goto out;

	if (MISALIGNED(new_size, tgt->u.crypt.sector_size >> SECTOR_SHIFT)) {
		log_err(cd, _("Device size is not aligned to requested sector size."));
		r = -EINVAL;
		goto out;
	}

	if (MISALIGNED(new_size, device_block_size(cd, crypt_data_device(cd)) >> SECTOR_SHIFT)) {
		log_err(cd, _("Device size is not aligned to device logical block size."));
		r = -EINVAL;
		goto out;
	}

	dmd.uuid = crypt_get_uuid(cd);
	dmd.size = new_size;
	dmd.flags = dmdq.flags | CRYPT_ACTIVATE_REFRESH;
	r = dm_crypt_target_set(&dmd.segment, 0, new_size, crypt_data_device(cd),
			tgt->u.crypt.vk, crypt_get_cipher_spec(cd),
			crypt_get_iv_offset(cd), crypt_get_data_offset(cd),
			crypt_get_integrity(cd), crypt_get_integrity_tag_size(cd),
			crypt_get_sector_size(cd));
	if (r < 0)
		goto out;

	if (new_size == dmdq.size) {
		log_dbg(cd, "Device has already requested size %" PRIu64
			" sectors.", dmdq.size);
		r = 0;
	} else {
		if (isTCRYPT(cd->type))
			r = -ENOTSUP;
		else if (isLUKS2(cd->type))
			r = LUKS2_unmet_requirements(cd, &cd->u.luks2.hdr, 0, 0);
		if (!r)
			r = _reload_device(cd, name, &dmd);
	}
out:
	dm_targets_free(cd, &dmd);
	dm_targets_free(cd, &dmdq);

	return r;
}
int crypt_resize(struct crypt_device *cd, const char *name, uint64_t new_size)
{
	struct crypt_dm_active_device dmdq, dmd = {};
	struct dm_target *tgt = &dmdq.segment;
	int r;

	 

	 
	if (!cd || !cd->type || !name)
		return -EINVAL;

	if (isTCRYPT(cd->type) || isBITLK(cd->type)) {
		log_err(cd, _("This operation is not supported for this device type."));
		return -ENOTSUP;
	}

	log_dbg(cd, "Resizing device %s to %" PRIu64 " sectors.", name, new_size);

	r = dm_query_device(cd, name, DM_ACTIVE_CRYPT_KEYSIZE | DM_ACTIVE_CRYPT_KEY, &dmdq);
	if (r < 0) {
		log_err(cd, _("Device %s is not active."), name);
		return -EINVAL;
	}
	if (!single_segment(&dmdq) || tgt->type != DM_CRYPT) {
		log_dbg(cd, "Unsupported device table detected in %s.", name);
		r = -EINVAL;
		goto out;
	}

	if ((dmdq.flags & CRYPT_ACTIVATE_KEYRING_KEY) && !crypt_key_in_keyring(cd)) {
		r = -EPERM;
		goto out;
	}

	if (crypt_key_in_keyring(cd)) {
		if (!isLUKS2(cd->type)) {
			r = -EINVAL;
			goto out;
		}
		r = LUKS2_key_description_by_segment(cd, &cd->u.luks2.hdr,
					tgt->u.crypt.vk, CRYPT_DEFAULT_SEGMENT);
		if (r)
			goto out;

		dmdq.flags |= CRYPT_ACTIVATE_KEYRING_KEY;
	}

	if (crypt_loop_device(crypt_get_device_name(cd))) {
		log_dbg(cd, "Trying to resize underlying loop device %s.",
			crypt_get_device_name(cd));
		 
		if (crypt_loop_resize(crypt_get_device_name(cd)))
			log_err(cd, _("Cannot resize loop device."));
	}

	r = device_block_adjust(cd, crypt_data_device(cd), DEV_OK,
				crypt_get_data_offset(cd), &new_size, &dmdq.flags);
	if (r)
		goto out;

	if (MISALIGNED(new_size, tgt->u.crypt.sector_size >> SECTOR_SHIFT)) {
		log_err(cd, _("Device size is not aligned to requested sector size."));
		r = -EINVAL;
		goto out;
	}

	if (MISALIGNED(new_size, device_block_size(cd, crypt_data_device(cd)) >> SECTOR_SHIFT)) {
		log_err(cd, _("Device size is not aligned to device logical block size."));
		r = -EINVAL;
		goto out;
	}

	dmd.uuid = crypt_get_uuid(cd);
	dmd.size = new_size;
	dmd.flags = dmdq.flags | CRYPT_ACTIVATE_REFRESH;
	r = dm_crypt_target_set(&dmd.segment, 0, new_size, crypt_data_device(cd),
			tgt->u.crypt.vk, crypt_get_cipher_spec(cd),
			crypt_get_iv_offset(cd), crypt_get_data_offset(cd),
			crypt_get_integrity(cd), crypt_get_integrity_tag_size(cd),
			crypt_get_sector_size(cd));
	if (r < 0)
		goto out;

	if (new_size == dmdq.size) {
		log_dbg(cd, "Device has already requested size %" PRIu64
			" sectors.", dmdq.size);
		r = 0;
	} else {
		if (isTCRYPT(cd->type))
			r = -ENOTSUP;
		else if (isLUKS2(cd->type))
			r = LUKS2_unmet_requirements(cd, &cd->u.luks2.hdr, 0, 0);
		if (!r)
			r = _reload_device(cd, name, &dmd);
	}
out:
	dm_targets_free(cd, &dmd);
	dm_targets_free(cd, &dmdq);

	return r;
}