scst: Fix race triggered by target unregistration

Without this patch it is possible that some target's sysfs attributes
can be called after release() callback returned, when, for instance,
tgt_priv is already set to NULL.



git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@4495 d57e44dd-8a1f-0410-8b47-8ef2f437770f
This commit is contained in:
Vladislav Bolkhovitin
2012-08-28 01:38:11 +00:00
parent aaac0d983d
commit 7f16c1b4a2
3 changed files with 28 additions and 9 deletions
+13 -4
View File
@@ -618,6 +618,17 @@ void scst_unregister_target(struct scst_tgt *tgt)
TRACE_ENTRY();
/*
* Remove the sysfs attributes of a target before invoking
* tgt->tgtt->release(tgt) such that the "enabled" attribute can't be
* accessed during or after the tgt->tgtt->release(tgt) call.
*/
#ifdef CONFIG_SCST_PROC
scst_cleanup_proc_target_entries(tgt);
#else
scst_tgt_sysfs_del(tgt);
#endif
TRACE_DBG("%s", "Calling target driver's release()");
tgt->tgtt->release(tgt);
TRACE_DBG("%s", "Target driver's release() returned");
@@ -653,9 +664,7 @@ again:
scst_tg_tgt_remove_by_tgt(tgt);
#ifdef CONFIG_SCST_PROC
scst_cleanup_proc_target_entries(tgt);
#else
#ifndef CONFIG_SCST_PROC
scst_del_free_acg(tgt->default_acg);
list_for_each_entry_safe(acg, acg_tmp, &tgt->tgt_acg_list,
@@ -668,7 +677,7 @@ again:
scst_resume_activity();
#ifndef CONFIG_SCST_PROC
scst_tgt_sysfs_del(tgt);
scst_tgt_sysfs_put(tgt);
#endif
PRINT_INFO("Target %s for template %s unregistered successfully",
+1
View File
@@ -415,6 +415,7 @@ void scst_tg_tgt_remove_by_tgt(struct scst_tgt *tgt);
#ifndef CONFIG_SCST_PROC
int scst_dg_sysfs_add(struct kobject *parent, struct scst_dev_group *dg);
void scst_dg_sysfs_del(struct scst_dev_group *dg);
void scst_tgt_sysfs_put(struct scst_tgt *tgt);
int scst_dg_dev_sysfs_add(struct scst_dev_group *dg, struct scst_dg_dev *dgdev);
void scst_dg_dev_sysfs_del(struct scst_dev_group *dg,
struct scst_dg_dev *dgdev);
+14 -5
View File
@@ -2399,13 +2399,8 @@ out_err:
*/
void scst_tgt_sysfs_del(struct scst_tgt *tgt)
{
int rc;
DECLARE_COMPLETION_ONSTACK(c);
TRACE_ENTRY();
tgt->tgt_kobj_release_cmpl = &c;
kobject_del(tgt->tgt_sess_kobj);
kobject_del(tgt->tgt_luns_kobj);
kobject_del(tgt->tgt_ini_grp_kobj);
@@ -2414,6 +2409,20 @@ void scst_tgt_sysfs_del(struct scst_tgt *tgt)
kobject_put(tgt->tgt_sess_kobj);
kobject_put(tgt->tgt_luns_kobj);
kobject_put(tgt->tgt_ini_grp_kobj);
TRACE_EXIT();
return;
}
void scst_tgt_sysfs_put(struct scst_tgt *tgt)
{
int rc;
DECLARE_COMPLETION_ONSTACK(c);
TRACE_ENTRY();
tgt->tgt_kobj_release_cmpl = &c;
kobject_put(&tgt->tgt_kobj);
rc = wait_for_completion_timeout(tgt->tgt_kobj_release_cmpl, HZ);