diff --git a/scst/src/dev_handlers/scst_vdisk.c b/scst/src/dev_handlers/scst_vdisk.c index b99aaa9ff..b361f032d 100644 --- a/scst/src/dev_handlers/scst_vdisk.c +++ b/scst/src/dev_handlers/scst_vdisk.c @@ -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)); } diff --git a/scst/src/scst_lib.c b/scst/src/scst_lib.c index 6d8a1c1bb..3b10f5b65 100644 --- a/scst/src/scst_lib.c +++ b/scst/src/scst_lib.c @@ -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; diff --git a/scst/src/scst_priv.h b/scst/src/scst_priv.h index f64bd31fe..cc75fdb64 100644 --- a/scst/src/scst_priv.h +++ b/scst/src/scst_priv.h @@ -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 diff --git a/scst/src/scst_targ.c b/scst/src/scst_targ.c index 7b5843923..7efd98775 100644 --- a/scst/src/scst_targ.c +++ b/scst/src/scst_targ.c @@ -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; diff --git a/usr/fileio/common.c b/usr/fileio/common.c index 4eb9ff183..19362a513 100644 --- a/usr/fileio/common.c +++ b/usr/fileio/common.c @@ -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)); diff --git a/usr/fileio/debug.h b/usr/fileio/debug.h index 17e7d6e63..a20a6022f 100644 --- a/usr/fileio/debug.h +++ b/usr/fileio/debug.h @@ -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); \