[PATCH] [Target_Core_Mod/ALUA]: Fix core_alua_free_*() lockinglogic

From: Nicholas A. Bellinger
Date: Fri Feb 06 2009 - 04:03:27 EST


>From 1656e4dd155664a0b864c01a0f5d1fcdcddde4e7 Mon Sep 17 00:00:00 2001
From: Nicholas Bellinger <nab@xxxxxxxxxxxxxxx>
Date: Fri, 6 Feb 2009 00:55:06 -0800
Subject: [PATCH] [Target_Core_Mod/ALUA]: Fix core_alua_free_*() locking logic

This patch releases the lu_gp->lu_gp_ref_lock in core_alua_free_lu_gp()
and tg_pt_gp->tg_pt_gp_ref_lock in core_alua_free_tg_pt_gp() before
clearing se_device_t->dev_alua_lu_gp and se_port_t->sep_alua_tg_pt_gp
pointers respectively.

It also moves list_del() in core_alua_free_lu_gp() and
core_alua_free_tg_pt_gp() to before the "loop through group list and release".
This is to prevent any concurrent ALUA association attempts by other
userspace processes into Target_Core_Mod/ConfigFS.

Signed-off-by: Nicholas A. Bellinger <nab@xxxxxxxxxxxxxxx>
---
drivers/lio-core/target_core_alua.c | 42 ++++++++++++++++++++++++++--------
1 files changed, 32 insertions(+), 10 deletions(-)

diff --git a/drivers/lio-core/target_core_alua.c b/drivers/lio-core/target_core_alua.c
index b5f5d66..722be1a 100644
--- a/drivers/lio-core/target_core_alua.c
+++ b/drivers/lio-core/target_core_alua.c
@@ -166,21 +166,32 @@ again:
extern void core_alua_free_lu_gp (t10_alua_lu_gp_t *lu_gp)
{
se_device_t *dev, *dev_tmp;
+ /*
+ * Once we have reached this point, config_item_put() has
+ * already been called from target_core_alua_drop_lu_gp().
+ *
+ * Here, we remove the *lu_gp from the global list so that
+ * no associations can be made while we are releasing
+ * t10_alua_lu_gp_t.
+ */
+ spin_lock(&se_global->lu_gps_lock);
+ list_del(&lu_gp->lu_gp_list);
+ se_global->alua_lu_gps_count--;
+ spin_unlock(&se_global->lu_gps_lock);

spin_lock(&lu_gp->lu_gp_ref_lock);
list_for_each_entry_safe(dev, dev_tmp, &lu_gp->lu_gp_ref_list, dev_lu_gp_list) {
list_del(&dev->dev_lu_gp_list);
+ spin_unlock(&lu_gp->lu_gp_ref_lock);
+
spin_lock(&dev->dev_alua_lock);
dev->dev_alua_lu_gp = NULL;
spin_unlock(&dev->dev_alua_lock);
+
+ spin_lock(&lu_gp->lu_gp_ref_lock);
}
spin_unlock(&lu_gp->lu_gp_ref_lock);

- spin_lock(&se_global->lu_gps_lock);
- list_del(&lu_gp->lu_gp_list);
- se_global->alua_lu_gps_count--;
- spin_unlock(&se_global->lu_gps_lock);
-
kmem_cache_free(t10_alua_lu_gp_cache, lu_gp);
return;
}
@@ -305,22 +316,33 @@ again:
extern void core_alua_free_tg_pt_gp (t10_alua_tg_pt_gp_t *tg_pt_gp)
{
se_port_t *port, *port_tmp;
+ /*
+ * Once we have reached this point, config_item_put() has already
+ * been called from target_core_alua_drop_tg_pt_gp().
+ *
+ * Here we remove *tg_pt_gp from the global list so that
+ * no assications *OR* explict ALUA via SET_TARGET_PORT_GROUPS
+ * can be made while we are releasing t10_alua_tg_pt_gp_t.
+ */
+ spin_lock(&se_global->tg_pt_gps_lock);
+ list_del(&tg_pt_gp->tg_pt_gp_list);
+ se_global->alua_tg_pt_gps_counter--;
+ spin_unlock(&se_global->tg_pt_gps_lock);

spin_lock(&tg_pt_gp->tg_pt_gp_ref_lock);
list_for_each_entry_safe(port, port_tmp, &tg_pt_gp->tg_pt_gp_ref_list,
sep_tg_pt_gp_list) {
list_del(&port->sep_tg_pt_gp_list);
+ spin_unlock(&tg_pt_gp->tg_pt_gp_ref_lock);
+
spin_lock(&port->sep_alua_lock);
port->sep_alua_tg_pt_gp = NULL;
spin_unlock(&port->sep_alua_lock);
+
+ spin_lock(&tg_pt_gp->tg_pt_gp_ref_lock);
}
spin_unlock(&tg_pt_gp->tg_pt_gp_ref_lock);

- spin_lock(&se_global->tg_pt_gps_lock);
- list_del(&tg_pt_gp->tg_pt_gp_list);
- se_global->alua_tg_pt_gps_counter--;
- spin_unlock(&se_global->tg_pt_gps_lock);
-
kmem_cache_free(t10_alua_tg_pt_gp_cache, tg_pt_gp);
return;
}
--
1.5.4.1



--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/