- Fixes scst_user brokennesses in various modes, especially in iSCSI-SCST
authorvlnb <vlnb@d57e44dd-8a1f-0410-8b47-8ef2f437770f>
Thu, 17 Apr 2008 15:25:39 +0000 (15:25 +0000)
committervlnb <vlnb@d57e44dd-8a1f-0410-8b47-8ef2f437770f>
Thu, 17 Apr 2008 15:25:39 +0000 (15:25 +0000)
 - Minor debug logging fixes
 - Minor cleanups

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

iscsi-scst/kernel/digest.c
iscsi-scst/kernel/iscsi.c
iscsi-scst/kernel/iscsi.h
iscsi-scst/kernel/nthread.c
scst/include/scst_debug.h
scst/src/dev_handlers/scst_user.c
scst/src/scst_debug.c
scst/src/scst_targ.c

index 8a2bf5c..7b79ca4 100644 (file)
@@ -106,9 +106,9 @@ static u32 digest_header(struct iscsi_pdu *pdu)
        return evaluate_crc32_from_sg(sg, nbytes, 0);
 }
 
-static u32 digest_data(struct iscsi_cmnd *req, u32 osize, u32 offset)
+static u32 digest_data(struct iscsi_cmnd *cmd, u32 osize, u32 offset)
 {
-       struct scatterlist *sg = req->sg;
+       struct scatterlist *sg = cmd->sg;
        int idx, count;
        struct scatterlist saved_sg;
        u32 size = (osize + 3) & ~3;
@@ -119,7 +119,10 @@ static u32 digest_data(struct iscsi_cmnd *req, u32 osize, u32 offset)
        offset &= ~PAGE_MASK;
        
        count = get_pgcnt(size, offset);
-       sBUG_ON(idx + count > get_pgcnt(req->bufflen, 0));
+
+       TRACE_DBG("req %p, idx %d, count %d, sg_cnt %d, size %d, "
+               "offset %d", cmd, idx, count, cmd->sg_cnt, size, offset);
+       sBUG_ON(idx + count > cmd->sg_cnt);
        sBUG_ON(count > ISCSI_CONN_IOV_MAX);
 
        saved_sg = sg[idx];
index de866e3..d9892a7 100644 (file)
@@ -567,12 +567,13 @@ static void iscsi_set_datasize(struct iscsi_cmnd *cmnd, u32 offset, u32 size)
 {
        cmnd->pdu.datasize = size;
 
-       if (cmnd->pdu.datasize & 3) {
-               int idx = (offset + cmnd->pdu.datasize) >> PAGE_SHIFT;
-               u8 *p = (u8 *)page_address(sg_page(&cmnd->sg[idx])) + 
-                       ((offset + cmnd->pdu.datasize) & ~PAGE_MASK);
-               int i = 4 - (cmnd->pdu.datasize & 3);
-               while (i--) 
+       if (size & 3) {
+               u32 last_off = offset + size;
+               int idx = last_off >> PAGE_SHIFT;
+               u8 *p = (u8*)page_address(sg_page(&cmnd->sg[idx])) +
+                       (last_off & ~PAGE_MASK);
+               int i = 4 - (size & 3);
+               while(i--) 
                    *p++ = 0;
        }
 }
@@ -586,16 +587,18 @@ static void send_data_rsp(struct iscsi_cmnd *req, u8 status, int send_status)
        LIST_HEAD(send);
 
        TRACE_DBG("req %p", req);
+
        pdusize = req->conn->session->sess_param.max_xmit_data_length;
        expsize = cmnd_read_size(req);
        size = min(expsize, (u32)req->bufflen);
        offset = 0;
        sn = 0;
 
-       while (1) {
+       while(1) {
                rsp = iscsi_cmnd_create_rsp_cmnd(req);
                TRACE_DBG("rsp %p", rsp);
                rsp->sg = req->sg;
+               rsp->sg_cnt = req->sg_cnt;
                rsp->bufflen = req->bufflen;
                rsp_hdr = (struct iscsi_data_in_hdr *)&rsp->pdu.bhs;
 
@@ -606,6 +609,7 @@ static void send_data_rsp(struct iscsi_cmnd *req, u8 status, int send_status)
                rsp_hdr->data_sn = cpu_to_be32(sn);
 
                if (size <= pdusize) {
+                       TRACE_DBG("offset %d, size %d", offset, size);
                        iscsi_set_datasize(rsp, offset, size);
                        if (send_status) {
                                TRACE_DBG("status %x", status);
@@ -627,6 +631,9 @@ static void send_data_rsp(struct iscsi_cmnd *req, u8 status, int send_status)
                        break;
                }
 
+               TRACE_DBG("pdusize %d, offset %d, size %d", pdusize, offset,
+                       size);
+
                iscsi_set_datasize(rsp, offset, pdusize);
 
                size -= pdusize;
@@ -1369,6 +1376,7 @@ static int scsi_cmnd_start(struct iscsi_cmnd *req)
        }
        req->target_task_tag = get_next_ttt(conn);
        req->sg = scst_cmd_get_sg(scst_cmd);
+       req->sg_cnt = scst_cmd_get_sg_cnt(scst_cmd);
        req->bufflen = scst_cmd_get_bufflen(scst_cmd);
        if (unlikely(req->r2t_length > req->bufflen)) {
                PRINT_ERROR("req->r2t_length %d > req->bufflen %d",
@@ -1903,10 +1911,12 @@ static void noop_out_exec(struct iscsi_cmnd *req)
 
                if (req->sg) {
                        rsp->sg = req->sg;
+                       rsp->sg_cnt = req->sg_cnt;
                        rsp->bufflen = req->bufflen;
                }
 
                sBUG_ON(get_pgcnt(req->pdu.datasize, 0) > ISCSI_CONN_IOV_MAX);
+
                rsp->pdu.datasize = req->pdu.datasize;
                iscsi_cmnd_init_write(rsp,
                        ISCSI_INIT_WRITE_REMOVE_HASH | ISCSI_INIT_WRITE_WAKE);
@@ -2529,9 +2539,11 @@ static int iscsi_xmit_response(struct scst_cmd *scst_cmd)
 
        req->bufflen = scst_cmd_get_resp_data_len(scst_cmd);
        req->sg = scst_cmd_get_sg(scst_cmd);
+       req->sg_cnt = scst_cmd_get_sg_cnt(scst_cmd);
 
-       TRACE_DBG("req %p, resp_flags=%x, req->bufflen=%d, req->sg=%p", req,
-               resp_flags, req->bufflen, req->sg);
+       TRACE_DBG("req %p, resp_flags=%x, req->bufflen=%d, req->sg=%p, "
+               "req->sg_cnt %d", req, resp_flags, req->bufflen, req->sg,
+               req->sg_cnt);
 
        if (unlikely((req->bufflen != 0) &&
                     !(resp_flags & SCST_TSC_FLAG_STATUS))) {
index b1223d1..237956d 100644 (file)
@@ -302,6 +302,7 @@ struct iscsi_cmnd {
        struct iscsi_pdu pdu;
 
        struct scatterlist *sg;
+       int sg_cnt;
        int bufflen;
        u32 r2t_sn;
        u32 r2t_length;
@@ -312,7 +313,6 @@ struct iscsi_cmnd {
        u32 hdigest;
        u32 ddigest;
 
-       int sg_cnt; /* valid only if own_sg is 1 */
        struct list_head cmd_list_entry;
 };
 
index 0c44798..2806a6a 100644 (file)
@@ -90,14 +90,12 @@ again:
                sBUG_ON(cmnd->parent_req != NULL);
 
                if (cmnd->sg != NULL) {
-                       int sg_cnt, i;
-
-                       sg_cnt = get_pgcnt(cmnd->bufflen,
-                               cmnd->sg[0].offset);
+                       int i;
 
                        if (cmnd_get_check(cmnd))
                                continue;
-                       for(i = 0; i < sg_cnt; i++) {
+
+                       for(i = 0; i < cmnd->sg_cnt; i++) {
                                struct page *page = sg_page(&cmnd->sg[i]);
                                TRACE_CONN_CLOSE_DBG("page %p, net_priv %p, "
                                        "_count %d", page, page->net_priv,
@@ -125,15 +123,12 @@ again:
                                atomic_read(&rsp->net_ref_cnt), rsp->sg);
 
                        if ((rsp->sg != cmnd->sg) && (rsp->sg != NULL)) {
-                               int sg_cnt, i;
-
-                               sg_cnt = get_pgcnt(rsp->bufflen,
-                                       rsp->sg[0].offset);
-                               sBUG_ON(rsp->sg_cnt != sg_cnt);
+                               int i;
 
                                if (cmnd_get_check(rsp))
                                        continue;
-                               for(i = 0; i < sg_cnt; i++) {
+
+                               for(i = 0; i < rsp->sg_cnt; i++) {
                                        struct page *page = sg_page(&rsp->sg[i]);
                                        TRACE_CONN_CLOSE_DBG("    page %p, net_priv %p, "
                                                "_count %d", page, page->net_priv,
@@ -383,10 +378,8 @@ static void close_conn(struct iscsi_conn *conn)
                                TRACE_CONN_CLOSE_DBG("net_ref_cnt %d, sg %p",
                                        atomic_read(&cmnd->net_ref_cnt), cmnd->sg);
                                if (cmnd->sg != NULL) {
-                                       int sg_cnt, i;
-                                       sg_cnt = get_pgcnt(cmnd->bufflen,
-                                               cmnd->sg[0].offset);
-                                       for(i = 0; i < sg_cnt; i++) {
+                                       int i;
+                                       for(i = 0; i < cmnd->sg_cnt; i++) {
                                                struct page *page = sg_page(&cmnd->sg[i]);
                                                TRACE_CONN_CLOSE_DBG("page %p, net_priv %p, _count %d",
                                                        page, page->net_priv,
@@ -402,11 +395,8 @@ static void close_conn(struct iscsi_conn *conn)
                                                "sg %p", rsp, atomic_read(&rsp->ref_cnt),
                                                atomic_read(&rsp->net_ref_cnt), rsp->sg);
                                        if ((rsp->sg != cmnd->sg) && (rsp->sg != NULL)) {
-                                               int sg_cnt, i;
-                                               sg_cnt = get_pgcnt(rsp->bufflen,
-                                                       rsp->sg[0].offset);
-                                               sBUG_ON(rsp->sg_cnt != sg_cnt);
-                                               for(i = 0; i < sg_cnt; i++) {
+                                               int i;
+                                               for(i = 0; i < rsp->sg_cnt; i++) {
                                                        TRACE_CONN_CLOSE_DBG("    page %p, net_priv %p, "
                                                                "_count %d", sg_page(&rsp->sg[i]),
                                                                sg_page(&rsp->sg[i])->net_priv,
@@ -858,45 +848,62 @@ int istrd(void *arg)
 }
 
 #ifdef NET_PAGE_CALLBACKS_DEFINED
-void iscsi_get_page_callback(struct page *page)
+static inline void __iscsi_get_page_callback(struct iscsi_cmnd *cmd)
 {
-       struct iscsi_cmnd *cmd = (struct iscsi_cmnd*)page->net_priv;
        int v;
 
-       TRACE_NET_PAGE("cmd %p, page %p, _count %d, new net_ref_cnt %d",
-               cmd, page, atomic_read(&page->_count),
-               atomic_read(&cmd->net_ref_cnt)+1);
+       TRACE_NET_PAGE("cmd %p, new net_ref_cnt %d",
+               cmd, atomic_read(&cmd->net_ref_cnt)+1);
 
        v = atomic_inc_return(&cmd->net_ref_cnt);
        if (v == 1) {
-               TRACE_NET_PAGE("getting cmd %p for page %p", cmd, page);
+               TRACE_NET_PAGE("getting cmd %p", cmd);
                cmnd_get(cmd);
        }
 }
 
-void iscsi_put_page_callback(struct page *page)
+void iscsi_get_page_callback(struct page *page)
 {
        struct iscsi_cmnd *cmd = (struct iscsi_cmnd*)page->net_priv;
 
-       TRACE_NET_PAGE("cmd %p, page %p, _count %d, new net_ref_cnt %d",
-               cmd, page, atomic_read(&page->_count),
+       TRACE_NET_PAGE("page %p, _count %d", page,
+               atomic_read(&page->_count));
+
+       __iscsi_get_page_callback(cmd);
+}
+
+static inline void __iscsi_put_page_callback(struct iscsi_cmnd *cmd)
+{
+       TRACE_NET_PAGE("cmd %p, new net_ref_cnt %d", cmd,
                atomic_read(&cmd->net_ref_cnt)-1);
 
        if (atomic_dec_and_test(&cmd->net_ref_cnt)) {
-               int i, sg_cnt = get_pgcnt(cmd->bufflen, cmd->sg[0].offset);
+               int i, sg_cnt = cmd->sg_cnt;
                for(i = 0; i < sg_cnt; i++) {
-                       TRACE_NET_PAGE("Clearing page %p", sg_page(&cmd->sg[i]));
-                       sg_page(&cmd->sg[i])->net_priv = NULL;
+                       struct page *page = sg_page(&cmd->sg[i]);
+                       TRACE_NET_PAGE("Clearing page %p", page);
+                       if (page->net_priv == cmd)
+                               page->net_priv = NULL;
                }
                cmnd_put(cmd);
        }
 }
 
+void iscsi_put_page_callback(struct page *page)
+{
+       struct iscsi_cmnd *cmd = (struct iscsi_cmnd*)page->net_priv;
+
+       TRACE_NET_PAGE("page %p, _count %d", page,
+               atomic_read(&page->_count));
+
+       __iscsi_put_page_callback(cmd);
+}
+
 static void check_net_priv(struct iscsi_cmnd *cmd, struct page *page)
 {
-       if (atomic_read(&cmd->net_ref_cnt) == 0) {
-               TRACE_DBG("%s", "sendpage() not called get_page(), "
-                       "zeroing net_priv");
+       if ((atomic_read(&cmd->net_ref_cnt) == 1) && (page->net_priv == cmd)) {
+               TRACE_DBG("sendpage() not called get_page(), zeroing net_priv "
+                       "%p (page %p)", page->net_priv, page);
                page->net_priv = NULL;
        }
 }
@@ -910,6 +917,7 @@ static int write_data(struct iscsi_conn *conn)
        mm_segment_t oldfs;
        struct file *file;
        struct socket *sock;
+       ssize_t (*sock_sendpage)(struct socket *, struct page *, int, size_t, int);
        ssize_t (*sendpage)(struct socket *, struct page *, int, size_t, int);
        struct iscsi_cmnd *write_cmnd = conn->write_cmnd;
        struct iscsi_cmnd *ref_cmd;
@@ -918,6 +926,9 @@ static int write_data(struct iscsi_conn *conn)
        int saved_size, size, sendsize;
        int offset, idx;
        int flags, res, count;
+       bool do_put = false;
+
+       TRACE_ENTRY();
 
        iscsi_extracheck_is_wr_thread(conn);
 
@@ -967,7 +978,7 @@ retry:
                set_fs(oldfs);
                TRACE_WRITE("%#Lx:%u: %d(%ld)",
                        (unsigned long long)conn->session->sid, conn->cid,
-                       res, (long) iop->iov_len);
+                       res, (long)iop->iov_len);
                if (unlikely(res <= 0)) {
                        if (res == -EAGAIN) {
                                conn->write_iop = iop;
@@ -975,7 +986,7 @@ retry:
                                goto out_iov;
                        } else if (res == -EINTR)
                                goto retry;
-                       goto err;
+                       goto out_err;
                }
 
                rest = res;
@@ -1000,58 +1011,86 @@ retry:
 
        sg = write_cmnd->sg;
        if (unlikely(sg == NULL)) {
-               PRINT_ERROR("%s", "warning data missing!");
-               return 0;
+               PRINT_INFO("WARNING: Data missed (cmd %p)!", write_cmnd);
+               res = 0;
+               goto out;
        }
-       offset = conn->write_offset;
+
+       /* To protect from too early transfer completion race */
+       __iscsi_get_page_callback(ref_cmd);
+       do_put = true;
+
+       offset = conn->write_offset + sg[0].offset;
        idx = offset >> PAGE_SHIFT;
        offset &= ~PAGE_MASK;
 
        sock = conn->sock;
 
 #ifdef NET_PAGE_CALLBACKS_DEFINED
-       sendpage = sock->ops->sendpage;
+       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))
-               sendpage = sock_no_sendpage;
+               sock_sendpage = sock_no_sendpage;
        else
-               sendpage = sock->ops->sendpage;
+               sock_sendpage = sock->ops->sendpage;
 #endif
 
        flags = MSG_DONTWAIT;
 
        while (1) {
+               sendpage = sock_sendpage;
+
 #ifdef NET_PAGE_CALLBACKS_DEFINED
-               if (unlikely((sg_page(&sg[idx])->net_priv != NULL) &&
-                               (sg_page(&sg[idx])->net_priv != ref_cmd))) {
-                       PRINT_CRIT_ERROR("net_priv isn't NULL and != ref_cmd "
-                               "(write_cmnd %p, ref_cmd %p, sg %p, idx %d, "
-                               "net_priv %p)", write_cmnd, ref_cmd, sg, idx,
-                               sg_page(&sg[idx])->net_priv);
-                       sBUG();
+               {
+                       static spinlock_t net_priv_lock = SPIN_LOCK_UNLOCKED;
+                       spin_lock(&net_priv_lock);
+                       if (sg_page(&sg[idx])->net_priv != NULL) {
+                               if (sg_page(&sg[idx])->net_priv != ref_cmd) {
+                                       /*
+                                        * This might happen if user space supplies
+                                        * to scst_user the same pages in different
+                                        * commands or in case of zero-copy FILEIO,
+                                        * when several initiators request the same
+                                        * data simultaneously.
+                                        */
+                                       TRACE_DBG("net_priv isn't NULL and != "
+                                               "ref_cmd (write_cmnd %p, ref_cmd %p, "
+                                               "sg %p, idx %d, page %p, net_priv %p)",
+                                               write_cmnd, ref_cmd, sg, idx,
+                                               sg_page(&sg[idx]),
+                                               sg_page(&sg[idx])->net_priv);
+                                       sendpage = sock_no_sendpage;
+                               }
+                       } else
+                               sg_page(&sg[idx])->net_priv = ref_cmd;
+                       spin_unlock(&net_priv_lock);
                }
-               sg_page(&sg[idx])->net_priv = ref_cmd;
 #endif
                sendsize = PAGE_SIZE - offset;
                if (size <= sendsize) {
 retry2:
                        res = sendpage(sock, sg_page(&sg[idx]), offset, size, flags);
-                       TRACE_WRITE("%s %#Lx:%u: %d(%lu,%u,%u)",
-                               sock->ops->sendpage ? "sendpage" : "sock_no_sendpage",
+                       TRACE_WRITE("Final %s %#Lx:%u: %d(%lu,%u,%u, cmd %p, page %p)",
+                               (sendpage != sock_no_sendpage) ? "sendpage" : 
+                                                                "sock_no_sendpage",
                                (unsigned long long)conn->session->sid, conn->cid,
-                               res, sg_page(&sg[idx])->index, offset, size);
+                               res, sg_page(&sg[idx])->index, offset, size,
+                               write_cmnd, sg_page(&sg[idx]));
                        if (unlikely(res <= 0)) {
                                if (res == -EINTR)
                                        goto retry2;
                                else
                                        goto out_res;
                        }
+
                        check_net_priv(ref_cmd, sg_page(&sg[idx]));
                        if (res == size) {
                                conn->write_size = 0;
-                               return saved_size;
+                               res = saved_size;
+                               goto out_put;
                        }
+
                        offset += res;
                        size -= res;
                        continue;
@@ -1060,40 +1099,55 @@ retry2:
 retry1:
                res = sendpage(sock, sg_page(&sg[idx]), offset, sendsize,
                        flags | MSG_MORE);
-               TRACE_WRITE("%s %#Lx:%u: %d(%lu,%u,%u)",
-                       sock->ops->sendpage ? "sendpage" : "sock_no_sendpage",
-                       (unsigned long long ) conn->session->sid, conn->cid,
-                       res, sg_page(&sg[idx])->index, offset, sendsize);
+               TRACE_WRITE("%s %#Lx:%u: %d(%lu,%u,%u, cmd %p, page %p)",
+                       (sendpage != sock_no_sendpage) ? "sendpage" : 
+                                                        "sock_no_sendpage",
+                       (unsigned long long)conn->session->sid, conn->cid,
+                       res, sg_page(&sg[idx])->index, offset, sendsize,
+                       write_cmnd, sg_page(&sg[idx]));
                if (unlikely(res <= 0)) {
                        if (res == -EINTR)
                                goto retry1;
                        else
                                goto out_res;
                }
+
                check_net_priv(ref_cmd, sg_page(&sg[idx]));
                if (res == sendsize) {
                        idx++;
                        offset = 0;
+                       EXTRACHECKS_BUG_ON(idx >= ref_cmd->sg_cnt);
                } else
                        offset += res;
+
                size -= res;
        }
-out:
-       conn->write_offset = (idx << PAGE_SHIFT) + offset;
+
+out_off:
+       conn->write_offset = (idx << PAGE_SHIFT) + offset - sg[0].offset;
+
 out_iov:
        conn->write_size = size;
        if ((saved_size == size) && res == -EAGAIN)
-               return res;
+               goto out_put;
+
+       res = saved_size - size;
+
+out_put:
+       if (do_put)
+               __iscsi_put_page_callback(ref_cmd);
 
-       return saved_size - size;
+out:
+       TRACE_EXIT_RES(res);
+       return res;
 
 out_res:
        check_net_priv(ref_cmd, sg_page(&sg[idx]));
        if (res == -EAGAIN)
-               goto out;
+               goto out_off;
        /* else go through */
 
-err:
+out_err:
 #ifndef DEBUG
        if (!conn->closing)
 #endif
@@ -1105,7 +1159,7 @@ err:
        if (ref_cmd->scst_cmd != NULL)
                scst_set_delivery_status(ref_cmd->scst_cmd,
                        SCST_CMD_DELIVERY_FAILED);
-       return res;
+       goto out_put;
 }
 
 static int exit_tx(struct iscsi_conn *conn, int res)
index 3184288..6cf75ca 100644 (file)
 #define TRACE_ALL            0xffffffff
 /* Flags 0xXXXX0000 are local for users */
 
-#define PRINT(log_flag, format, args...)  printk(log_flag format "\n", ## args);
-#define PRINTN(log_flag, format, args...) printk(log_flag format, ## args);
+#define PRINT(log_flag, format, args...)  printk("%s" format "\n", log_flag, ## args);
+#define PRINTN(log_flag, format, args...) printk("%s" format, log_flag, ## args);
 
 #ifdef LOG_PREFIX
 #define __LOG_PREFIX   LOG_PREFIX
 #define ___unlikely(a)         unlikely(a)
 #endif
 
-extern int debug_print_prefix(unsigned long trace_flag, const char *prefix,
-               const char *func, int line);
-extern void debug_print_buffer(const void *data, int len);
+extern int debug_print_prefix(unsigned long trace_flag, const char *log_level,
+       const char *prefix, const char *func, int line);
+extern void debug_print_buffer(const char *log_level, const void *data,
+       int len);
 
 #define TRACE(trace, format, args...)                               \
 do {                                                                \
   if (___unlikely(trace_flag & (trace)))                            \
   {                                                                 \
     char *__tflag = LOG_FLAG;                                       \
-    if (debug_print_prefix(trace_flag, __LOG_PREFIX, __FUNCTION__,  \
-                            __LINE__) > 0)                          \
+    if (debug_print_prefix(trace_flag, __tflag, __LOG_PREFIX,       \
+                __FUNCTION__, __LINE__) > 0)                       \
     {                                                               \
       __tflag = NO_FLAG;                                            \
     }                                                               \
@@ -162,21 +163,21 @@ do {                                                                \
 #define PRINT_BUFFER(message, buff, len)                            \
 do {                                                                \
     PRINT(NO_FLAG, "%s:", message);                                 \
-    debug_print_buffer(buff, len);                                  \
+    debug_print_buffer(INFO_FLAG, buff, len);                       \
 } while(0)
 
 #define PRINT_BUFF_FLAG(flag, message, buff, len)                   \
 do {                                                                \
   if (___unlikely(trace_flag & (flag)))                             \
   {                                                                 \
-    char *__tflag = LOG_FLAG;                                       \
-    if (debug_print_prefix(trace_flag, NULL, __FUNCTION__,          \
+    char *__tflag = INFO_FLAG;                                      \
+    if (debug_print_prefix(trace_flag, __tflag, NULL, __FUNCTION__, \
                             __LINE__) > 0)                          \
     {                                                               \
       __tflag = NO_FLAG;                                            \
     }                                                               \
     PRINT(NO_FLAG, "%s%s:", __tflag, message);                      \
-    debug_print_buffer(buff, len);                                  \
+    debug_print_buffer(INFO_FLAG, buff, len);                       \
   }                                                                 \
 } while(0)
 
@@ -195,7 +196,7 @@ do {                                                                \
   if (trace_flag & (trace))                                         \
   {                                                                 \
     char *__tflag = LOG_FLAG;                                       \
-    if (debug_print_prefix(trace_flag, NULL, __FUNCTION__,          \
+    if (debug_print_prefix(trace_flag, __tflag, NULL, __FUNCTION__, \
                             __LINE__) > 0)                          \
     {                                                               \
       __tflag = NO_FLAG;                                            \
@@ -216,13 +217,13 @@ do {                                                                \
   if (trace_flag & TRACE_BUFF)                                      \
   {                                                                 \
     char *__tflag = LOG_FLAG;                                       \
-    if (debug_print_prefix(trace_flag, NULL, __FUNCTION__,          \
+    if (debug_print_prefix(trace_flag, __tflag, NULL, __FUNCTION__, \
                             __LINE__) > 0)                          \
     {                                                               \
       __tflag = NO_FLAG;                                            \
     }                                                               \
     PRINT(NO_FLAG, "%s%s:", __tflag, message);                      \
-    debug_print_buffer(buff, len);                                 \
+    debug_print_buffer(LOG_FLAG, buff, len);                       \
   }                                                                 \
 } while(0)
 
@@ -231,21 +232,21 @@ do {                                                                \
   if (trace_flag & (flag))                                          \
   {                                                                 \
     char *__tflag = LOG_FLAG;                                       \
-    if (debug_print_prefix(trace_flag, NULL, __FUNCTION__,          \
+    if (debug_print_prefix(trace_flag, __tflag, NULL, __FUNCTION__, \
                             __LINE__) > 0)                          \
     {                                                               \
       __tflag = NO_FLAG;                                            \
     }                                                               \
     PRINT(NO_FLAG, "%s%s:", __tflag, message);                      \
-    debug_print_buffer(buff, len);                                  \
+    debug_print_buffer(LOG_FLAG, buff, len);                        \
   }                                                                 \
 } while(0)
 
 #define PRINT_LOG_FLAG(log_flag, format, args...)                   \
 do {                                                                \
   char *__tflag = log_flag;                                         \
-  if (debug_print_prefix(trace_flag, __LOG_PREFIX, __FUNCTION__,    \
-                          __LINE__) > 0)                            \
+  if (debug_print_prefix(trace_flag, __tflag, __LOG_PREFIX,         \
+               __FUNCTION__, __LINE__) > 0)                        \
   {                                                                 \
     __tflag = NO_FLAG;                                              \
   }                                                                 \
@@ -263,14 +264,13 @@ do {                                                                \
 
 #define PRINT_CRIT_ERROR(format, args...)                          \
 do {                                                                \
-  if (strcmp(CRIT_FLAG, LOG_FLAG))                                  \
+/*  if (strcmp(CRIT_FLAG, LOG_FLAG))                                  \
   {                                                                 \
     PRINT_LOG_FLAG(LOG_FLAG, "***CRITICAL ERROR*** " format, args); \
-  }                                                                 \
+  }*/                                                                 \
   PRINT_LOG_FLAG(CRIT_FLAG, "***CRITICAL ERROR*** " format, args);  \
 } while(0)
 
-
 #define PRINT_INFO(format, args...)                   \
 do {                                                  \
   if (strcmp(INFO_FLAG, LOG_FLAG))                    \
index 6d912d6..ab377f8 100644 (file)
@@ -328,6 +328,7 @@ static struct page *dev_user_alloc_pages(struct scatterlist *sg,
        gfp_t gfp_mask, void *priv)
 {
        struct scst_user_cmd *ucmd = (struct scst_user_cmd*)priv;
+       int offset = 0;
 
        TRACE_ENTRY();
 
@@ -339,7 +340,7 @@ static struct page *dev_user_alloc_pages(struct scatterlist *sg,
        if (ucmd->cur_data_page == 0) {
                TRACE_MEM("ucmd->first_page_offset %d",
                        ucmd->first_page_offset);
-               sg->offset = ucmd->first_page_offset;
+               offset = ucmd->first_page_offset;
                ucmd_get(ucmd, 0);
        }
 
@@ -347,10 +348,11 @@ static struct page *dev_user_alloc_pages(struct scatterlist *sg,
                goto out;
 
        sg_set_page(sg, ucmd->data_pages[ucmd->cur_data_page],
-               PAGE_SIZE - sg->offset, 0);
+               PAGE_SIZE - offset, offset);
        ucmd->cur_data_page++;
 
-       TRACE_MEM("page=%p, length=%d", sg_page(sg), sg->length);
+       TRACE_MEM("page=%p, length=%d, offset=%d", sg_page(sg), sg->length,
+               sg->offset);
        TRACE_BUFFER("Page data", sg_virt(sg), sg->length);
 
 out:
@@ -498,10 +500,6 @@ static int dev_user_alloc_sg(struct scst_user_cmd *ucmd, int cached_buff)
                ucmd->ubuff = buf_ucmd->ubuff;
                ucmd->buf_ucmd = buf_ucmd;
 
-               TRACE_MEM("Buf alloced (ucmd %p, cached_buff %d, ubuff %lx, "
-                       "last_len %d, l %d)", ucmd, cached_buff, ucmd->ubuff,
-                       last_len, cmd->sg[cmd->sg_cnt-1].length);
-
                EXTRACHECKS_BUG_ON((ucmd->data_pages != NULL) &&
                                   (ucmd != buf_ucmd));
 
@@ -510,6 +508,10 @@ static int dev_user_alloc_sg(struct scst_user_cmd *ucmd, int cached_buff)
                        cmd->sg[cmd->sg_cnt-1].length = last_len;
                }
 
+               TRACE_MEM("Buf alloced (ucmd %p, cached_buff %d, ubuff %lx, "
+                       "last_len %d, l %d)", ucmd, cached_buff, ucmd->ubuff,
+                       last_len, cmd->sg[cmd->sg_cnt-1].length);
+
                if (unlikely(cmd->sg_cnt > cmd->tgt_dev->max_sg_cnt)) {
                        static int ll;
                        if (ll < 10) {
index b4e6fe9..63c543c 100644 (file)
 static char trace_buf[TRACE_BUF_SIZE];
 static spinlock_t trace_buf_lock = SPIN_LOCK_UNLOCKED;
 
-int debug_print_prefix(unsigned long trace_flag, const char *prefix,
-       const char *func, int line)
+static inline int get_current_tid(void)
+{
+       /* Code should be the same as in sys_gettid() */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)
+       return current->pid;
+#else
+       return task_pid_vnr(current);
+#endif
+}
+
+int debug_print_prefix(unsigned long trace_flag, const char *log_level,
+       const char *prefix, const char *func, int line)
 {
        int i = 0;
        unsigned long flags;
@@ -38,7 +48,7 @@ int debug_print_prefix(unsigned long trace_flag, const char *prefix,
 
        if (trace_flag & TRACE_PID)
                i += snprintf(&trace_buf[i], TRACE_BUF_SIZE, "[%d]: ",
-                             current->pid);
+                             get_current_tid());
        if (prefix != NULL)
                i += snprintf(&trace_buf[i], TRACE_BUF_SIZE - i, "%s: ", prefix);
        if (trace_flag & TRACE_FUNCTION)
@@ -47,14 +57,14 @@ int debug_print_prefix(unsigned long trace_flag, const char *prefix,
                i += snprintf(&trace_buf[i], TRACE_BUF_SIZE - i, "%i:", line);
 
        if (i > 0)
-               PRINTN(LOG_FLAG, "%s", trace_buf);
+               PRINTN(log_level, "%s", trace_buf);
 
        spin_unlock_irqrestore(&trace_buf_lock, flags);
 
        return i;
 }
 
-void debug_print_buffer(const void *data, int len)
+void debug_print_buffer(const char *log_level, const void *data, int len)
 {
        int z, z1, i;
        const unsigned char *buf = (const unsigned char *) data;
@@ -100,7 +110,7 @@ void debug_print_buffer(const void *data, int len)
        }
        trace_buf[i] = '\0';
        if (f) {
-               PRINT(LOG_FLAG, "%s", trace_buf)
+               PRINT(log_level, "%s", trace_buf)
        } else {
                PRINT(NO_FLAG, "%s", trace_buf);
        }
index b0a4a5d..24aa2f3 100644 (file)
@@ -658,7 +658,10 @@ static int scst_prepare_space(struct scst_cmd *cmd)
        }
 
 alloc:
-       r = scst_alloc_space(cmd);
+       if (!cmd->data_buf_alloced)
+               r = scst_alloc_space(cmd);
+       else
+               TRACE_MEM("%s", "data_buf_alloced set, returning");
        
 check:
        if (r != 0) {