mirror of
https://github.com/SCST-project/scst.git
synced 2026-05-22 05:01:27 +00:00
- Fixed crash introduced by r710 reported by andy yan <andyysj@gmail.com>
- Improve logging on write access on read-only devices - Make the same initiator coming through different sessions use shared IO context - Cleanups git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@721 d57e44dd-8a1f-0410-8b47-8ef2f437770f
This commit is contained in:
@@ -920,8 +920,10 @@ static int vdisk_do_job(struct scst_cmd *cmd)
|
||||
if (do_fsync || fua)
|
||||
vdisk_fsync(thr, loff, data_len, cmd);
|
||||
} else {
|
||||
TRACE(TRACE_MINOR, "Attempt to write to read-only "
|
||||
"device %s", virt_dev->name);
|
||||
PRINT_WARNING("Attempt of write access to read-only "
|
||||
"device %s: initiator %s, op %x",
|
||||
virt_dev->name, cmd->sess->initiator_name,
|
||||
cmd->cdb[0]);
|
||||
scst_set_cmd_error(cmd,
|
||||
SCST_LOAD_SENSE(scst_sense_data_protect));
|
||||
}
|
||||
@@ -956,8 +958,10 @@ static int vdisk_do_job(struct scst_cmd *cmd)
|
||||
else if (do_fsync)
|
||||
vdisk_fsync(thr, loff, data_len, cmd);
|
||||
} else {
|
||||
TRACE(TRACE_MINOR, "Attempt to write to read-only "
|
||||
"device %s", virt_dev->name);
|
||||
PRINT_WARNING("Attempt of write access to read-only "
|
||||
"device %s: initiator %s, op %x",
|
||||
virt_dev->name, cmd->sess->initiator_name,
|
||||
cmd->cdb[0]);
|
||||
scst_set_cmd_error(cmd,
|
||||
SCST_LOAD_SENSE(scst_sense_data_protect));
|
||||
}
|
||||
|
||||
@@ -936,11 +936,12 @@ static struct scst_tgt_dev *scst_alloc_add_tgt_dev(struct scst_session *sess,
|
||||
struct scst_acg_dev *acg_dev)
|
||||
{
|
||||
int ini_sg, ini_unchecked_isa_dma, ini_use_clustering;
|
||||
struct scst_tgt_dev *tgt_dev;
|
||||
struct scst_tgt_dev *tgt_dev, *t;
|
||||
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;
|
||||
bool share_io_ctx = false;
|
||||
uint8_t sense_buffer[SCST_STANDARD_SENSE_LEN];
|
||||
|
||||
TRACE_ENTRY();
|
||||
@@ -1041,17 +1042,42 @@ static struct scst_tgt_dev *scst_alloc_add_tgt_dev(struct scst_session *sess,
|
||||
|
||||
tm_dbg_init_tgt_dev(tgt_dev, acg_dev);
|
||||
|
||||
if (tgt_dev->sess->initiator_name != NULL) {
|
||||
spin_lock_bh(&dev->dev_lock);
|
||||
list_for_each_entry(t, &dev->dev_tgt_dev_list,
|
||||
dev_tgt_dev_list_entry) {
|
||||
TRACE_DBG("t name %s (tgt_dev name %s)",
|
||||
t->sess->initiator_name,
|
||||
tgt_dev->sess->initiator_name);
|
||||
if (t->sess->initiator_name == NULL)
|
||||
continue;
|
||||
if (strcmp(t->sess->initiator_name,
|
||||
tgt_dev->sess->initiator_name) == 0) {
|
||||
share_io_ctx = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
spin_unlock_bh(&dev->dev_lock);
|
||||
}
|
||||
|
||||
if (share_io_ctx) {
|
||||
TRACE_MGMT_DBG("Sharing IO context %p (tgt_dev %p, ini %s)",
|
||||
t->tgt_dev_io_ctx, tgt_dev,
|
||||
tgt_dev->sess->initiator_name);
|
||||
tgt_dev->tgt_dev_io_ctx = ioc_task_link(t->tgt_dev_io_ctx);
|
||||
} else {
|
||||
#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;
|
||||
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
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
if (vtt->threads_num > 0) {
|
||||
rc = 0;
|
||||
|
||||
@@ -179,37 +179,49 @@ struct scst_cmd_thread_t {
|
||||
|
||||
#if defined(SCST_IO_CONTEXT)
|
||||
|
||||
static inline void scst_set_io_context(struct scst_tgt_dev *tgt_dev)
|
||||
static inline bool scst_set_io_context(struct scst_cmd *cmd,
|
||||
struct io_context **old)
|
||||
{
|
||||
if (tgt_dev->dev->p_cmd_lists == &scst_main_cmd_lists) {
|
||||
EXTRACHECKS_BUG_ON(current->io_context);
|
||||
bool res;
|
||||
|
||||
if (cmd->cmd_lists == &scst_main_cmd_lists) {
|
||||
EXTRACHECKS_BUG_ON(in_interrupt());
|
||||
/*
|
||||
* 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);
|
||||
}
|
||||
current->io_context = cmd->tgt_dev->tgt_dev_io_ctx;
|
||||
res = true;
|
||||
TRACE_DBG("io_context %p", cmd->tgt_dev->tgt_dev_io_ctx);
|
||||
} else
|
||||
res = false;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static inline void scst_reset_io_context(struct scst_tgt_dev *tgt_dev)
|
||||
static inline void scst_reset_io_context(struct scst_tgt_dev *tgt_dev,
|
||||
struct io_context *old)
|
||||
{
|
||||
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);
|
||||
}
|
||||
current->io_context = old;
|
||||
TRACE_DBG("io_context %p reset", current->io_context);
|
||||
return;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static inline void scst_set_io_context(struct scst_tgt_dev *tgt_dev) {}
|
||||
static inline void scst_reset_io_context(struct scst_tgt_dev *tgt_dev) {}
|
||||
static inline bool scst_set_io_context(struct scst_cmd *cmd,
|
||||
struct io_context **old)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
static inline void scst_reset_io_context(struct scst_tgt_dev *tgt_dev,
|
||||
struct io_context *old) {}
|
||||
static inline void __exit_io_context(struct io_context *ioc) {}
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 25)
|
||||
static inline struct io_context *ioc_task_link(struct io_context *ioc)
|
||||
{
|
||||
return NULL;
|
||||
};
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1858,18 +1858,21 @@ static int scst_do_real_exec(struct scst_cmd *cmd)
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 18)
|
||||
int rc;
|
||||
#endif
|
||||
bool atomic = scst_cmd_atomic(cmd);
|
||||
struct scst_device *dev = cmd->dev;
|
||||
struct scst_dev_type *handler = dev->handler;
|
||||
struct io_context *old_ctx = NULL;
|
||||
bool ctx_changed = false;
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
scst_set_io_context(cmd->tgt_dev);
|
||||
if (!atomic)
|
||||
ctx_changed = scst_set_io_context(cmd, &old_ctx);
|
||||
|
||||
cmd->state = SCST_CMD_STATE_REAL_EXECUTING;
|
||||
|
||||
if (handler->exec) {
|
||||
if (unlikely(!dev->handler->exec_atomic &&
|
||||
scst_cmd_atomic(cmd))) {
|
||||
if (unlikely(!dev->handler->exec_atomic && atomic)) {
|
||||
/*
|
||||
* It shouldn't be because of SCST_TGT_DEV_AFTER_*
|
||||
* optimization.
|
||||
@@ -1910,7 +1913,7 @@ static int scst_do_real_exec(struct scst_cmd *cmd)
|
||||
goto out_done;
|
||||
|
||||
#ifndef CONFIG_SCST_ALLOW_PASSTHROUGH_IO_SUBMIT_IN_SIRQ
|
||||
if (unlikely(scst_cmd_atomic(cmd))) {
|
||||
if (unlikely(atomic)) {
|
||||
TRACE_DBG("Pass-through exec() can not be called in atomic "
|
||||
"context, rescheduling to the thread (handler %s)",
|
||||
handler->name);
|
||||
@@ -1921,7 +1924,7 @@ static int scst_do_real_exec(struct scst_cmd *cmd)
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18)
|
||||
if (unlikely(scst_alloc_request(cmd) != 0)) {
|
||||
if (scst_cmd_atomic(cmd)) {
|
||||
if (atomic) {
|
||||
res = SCST_EXEC_NEED_THREAD;
|
||||
goto out_restore;
|
||||
} else {
|
||||
@@ -1939,9 +1942,9 @@ static int scst_do_real_exec(struct scst_cmd *cmd)
|
||||
rc = scst_exec_req(dev->scsi_dev, cmd->cdb, cmd->cdb_len,
|
||||
cmd->data_direction, cmd->sg, cmd->bufflen, cmd->sg_cnt,
|
||||
cmd->timeout, cmd->retries, cmd, scst_cmd_done,
|
||||
scst_cmd_atomic(cmd) ? GFP_ATOMIC : GFP_KERNEL);
|
||||
atomic ? GFP_ATOMIC : GFP_KERNEL);
|
||||
if (unlikely(rc != 0)) {
|
||||
if (scst_cmd_atomic(cmd)) {
|
||||
if (atomic) {
|
||||
res = SCST_EXEC_NEED_THREAD;
|
||||
goto out_restore;
|
||||
} else {
|
||||
@@ -1954,8 +1957,9 @@ static int scst_do_real_exec(struct scst_cmd *cmd)
|
||||
out_complete:
|
||||
res = SCST_EXEC_COMPLETED;
|
||||
|
||||
out_reset:
|
||||
scst_reset_io_context(cmd->tgt_dev);
|
||||
out_reset_ctx:
|
||||
if (ctx_changed)
|
||||
scst_reset_io_context(cmd->tgt_dev, old_ctx);
|
||||
|
||||
TRACE_EXIT();
|
||||
return res;
|
||||
@@ -1963,7 +1967,7 @@ out_reset:
|
||||
out_restore:
|
||||
/* Restore the state */
|
||||
cmd->state = SCST_CMD_STATE_REAL_EXEC;
|
||||
goto out_reset;
|
||||
goto out_reset_ctx;
|
||||
|
||||
out_error:
|
||||
scst_set_cmd_error(cmd, SCST_LOAD_SENSE(scst_sense_hardw_error));
|
||||
@@ -2030,6 +2034,9 @@ static int scst_do_local_exec(struct scst_cmd *cmd)
|
||||
cmd->cdb[0] == WRITE_VERIFY_16 ||
|
||||
(cmd->dev->handler->type == TYPE_TAPE &&
|
||||
(cmd->cdb[0] == ERASE || cmd->cdb[0] == WRITE_FILEMARKS)))) {
|
||||
PRINT_WARNING("Attempt of write access to read-only device: "
|
||||
"initiator %s, LUN %lld, op %x",
|
||||
cmd->sess->initiator_name, cmd->lun, cmd->cdb[0]);
|
||||
scst_set_cmd_error(cmd,
|
||||
SCST_LOAD_SENSE(scst_sense_data_protect));
|
||||
goto out_done;
|
||||
|
||||
@@ -428,7 +428,7 @@ static int do_exec(struct vdisk_cmd *vcmd)
|
||||
if (do_fsync || fua)
|
||||
exec_fsync(vcmd);
|
||||
} else {
|
||||
TRACE(TRACE_MINOR, "Attempt to write to read-only "
|
||||
PRINT_WARNING("Attempt to write to read-only "
|
||||
"device %s", dev->name);
|
||||
set_cmd_error(vcmd,
|
||||
SCST_LOAD_SENSE(scst_sense_data_protect));
|
||||
@@ -469,7 +469,7 @@ static int do_exec(struct vdisk_cmd *vcmd)
|
||||
else if (do_fsync)
|
||||
exec_fsync(vcmd);
|
||||
} else {
|
||||
TRACE(TRACE_MINOR, "Attempt to write to read-only "
|
||||
PRINT_WARNING("Attempt to write to read-only "
|
||||
"device %s", dev->name);
|
||||
set_cmd_error(vcmd,
|
||||
SCST_LOAD_SENSE(scst_sense_data_protect));
|
||||
|
||||
@@ -163,13 +163,6 @@ do { \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
#define PRINT_ERROR(format, args...) \
|
||||
do { \
|
||||
debug_print_prefix(trace_flag, __LOG_PREFIX, __FUNCTION__, \
|
||||
__LINE__); \
|
||||
PRINT("***ERROR*** " format, args); \
|
||||
} while(0)
|
||||
|
||||
#define PRINT_INFO(format, args...) \
|
||||
do { \
|
||||
debug_print_prefix(trace_flag, __LOG_PREFIX, __FUNCTION__, \
|
||||
@@ -177,6 +170,20 @@ do { \
|
||||
PRINT(format, args); \
|
||||
} while(0)
|
||||
|
||||
#define PRINT_WARNING(format, args...) \
|
||||
do { \
|
||||
debug_print_prefix(trace_flag, __LOG_PREFIX, __FUNCTION__, \
|
||||
__LINE__); \
|
||||
PRINT("***WARNING*** " format, args); \
|
||||
} while(0)
|
||||
|
||||
#define PRINT_ERROR(format, args...) \
|
||||
do { \
|
||||
debug_print_prefix(trace_flag, __LOG_PREFIX, __FUNCTION__, \
|
||||
__LINE__); \
|
||||
PRINT("***ERROR*** " format, args); \
|
||||
} while(0)
|
||||
|
||||
#define TRACE_ENTRY() \
|
||||
do { \
|
||||
if (trace_flag & TRACE_ENTRYEXIT) \
|
||||
@@ -264,6 +271,12 @@ do { \
|
||||
PRINT("%s: " format, LOG_PREFIX, args); \
|
||||
} while(0)
|
||||
|
||||
#define PRINT_WARNING(format, args...) \
|
||||
do { \
|
||||
PRINT("%s: ***WARNING*** " \
|
||||
format, LOG_PREFIX, args); \
|
||||
} while(0)
|
||||
|
||||
#define PRINT_ERROR(format, args...) \
|
||||
do { \
|
||||
PRINT("%s: ***ERROR*** " \
|
||||
@@ -277,6 +290,12 @@ do { \
|
||||
PRINT(format, args); \
|
||||
} while(0)
|
||||
|
||||
#define PRINT_WARNING(format, args...) \
|
||||
do { \
|
||||
PRINT("***WARNING*** " format, args); \
|
||||
} while(0)
|
||||
|
||||
|
||||
#define PRINT_ERROR(format, args...) \
|
||||
do { \
|
||||
PRINT("***ERROR*** " format, args); \
|
||||
|
||||
Reference in New Issue
Block a user