mirror of
https://github.com/SCST-project/scst.git
synced 2026-05-20 12:11:26 +00:00
Fix for possible crash on unload for kernels below 2.6.25
git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@1633 d57e44dd-8a1f-0410-8b47-8ef2f437770f
This commit is contained in:
@@ -2548,6 +2548,25 @@ static int scst_ioc_keeper_thread(void *arg)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 25)
|
||||
static struct kref *scst_alloc_io_context_kref(void)
|
||||
{
|
||||
struct kref *io_context_kref;
|
||||
|
||||
io_context_kref = kmalloc(sizeof(*io_context_kref), GFP_KERNEL);
|
||||
if (io_context_kref == NULL) {
|
||||
PRINT_ERROR("Unable to alloc io_context_kref "
|
||||
"(size %zd)", sizeof(*io_context_kref));
|
||||
goto out;
|
||||
}
|
||||
|
||||
kref_init(io_context_kref);
|
||||
|
||||
out:
|
||||
return io_context_kref;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* scst_mutex supposed to be held */
|
||||
int scst_tgt_dev_setup_threads(struct scst_tgt_dev *tgt_dev)
|
||||
{
|
||||
@@ -2640,17 +2659,11 @@ int scst_tgt_dev_setup_threads(struct scst_tgt_dev *tgt_dev)
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 25)
|
||||
else {
|
||||
struct kref *io_context_kref;
|
||||
|
||||
io_context_kref = kmalloc(sizeof(*io_context_kref),
|
||||
GFP_KERNEL);
|
||||
io_context_kref = scst_alloc_io_context_kref();
|
||||
if (io_context_kref == NULL) {
|
||||
PRINT_ERROR("Unable to alloc io_context_kref "
|
||||
"(size %zd)", sizeof(*io_context_kref));
|
||||
res = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
kref_init(io_context_kref);
|
||||
tgt_dev->tgt_dev_cmd_threads.io_context_kref =
|
||||
io_context_kref;
|
||||
}
|
||||
@@ -2674,11 +2687,21 @@ int scst_tgt_dev_setup_threads(struct scst_tgt_dev *tgt_dev)
|
||||
break;
|
||||
}
|
||||
case SCST_THREADS_POOL_SHARED:
|
||||
{
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 25)
|
||||
struct kref *io_context_kref = scst_alloc_io_context_kref();
|
||||
if (io_context_kref == NULL) {
|
||||
res = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
dev->dev_cmd_threads.io_context_kref = io_context_kref;
|
||||
#endif
|
||||
tgt_dev->active_cmd_threads = &dev->dev_cmd_threads;
|
||||
|
||||
res = scst_add_threads(tgt_dev->active_cmd_threads, dev, NULL,
|
||||
tgt_dev->sess->tgt->tgtt->threads_num);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
PRINT_CRIT_ERROR("Unknown threads pool type %d (dev %s)",
|
||||
dev->threads_pool_type, dev->virt_name);
|
||||
|
||||
@@ -1430,7 +1430,7 @@ int scst_add_threads(struct scst_cmd_threads *cmd_threads,
|
||||
thr = kmalloc(sizeof(*thr), GFP_KERNEL);
|
||||
if (!thr) {
|
||||
res = -ENOMEM;
|
||||
PRINT_ERROR("fail to allocate thr %d", res);
|
||||
PRINT_ERROR("Fail to allocate thr %d", res);
|
||||
goto out_error;
|
||||
}
|
||||
|
||||
@@ -1461,6 +1461,15 @@ int scst_add_threads(struct scst_cmd_threads *cmd_threads,
|
||||
wake_up_process(thr->cmd_thread);
|
||||
}
|
||||
|
||||
if (cmd_threads != &scst_main_cmd_threads) {
|
||||
/*
|
||||
* Wait for io_context gets initialized to avoid possible races
|
||||
* for it from the sharing it tgt_devs.
|
||||
*/
|
||||
while (cmd_threads->io_context == NULL)
|
||||
msleep(50);
|
||||
}
|
||||
|
||||
res = 0;
|
||||
|
||||
out:
|
||||
|
||||
@@ -3893,6 +3893,9 @@ int scst_cmd_thread(void *arg)
|
||||
#else
|
||||
current->io_context = p_cmd_threads->io_context;
|
||||
kref_get(p_cmd_threads->io_context_kref);
|
||||
TRACE_DBG("kref %p, new refcount %d",
|
||||
p_cmd_threads->io_context_kref,
|
||||
atomic_read(&p_cmd_threads->io_context_kref->refcount));
|
||||
#endif
|
||||
TRACE_MGMT_DBG("Linked IO context %p "
|
||||
"(p_cmd_threads %p)", p_cmd_threads->io_context,
|
||||
@@ -3937,16 +3940,19 @@ int scst_cmd_thread(void *arg)
|
||||
EXTRACHECKS_BUG_ON((p_cmd_threads->nr_threads == 1) &&
|
||||
!list_empty(&p_cmd_threads->active_cmd_list));
|
||||
|
||||
if ((p_cmd_threads->nr_threads == 1) &&
|
||||
(p_cmd_threads != &scst_main_cmd_threads))
|
||||
p_cmd_threads->io_context = NULL;
|
||||
|
||||
if (p_cmd_threads != &scst_main_cmd_threads) {
|
||||
if (p_cmd_threads->nr_threads == 1)
|
||||
p_cmd_threads->io_context = NULL;
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 25)
|
||||
if (!kref_put(p_cmd_threads->io_context_kref, kref_free))
|
||||
current->io_context = NULL;
|
||||
else
|
||||
p_cmd_threads->io_context_kref = NULL;
|
||||
TRACE_DBG("kref %p, old refcount %d",
|
||||
p_cmd_threads->io_context_kref,
|
||||
atomic_read(&p_cmd_threads->io_context_kref->refcount));
|
||||
if (kref_put(p_cmd_threads->io_context_kref, kref_free))
|
||||
p_cmd_threads->io_context_kref = NULL;
|
||||
else
|
||||
current->io_context = NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
PRINT_INFO("Processing thread %s (PID %d) finished", current->comm,
|
||||
current->pid);
|
||||
|
||||
Reference in New Issue
Block a user