- Fixed BUG() with put_page_callback patch for network hardware without TX offload
authorvlnb <vlnb@d57e44dd-8a1f-0410-8b47-8ef2f437770f>
Thu, 18 Oct 2007 10:12:34 +0000 (10:12 +0000)
committervlnb <vlnb@d57e44dd-8a1f-0410-8b47-8ef2f437770f>
Thu, 18 Oct 2007 10:12:34 +0000 (10:12 +0000)
 - Fixed 2 corner cases crashes with disabled pass-through devices
 - Docs updated

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

iscsi-scst/README
iscsi-scst/kernel/nthread.c
scst/src/scst_lib.c
scst/src/scst_main.c
scst/src/scst_priv.h
scst/src/scst_targ.c

index 20ee4a9..65ff5b2 100644 (file)
@@ -52,7 +52,15 @@ original IET behavior, when for data transmission:
    data will be additionally copied into temporary TCP buffers. The
    performance hit will be quite noticeable.
 
-If you have error messages like:
+Note, that if your network hardware does not support TX offload
+functions of has them disabled, then TCP zero-copy transmit functions on
+your system will not be used by Linux networking in any case, so
+put_page_callback patch will not be able to improve performance for you.
+You can check your network hardware offload capabilities by command
+"ethtool -k ethX", where X is the network device number. At least
+"tx-checksumming" and "scatter-gather" should be enabled.
+
+If you have in your kernel log error messages like:
 
 iscsi-scst: ***ERROR*** net_priv isn't NULL and != ref_cmd
 
index a0211ca..359f5d2 100644 (file)
@@ -689,6 +689,13 @@ retry2:
                                else
                                        goto out_res;
                        }
+#ifdef NET_PAGE_CALLBACKS_DEFINED
+                       if (atomic_read(&ref_cmd->net_ref_cnt) == 0) {
+                               TRACE_DBG("%s", "sendpage() not called "
+                                       "get_page(), zeroing net_priv");
+                               sg[idx].page->net_priv = NULL;
+                       }
+#endif
                        if (res == size) {
                                conn->write_size = 0;
                                return saved_size;
@@ -711,6 +718,13 @@ retry1:
                        else
                                goto out_res;
                }
+#ifdef NET_PAGE_CALLBACKS_DEFINED
+               if (atomic_read(&ref_cmd->net_ref_cnt) == 0) {
+                       TRACE_DBG("%s", "sendpage() not called get_page(), "
+                               "zeroing net_priv");
+                       sg[idx].page->net_priv = NULL;
+               }
+#endif
                if (res == sendsize) {
                        idx++;
                        offset = 0;
index 6af05aa..15cce60 100644 (file)
@@ -161,6 +161,7 @@ int scst_alloc_device(int gfp_mask, struct scst_device **out_dev)
                goto out;
        }
 
+       dev->handler = &scst_null_devtype;
        dev->p_cmd_lists = &scst_main_cmd_lists;
        atomic_set(&dev->dev_cmd_count, 0);
        spin_lock_init(&dev->dev_lock);
@@ -357,7 +358,6 @@ static struct scst_tgt_dev *scst_alloc_add_tgt_dev(struct scst_session *sess,
        tgt_dev->acg_dev = acg_dev;
        tgt_dev->sess = sess;
        atomic_set(&tgt_dev->tgt_dev_cmd_count, 0);
-
        
        scst_sgv_pool_use_norm(tgt_dev);
 
@@ -387,14 +387,14 @@ static struct scst_tgt_dev *scst_alloc_add_tgt_dev(struct scst_session *sess,
        }
 
        if (dev->scsi_dev != NULL) {
-               TRACE_DBG("host=%d, channel=%d, id=%d, lun=%d, "
+               TRACE_MGMT_DBG("host=%d, channel=%d, id=%d, lun=%d, "
                      "SCST lun=%Ld", dev->scsi_dev->host->host_no, 
                      dev->scsi_dev->channel, dev->scsi_dev->id, 
                      dev->scsi_dev->lun, (uint64_t)tgt_dev->lun);
        }
        else {
-               TRACE_MGMT_DBG("Virtual device SCST lun=%Ld", 
-                     (uint64_t)tgt_dev->lun);
+               TRACE_MGMT_DBG("Virtual device %s on SCST lun=%Ld", 
+                       dev->virt_name, (uint64_t)tgt_dev->lun);
        }
 
        spin_lock_init(&tgt_dev->tgt_dev_lock);
index a00877f..d329505 100644 (file)
@@ -101,7 +101,6 @@ struct scst_cmd_lists scst_main_cmd_lists;
 
 struct scst_tasklet scst_tasklets[NR_CPUS];
 
-
 spinlock_t scst_mcmd_lock = SPIN_LOCK_UNLOCKED;
 LIST_HEAD(scst_active_mgmt_cmd_list);
 LIST_HEAD(scst_delayed_mgmt_cmd_list);
@@ -138,6 +137,11 @@ module_param_named(scst_max_cmd_mem, scst_max_cmd_mem, long, 0);
 MODULE_PARM_DESC(scst_max_cmd_mem, "Maximum memory allowed to be consumed by "
        "the SCST commands at any given time in Mb");
 
+struct scst_dev_type scst_null_devtype = 
+{
+  name:     "null_handler",
+};
+
 int scst_register_target_template(struct scst_tgt_template *vtt)
 {
        int res = 0;
@@ -574,7 +578,7 @@ static void scst_unregister_device(struct scsi_device *scsidp)
                scst_acg_remove_dev(acg_dev->acg, dev);
        }
 
-       scst_assign_dev_handler(dev, NULL);
+       scst_assign_dev_handler(dev, &scst_null_devtype);
 
        put_disk(dev->rq_disk);
        scst_free_device(dev);
@@ -718,7 +722,7 @@ void scst_unregister_virtual_device(int id)
                scst_acg_remove_dev(acg_dev->acg, dev);
        }
 
-       scst_assign_dev_handler(dev, NULL);
+       scst_assign_dev_handler(dev, &scst_null_devtype);
 
        PRINT_INFO_PR("Detached SCSI target mid-level from virtual device %s "
                "(id %d)", dev->virt_name, dev->virt_id);
@@ -744,7 +748,7 @@ int scst_register_dev_driver(struct scst_dev_type *dev_type)
 
        res = scst_dev_handler_check(dev_type);
        if (res != 0)
-               goto out_err;
+               goto out_error;
 
 #if !defined(SCSI_EXEC_REQ_FIFO_DEFINED) && !defined(STRICT_SERIALIZING)
        if (dev_type->exec == NULL) {
@@ -753,14 +757,14 @@ int scst_register_dev_driver(struct scst_dev_type *dev_type)
                        "scst_exec_req_fifo-<kernel-version>.patch or define "
                        "STRICT_SERIALIZING", dev_type->name);
                res = -EINVAL;
-               goto out_err;
+               goto out;
        }
 #endif
 
        scst_suspend_activity();
        if (mutex_lock_interruptible(&scst_mutex) != 0) {
                res = -EINTR;
-               goto out_err;
+               goto out_err_res;
        }
 
        exist = 0;
