static int reencrypt_assign_segments(struct crypt_device *cd,
		struct luks2_hdr *hdr,
		struct luks2_reencrypt *rh,
		unsigned hot,
		unsigned commit)
{
	bool forward;
	int rseg, scount, r = -EINVAL;

	/* FIXME: validate in reencrypt context load */
	if (rh->digest_new < 0 && rh->mode != CRYPT_REENCRYPT_DECRYPT)
		return -EINVAL;

	if (LUKS2_digest_segment_assign(cd, hdr, CRYPT_ANY_SEGMENT, CRYPT_ANY_DIGEST, 0, 0))
		return -EINVAL;

	if (rh->mode == CRYPT_REENCRYPT_ENCRYPT || rh->mode == CRYPT_REENCRYPT_DECRYPT)
		return reencrypt_assign_segments_simple(cd, hdr, rh, hot, commit);

	if (hot && rh->jobj_segs_hot) {
		log_dbg(cd, "Setting 'hot' segments.");

		r = LUKS2_segments_set(cd, hdr, rh->jobj_segs_hot, 0);
		if (!r)
			rh->jobj_segs_hot = NULL;
	} else if (!hot && rh->jobj_segs_post) {
		log_dbg(cd, "Setting 'post' segments.");
		r = LUKS2_segments_set(cd, hdr, rh->jobj_segs_post, 0);
		if (!r)
			rh->jobj_segs_post = NULL;
	}

	if (r)
		return r;

	scount = LUKS2_segments_count(hdr);

	/* segment in reencryption has to hold reference on both digests */
	rseg = json_segments_segment_in_reencrypt(LUKS2_get_segments_jobj(hdr));
	if (rseg < 0 && hot)
		return -EINVAL;

	if (rseg >= 0) {
		LUKS2_digest_segment_assign(cd, hdr, rseg, rh->digest_new, 1, 0);
		LUKS2_digest_segment_assign(cd, hdr, rseg, rh->digest_old, 1, 0);
	}

	forward = (rh->direction == CRYPT_REENCRYPT_FORWARD);
	if (hot) {
		if (rseg > 0)
			LUKS2_digest_segment_assign(cd, hdr, 0, forward ? rh->digest_new : rh->digest_old, 1, 0);
		if (scount > rseg + 1)
			LUKS2_digest_segment_assign(cd, hdr, rseg + 1, forward ? rh->digest_old : rh->digest_new, 1, 0);
	} else {
		LUKS2_digest_segment_assign(cd, hdr, 0, forward || scount == 1 ? rh->digest_new : rh->digest_old, 1, 0);
		if (scount > 1)
			LUKS2_digest_segment_assign(cd, hdr, 1, forward ? rh->digest_old : rh->digest_new, 1, 0);
	}

	r = reencrypt_add_backup_segment(cd, hdr, rh, 0);
	if (r) {
		log_dbg(cd, "Failed to assign hot reencryption backup segment.");
		return r;
	}
	r = reencrypt_add_backup_segment(cd, hdr, rh, 1);
	if (r) {
		log_dbg(cd, "Failed to assign post reencryption backup segment.");
		return r;
	}

	return commit ? LUKS2_hdr_write(cd, hdr) : 0;
}
static int reencrypt_assign_segments(struct crypt_device *cd,
		struct luks2_hdr *hdr,
		struct luks2_reencrypt *rh,
		unsigned hot,
		unsigned commit)
{
	bool forward;
	int rseg, scount, r = -EINVAL;

	 
	if (rh->digest_new < 0 && rh->mode != CRYPT_REENCRYPT_DECRYPT)
		return -EINVAL;

	if (LUKS2_digest_segment_assign(cd, hdr, CRYPT_ANY_SEGMENT, CRYPT_ANY_DIGEST, 0, 0))
		return -EINVAL;

	if (rh->mode == CRYPT_REENCRYPT_ENCRYPT || rh->mode == CRYPT_REENCRYPT_DECRYPT)
		return reencrypt_assign_segments_simple(cd, hdr, rh, hot, commit);

	if (hot && rh->jobj_segs_hot) {
		log_dbg(cd, "Setting 'hot' segments.");

		r = LUKS2_segments_set(cd, hdr, rh->jobj_segs_hot, 0);
		if (!r)
			rh->jobj_segs_hot = NULL;
	} else if (!hot && rh->jobj_segs_post) {
		log_dbg(cd, "Setting 'post' segments.");
		r = LUKS2_segments_set(cd, hdr, rh->jobj_segs_post, 0);
		if (!r)
			rh->jobj_segs_post = NULL;
	}

	if (r)
		return r;

	scount = LUKS2_segments_count(hdr);

	 
	rseg = json_segments_segment_in_reencrypt(LUKS2_get_segments_jobj(hdr));
	if (rseg < 0 && hot)
		return -EINVAL;

	if (rseg >= 0) {
		LUKS2_digest_segment_assign(cd, hdr, rseg, rh->digest_new, 1, 0);
		LUKS2_digest_segment_assign(cd, hdr, rseg, rh->digest_old, 1, 0);
	}

	forward = (rh->direction == CRYPT_REENCRYPT_FORWARD);
	if (hot) {
		if (rseg > 0)
			LUKS2_digest_segment_assign(cd, hdr, 0, forward ? rh->digest_new : rh->digest_old, 1, 0);
		if (scount > rseg + 1)
			LUKS2_digest_segment_assign(cd, hdr, rseg + 1, forward ? rh->digest_old : rh->digest_new, 1, 0);
	} else {
		LUKS2_digest_segment_assign(cd, hdr, 0, forward || scount == 1 ? rh->digest_new : rh->digest_old, 1, 0);
		if (scount > 1)
			LUKS2_digest_segment_assign(cd, hdr, 1, forward ? rh->digest_old : rh->digest_new, 1, 0);
	}

	r = reencrypt_add_backup_segment(cd, hdr, rh, 0);
	if (r) {
		log_dbg(cd, "Failed to assign hot reencryption backup segment.");
		return r;
	}
	r = reencrypt_add_backup_segment(cd, hdr, rh, 1);
	if (r) {
		log_dbg(cd, "Failed to assign post reencryption backup segment.");
		return r;
	}

	return commit ? LUKS2_hdr_write(cd, hdr) : 0;
}