- Threads made per-device
authorvlnb <vlnb@d57e44dd-8a1f-0410-8b47-8ef2f437770f>
Fri, 8 Jun 2007 10:25:29 +0000 (10:25 +0000)
committervlnb <vlnb@d57e44dd-8a1f-0410-8b47-8ef2f437770f>
Fri, 8 Jun 2007 10:25:29 +0000 (10:25 +0000)
 - Minor cleanups and fixes

git-svn-id: https://scst.svn.sourceforge.net/svnroot/scst/trunk@125 d57e44dd-8a1f-0410-8b47-8ef2f437770f

12 files changed:
Makefile
doc/scst_user_spec.txt
scst/include/scsi_tgt.h
scst/include/scst_debug.h
scst/include/scst_user.h
scst/src/dev_handlers/scst_user.c
scst/src/scst.c
scst/src/scst_lib.c
scst/src/scst_mem.c
scst/src/scst_priv.h
scst/src/scst_targ.c
usr/fileio/common.c

index 31f93f9..a2d1d8e 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -154,5 +154,5 @@ help:
 .PHONY: all install uninstall clean extraclean help \
        qla qla_install qla_uninstall qla_clean qla_extraclean \
        lsi lsi_install lsi_uninstall lsi_clean lsi_extraclean \
-       scst scst_install scst_uninstall scst_clean scst_extraclean
+       scst scst_install scst_uninstall scst_clean scst_extraclean \
        usr usr_install usr_uninstall usr_clean usr_extraclean
index 35ab443..423e182 100644 (file)
@@ -251,6 +251,7 @@ struct scst_user_sess
 {
        uint64_t sess_h;
        uint64_t lun;
+       uint16_t threads_num;
        uint8_t rd_only;
        char initiator_name[SCST_MAX_NAME];
 },
@@ -260,7 +261,10 @@ where:
  - sess_h - session's handle, may not be 0
 
  - lun - assigned LUN for this device in this session
+
+ - threads_num - specifies amount of additional threads, requested by
+   the corresponding target driver
+
  - rd_only - if true, this device is read only in this session
 
  - initiator_name - name of the remote initiator, which initiated this
index cf6e3bc..61e813f 100644 (file)
@@ -619,9 +619,6 @@ struct scst_tgt_template
        /* The pointer to the /proc directory entry */
        struct proc_dir_entry *proc_tgt_root;
 
-       /* Dedicated thread number */
-       int thread_num;
-       
        /* Device number in /proc */
        int proc_dev_num;
 };
@@ -1181,6 +1178,12 @@ struct scst_device
 {
        struct scst_dev_type *handler;  /* corresponding dev handler */
 
+       /* Pointer to lists of commands with the lock */
+       struct scst_cmd_lists *p_cmd_lists;
+
+       /* Lists of commands with the lock, if dedicated threads are used */
+       struct scst_cmd_lists cmd_lists;
+
        unsigned short type;    /* SCSI type of the device */
 
        /*************************************************************
@@ -1250,6 +1253,9 @@ struct scst_device
        
        /* List of acg_dev's, one per acg, protected by scst_mutex */
        struct list_head dev_acg_dev_list;
+
+       /* List of dedicated threads. Doesn't need any protection.  */
+       struct list_head threads_list;
 };
 
 /*
@@ -1276,9 +1282,6 @@ struct scst_tgt_dev
        struct scst_device *dev; /* to save extra dereferences */
        lun_t lun;               /* to save extra dereferences */
 
-       /* Pointer to lists of commands with the lock */
-       struct scst_cmd_lists *p_cmd_lists;
-
        /* How many cmds alive on this dev in this session */
        atomic_t cmd_count; 
 
@@ -1313,9 +1316,6 @@ struct scst_tgt_dev
        atomic_t *cur_sn_slot;
        atomic_t sn_slots[10];
 
-       /* Lists of commands with the lock, if dedicated threads are used */
-       struct scst_cmd_lists cmd_lists;
-
        /* Used for storage of dev handler private stuff */
        void *dh_priv;
 
