Added possibility to coexist if both target driver and dev handler need custom memory...
authorvlnb <vlnb@d57e44dd-8a1f-0410-8b47-8ef2f437770f>
Tue, 11 Nov 2008 11:56:18 +0000 (11:56 +0000)
committervlnb <vlnb@d57e44dd-8a1f-0410-8b47-8ef2f437770f>
Tue, 11 Nov 2008 11:56:18 +0000 (11:56 +0000)
1. scst_local can work with scst_user's devices

2. scst_user now compatible with iscsi-scst if put_page_callback not applied

+ some cosmetics

git-svn-id: https://scst.svn.sourceforge.net/svnroot/scst/trunk@567 d57e44dd-8a1f-0410-8b47-8ef2f437770f

iscsi-scst/kernel/iscsi.c
iscsi-scst/kernel/nthread.c
scst/include/scst.h
scst/src/dev_handlers/scst_user.c
scst/src/scst_lib.c
scst/src/scst_priv.h
scst/src/scst_targ.c
scst_local/scst_local.c

index 3fed97c..28d8075 100644 (file)
@@ -1322,13 +1322,13 @@ static int scsi_cmnd_start(struct iscsi_cmnd *req)
        req->scst_cmd = scst_cmd;
        scst_cmd_set_tag(scst_cmd, req_hdr->itt);
        scst_cmd_set_tgt_priv(scst_cmd, req);
-#if !defined(CONFIG_TCP_ZERO_COPY_TRANSFER_COMPLETION_NOTIFICATION)
-       scst_cmd_set_data_buf_tgt_alloc(scst_cmd);
-#endif
 
-       if (req_hdr->flags & ISCSI_CMD_READ)
+       if (req_hdr->flags & ISCSI_CMD_READ) {
                dir = SCST_DATA_READ;
-       else if (req_hdr->flags & ISCSI_CMD_WRITE)
+#if !defined(CONFIG_TCP_ZERO_COPY_TRANSFER_COMPLETION_NOTIFICATION)
+               scst_cmd_set_tgt_need_alloc_data_buf(scst_cmd);
+#endif
+       } else if (req_hdr->flags & ISCSI_CMD_WRITE)
                dir = SCST_DATA_WRITE;
        else
                dir = SCST_DATA_NONE;
@@ -2451,16 +2451,15 @@ out_rejected:
 #if !defined(CONFIG_TCP_ZERO_COPY_TRANSFER_COMPLETION_NOTIFICATION)
 static int iscsi_alloc_data_buf(struct scst_cmd *cmd)
 {
-       if (scst_cmd_get_data_direction(cmd) == SCST_DATA_READ) {
-               /*
-                * sock->ops->sendpage() is async zero copy operation,
-                * so we must be sure not to free and reuse
-                * the command's buffer before the sending was completed
-                * by the network layers. It is possible only if we
-                * don't use SGV cache.
-                */
-               scst_cmd_set_no_sgv(cmd);
-       }
+       /*
+        * sock->ops->sendpage() is async zero copy operation,
+        * so we must be sure not to free and reuse
+        * the command's buffer before the sending was completed
+        * by the network layers. It is possible only if we
+        * don't use SGV cache.
+        */
+       EXTRACHECKS_BUG_ON(scst_cmd_get_data_direction(cmd) != SCST_DATA_READ);
+       scst_cmd_set_no_sgv(cmd);
        return 1;
 }
 #endif
@@ -2982,9 +2981,9 @@ out_reg:
 out_callb:
 #if defined(CONFIG_TCP_ZERO_COPY_TRANSFER_COMPLETION_NOTIFICATION)
        net_set_get_put_page_callbacks(NULL, NULL);
-#endif
 
 out_free_dummy:
+#endif
        __free_pages(dummy_page, 0);
        goto out;
 }
