From acbfc9a0d24b143ee678ba827f976bf7750bc5c9 Mon Sep 17 00:00:00 2001 From: Vladislav Bolkhovitin Date: Mon, 23 Mar 2009 19:19:56 +0000 Subject: [PATCH] - Make dynamic io_context assignment complete. Old export_alloc_io_context patch should be reverted and new io_context patch applied instead. - Make BLOCKIO io_contex be per-(device,session) - Cleanups git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@710 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- scst/include/scst.h | 14 +- .../export_alloc_io_context-2.6.27.patch | 22 --- .../export_alloc_io_context-2.6.28.patch | 22 --- scst/kernel/io_context-2.6.27.patch | 61 ++++++ scst/kernel/io_context-2.6.28.patch | 61 ++++++ scst/src/scst_lib.c | 44 ++++- scst/src/scst_main.c | 174 +++++++----------- scst/src/scst_priv.h | 52 ++++-- scst/src/scst_proc.c | 12 +- scst/src/scst_targ.c | 16 +- 10 files changed, 294 insertions(+), 184 deletions(-) delete mode 100644 scst/kernel/export_alloc_io_context-2.6.27.patch delete mode 100644 scst/kernel/export_alloc_io_context-2.6.28.patch create mode 100644 scst/kernel/io_context-2.6.27.patch create mode 100644 scst/kernel/io_context-2.6.28.patch diff --git a/scst/include/scst.h b/scst/include/scst.h index 8306c9bf5..f5c7386de 100644 --- a/scst/include/scst.h +++ b/scst/include/scst.h @@ -1460,6 +1460,9 @@ struct scst_device { /* Lists of commands with lock, if dedicated threads are used */ struct scst_cmd_lists cmd_lists; + /* Per-device dedicated IO context */ + struct io_context *dev_io_ctx; + /* How many cmds alive on this dev */ atomic_t dev_cmd_count; @@ -1577,6 +1580,9 @@ struct scst_tgt_dev { spinlock_t thr_data_lock; struct list_head thr_data_list; + /* Per-(device, session) dedicated IO context */ + struct io_context *tgt_dev_io_ctx; + spinlock_t tgt_dev_lock; /* per-session device lock */ /* List of UA's for this device, protected by tgt_dev_lock */ @@ -2770,11 +2776,11 @@ struct proc_dir_entry *scst_create_proc_entry(struct proc_dir_entry *root, }, /* - * Adds and deletes (stops) num SCST's threads. Returns 0 on success, - * error code otherwise. + * Adds and deletes (stops) num of global SCST's threads. Returns 0 on + * success, error code otherwise. */ -int scst_add_cmd_threads(int num); -void scst_del_cmd_threads(int num); +int scst_add_global_threads(int num); +void scst_del_global_threads(int num); int scst_alloc_sense(struct scst_cmd *cmd, int atomic); int scst_alloc_set_sense(struct scst_cmd *cmd, int atomic, diff --git a/scst/kernel/export_alloc_io_context-2.6.27.patch b/scst/kernel/export_alloc_io_context-2.6.27.patch deleted file mode 100644 index a051ea04e..000000000 --- a/scst/kernel/export_alloc_io_context-2.6.27.patch +++ /dev/null @@ -1,22 +0,0 @@ -diff -upkr linux-2.6.27.2/block/blk-ioc.c linux-2.6.27.2/block/blk-ioc.c ---- linux-2.6.27.2/block/blk-ioc.c 2008-10-10 02:13:53.000000000 +0400 -+++ linux-2.6.27.2/block/blk-ioc.c 2008-11-25 21:27:01.000000000 +0300 -@@ -105,6 +105,7 @@ struct io_context *alloc_io_context(gfp_ - - return ret; - } -+EXPORT_SYMBOL(alloc_io_context); - - /* - * If the current task has no IO context then create one and initialise it. -diff -upkr linux-2.6.27.2/include/linux/iocontext.h linux-2.6.27.2/include/linux/iocontext.h ---- linux-2.6.27.2/include/linux/iocontext.h 2008-10-10 02:13:53.000000000 +0400 -+++ linux-2.6.27.2/include/linux/iocontext.h 2008-11-26 13:23:03.000000000 +0300 -@@ -103,6 +103,7 @@ static inline struct io_context *ioc_tas - int put_io_context(struct io_context *ioc); - void exit_io_context(void); - struct io_context *get_io_context(gfp_t gfp_flags, int node); -+#define SCST_ALLOC_IO_CONTEXT_EXPORTED - struct io_context *alloc_io_context(gfp_t gfp_flags, int node); - void copy_io_context(struct io_context **pdst, struct io_context **psrc); - #else diff --git a/scst/kernel/export_alloc_io_context-2.6.28.patch b/scst/kernel/export_alloc_io_context-2.6.28.patch deleted file mode 100644 index 302cfa213..000000000 --- a/scst/kernel/export_alloc_io_context-2.6.28.patch +++ /dev/null @@ -1,22 +0,0 @@ -diff -upkr linux-2.6.28/block/blk-ioc.c linux-2.6.28/block/blk-ioc.c ---- linux-2.6.28/block/blk-ioc.c 2008-10-10 02:13:53.000000000 +0400 -+++ linux-2.6.28/block/blk-ioc.c 2008-11-25 21:27:01.000000000 +0300 -@@ -105,6 +105,7 @@ struct io_context *alloc_io_context(gfp_ - - return ret; - } -+EXPORT_SYMBOL(alloc_io_context); - - /* - * If the current task has no IO context then create one and initialise it. -diff -upkr linux-2.6.28/include/linux/iocontext.h linux-2.6.28/include/linux/iocontext.h ---- linux-2.6.28/include/linux/iocontext.h 2008-10-10 02:13:53.000000000 +0400 -+++ linux-2.6.28/include/linux/iocontext.h 2008-11-26 13:23:03.000000000 +0300 -@@ -103,6 +103,7 @@ static inline struct io_context *ioc_tas - int put_io_context(struct io_context *ioc); - void exit_io_context(void); - struct io_context *get_io_context(gfp_t gfp_flags, int node); -+#define SCST_ALLOC_IO_CONTEXT_EXPORTED - struct io_context *alloc_io_context(gfp_t gfp_flags, int node); - void copy_io_context(struct io_context **pdst, struct io_context **psrc); - #else diff --git a/scst/kernel/io_context-2.6.27.patch b/scst/kernel/io_context-2.6.27.patch new file mode 100644 index 000000000..e20a8d036 --- /dev/null +++ b/scst/kernel/io_context-2.6.27.patch @@ -0,0 +1,61 @@ +diff -upkr linux-2.6.27.2/block/blk-ioc.c linux-2.6.27.2/block/blk-ioc.c +--- linux-2.6.27.2/block/blk-ioc.c 2008-10-10 02:13:53.000000000 +0400 ++++ linux-2.6.27.2/block/blk-ioc.c 2009-03-23 21:32:37.000000000 +0300 +@@ -65,6 +65,21 @@ static void cfq_exit(struct io_context * + rcu_read_unlock(); + } + ++void __exit_io_context(struct io_context *ioc) ++{ ++ if (ioc == NULL) ++ return; ++ ++ if (atomic_dec_and_test(&ioc->nr_tasks)) { ++ if (ioc->aic && ioc->aic->exit) ++ ioc->aic->exit(ioc->aic); ++ cfq_exit(ioc); ++ ++ put_io_context(ioc); ++ } ++} ++EXPORT_SYMBOL(__exit_io_context); ++ + /* Called by the exitting task */ + void exit_io_context(void) + { +@@ -75,13 +90,7 @@ void exit_io_context(void) + current->io_context = NULL; + task_unlock(current); + +- if (atomic_dec_and_test(&ioc->nr_tasks)) { +- if (ioc->aic && ioc->aic->exit) +- ioc->aic->exit(ioc->aic); +- cfq_exit(ioc); +- +- put_io_context(ioc); +- } ++ __exit_io_context(ioc); + } + + struct io_context *alloc_io_context(gfp_t gfp_flags, int node) +@@ -105,6 +114,7 @@ struct io_context *alloc_io_context(gfp_ + + return ret; + } ++EXPORT_SYMBOL(alloc_io_context); + + /* + * If the current task has no IO context then create one and initialise it. +diff -upkr linux-2.6.27.2/include/linux/iocontext.h linux-2.6.27.2/include/linux/iocontext.h +--- linux-2.6.27.2/include/linux/iocontext.h 2008-10-10 02:13:53.000000000 +0400 ++++ linux-2.6.27.2/include/linux/iocontext.h 2009-03-23 21:32:37.000000000 +0300 +@@ -103,7 +103,9 @@ static inline struct io_context *ioc_tas + int put_io_context(struct io_context *ioc); + void exit_io_context(void); + struct io_context *get_io_context(gfp_t gfp_flags, int node); ++#define SCST_IO_CONTEXT + struct io_context *alloc_io_context(gfp_t gfp_flags, int node); ++void __exit_io_context(struct io_context *ioc); + void copy_io_context(struct io_context **pdst, struct io_context **psrc); + #else + static inline void exit_io_context(void) diff --git a/scst/kernel/io_context-2.6.28.patch b/scst/kernel/io_context-2.6.28.patch new file mode 100644 index 000000000..28558cd96 --- /dev/null +++ b/scst/kernel/io_context-2.6.28.patch @@ -0,0 +1,61 @@ +diff -upkr linux-2.6.28/block/blk-ioc.c linux-2.6.28/block/blk-ioc.c +--- linux-2.6.28/block/blk-ioc.c 2008-12-25 02:26:37.000000000 +0300 ++++ linux-2.6.28/block/blk-ioc.c 2009-03-23 14:28:48.000000000 +0300 +@@ -65,6 +65,21 @@ static void cfq_exit(struct io_context * + rcu_read_unlock(); + } + ++void __exit_io_context(struct io_context *ioc) ++{ ++ if (ioc == NULL) ++ return; ++ ++ if (atomic_dec_and_test(&ioc->nr_tasks)) { ++ if (ioc->aic && ioc->aic->exit) ++ ioc->aic->exit(ioc->aic); ++ cfq_exit(ioc); ++ ++ put_io_context(ioc); ++ } ++} ++EXPORT_SYMBOL(__exit_io_context); ++ + /* Called by the exitting task */ + void exit_io_context(void) + { +@@ -75,13 +90,7 @@ void exit_io_context(void) + current->io_context = NULL; + task_unlock(current); + +- if (atomic_dec_and_test(&ioc->nr_tasks)) { +- if (ioc->aic && ioc->aic->exit) +- ioc->aic->exit(ioc->aic); +- cfq_exit(ioc); +- +- put_io_context(ioc); +- } ++ __exit_io_context(ioc); + } + + struct io_context *alloc_io_context(gfp_t gfp_flags, int node) +@@ -105,6 +114,7 @@ struct io_context *alloc_io_context(gfp_ + + return ret; + } ++EXPORT_SYMBOL(alloc_io_context); + + /* + * If the current task has no IO context then create one and initialise it. +diff -upkr linux-2.6.28/include/linux/iocontext.h linux-2.6.28/include/linux/iocontext.h +--- linux-2.6.28/include/linux/iocontext.h 2008-12-25 02:26:37.000000000 +0300 ++++ linux-2.6.28/include/linux/iocontext.h 2009-03-23 14:05:01.000000000 +0300 +@@ -103,7 +103,9 @@ static inline struct io_context *ioc_tas + int put_io_context(struct io_context *ioc); + void exit_io_context(void); + struct io_context *get_io_context(gfp_t gfp_flags, int node); ++#define SCST_IO_CONTEXT + struct io_context *alloc_io_context(gfp_t gfp_flags, int node); ++void __exit_io_context(struct io_context *ioc); + void copy_io_context(struct io_context **pdst, struct io_context **psrc); + #else + static inline void exit_io_context(void) diff --git a/scst/src/scst_lib.c b/scst/src/scst_lib.c index 0dd88b1cc..c125bd75c 100644 --- a/scst/src/scst_lib.c +++ b/scst/src/scst_lib.c @@ -758,6 +758,18 @@ int scst_alloc_device(gfp_t gfp_mask, struct scst_device **out_dev) dev->queue_alg = SCST_CONTR_MODE_QUEUE_ALG_UNRESTRICTED_REORDER; dev->dev_num = dev_num++; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25) +#if defined(CONFIG_BLOCK) && defined(SCST_IO_CONTEXT) + dev->dev_io_ctx = alloc_io_context(GFP_KERNEL, -1); + if (dev->dev_io_ctx == NULL) { + TRACE(TRACE_OUT_OF_MEM, "%s", "Failed to alloc dev IO context"); + res = -ENOMEM; + kfree(dev); + goto out; + } +#endif +#endif + *out_dev = dev; out: @@ -779,6 +791,12 @@ void scst_free_device(struct scst_device *dev) } #endif +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25) +#if defined(CONFIG_BLOCK) && defined(SCST_IO_CONTEXT) + __exit_io_context(dev->dev_io_ctx); +#endif +#endif + kfree(dev); TRACE_EXIT(); @@ -1024,12 +1042,24 @@ static struct scst_tgt_dev *scst_alloc_add_tgt_dev(struct scst_session *sess, tm_dbg_init_tgt_dev(tgt_dev, acg_dev); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25) +#if defined(CONFIG_BLOCK) && defined(SCST_IO_CONTEXT) + tgt_dev->tgt_dev_io_ctx = alloc_io_context(GFP_KERNEL, -1); + if (tgt_dev->tgt_dev_io_ctx == NULL) { + TRACE(TRACE_OUT_OF_MEM, "Failed to alloc tgt_dev IO context " + "for dev %s (initiator %s)", dev->virt_name, + sess->initiator_name); + goto out_free; + } +#endif +#endif + if (vtt->threads_num > 0) { rc = 0; if (dev->handler->threads_num > 0) rc = scst_add_dev_threads(dev, vtt->threads_num); else if (dev->handler->threads_num == 0) - rc = scst_add_cmd_threads(vtt->threads_num); + rc = scst_add_global_threads(vtt->threads_num); if (rc != 0) goto out_free; } @@ -1066,10 +1096,12 @@ out_thr_free: if (dev->handler->threads_num > 0) scst_del_dev_threads(dev, vtt->threads_num); else if (dev->handler->threads_num == 0) - scst_del_cmd_threads(vtt->threads_num); + scst_del_global_threads(vtt->threads_num); } out_free: + __exit_io_context(tgt_dev->tgt_dev_io_ctx); + kmem_cache_free(scst_tgtd_cachep, tgt_dev); tgt_dev = NULL; goto out; @@ -1135,9 +1167,15 @@ static void scst_free_tgt_dev(struct scst_tgt_dev *tgt_dev) if (dev->handler->threads_num > 0) scst_del_dev_threads(dev, vtt->threads_num); else if (dev->handler->threads_num == 0) - scst_del_cmd_threads(vtt->threads_num); + scst_del_global_threads(vtt->threads_num); } +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25) +#if defined(CONFIG_BLOCK) && defined(SCST_IO_CONTEXT) + __exit_io_context(tgt_dev->tgt_dev_io_ctx); +#endif +#endif + kmem_cache_free(scst_tgtd_cachep, tgt_dev); TRACE_EXIT(); diff --git a/scst/src/scst_main.c b/scst/src/scst_main.c index f30178f7c..f40d2834c 100644 --- a/scst/src/scst_main.c +++ b/scst/src/scst_main.c @@ -48,8 +48,8 @@ #endif #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25) -#if !defined(SCST_ALLOC_IO_CONTEXT_EXPORTED) -#warning "Patch export_alloc_io_context-.patch was not applied \ +#if !defined(SCST_IO_CONTEXT) +#warning "Patch io_context-.patch was not applied \ on your kernel. SCST will be working with not the best performance." #endif #endif @@ -129,18 +129,17 @@ static struct mutex scst_suspend_mutex; static struct list_head scst_cmd_lists_list; static int scst_threads; -struct scst_threads_info_t scst_threads_info; +struct mutex scst_global_threads_mutex; +u32 scst_nr_global_threads; +static struct list_head scst_global_threads_list; +static struct task_struct *scst_init_cmd_thread; +static struct task_struct *scst_mgmt_thread; +static struct task_struct *scst_mgmt_cmd_thread; static int suspend_count; static int scst_virt_dev_last_id; /* protected by scst_mutex */ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25) -#if defined(CONFIG_BLOCK) && defined(SCST_ALLOC_IO_CONTEXT_EXPORTED) -static struct io_context *scst_ioc; -#endif -#endif - static unsigned int scst_max_cmd_mem; unsigned int scst_max_dev_cmd_mem; @@ -1101,7 +1100,6 @@ int scst_add_dev_threads(struct scst_device *dev, int num) int i, res = 0; int n = 0; struct scst_cmd_thread_t *thr; - struct io_context *ioc = NULL; char nm[12]; TRACE_ENTRY(); @@ -1131,25 +1129,14 @@ int scst_add_dev_threads(struct scst_device *dev, int num) list_add(&thr->thread_list_entry, &dev->threads_list); #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25) -#if defined(CONFIG_BLOCK) && defined(SCST_ALLOC_IO_CONTEXT_EXPORTED) +#if defined(CONFIG_BLOCK) && defined(SCST_IO_CONTEXT) /* - * It would be better to keep io_context in tgt_dev and - * dynamically assign it to the current thread on the IO - * submission time to let each initiator have own - * io_context. But, unfortunately, CFQ doesn't - * support if a task has dynamically switched - * io_context, it oopses on BUG_ON(!cic->dead_key) in - * cic_free_func(). So, we have to have the same io_context - * for all initiators. + * ToDo: better to use tgt_dev_io_context instead, but we + * are not ready for that yet. */ - if (ioc == NULL) { - ioc = alloc_io_context(GFP_KERNEL, -1); - TRACE_DBG("ioc %p (thr %d)", ioc, thr->cmd_thread->pid); - } - - put_io_context(thr->cmd_thread->io_context); - thr->cmd_thread->io_context = ioc_task_link(ioc); - TRACE_DBG("Setting ioc %p on thr %d", ioc, + __exit_io_context(thr->cmd_thread->io_context); + thr->cmd_thread->io_context = ioc_task_link(dev->dev_io_ctx); + TRACE_DBG("Setting dev io ctx %p on thr %d", dev->dev_io_ctx, thr->cmd_thread->pid); #endif #endif @@ -1157,8 +1144,6 @@ int scst_add_dev_threads(struct scst_device *dev, int num) } out: - put_io_context(ioc); - TRACE_EXIT_RES(res); return res; } @@ -1355,41 +1340,40 @@ out_err_detach_tgt: goto out_null; } -int scst_cmd_threads_count(void) +int scst_global_threads_count(void) { int i; /* * Just to lower the race window, when user can get just changed value */ - mutex_lock(&scst_threads_info.cmd_threads_mutex); - i = scst_threads_info.nr_cmd_threads; - mutex_unlock(&scst_threads_info.cmd_threads_mutex); + mutex_lock(&scst_global_threads_mutex); + i = scst_nr_global_threads; + mutex_unlock(&scst_global_threads_mutex); return i; } static void scst_threads_info_init(void) { - memset(&scst_threads_info, 0, sizeof(scst_threads_info)); - mutex_init(&scst_threads_info.cmd_threads_mutex); - INIT_LIST_HEAD(&scst_threads_info.cmd_threads_list); + mutex_init(&scst_global_threads_mutex); + INIT_LIST_HEAD(&scst_global_threads_list); } -/* scst_threads_info.cmd_threads_mutex supposed to be held */ -void __scst_del_cmd_threads(int num) +/* scst_global_threads_mutex supposed to be held */ +void __scst_del_global_threads(int num) { struct scst_cmd_thread_t *ct, *tmp; int i; TRACE_ENTRY(); - i = scst_threads_info.nr_cmd_threads; + i = scst_nr_global_threads; if (num <= 0 || num > i) { PRINT_ERROR("can not del %d cmd threads from %d", num, i); return; } - list_for_each_entry_safe(ct, tmp, &scst_threads_info.cmd_threads_list, + list_for_each_entry_safe(ct, tmp, &scst_global_threads_list, thread_list_entry) { int res; @@ -1398,7 +1382,7 @@ void __scst_del_cmd_threads(int num) TRACE_MGMT_DBG("kthread_stop() failed: %d", res); list_del(&ct->thread_list_entry); kfree(ct); - scst_threads_info.nr_cmd_threads--; + scst_nr_global_threads--; --num; if (num == 0) break; @@ -1408,8 +1392,8 @@ void __scst_del_cmd_threads(int num) return; } -/* scst_threads_info.cmd_threads_mutex supposed to be held */ -int __scst_add_cmd_threads(int num) +/* scst_global_threads_mutex supposed to be held */ +int __scst_add_global_threads(int num) { int res = 0, i; static int scst_thread_num; @@ -1435,25 +1419,9 @@ int __scst_add_cmd_threads(int num) goto out_error; } - list_add(&thr->thread_list_entry, - &scst_threads_info.cmd_threads_list); - scst_threads_info.nr_cmd_threads++; + list_add(&thr->thread_list_entry, &scst_global_threads_list); + scst_nr_global_threads++; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25) -#if defined(CONFIG_BLOCK) && defined(SCST_ALLOC_IO_CONTEXT_EXPORTED) - /* See comment in scst_add_dev_threads() */ - if (scst_ioc == NULL) { - scst_ioc = alloc_io_context(GFP_KERNEL, -1); - TRACE_DBG("scst_ioc %p (thr %d)", scst_ioc, - thr->cmd_thread->pid); - } - - put_io_context(thr->cmd_thread->io_context); - thr->cmd_thread->io_context = ioc_task_link(scst_ioc); - TRACE_DBG("Setting scst_ioc %p on thr %d", - scst_ioc, thr->cmd_thread->pid); -#endif -#endif wake_up_process(thr->cmd_thread); } res = 0; @@ -1464,51 +1432,51 @@ out: out_error: if (i > 0) - __scst_del_cmd_threads(i - 1); + __scst_del_global_threads(i - 1); goto out; } -int scst_add_cmd_threads(int num) +int scst_add_global_threads(int num) { int res; TRACE_ENTRY(); - mutex_lock(&scst_threads_info.cmd_threads_mutex); - res = __scst_add_cmd_threads(num); - mutex_unlock(&scst_threads_info.cmd_threads_mutex); + mutex_lock(&scst_global_threads_mutex); + res = __scst_add_global_threads(num); + mutex_unlock(&scst_global_threads_mutex); TRACE_EXIT_RES(res); return res; } -EXPORT_SYMBOL(scst_add_cmd_threads); +EXPORT_SYMBOL(scst_add_global_threads); -void scst_del_cmd_threads(int num) +void scst_del_global_threads(int num) { TRACE_ENTRY(); - mutex_lock(&scst_threads_info.cmd_threads_mutex); - __scst_del_cmd_threads(num); - mutex_unlock(&scst_threads_info.cmd_threads_mutex); + mutex_lock(&scst_global_threads_mutex); + __scst_del_global_threads(num); + mutex_unlock(&scst_global_threads_mutex); TRACE_EXIT(); return; } -EXPORT_SYMBOL(scst_del_cmd_threads); +EXPORT_SYMBOL(scst_del_global_threads); static void scst_stop_all_threads(void) { TRACE_ENTRY(); - mutex_lock(&scst_threads_info.cmd_threads_mutex); - __scst_del_cmd_threads(scst_threads_info.nr_cmd_threads); - if (scst_threads_info.mgmt_cmd_thread) - kthread_stop(scst_threads_info.mgmt_cmd_thread); - if (scst_threads_info.mgmt_thread) - kthread_stop(scst_threads_info.mgmt_thread); - if (scst_threads_info.init_cmd_thread) - kthread_stop(scst_threads_info.init_cmd_thread); - mutex_unlock(&scst_threads_info.cmd_threads_mutex); + mutex_lock(&scst_global_threads_mutex); + __scst_del_global_threads(scst_nr_global_threads); + if (scst_mgmt_cmd_thread) + kthread_stop(scst_mgmt_cmd_thread); + if (scst_mgmt_thread) + kthread_stop(scst_mgmt_thread); + if (scst_init_cmd_thread) + kthread_stop(scst_init_cmd_thread); + mutex_unlock(&scst_global_threads_mutex); TRACE_EXIT(); return; @@ -1520,40 +1488,40 @@ static int scst_start_all_threads(int num) TRACE_ENTRY(); - mutex_lock(&scst_threads_info.cmd_threads_mutex); - res = __scst_add_cmd_threads(num); + mutex_lock(&scst_global_threads_mutex); + res = __scst_add_global_threads(num); if (res < 0) goto out; - scst_threads_info.init_cmd_thread = kthread_run(scst_init_cmd_thread, + scst_init_cmd_thread = kthread_run(scst_init_thread, NULL, "scsi_tgt_init"); - if (IS_ERR(scst_threads_info.init_cmd_thread)) { - res = PTR_ERR(scst_threads_info.init_cmd_thread); + if (IS_ERR(scst_init_cmd_thread)) { + res = PTR_ERR(scst_init_cmd_thread); PRINT_ERROR("kthread_create() for init cmd failed: %d", res); - scst_threads_info.init_cmd_thread = NULL; + scst_init_cmd_thread = NULL; goto out; } - scst_threads_info.mgmt_cmd_thread = kthread_run(scst_mgmt_cmd_thread, - NULL, "scsi_tgt_mc"); - if (IS_ERR(scst_threads_info.mgmt_cmd_thread)) { - res = PTR_ERR(scst_threads_info.mgmt_cmd_thread); - PRINT_ERROR("kthread_create() for mcmd failed: %d", res); - scst_threads_info.mgmt_cmd_thread = NULL; + scst_mgmt_cmd_thread = kthread_run(scst_tm_thread, + NULL, "scsi_tm"); + if (IS_ERR(scst_mgmt_cmd_thread)) { + res = PTR_ERR(scst_mgmt_cmd_thread); + PRINT_ERROR("kthread_create() for TM failed: %d", res); + scst_mgmt_cmd_thread = NULL; goto out; } - scst_threads_info.mgmt_thread = kthread_run(scst_mgmt_thread, + scst_mgmt_thread = kthread_run(scst_global_mgmt_thread, NULL, "scsi_tgt_mgmt"); - if (IS_ERR(scst_threads_info.mgmt_thread)) { - res = PTR_ERR(scst_threads_info.mgmt_thread); + if (IS_ERR(scst_mgmt_thread)) { + res = PTR_ERR(scst_mgmt_thread); PRINT_ERROR("kthread_create() for mgmt failed: %d", res); - scst_threads_info.mgmt_thread = NULL; + scst_mgmt_thread = NULL; goto out; } out: - mutex_unlock(&scst_threads_info.cmd_threads_mutex); + mutex_unlock(&scst_global_threads_mutex); TRACE_EXIT_RES(res); return res; } @@ -1728,8 +1696,8 @@ static int __init init_scst(void) BUILD_BUG_ON(SCST_DATA_NONE != DMA_NONE); #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25) -#if !defined(SCST_ALLOC_IO_CONTEXT_EXPORTED) - PRINT_WARNING("%s", "Patch export_alloc_io_context was not applied on " +#if !defined(SCST_IO_CONTEXT) + PRINT_WARNING("%s", "Patch io_context was not applied on " "your kernel. SCST will be working with not the best " "performance."); #endif @@ -2006,12 +1974,6 @@ static void __exit exit_scst(void) DEINIT_CACHEP(scst_tgtd_cachep); DEINIT_CACHEP(scst_acgd_cachep); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25) -#if defined(CONFIG_BLOCK) && defined(SCST_ALLOC_IO_CONTEXT_EXPORTED) - put_io_context(scst_ioc); -#endif -#endif - PRINT_INFO("%s", "SCST unloaded"); TRACE_EXIT(); diff --git a/scst/src/scst_priv.h b/scst/src/scst_priv.h index b5da43d6a..58edb6a7e 100644 --- a/scst/src/scst_priv.h +++ b/scst/src/scst_priv.h @@ -177,19 +177,41 @@ struct scst_cmd_thread_t { struct list_head thread_list_entry; }; -struct scst_threads_info_t { - struct mutex cmd_threads_mutex; - u32 nr_cmd_threads; - struct list_head cmd_threads_list; - struct task_struct *init_cmd_thread; - struct task_struct *mgmt_thread; - struct task_struct *mgmt_cmd_thread; -}; +static inline void scst_set_io_context(struct scst_tgt_dev *tgt_dev) +{ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25) +#if defined(CONFIG_BLOCK) && defined(SCST_IO_CONTEXT) + if (tgt_dev->dev->p_cmd_lists == &scst_main_cmd_lists) { + EXTRACHECKS_BUG_ON(current->io_context); + /* + * No need to call ioc_task_link(), because io_context + * supposed to be cleared in the end of the caller function. + */ + current->io_context = tgt_dev->tgt_dev_io_ctx; + TRACE_DBG("io_context %p", tgt_dev->tgt_dev_io_ctx); + } +#endif +#endif +} -extern struct scst_threads_info_t scst_threads_info; -extern int scst_cmd_threads_count(void); -extern int __scst_add_cmd_threads(int num); -extern void __scst_del_cmd_threads(int num); +static inline void scst_reset_io_context(struct scst_tgt_dev *tgt_dev) +{ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25) +#if defined(CONFIG_BLOCK) && defined(SCST_IO_CONTEXT) + if (current->io_context == tgt_dev->tgt_dev_io_ctx) { + current->io_context = NULL; + TRACE_DBG("io_context %p reset", tgt_dev->tgt_dev_io_ctx); + } +#endif +#endif +} + +extern struct mutex scst_global_threads_mutex; +extern u32 scst_nr_global_threads; + +extern int scst_global_threads_count(void); +extern int __scst_add_global_threads(int num); +extern void __scst_del_global_threads(int num); extern struct scst_dev_type scst_null_devtype; @@ -235,9 +257,9 @@ void scst_xmit_process_aborted_cmd(struct scst_cmd *cmd); int scst_cmd_thread(void *arg); void scst_cmd_tasklet(long p); -int scst_init_cmd_thread(void *arg); -int scst_mgmt_cmd_thread(void *arg); -int scst_mgmt_thread(void *arg); +int scst_init_thread(void *arg); +int scst_tm_thread(void *arg); +int scst_global_mgmt_thread(void *arg); int scst_add_dev_threads(struct scst_device *dev, int num); void scst_del_dev_threads(struct scst_device *dev, int num); diff --git a/scst/src/scst_proc.c b/scst/src/scst_proc.c index 6f7a8c781..ed6c2c171 100644 --- a/scst/src/scst_proc.c +++ b/scst/src/scst_proc.c @@ -923,9 +923,9 @@ static ssize_t scst_proc_threads_write(struct file *file, goto out_free; } - mutex_lock(&scst_threads_info.cmd_threads_mutex); + mutex_lock(&scst_global_threads_mutex); - oldtn = scst_threads_info.nr_cmd_threads; + oldtn = scst_nr_global_threads; newtn = simple_strtoul(buffer, NULL, 0); if (newtn <= 0) { PRINT_ERROR("Illegal threads num value %d", newtn); @@ -934,14 +934,14 @@ static ssize_t scst_proc_threads_write(struct file *file, } delta = newtn - oldtn; if (delta < 0) - __scst_del_cmd_threads(-delta); + __scst_del_global_threads(-delta); else - __scst_add_cmd_threads(delta); + __scst_add_global_threads(delta); PRINT_INFO("Changed cmd threads num: old %d, new %d", oldtn, newtn); out_up_thr_free: - mutex_unlock(&scst_threads_info.cmd_threads_mutex); + mutex_unlock(&scst_global_threads_mutex); mutex_unlock(&scst_proc_mutex); @@ -2102,7 +2102,7 @@ static int scst_threads_info_show(struct seq_file *seq, void *v) { TRACE_ENTRY(); - seq_printf(seq, "%d\n", scst_cmd_threads_count()); + seq_printf(seq, "%d\n", scst_global_threads_count()); TRACE_EXIT(); return 0; diff --git a/scst/src/scst_targ.c b/scst/src/scst_targ.c index b83bbc466..7b5843923 100644 --- a/scst/src/scst_targ.c +++ b/scst/src/scst_targ.c @@ -1863,6 +1863,8 @@ static int scst_do_real_exec(struct scst_cmd *cmd) TRACE_ENTRY(); + scst_set_io_context(cmd->tgt_dev); + cmd->state = SCST_CMD_STATE_REAL_EXECUTING; if (handler->exec) { @@ -1952,14 +1954,16 @@ static int scst_do_real_exec(struct scst_cmd *cmd) out_complete: res = SCST_EXEC_COMPLETED; -out: +out_reset: + scst_reset_io_context(cmd->tgt_dev); + TRACE_EXIT(); return res; out_restore: /* Restore the state */ cmd->state = SCST_CMD_STATE_REAL_EXEC; - goto out; + goto out_reset; out_error: scst_set_cmd_error(cmd, SCST_LOAD_SENSE(scst_sense_hardw_error)); @@ -3338,7 +3342,7 @@ static inline int test_init_cmd_list(void) return res; } -int scst_init_cmd_thread(void *arg) +int scst_init_thread(void *arg) { TRACE_ENTRY(); @@ -3626,7 +3630,7 @@ int scst_cmd_thread(void *arg) * process the commands lists. */ if (p_cmd_lists == &scst_main_cmd_lists) { - sBUG_ON((scst_threads_info.nr_cmd_threads == 1) && + sBUG_ON((scst_nr_global_threads == 1) && !list_empty(&scst_main_cmd_lists.active_cmd_list)); } #endif @@ -4906,7 +4910,7 @@ static inline int test_mgmt_cmd_list(void) return res; } -int scst_mgmt_cmd_thread(void *arg) +int scst_tm_thread(void *arg) { TRACE_ENTRY(); @@ -5445,7 +5449,7 @@ static inline int test_mgmt_list(void) return res; } -int scst_mgmt_thread(void *arg) +int scst_global_mgmt_thread(void *arg) { struct scst_session *sess;