@@ -1337,8 +1337,7 @@ struct scst_tgt_dev
        /* internal tmp list entry */
        struct list_head extra_tgt_dev_list_entry;
 
-       /* List of dedicated threads. Doesn't need any protection.  */
-       struct list_head threads_list;
+       
 };
 
 /*
index 040994e..3b9fc14 100644 (file)
 #endif
 
 #ifdef EXTRACHECKS
-#define EXTRACHECKS_BUG_ON(a)  sBUG_ON(a)
+#define EXTRACHECKS_BUG_ON(a)          sBUG_ON(a)
+#define EXTRACHECKS_WARN_ON(a)         WARN_ON(a)
+#define EXTRACHECKS_WARN_ON_ONCE(a)    WARN_ON_ONCE(a)
 #else
 #define EXTRACHECKS_BUG_ON(a)
+#define EXTRACHECKS_WARN_ON(a)
+#define EXTRACHECKS_WARN_ON_ONCE(a)
 #endif
 
 #ifdef DEBUG
index 3c036cb..dfcac09 100644 (file)
@@ -106,6 +106,7 @@ struct scst_user_sess
 {
        aligned_u64 sess_h;
        aligned_u64 lun;
+       uint16_t threads_num;
        uint8_t rd_only;
        char initiator_name[SCST_MAX_NAME];
 };
index 54be32c..339a567 100644 (file)
@@ -2148,6 +2148,8 @@ static int dev_user_attach(struct scst_device *sdev)
                goto out;
        }
 
+       sdev->p_cmd_lists = &dev->cmd_lists;
+
        sdev->dh_priv = dev;
 
        PRINT_INFO_PR("Attached user space SCSI target virtual device \"%s\"",
@@ -2219,8 +2221,6 @@ static int dev_user_attach_tgt(struct scst_tgt_dev *tgt_dev)
 
        TRACE_ENTRY();
 
-       tgt_dev->p_cmd_lists = &dev->cmd_lists;
-
        ucmd = dev_user_alloc_ucmd(dev, GFP_KERNEL);
        if (ucmd == NULL)
                goto out_nomem;
@@ -2235,6 +2235,7 @@ static int dev_user_attach_tgt(struct scst_tgt_dev *tgt_dev)
        ucmd->user_cmd.subcode = SCST_USER_ATTACH_SESS;
        ucmd->user_cmd.sess.sess_h = (unsigned long)tgt_dev;
        ucmd->user_cmd.sess.lun = (uint64_t)tgt_dev->lun;
+       ucmd->user_cmd.sess.threads_num = tgt_dev->sess->tgt->tgtt->threads_num;
        ucmd->user_cmd.sess.rd_only = tgt_dev->acg_dev->rd_only_flag;
        strncpy(ucmd->user_cmd.sess.initiator_name,
                tgt_dev->sess->initiator_name,
@@ -2243,9 +2244,10 @@ static int dev_user_attach_tgt(struct scst_tgt_dev *tgt_dev)
                sizeof(ucmd->user_cmd.sess.initiator_name)-1] = '\0';
 
        TRACE_MGMT_DBG("Preparing ATTACH_SESS %p (h %d, sess_h %Lx, LUN %Lx, "
-               "rd_only_flag %d, initiator %s)", ucmd, ucmd->h,
+               "threads_num %d, rd_only_flag %d, initiator %s)", ucmd, ucmd->h,
                ucmd->user_cmd.sess.sess_h, ucmd->user_cmd.sess.lun,
-               ucmd->user_cmd.sess.rd_only, ucmd->user_cmd.sess.initiator_name);
+               ucmd->user_cmd.sess.threads_num, ucmd->user_cmd.sess.rd_only,
+               ucmd->user_cmd.sess.initiator_name);
 
        ucmd->state = UCMD_STATE_ATTACH_SESS;
 
index 84d5067..d85a1bb 100644 (file)
@@ -156,6 +156,14 @@ int scst_register_target_template(struct scst_tgt_template *vtt)
                goto out_err;
        }
 
+       if (vtt->threads_num < 0) {
+               PRINT_ERROR_PR("Wrong threads_num value %d for "
+                       "target \"%s\"", vtt->threads_num,
+                       vtt->name);
+               res = -EINVAL;
+               goto out_err;
+       }
+
        if (!vtt->no_proc_entry) {
                res = scst_build_proc_target_dir_entries(vtt);
                if (res < 0)
@@ -467,11 +475,9 @@ static int scst_register_device(struct scsi_device *scsidp)
        scst_suspend_activity();
        down(&scst_mutex);
 
-       dev = scst_alloc_device(GFP_KERNEL);
-       if (dev == NULL) {
-               res = -ENOMEM;
+       res = scst_alloc_device(GFP_KERNEL, &dev);
+       if (res != 0)
                goto out_up;
-       }
 
        dev->type = scsidp->type;
 
@@ -618,22 +624,19 @@ int scst_register_virtual_device(struct scst_dev_type *dev_handler,
        if (res != 0)
                goto out;
 
-       dev = scst_alloc_device(GFP_KERNEL);
-       if (dev == NULL) {
-               res = -ENOMEM;
-               goto out;
-       }
-
-       dev->type = dev_handler->type;
-       dev->scsi_dev = NULL;
-       dev->virt_name = dev_name;
-
        scst_suspend_activity();
        if (down_interruptible(&scst_mutex) != 0) {
                res = -EINTR;
-               goto out_free_dev;
+               goto out_resume;
        }
 
+       res = scst_alloc_device(GFP_KERNEL, &dev);
+       if (res != 0)
+               goto out_up;
+
+       dev->type = dev_handler->type;
+       dev->scsi_dev = NULL;
+       dev->virt_name = dev_name;
        dev->virt_id = scst_virt_dev_last_id++;
 
        list_add_tail(&dev->dev_list_entry, &scst_dev_list);
@@ -645,7 +648,8 @@ int scst_register_virtual_device(struct scst_dev_type *dev_handler,
                res = rc;
                goto out_free_del;
        }
-       
+
+out_up:
        up(&scst_mutex);
 
 out_resume:
@@ -666,11 +670,8 @@ out:
 
 out_free_del:
        list_del(&dev->dev_list_entry);
-       up(&scst_mutex);
-
-out_free_dev:
        scst_free_device(dev);
-       goto out_resume;
+       goto out_up;
 }
 
 void scst_unregister_virtual_device(int id)
@@ -893,6 +894,123 @@ void scst_unregister_virtual_dev_driver(struct scst_dev_type *dev_type)
        return;
 }
 
+/* Called under scst_mutex and suspended activity */
+int scst_add_dev_threads(struct scst_device *dev, int num)
+{
+       int i, res = 0;
+       static atomic_t major = ATOMIC_INIT(0);
+       int N, n = 0;
+       char nm[12];
+
+       TRACE_ENTRY();
+
+       N = atomic_inc_return(&major);
+
+       for (i = 0; i < num; i++) {
+               struct scst_cmd_thread_t *thr;
+
+               thr = kmalloc(sizeof(*thr), GFP_KERNEL);
+               if (!thr) {
+                       res = -ENOMEM;
+                       PRINT_ERROR_PR("Failed to allocate thr %d", res);
+                       goto out;
+               }
+               strncpy(nm, dev->handler->name, ARRAY_SIZE(nm)-1);
+               nm[ARRAY_SIZE(nm)-1] = '\0';
+               thr->cmd_thread = kthread_run(scst_cmd_thread,
+                       &dev->cmd_lists, "%sd%d_%d", nm, N, n++);
+               if (IS_ERR(thr->cmd_thread)) {
+                       res = PTR_ERR(thr->cmd_thread);
+                       PRINT_ERROR_PR("kthread_create() failed: %d", res);
+                       kfree(thr);
+                       goto out;
+               }
+               list_add(&thr->thread_list_entry, &dev->threads_list);
+       }
+
+out:
+       TRACE_EXIT_RES(res);
+       return res;
+}
+
+/* Called under scst_mutex and suspended activity */
+static int scst_create_dev_threads(struct scst_device *dev)
+{
+       int res = 0;
+       int threads_num;
+
+       TRACE_ENTRY();
+
+       if (dev->handler->threads_num <= 0)
+               goto out;
+
+       threads_num = dev->handler->threads_num;
+
+       spin_lock_init(&dev->cmd_lists.cmd_list_lock);
+       INIT_LIST_HEAD(&dev->cmd_lists.active_cmd_list);
+       init_waitqueue_head(&dev->cmd_lists.cmd_list_waitQ);
+
+       res = scst_add_dev_threads(dev, threads_num);
+       if (res != 0)
+               goto out;
+
+       down(&scst_suspend_mutex);
+       list_add_tail(&dev->cmd_lists.lists_list_entry,
+               &scst_cmd_lists_list);
+       up(&scst_suspend_mutex);
+
+       dev->p_cmd_lists = &dev->cmd_lists;
+
+out:
+       TRACE_EXIT_RES(res);
+       return res;
+}
+
+/* Called under scst_mutex and suspended activity */
+void scst_del_dev_threads(struct scst_device *dev, int num)
+{
+       struct scst_cmd_thread_t *ct, *tmp;
+       int i = 0;
+
+       TRACE_ENTRY();
+
+       list_for_each_entry_safe(ct, tmp, &dev->threads_list,
+                               thread_list_entry) {
+               int rc = kthread_stop(ct->cmd_thread);
+               if (rc < 0) {
+                       TRACE_MGMT_DBG("kthread_stop() failed: %d", rc);
+               }
+               list_del(&ct->thread_list_entry);
+               kfree(ct);
+               if ((num >0) && (++i >= num))
+                       break;
+       }
+
+       TRACE_EXIT();
+       return;
+}
+
+/* Called under scst_mutex and suspended activity */
+static void scst_stop_dev_threads(struct scst_device *dev)
+{
+       TRACE_ENTRY();
+
+       if (list_empty(&dev->threads_list))
+               goto out;
+
+       scst_del_dev_threads(dev, -1);
+
+       if (dev->p_cmd_lists == &dev->cmd_lists) {
+               down(&scst_suspend_mutex);
+               list_del(&dev->cmd_lists.lists_list_entry);
+               up(&scst_suspend_mutex);
+       }
+
+out:
+       TRACE_EXIT();
+       return;
+}
+
 /* The activity supposed to be suspended and scst_mutex held */
 int scst_assign_dev_handler(struct scst_device *dev, 
        struct scst_dev_type *handler)