@@ -783,7 +787,7 @@ int scst_register_dev_driver(struct scst_dev_type *dev_type)
        list_add_tail(&dev_type->dev_type_list_entry, &scst_dev_type_list);
 
        list_for_each_entry(dev, &scst_dev_list, dev_list_entry) {
-               if ((dev->scsi_dev == NULL) || (dev->handler != NULL))
+               if ((dev->scsi_dev == NULL) || (dev->handler != &scst_null_devtype))
                        continue;
                if (dev->scsi_dev->type == dev_type->type)
                        scst_assign_dev_handler(dev, dev_type);
@@ -804,8 +808,10 @@ out:
 out_up:
        mutex_unlock(&scst_mutex);
 
-out_err:
+out_err_res:
        scst_resume_activity();
+
+out_error:
        PRINT_ERROR_PR("Failed to register device handler \"%s\" for type %d",
                dev_type->name, dev_type->type);
        goto out;
@@ -836,7 +842,7 @@ void scst_unregister_dev_driver(struct scst_dev_type *dev_type)
 
        list_for_each_entry(dev, &scst_dev_list, dev_list_entry) {
                if (dev->handler == dev_type) {
-                       scst_assign_dev_handler(dev, NULL);
+                       scst_assign_dev_handler(dev, &scst_null_devtype);
                        TRACE_DBG("Dev handler removed from device %p", dev);
                }
        }
@@ -1035,6 +1041,8 @@ int scst_assign_dev_handler(struct scst_device *dev,
        LIST_HEAD(attached_tgt_devs);
        
        TRACE_ENTRY();
+
+       sBUG_ON(handler == NULL);
        
        if (dev->handler == handler)
                goto out;
@@ -1099,7 +1107,7 @@ out_thr_null:
 
 out_null:
        if (res != 0)
-               dev->handler = NULL;
+               dev->handler = &scst_null_devtype;
        
 out:
        TRACE_EXIT_RES(res);
index ecd0013..7880d11 100644 (file)
@@ -212,6 +212,8 @@ extern void __scst_del_cmd_threads(int num);
 extern spinlock_t scst_temp_UA_lock;
 extern uint8_t scst_temp_UA[SCST_SENSE_BUFFERSIZE];
 
+extern struct scst_dev_type scst_null_devtype;
+
 extern struct scst_cmd *__scst_check_deferred_commands(
        struct scst_tgt_dev *tgt_dev);
 
index e5d945f..1b8b6bb 100644 (file)
@@ -2596,7 +2596,7 @@ static int scst_translate_lun(struct scst_cmd *cmd)
                        if (tgt_dev->lun == cmd->lun) {
                                TRACE_DBG("tgt_dev %p found", tgt_dev);
 
-                               if (unlikely(tgt_dev->dev->handler == NULL)) {
+                               if (unlikely(tgt_dev->dev->handler == &scst_null_devtype)) {
                                        PRINT_INFO_PR("Dev handler for device "
                                          "%Ld is NULL, the device will not be "
                                          "visible remotely", (uint64_t)cmd->lun);