index ce4a4f1..6515479 100644 (file)
@@ -1046,7 +1046,7 @@ static int write_data(struct iscsi_conn *conn)
        sock_sendpage = sock->ops->sendpage;
 #else
        if ((write_cmnd->parent_req->scst_cmd != NULL) &&
-           scst_cmd_get_data_buff_alloced(write_cmnd->parent_req->scst_cmd))
+           scst_cmd_get_dh_data_buff_alloced(write_cmnd->parent_req->scst_cmd))
                sock_sendpage = sock_no_sendpage;
        else
                sock_sendpage = sock->ops->sendpage;
index 3b1fb3e..0ef7835 100644 (file)
@@ -548,9 +548,13 @@ struct scst_tgt_template {
         *
         * Shall return 0 in case of success or < 0 (preferrably -ENOMEM)
         * in case of error, or > 0 if the regular SCST allocation should be
-        * done. In case of returning successfully, scst_cmd->data_buf_alloced
+        * done. In case of returning successfully, scst_cmd->tgt_data_buf_alloced
         * will be set by SCST.
         *
+        * It is possible that both target driver and dev handler request own
+        * memory allocation. In this case, data will be memcpy() between
+        * buffers, where necessary.
+        *
         * If allocation in atomic context - cf. scst_cmd_atomic() - is not
         * desired or fails and consequently < 0 is returned, this function
         * will be re-called in thread context.
@@ -1051,13 +1055,16 @@ struct scst_cmd {
         * In this case alloc_data_buf() must be provided in the target driver
         * template.
         */
-       unsigned int data_buf_tgt_alloc:1;
+       unsigned int tgt_need_alloc_data_buf:1;
 
        /*
         * Set by SCST if the custom data buffer allocation by the target driver
         * succeeded.
         */
-       unsigned int data_buf_alloced:1;
+       unsigned int tgt_data_buf_alloced:1;
+
+       /* Set if custom data buffer allocated by dev handler */
+       unsigned int dh_data_buf_alloced:1;
 
        /* Set if the target driver called scst_set_expected() */
        unsigned int expected_values_set:1;
@@ -1208,6 +1215,18 @@ struct scst_cmd {
         */
        int resp_data_len;
 
+       /*
+        * Used if both target driver and dev handler request own memory
+        * allocation. In other cases, both are equal to sg and sg_cnt
+        * correspondingly.
+        *
+        * If target driver requests own memory allocations, it MUST use
+        * functions scst_cmd_get_tgt_sg*() to get sg and sg_cnt! Otherwise,
+        * it may use functions scst_cmd_get_sg*().
+        */
+       struct scatterlist *tgt_sg;
+       int tgt_sg_cnt;
+
        /*
         * The status fields in case of errors must be set using
         * scst_set_cmd_error_status()!
@@ -2073,6 +2092,17 @@ static inline struct scatterlist *scst_cmd_get_sg(struct scst_cmd *cmd)
        return cmd->sg;
 }
 
+/*
+ * Returns cmd's sg_cnt.
+ *
+ * Usage of this function is not recommended, use scst_get_buf_*()
+ * family of functions instead.
+ */
+static inline unsigned int scst_cmd_get_sg_cnt(struct scst_cmd *cmd)
+{
+       return cmd->sg_cnt;
+}
+
 /*
  * Returns cmd's data buffer length.
  *
@@ -2085,15 +2115,25 @@ static inline unsigned int scst_cmd_get_bufflen(struct scst_cmd *cmd)
        return cmd->bufflen;
 }
 
-/*
- * Returns cmd's sg_cnt.
- *
- * Usage of this function is not recommended, use scst_get_buf_*()
- * family of functions instead.
- */
-static inline unsigned short scst_cmd_get_sg_cnt(struct scst_cmd *cmd)
+/* Returns pointer to cmd's target's SG data buffer */
+static inline struct scatterlist *scst_cmd_get_tgt_sg(struct scst_cmd *cmd)
 {
-       return cmd->sg_cnt;
+       return cmd->tgt_sg;
+}
+
+/* Returns cmd's target's sg_cnt */
+static inline unsigned int scst_cmd_get_tgt_sg_cnt(struct scst_cmd *cmd)
+{
+       return cmd->tgt_sg_cnt;
+}
+
+/* Sets cmd's target's SG data buffer */
+static inline void scst_cmd_set_tgt_sg(struct scst_cmd *cmd,
+       struct scatterlist *sg, unsigned int sg_cnt)
+{
+       cmd->tgt_sg = sg;
+       cmd->tgt_sg_cnt = sg_cnt;
+       cmd->tgt_data_buf_alloced = 1;
 }
 
 /* Returns cmd's data direction */
@@ -2172,29 +2212,42 @@ void *scst_cmd_get_tgt_priv_lock(struct scst_cmd *cmd);
 void scst_cmd_set_tgt_priv_lock(struct scst_cmd *cmd, void *val);
 
 /*
- * Get/Set functions for data_buf_tgt_alloc flag
+ * Get/Set functions for tgt_need_alloc_data_buf flag
+ */
+static inline int scst_cmd_get_tgt_need_alloc_data_buf(struct scst_cmd *cmd)
+{
+       return cmd->tgt_need_alloc_data_buf;
+}
+
+static inline void scst_cmd_set_tgt_need_alloc_data_buf(struct scst_cmd *cmd)
+{
+       cmd->tgt_need_alloc_data_buf = 1;
+}
+
+/*
+ * Get/Set functions for tgt_data_buf_alloced flag
  */
-static inline int scst_cmd_get_data_buf_tgt_alloc(struct scst_cmd *cmd)
+static inline int scst_cmd_get_tgt_data_buff_alloced(struct scst_cmd *cmd)
 {
-       return cmd->data_buf_tgt_alloc;
+       return cmd->tgt_data_buf_alloced;
 }
 
-static inline void scst_cmd_set_data_buf_tgt_alloc(struct scst_cmd *cmd)
+static inline void scst_cmd_set_tgt_data_buff_alloced(struct scst_cmd *cmd)
 {
-       cmd->data_buf_tgt_alloc = 1;
+       cmd->tgt_data_buf_alloced = 1;
 }
 
 /*
- * Get/Set functions for data_buf_alloced flag
+ * Get/Set functions for dh_data_buf_alloced flag
  */
-static inline int scst_cmd_get_data_buff_alloced(struct scst_cmd *cmd)
+static inline int scst_cmd_get_dh_data_buff_alloced(struct scst_cmd *cmd)
 {
-       return cmd->data_buf_alloced;
+       return cmd->dh_data_buf_alloced;
 }
 
-static inline void scst_cmd_set_data_buff_alloced(struct scst_cmd *cmd)
+static inline void scst_cmd_set_dh_data_buff_alloced(struct scst_cmd *cmd)
 {
-       cmd->data_buf_alloced = 1;
+       cmd->dh_data_buf_alloced = 1;
 }
 
 /*
index 5a4f6ba..edd490c 100644 (file)
@@ -609,17 +609,8 @@ static int dev_user_alloc_space(struct scst_user_cmd *ucmd)
 
        TRACE_ENTRY();
 
-       if (unlikely(ucmd->cmd->data_buf_tgt_alloc)) {
-               PRINT_ERROR("Target driver %s requested own memory "
-                       "allocation", ucmd->cmd->tgtt->name);
-               scst_set_cmd_error(cmd,
-                       SCST_LOAD_SENSE(scst_sense_hardw_error));
-               res = scst_get_cmd_abnormal_done_state(cmd);
-               goto out;
-       }
-
        ucmd->state = UCMD_STATE_BUF_ALLOCING;
-       cmd->data_buf_alloced = 1;
+       cmd->dh_data_buf_alloced = 1;
 
        rc = dev_user_alloc_sg(ucmd, is_buff_cached(ucmd));
        if (rc == 0)
index 20eb097..d257e50 100644 (file)
@@ -1700,8 +1700,8 @@ void scst_release_space(struct scst_cmd *cmd)
        if (cmd->sgv == NULL)
                goto out;
 
-       if (cmd->data_buf_alloced) {
-               TRACE_MEM("%s", "data_buf_alloced set, returning");
+       if (cmd->tgt_data_buf_alloced || cmd->dh_data_buf_alloced) {
+               TRACE_MEM("%s", "*data_buf_alloced set, returning");
                goto out;
        }
 
@@ -1718,6 +1718,91 @@ out:
        return;
 }
 
+void scst_copy_sg(struct scst_cmd *cmd, enum scst_sg_copy_dir copy_dir)
+{
+       struct scatterlist *src_sg, *dst_sg;
+       unsigned int src_sg_cnt, src_len, dst_len, src_offs, dst_offs;
+       struct page *src, *dst;
+       int s, d, to_copy;
+
+       TRACE_ENTRY();
+
+       if (copy_dir == SCST_SG_COPY_FROM_TARGET) {
+               src_sg = cmd->tgt_sg;
+               src_sg_cnt = cmd->tgt_sg_cnt;
+               dst_sg = cmd->sg;
+               to_copy = cmd->bufflen;
+       } else {
+               src_sg = cmd->sg;
+               src_sg_cnt = cmd->sg_cnt;
+               dst_sg = cmd->tgt_sg;
+               to_copy = cmd->resp_data_len;
+       }
+
+       TRACE_MEM("cmd %p, copy_dir %d, src_sg %p, src_sg_cnt %d, dst_sg %p, "
+               "to_copy %d", cmd, copy_dir, src_sg, src_sg_cnt, dst_sg,
+               to_copy);
+
+       dst = sg_page(dst_sg);
+       dst_len = dst_sg->length;
+       dst_offs = dst_sg->offset;
+
+       s = 0;
+       d = 0;
+       src_offs = 0;
+       while (s < src_sg_cnt) {
+               src = sg_page(&src_sg[s]);
+               src_len = src_sg[s].length;
+               src_offs += src_sg[s].offset;
+
+               do {
+                       unsigned int n;
+
+                       TRACE_MEM("cmd %p, to_copy %d, src %p, src_len %d, "
+                               "src_offs %d, dst %p, dst_len %d, dst_offs %d",
+                               cmd, to_copy, src, src_len, src_offs, dst,
+                               dst_len, dst_offs);
+
+                       if ((src_offs == 0) && (dst_offs == 0) &&
+                           (src_len >= PAGE_SIZE) && (dst_len >= PAGE_SIZE) &&
+                           !PageHighMem(dst) && !PageHighMem(src)) {
+                               copy_page(page_address(dst), page_address(src));
+                               n = PAGE_SIZE;
+                       } else {
+                               n = min(PAGE_SIZE - dst_offs,
+                                       PAGE_SIZE - src_offs);
+                               n = min(n, src_len);
+                               n = min(n, dst_len);
+                               memcpy(page_address(dst) + dst_offs,
+                                      page_address(src) + src_offs, n);
+                               dst_offs -= min(n, dst_offs);
+                               src_offs -= min(n, src_offs);
+                       }
+
+                       TRACE_MEM("cmd %p, n %d, s %d", cmd, n, s);
+
+                       to_copy -= n;
+                       if (to_copy <= 0)
+                               goto out;
+
+                       src_len -= n;
+                       dst_len -= n;
+                       if (dst_len == 0) {
+                               d++;
+                               dst = sg_page(&dst_sg[d]);
+                               dst_len = dst_sg[d].length;
+                               dst_offs += dst_sg[d].offset;
+                       }
+               } while (src_len > 0);
+
+               s++;
+       }
+
+out:
+       TRACE_EXIT();
+       return;
+}
+
 static const int SCST_CDB_LENGTH[8] = { 6, 10, 10, -1, 16, 12, -1, -1 };
 
 #define SCST_CDB_GROUP(opcode)   ((opcode >> 5) & 0x7)
index 391ced3..dfecf2c 100644 (file)
@@ -341,6 +341,12 @@ int scst_alloc_space(struct scst_cmd *cmd);
 void scst_release_space(struct scst_cmd *cmd);
 void scst_scsi_op_list_init(void);
 
+enum scst_sg_copy_dir {
+       SCST_SG_COPY_FROM_TARGET,
+       SCST_SG_COPY_TO_TARGET
+};
+void scst_copy_sg(struct scst_cmd *cmd, enum scst_sg_copy_dir);
+
 uint64_t scst_unpack_lun(const uint8_t *lun, int len);
 
 struct scst_cmd *__scst_find_cmd_by_tag(struct scst_session *sess,
index 42a922f..e35a4ab 100644 (file)
@@ -199,10 +199,10 @@ void scst_cmd_init_done(struct scst_cmd *cmd,
 #endif
 
        TRACE_DBG("Preferred context: %d (cmd %p)", pref_context, cmd);
-       TRACE(TRACE_SCSI, "tag=%llu, lun=%lld, CDB len=%d",
-             (long long unsigned int)cmd->tag,
-             (long long unsigned int)cmd->lun,
-             cmd->cdb_len);
+       TRACE(TRACE_SCSI, "tag=%llu, lun=%lld, CDB len=%d, queue_type=%x "
+               "(cmd %p)", (long long unsigned int)cmd->tag,
+               (long long unsigned int)cmd->lun, cmd->cdb_len,
+               cmd->queue_type, cmd);
        PRINT_BUFF_FLAG(TRACE_SCSI|TRACE_RCV_BOT, "Recieving CDB",
                cmd->cdb, cmd->cdb_len);
 
@@ -389,10 +389,10 @@ static int scst_pre_parse(struct scst_cmd *cmd)
                goto out_xmit;
 #endif
        } else {
-               TRACE(TRACE_SCSI, "op_name <%s>, direction=%d (expected %d, "
-                       "set %s), transfer_len=%d (expected len %d), flags=%d",
-                       cmd->op_name, cmd->data_direction,
-                       cmd->expected_data_direction,
+               TRACE(TRACE_SCSI, "op_name <%s> (cmd %p), direction=%d "
+                       "(expected %d, set %s), transfer_len=%d (expected "
+                       "len %d), flags=%d", cmd->op_name, cmd,
+                       cmd->data_direction, cmd->expected_data_direction,
                        scst_cmd_is_expected_set(cmd) ? "yes" : "no",
                        cmd->bufflen, cmd->expected_transfer_len,
                        cmd->op_flags);
@@ -521,7 +521,8 @@ static int scst_parse_cmd(struct scst_cmd *cmd)
        if (cmd->data_len == -1)
                cmd->data_len = cmd->bufflen;
 
-       if (cmd->data_buf_alloced && unlikely((orig_bufflen > cmd->bufflen))) {
+       if (cmd->dh_data_buf_alloced &&
+           unlikely((orig_bufflen > cmd->bufflen))) {
                PRINT_ERROR("Dev handler supplied data buffer (size %d), "
                        "is less, than required (size %d)", cmd->bufflen,
                        orig_bufflen);
@@ -688,10 +689,11 @@ static int scst_prepare_space(struct scst_cmd *cmd)
        if (cmd->data_direction == SCST_DATA_NONE)
                goto prep_done;
 
-       if (cmd->data_buf_tgt_alloc) {
+       if (cmd->tgt_need_alloc_data_buf) {
                int orig_bufflen = cmd->bufflen;
 
-               TRACE_MEM("%s", "Custom tgt data buf allocation requested");
+               TRACE_MEM("Custom tgt data buf allocation requested (cmd %p)",
+                       cmd);
 
                r = cmd->tgtt->alloc_data_buf(cmd);
                if (r > 0)
@@ -702,7 +704,9 @@ static int scst_prepare_space(struct scst_cmd *cmd)
                                if (cmd->sg == NULL)
                                        goto alloc;
                        }
-                       cmd->data_buf_alloced = 1;
+
+                       cmd->tgt_data_buf_alloced = 1;
+
                        if (unlikely(orig_bufflen < cmd->bufflen)) {
                                PRINT_ERROR("Target driver allocated data "
                                        "buffer (size %d), is less, than "
@@ -710,16 +714,32 @@ static int scst_prepare_space(struct scst_cmd *cmd)
                                        cmd->bufflen);
                                goto out_error;
                        }
-                       TRACE_MEM("%s", "data_buf_alloced, returning");
-               }
-               goto check;
+                       TRACE_MEM("tgt_data_buf_alloced (cmd %p)", cmd);
+               } else
+                       goto check;
        }
 
 alloc:
-       if (!cmd->data_buf_alloced)
+       if (!cmd->tgt_data_buf_alloced && !cmd->dh_data_buf_alloced) {
                r = scst_alloc_space(cmd);
-       else
-               TRACE_MEM("%s", "data_buf_alloced set, returning");
+               cmd->tgt_sg = cmd->sg;
+               cmd->tgt_sg_cnt = cmd->sg_cnt;
+       } else if (cmd->dh_data_buf_alloced && !cmd->tgt_data_buf_alloced) {
+               TRACE_MEM("dh_data_buf_alloced set (cmd %p)", cmd);
+               cmd->tgt_sg = cmd->sg;
+               cmd->tgt_sg_cnt = cmd->sg_cnt;
+               r = 0;
+       } else if (cmd->tgt_data_buf_alloced && !cmd->dh_data_buf_alloced) {
+               TRACE_MEM("tgt_data_buf_alloced set (cmd %p)", cmd);
+               cmd->sg = cmd->tgt_sg;
+               cmd->sg_cnt = cmd->tgt_sg_cnt;
+               r = 0;
+       } else {
+               TRACE_MEM("Both *_data_buf_alloced set (cmd %p, sg %p, "
+                       "sg_cnt %d, tgt_sg %p, tgt_sg_cnt %d)", cmd, cmd->sg,
+                       cmd->sg_cnt, cmd->tgt_sg, cmd->tgt_sg_cnt);
+               r = 0;
+       }
 
 check:
        if (r != 0) {
@@ -1049,9 +1069,7 @@ void scst_rx_data(struct scst_cmd *cmd, int status,
        TRACE_ENTRY();
 
        TRACE_DBG("Preferred context: %d", pref_context);
-       TRACE(TRACE_SCSI, "tag=%llu status=%#x",
-             (long long unsigned int)scst_cmd_get_tag(cmd),
-             status);
+       TRACE(TRACE_SCSI, "cmd %p, status %#x", cmd, status);
 
 #ifdef CONFIG_SCST_EXTRACHECKS
        if ((in_irq() || irqs_disabled()) &&
@@ -1066,6 +1084,19 @@ void scst_rx_data(struct scst_cmd *cmd, int status,
 
        switch (status) {
        case SCST_RX_STATUS_SUCCESS:
+#if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
+               if (cmd->tgt_sg) {
+                       int i;
+                       struct scatterlist *sg = cmd->tgt_sg;
+                       TRACE_RECV_BOT("RX data for cmd %p "
+                               "(sg_cnt %d, sg %p, sg[0].page %p)", cmd,
+                               cmd->tgt_sg_cnt, sg, (void *)sg_page(&sg[0]));
+                       for (i = 0; i < cmd->tgt_sg_cnt; ++i) {
+                               PRINT_BUFF_FLAG(TRACE_RCV_BOT, "RX sg",
+                                       sg_virt(&sg[i]), sg[i].length);
+                       }
+               }
+#endif
                cmd->state = SCST_CMD_STATE_TGT_PRE_EXEC;
                /* Small context optimization */
                if ((pref_context == SCST_CONTEXT_TASKLET) ||
@@ -1190,10 +1221,10 @@ static void scst_do_cmd_done(struct scst_cmd *cmd, int result,
                scst_alloc_set_sense(cmd, 1, rq_sense, rq_sense_len);
        }
 
-       TRACE(TRACE_SCSI, "cmd%p, result=%x, cmd->status=%x, resid=%d, "
+       TRACE(TRACE_SCSI, "cmd %p, result=%x, cmd->status=%x, resid=%d, "
              "cmd->msg_status=%x, cmd->host_status=%x, "
-             "cmd->driver_status=%x", cmd, result, cmd->status, resid,
-             cmd->msg_status, cmd->host_status, cmd->driver_status);
+             "cmd->driver_status=%x (cmd %p)",cmd,  result, cmd->status, resid,
+             cmd->msg_status, cmd->host_status, cmd->driver_status, cmd);
 
        cmd->completed = 1;
 
@@ -2041,6 +2072,10 @@ static int scst_exec(struct scst_cmd **active_cmd)
                cmd->scst_cmd_done = scst_cmd_done_local;
                cmd->state = SCST_CMD_STATE_LOCAL_EXEC;
 
+               if (cmd->tgt_data_buf_alloced && cmd->dh_data_buf_alloced &&
+                   (cmd->data_direction == SCST_DATA_WRITE))
+                       scst_copy_sg(cmd, SCST_SG_COPY_FROM_TARGET);
+
                rc = scst_do_local_exec(cmd);
                if (likely(rc == SCST_EXEC_NOT_COMPLETED))
                        /* Nothing to do */;
@@ -2272,8 +2307,9 @@ static int scst_check_auto_sense(struct scst_cmd *cmd)
             SCST_NO_SENSE(cmd->sense))) {
                TRACE(TRACE_SCSI|TRACE_MINOR, "CHECK_CONDITION, but no sense: "
                      "cmd->status=%x, cmd->msg_status=%x, "
-                     "cmd->host_status=%x, cmd->driver_status=%x", cmd->status,
-                     cmd->msg_status, cmd->host_status, cmd->driver_status);
+                     "cmd->host_status=%x, cmd->driver_status=%x (cmd %p)",
+                     cmd->status, cmd->msg_status, cmd->host_status,
+                     cmd->driver_status, cmd);
                res = 1;
        } else if (unlikely(cmd->host_status)) {
                if ((cmd->host_status == DID_REQUEUE) ||
@@ -2283,8 +2319,8 @@ static int scst_check_auto_sense(struct scst_cmd *cmd)
                        scst_set_busy(cmd);
                } else {
                        TRACE(TRACE_SCSI|TRACE_MINOR, "Host status %x "
-                               "received, returning HARDWARE ERROR instead",
-                               cmd->host_status);
+                               "received, returning HARDWARE ERROR instead "
+                               "(cmd %p)", cmd->host_status, cmd);
                        scst_set_cmd_error(cmd,
                                SCST_LOAD_SENSE(scst_sense_hardw_error));
                }
@@ -2685,6 +2721,10 @@ static int scst_pre_xmit_response(struct scst_cmd *cmd)
                goto out;
        }
 