@@ -908,8 +1026,7 @@ int scst_assign_dev_handler(struct scst_device *dev,
        
        if (dev->handler && dev->handler->detach_tgt) {
                list_for_each_entry(tgt_dev, &dev->dev_tgt_dev_list, 
-                       dev_tgt_dev_list_entry) 
-               {
+                               dev_tgt_dev_list_entry) {
                        TRACE_DBG("Calling dev handler's detach_tgt(%p)",
                                tgt_dev);
                        dev->handler->detach_tgt(tgt_dev);
@@ -923,8 +1040,16 @@ int scst_assign_dev_handler(struct scst_device *dev,
                TRACE_DBG("%s", "Old handler's detach() returned");
        }
 
+       scst_stop_dev_threads(dev);
+
        dev->handler = handler;
 
+       if (handler) {
+               res = scst_create_dev_threads(dev);
+               if (res != 0)
+                       goto out_null;
+       }
+
        if (handler && handler->attach) {
                TRACE_DBG("Calling new dev handler's attach(%p)", dev);
                res = handler->attach(dev);
@@ -933,13 +1058,12 @@ int scst_assign_dev_handler(struct scst_device *dev,
                        PRINT_ERROR_PR("New device handler's %s attach() "
                                "failed: %d", handler->name, res);
                }
-               goto out_null;
+               goto out_thr_null;
        }
        
        if (handler && handler->attach_tgt) {
                list_for_each_entry(tgt_dev, &dev->dev_tgt_dev_list, 
-                       dev_tgt_dev_list_entry) 
-               {
+                               dev_tgt_dev_list_entry) {
                        TRACE_DBG("Calling dev handler's attach_tgt(%p)",
                                tgt_dev);
                        res = handler->attach_tgt(tgt_dev);
@@ -953,7 +1077,11 @@ int scst_assign_dev_handler(struct scst_device *dev,
                                &attached_tgt_devs);
                }
        }
-       
+
+out_thr_null:
+       if (res != 0)
+               scst_stop_dev_threads(dev);
+
 out_null:
        if (res != 0)
                dev->handler = NULL;
index aa3d1ed..63c5dc4 100644 (file)
@@ -145,33 +145,41 @@ out:
        return;
 }
 
-struct scst_device *scst_alloc_device(int gfp_mask)
+/* Called under scst_mutex and suspended activity */
+int scst_alloc_device(int gfp_mask, struct scst_device **out_dev)
 {
        struct scst_device *dev;
+       int res = 0;
 
        TRACE_ENTRY();
 
        dev = kzalloc(sizeof(*dev), gfp_mask);
        if (dev == NULL) {
                TRACE(TRACE_OUT_OF_MEM, "%s",
-                     "Allocation of scst_device failed");
+                       "Allocation of scst_device failed");
+               res = -ENOMEM;
                goto out;
        }
 
+       dev->p_cmd_lists = &scst_main_cmd_lists;
        spin_lock_init(&dev->dev_lock);
        atomic_set(&dev->on_dev_count, 0);
        INIT_LIST_HEAD(&dev->blocked_cmd_list);
        INIT_LIST_HEAD(&dev->dev_tgt_dev_list);
        INIT_LIST_HEAD(&dev->dev_acg_dev_list);
+       INIT_LIST_HEAD(&dev->threads_list);
        init_waitqueue_head(&dev->on_dev_waitQ);
        dev->dev_double_ua_possible = 1;
        dev->dev_serialized = 1;
 
+       *out_dev = dev;
+
 out:
-       TRACE_EXIT_HRES(dev);
-       return dev;
+       TRACE_EXIT_RES(res);
+       return res;
 }
 
+/* Called under scst_mutex and suspended activity */
 void scst_free_device(struct scst_device *dev)
 {
        TRACE_ENTRY();
@@ -312,96 +320,6 @@ out:
        return res;
 }
 
-static int scst_create_tgt_threads(struct scst_tgt_dev *tgt_dev)
-{
-       int i, res = 0;
-       int threads_num = tgt_dev->dev->handler->threads_num +
-               tgt_dev->sess->tgt->tgtt->threads_num;
-       static atomic_t major = ATOMIC_INIT(0);
-       int N, n = 0;
-       char nm[12];
-
-       TRACE_ENTRY();
-
-       if (tgt_dev->dev->handler->threads_num < 0)
-               threads_num = 0;
-
-       if (threads_num == 0)
-               goto out;
-
-       spin_lock_init(&tgt_dev->cmd_lists.cmd_list_lock);
-       INIT_LIST_HEAD(&tgt_dev->cmd_lists.active_cmd_list);
-       init_waitqueue_head(&tgt_dev->cmd_lists.cmd_list_waitQ);
-
-       if (tgt_dev->dev->handler->threads_num == 0)
-               threads_num += num_online_cpus();
-
-       N = atomic_inc_return(&major);
-
-       for (i = 0; i < threads_num; i++) {
-               struct scst_cmd_thread_t *thr;
-
-               thr = kmalloc(sizeof(*thr), GFP_KERNEL);
-               if (!thr) {
-                       res = -ENOMEM;
-                       PRINT_ERROR_PR("fail to allocate thr %d", res);
-                       goto out;
-               }
-               strncpy(nm, tgt_dev->dev->handler->name, ARRAY_SIZE(nm)-1);
-               nm[ARRAY_SIZE(nm)-1] = '\0';
-               thr->cmd_thread = kthread_run(scst_cmd_thread,
-                       &tgt_dev->cmd_lists, "%sd%d_%d", nm, N, n++);
-               if (IS_ERR(thr->cmd_thread)) {
-                       res = PTR_ERR(thr->cmd_thread);
-                       PRINT_ERROR_PR("kthread_create() failed: %d", res);
-                       kfree(thr);
-                       goto out;
-               }
-               list_add(&thr->thread_list_entry, &tgt_dev->threads_list);
-       }
-
-       down(&scst_suspend_mutex);
-       list_add_tail(&tgt_dev->cmd_lists.lists_list_entry,
-               &scst_cmd_lists_list);
-       up(&scst_suspend_mutex);
-
-       tgt_dev->p_cmd_lists = &tgt_dev->cmd_lists;
-
-out:
-       TRACE_EXIT();
-       return res;
-}
-
-static void scst_stop_tgt_threads(struct scst_tgt_dev *tgt_dev)
-{
-       struct scst_cmd_thread_t *ct, *tmp;
-
-       TRACE_ENTRY();
-
-       if (list_empty(&tgt_dev->threads_list))
-               goto out;
-
-       list_for_each_entry_safe(ct, tmp, &tgt_dev->threads_list,
-                               thread_list_entry) {
-               int rc = kthread_stop(ct->cmd_thread);
-               if (rc < 0) {
-                       TRACE_MGMT_DBG("kthread_stop() failed: %d", rc);
-               }
-               list_del(&ct->thread_list_entry);
-               kfree(ct);
-       }
-
-       if (tgt_dev->p_cmd_lists == &tgt_dev->cmd_lists) {
-               down(&scst_suspend_mutex);
-               list_del(&tgt_dev->cmd_lists.lists_list_entry);
-               up(&scst_suspend_mutex);
-       }
-
-out:
-       TRACE_EXIT();
-       return;
-}
-
 /*
  * No spin locks supposed to be held, scst_mutex - held.
  * The activity is suspended.
@@ -413,6 +331,7 @@ static struct scst_tgt_dev *scst_alloc_add_tgt_dev(struct scst_session *sess,
        struct scst_tgt_dev *tgt_dev;
        struct scst_device *dev = acg_dev->dev;
        struct list_head *sess_tgt_dev_list_head;
+       struct scst_tgt_template *vtt = sess->tgt->tgtt;
        int rc, i;
 
        TRACE_ENTRY();
@@ -431,7 +350,7 @@ static struct scst_tgt_dev *scst_alloc_add_tgt_dev(struct scst_session *sess,
        memset(tgt_dev, 0, sizeof(*tgt_dev));
 #endif
 
-       tgt_dev->dev = acg_dev->dev;
+       tgt_dev->dev = dev;
        tgt_dev->lun = acg_dev->lun;
        tgt_dev->acg_dev = acg_dev;
        tgt_dev->sess = sess;
@@ -440,12 +359,10 @@ static struct scst_tgt_dev *scst_alloc_add_tgt_dev(struct scst_session *sess,
        tgt_dev->gfp_mask = __GFP_NOWARN;
        tgt_dev->pool = &scst_sgv.norm;
 
-       if (tgt_dev->dev->scsi_dev != NULL) {
-               ini_sg = tgt_dev->dev->scsi_dev->host->sg_tablesize;
-               ini_unchecked_isa_dma = 
-                       tgt_dev->dev->scsi_dev->host->unchecked_isa_dma;
-               ini_use_clustering = 
-                       (tgt_dev->dev->scsi_dev->host->use_clustering == 
+       if (dev->scsi_dev != NULL) {
+               ini_sg = dev->scsi_dev->host->sg_tablesize;
+               ini_unchecked_isa_dma = dev->scsi_dev->host->unchecked_isa_dma;
+               ini_use_clustering = (dev->scsi_dev->host->use_clustering == 
                                ENABLE_CLUSTERING);
        } else {
                ini_sg = (1 << 15) /* infinite */;
@@ -471,8 +388,6 @@ static struct scst_tgt_dev *scst_alloc_add_tgt_dev(struct scst_session *sess,
 #endif
        }
 
-       tgt_dev->p_cmd_lists = &scst_main_cmd_lists;
-       
        if (dev->scsi_dev != NULL) {
                TRACE_DBG("host=%d, channel=%d, id=%d, lun=%d, "
                      "SCST lun=%Ld", dev->scsi_dev->host->host_no, 
@@ -497,7 +412,6 @@ static struct scst_tgt_dev *scst_alloc_add_tgt_dev(struct scst_session *sess,
        tgt_dev->cur_sn_slot = &tgt_dev->sn_slots[0];
        for(i = 0; i < (int)ARRAY_SIZE(tgt_dev->sn_slots); i++)
                atomic_set(&tgt_dev->sn_slots[i], 0);
-       INIT_LIST_HEAD(&tgt_dev->threads_list);
 
        if (dev->handler->parse_atomic && 
            sess->tgt->tgtt->preprocessing_done_atomic) {
@@ -531,9 +445,15 @@ static struct scst_tgt_dev *scst_alloc_add_tgt_dev(struct scst_session *sess,
 
        tm_dbg_init_tgt_dev(tgt_dev, acg_dev);
 
-       rc = scst_create_tgt_threads(tgt_dev);
-       if (rc != 0)
-               goto out_free;
+       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);
+               if (rc != 0)
+                       goto out_free;
+       }
 
        if (dev->handler && dev->handler->attach_tgt) {
                TRACE_DBG("Calling dev handler's attach_tgt(%p)",
@@ -543,7 +463,7 @@ static struct scst_tgt_dev *scst_alloc_add_tgt_dev(struct scst_session *sess,
                if (rc != 0) {
                        PRINT_ERROR_PR("Device handler's %s attach_tgt() "
                            "failed: %d", dev->handler->name, rc);
-                       goto out_stop_free;
+                       goto out_thr_free;
                }
        }
        
@@ -559,8 +479,13 @@ out:
        TRACE_EXIT();
        return tgt_dev;
 
-out_stop_free:
-       scst_stop_tgt_threads(tgt_dev);
+out_thr_free:
+       if (vtt->threads_num > 0) {
+               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);
+       }
 
 out_free:
        kmem_cache_free(scst_tgtd_cachep, tgt_dev);
@@ -613,6 +538,7 @@ void scst_reset_tgt_dev(struct scst_tgt_dev *tgt_dev, int nexus_loss)
 static void scst_free_tgt_dev(struct scst_tgt_dev *tgt_dev)
 {
        struct scst_device *dev = tgt_dev->dev;
+       struct scst_tgt_template *vtt = tgt_dev->sess->tgt->tgtt;
 
        TRACE_ENTRY();
 
@@ -631,7 +557,12 @@ static void scst_free_tgt_dev(struct scst_tgt_dev *tgt_dev)
                TRACE_DBG("%s", "Dev handler's detach_tgt() returned");
        }
 
-       scst_stop_tgt_threads(tgt_dev);
+       if (vtt->threads_num > 0) {
+               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);
+       }
 
        kmem_cache_free(scst_tgtd_cachep, tgt_dev);
 
@@ -2984,7 +2915,7 @@ void tm_dbg_init_tgt_dev(struct scst_tgt_dev *tgt_dev,
                if (!tm_dbg_flags.tm_dbg_active) {
                        /* Do TM debugging only for LUN 0 */
                        tm_dbg_p_cmd_list_waitQ = 
-                               &tgt_dev->p_cmd_lists->cmd_list_waitQ;
+                               &tgt_dev->dev->p_cmd_lists->cmd_list_waitQ;
                        tm_dbg_state = INIT_TM_DBG_STATE;
                        tm_dbg_on_state_passes =
                                tm_dbg_on_state_num_passes[tm_dbg_state];
index 60c5cfa..947c2ec 100644 (file)
@@ -352,7 +352,7 @@ struct scatterlist *sgv_pool_alloc(struct sgv_pool *pool, unsigned int size,
                                        (obj->sg_entries + pages_to_alloc);
                                TRACE_MEM("trans_tbl %p", obj->trans_tbl);
                                /* We want to have all the data on the same page */
-                               EXTRACHECKS_BUG_ON(((unsigned long)obj->sg_entries & PAGE_MASK) !=
+                               EXTRACHECKS_WARN_ON_ONCE(((unsigned long)obj->sg_entries & PAGE_MASK) !=
                                        ((unsigned long)&obj->trans_tbl[pages_to_alloc-1] & PAGE_MASK));
                                /*
                                 * No need to clear trans_tbl, if needed, it will
@@ -360,7 +360,7 @@ struct scatterlist *sgv_pool_alloc(struct sgv_pool *pool, unsigned int size,
                                 */
                        } else {
                                /* We want to have all the data on the same page */
-                               EXTRACHECKS_BUG_ON(((unsigned long)obj->sg_entries & PAGE_MASK) !=
+                               EXTRACHECKS_WARN_ON_ONCE(((unsigned long)obj->sg_entries & PAGE_MASK) !=
                                        ((unsigned long)&obj->sg_entries[pages_to_alloc-1] & PAGE_MASK));
                        }
                } else {
index 72ad238..cca7203 100644 (file)
@@ -246,7 +246,10 @@ void scst_cmd_mem_work_fn(void *p);
 void scst_cmd_mem_work_fn(struct work_struct *work);
 #endif
 
-struct scst_device *scst_alloc_device(int gfp_mask);
+int scst_add_dev_threads(struct scst_device *dev, int num);
+void scst_del_dev_threads(struct scst_device *dev, int num);
+
+int scst_alloc_device(int gfp_mask, struct scst_device **out_dev);
 void scst_free_device(struct scst_device *tgt_dev);
 
 struct scst_acg *scst_alloc_add_acg(const char *acg_name);
index aea1652..f37ac72 100644 (file)
@@ -2593,7 +2593,7 @@ static int scst_translate_lun(struct scst_cmd *cmd)
                                        break;
                                }
                                
-                               cmd->cmd_lists = tgt_dev->p_cmd_lists;
+                               cmd->cmd_lists = tgt_dev->dev->p_cmd_lists;
                                cmd->tgt_dev = tgt_dev;
                                cmd->dev = tgt_dev->dev;
 
@@ -4156,8 +4156,7 @@ static int scst_init_session(struct scst_session *sess)
 
 restart:
        list_for_each_entry(cmd, &sess->init_deferred_cmd_list,
-                               cmd_list_entry)
-       {
+                               cmd_list_entry) {
                TRACE_DBG("Deleting cmd %p from init deferred cmd list", cmd);
                list_del(&cmd->cmd_list_entry);
                sess->sess_cmd_count--;
@@ -4170,8 +4169,7 @@ restart:
 
        spin_lock(&scst_mcmd_lock);
        list_for_each_entry_safe(mcmd, tm, &sess->init_deferred_mcmd_list,
-                               mgmt_cmd_list_entry)
-       {
+                               mgmt_cmd_list_entry) {
                TRACE_DBG("Moving mgmt command %p from init deferred mcmd list",
                        mcmd);
                list_move_tail(&mcmd->mgmt_cmd_list_entry,
index 7c5dfd2..1630501 100644 (file)
@@ -594,8 +594,10 @@ static int do_sess(struct vdisk_cmd *vcmd)
                tgt_dev->last_write_cmd_queue_type = SCST_CMD_QUEUE_SIMPLE;
 
                PRINT_INFO_PR("Session from initiator %s attached (LUN %Lx, "
-                       "rd_only %d, sess_h %Lx)", cmd->sess.initiator_name,
-                       cmd->sess.lun, cmd->sess.rd_only, cmd->sess.sess_h);
+                       "threads_num %d, rd_only %d, sess_h %Lx)",
+                       cmd->sess.initiator_name, cmd->sess.lun,
+                       cmd->sess.threads_num, cmd->sess.rd_only,
+                       cmd->sess.sess_h);
        } else {
                if (tgt_dev == NULL) {
                        PRINT_ERROR_PR("Session %Lx not found)", cmd->sess.sess_h);