- Fixed crash introduced by r710 reported by andy yan <andyysj@gmail.com>
authorvlnb <vlnb@d57e44dd-8a1f-0410-8b47-8ef2f437770f>
Thu, 26 Mar 2009 18:25:00 +0000 (18:25 +0000)
committervlnb <vlnb@d57e44dd-8a1f-0410-8b47-8ef2f437770f>
Thu, 26 Mar 2009 18:25:00 +0000 (18:25 +0000)
 - 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: https://scst.svn.sourceforge.net/svnroot/scst/trunk@721 d57e44dd-8a1f-0410-8b47-8ef2f437770f

scst/src/dev_handlers/scst_vdisk.c
scst/src/scst_lib.c
scst/src/scst_priv.h
scst/src/scst_targ.c
usr/fileio/common.c
usr/fileio/debug.h

index b99aaa9..b361f03 100644 (file)
@@ -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));
                }
index 6d8a1c1..3b10f5b 100644 (file)
@@ -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
+       }
 
        if (vtt->threads_num > 0) {
                rc = 0;
index f64bd31..cc75fdb 100644 (file)
@@ -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
index 7b58439..7efd987 100644 (file)
@@ -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;
index 4eb9ff1..19362a5 100644 (file)
@@ -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));
index 17e7d6e..a20a602 100644 (file)
@@ -163,18 +163,25 @@ do {                                                              \
   }                                                            \
 } 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()                                          \
@@ -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);                          \