mirror of
https://github.com/SCST-project/scst.git
synced 2026-08-20 14:16:31 +00:00
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:
+13
-4
@@ -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",
|
||||
|
||||
@@ -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
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user