+       if (cmd->tgt_data_buf_alloced && cmd->dh_data_buf_alloced &&
+           (cmd->data_direction == SCST_DATA_READ))
+               scst_copy_sg(cmd, SCST_SG_COPY_TO_TARGET);
+
        cmd->state = SCST_CMD_STATE_XMIT_RESP;
        res = SCST_CMD_STATE_RES_CONT_SAME;
 
@@ -2746,16 +2786,16 @@ static int scst_xmit_response(struct scst_cmd *cmd)
 
                TRACE_DBG("Calling xmit_response(%p)", cmd);
 
-#if defined(CONFIG_SCST_DEBUG)
-               if (cmd->sg) {
+#if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
+               if (cmd->tgt_sg) {
                        int i;
-                       struct scatterlist *sg = cmd->sg;
-                       TRACE_SEND_BOT("Xmitting %d S/G(s) at %p sg[0].page at "
-                               "%p", cmd->sg_cnt, sg, (void *)sg_page(&sg[0]));
-                       for (i = 0; i < cmd->sg_cnt; ++i) {
-                               TRACE_BUFF_FLAG(TRACE_SND_BOT,
-                                   "Xmitting sg", sg_virt(&sg[i]),
-                                   sg[i].length);
+                       struct scatterlist *sg = cmd->tgt_sg;
+                       TRACE(TRACE_SND_BOT, "Xmitting data for cmd %p "
+                               "(sg_cnt %d, sg %p, sg[0].page %p)", cmd,
+                               cmd->tgt_sg_cnt, sg, (void *)sg_page(&sg[0]));
+                       for (i = 0; i < cmd->tgt_sg_cnt; ++i) {
+                               PRINT_BUFF_FLAG(TRACE_SND_BOT, "Xmitting sg",
+                                       sg_virt(&sg[i]), sg[i].length);
                        }
                }
 #endif
@@ -2878,8 +2918,7 @@ static void scst_cmd_set_sn(struct scst_cmd *cmd)
        TRACE_ENTRY();
 
        if (scst_is_implicit_hq(cmd)) {
-               TRACE(TRACE_SCSI|TRACE_SCSI_SERIALIZING,
-                       "Implicit HQ cmd %p", cmd);
+               TRACE_SN("Implicit HQ cmd %p", cmd);
                cmd->queue_type = SCST_CMD_QUEUE_HEAD_OF_QUEUE;
        }
 
@@ -2932,8 +2971,7 @@ static void scst_cmd_set_sn(struct scst_cmd *cmd)
                break;
 
        case SCST_CMD_QUEUE_ORDERED:
-               TRACE(TRACE_SCSI|TRACE_SCSI_SERIALIZING, "ORDERED cmd %p "
-                       "(op %x)", cmd, cmd->cdb[0]);
+               TRACE_SN("ORDERED cmd %p (op %x)", cmd, cmd->cdb[0]);
 ordered:
                if (!tgt_dev->prev_cmd_ordered) {
                        spin_lock_irqsave(&tgt_dev->sn_lock, flags);
@@ -2969,8 +3007,7 @@ ordered:
                break;
 
        case SCST_CMD_QUEUE_HEAD_OF_QUEUE:
-               TRACE(TRACE_SCSI|TRACE_SCSI_SERIALIZING, "HQ cmd %p "
-                       "(op %x)", cmd, cmd->cdb[0]);
+               TRACE_SN("HQ cmd %p (op %x)", cmd, cmd->cdb[0]);
                spin_lock_irqsave(&tgt_dev->sn_lock, flags);
                tgt_dev->hq_cmd_count++;
                spin_unlock_irqrestore(&tgt_dev->sn_lock, flags);
index afa1ca6..341b7b1 100644 (file)
@@ -490,11 +490,6 @@ static int scst_local_queuecommand(struct scsi_cmnd *SCpnt,
                break;
        }
 
-       /*
-        * We get given data buffers by the SML
-        */
-       scst_cmd_set_data_buff_alloced(scst_cmd);
-
        dir = SCST_DATA_NONE;
        switch (SCpnt->sc_data_direction) {
        case DMA_TO_DEVICE:
@@ -517,11 +512,8 @@ static int scst_local_queuecommand(struct scsi_cmnd *SCpnt,
        }
        scst_cmd_set_expected(scst_cmd, dir, scsi_bufflen(SCpnt));
 
-       /*
-        * Set the SGL things directly ...
-        */
-       scst_cmd->sg_cnt = scsi_sg_count(SCpnt);
-       scst_cmd->sg     = scsi_sglist(SCpnt);
+       /* Set the SGL things directly ... */
+       scst_cmd_set_tgt_sg(scst_cmd, scsi_sglist(SCpnt), scsi_sg_count(SCpnt));
 
        /*
         * Unfortunately, we called with IRQs disabled, so have no choice,