Commit 8ccf24ed authored by Changpeng Liu's avatar Changpeng Liu
Browse files

nvmf: release the reservation when unregistering one registrant



Unregistering by a host may cause a reservation held by the host
to be released. If a host is the last remaining reservation holder
or is the only reservation holder, then the reservation is released
when the host unregisters.  This may occur with Acquire/preempt
and Register/unregister commands.

Change-Id: If59fe2fdaa69c8ad70f364618d6c281494ad6245
Signed-off-by: default avatarChangpeng Liu <changpeng.liu@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/446821


Tested-by: default avatarSPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: default avatarShuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
Reviewed-by: default avatarBen Walker <benjamin.walker@intel.com>
parent 71ac18d1
Loading
Loading
Loading
Loading
+26 −0
Original line number Diff line number Diff line
@@ -1335,11 +1335,37 @@ nvmf_ns_reservation_add_registrant(struct spdk_nvmf_ns *ns,
	return 0;
}

/* release the reservation if the last registrant was removed */
static void
nvmf_ns_reservation_check_release_on_remove_registrant(struct spdk_nvmf_ns *ns,
		struct spdk_nvmf_registrant *reg)
{
	struct spdk_nvmf_registrant *next_reg;

	/* no reservation holder */
	if (!ns->holder) {
		assert(ns->rtype == 0);
		return;
	}

	next_reg = TAILQ_FIRST(&ns->registrants);
	if (next_reg && nvmf_ns_reservation_all_registrants_type(ns)) {
		/* the next valid registrant is the new holder now */
		ns->holder = next_reg;
	} else if (nvmf_ns_reservation_registrant_is_holder(ns, reg)) {
		/* release the reservation */
		ns->rtype = 0;
		ns->crkey = 0;
		ns->holder = NULL;
	}
}

static void
nvmf_ns_reservation_remove_registrant(struct spdk_nvmf_ns *ns,
				      struct spdk_nvmf_registrant *reg)
{
	TAILQ_REMOVE(&ns->registrants, reg, link);
	nvmf_ns_reservation_check_release_on_remove_registrant(ns, reg);
	free(reg);
	ns->gen++;
	return;