- Fixed BUG() with put_page_callback patch for network hardware without TX offload

- Fixed 2 corner cases crashes with disabled pass-through devices
 - Docs updated


git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@205 d57e44dd-8a1f-0410-8b47-8ef2f437770f
This commit is contained in:
Vladislav Bolkhovitin
2007-10-18 10:12:34 +00:00
parent a8c124da1b
commit 1d77a72af3
6 changed files with 48 additions and 16 deletions

View 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

View 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;

View 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);

View 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);

View 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);

View 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);