From 8ccf24ed52de865fc95ed2dc8b83939ae38854a2 Mon Sep 17 00:00:00 2001 From: Changpeng Liu Date: Thu, 28 Feb 2019 19:54:52 -0500 Subject: [PATCH] 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: Changpeng Liu Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/446821 Tested-by: SPDK CI Jenkins Reviewed-by: Shuhei Matsumoto Reviewed-by: Ben Walker --- lib/nvmf/subsystem.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/lib/nvmf/subsystem.c b/lib/nvmf/subsystem.c index 247430b80..70feb9893 100644 --- a/lib/nvmf/subsystem.c +++ b/lib/nvmf/subsystem.c @@ -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;