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));
}
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));
}
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();
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
+ }
if (vtt->threads_num > 0) {
rc = 0;
#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
#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.
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);
#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 {
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 {
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;
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));
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;
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));
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));
} \
} while(0)
-#define PRINT_ERROR(format, args...) \
+#define PRINT_INFO(format, args...) \
do { \
debug_print_prefix(trace_flag, __LOG_PREFIX, __FUNCTION__, \
__LINE__); \
- PRINT("***ERROR*** " format, args); \
+ PRINT(format, args); \
} while(0)
-#define PRINT_INFO(format, args...) \
+#define PRINT_WARNING(format, args...) \
do { \
debug_print_prefix(trace_flag, __LOG_PREFIX, __FUNCTION__, \
__LINE__); \
- PRINT(format, args); \
+ 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() \
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*** " \
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); \