Diff for /embedaddon/istgt/src/istgt_iscsi.c between versions 1.1.1.1 and 1.1.1.3

version 1.1.1.1, 2012/02/21 16:42:02 version 1.1.1.3, 2013/07/21 23:49:22
Line 1 Line 1
 /*  /*
 * Copyright (C) 2008-2011 Daisuke Aoyama <aoyama@peach.ne.jp>. * Copyright (C) 2008-2012 Daisuke Aoyama <aoyama@peach.ne.jp>.
  * All rights reserved.   * All rights reserved.
  *   *
  * Redistribution and use in source and binary forms, with or without   * Redistribution and use in source and binary forms, with or without
Line 68 Line 68
 #include <sys/time.h>  #include <sys/time.h>
 #endif  #endif
   
   #if !defined(__GNUC__)
   #undef __attribute__
   #define __attribute__(x)
   #endif
   
 /* according to RFC1982 */  /* according to RFC1982 */
 #define SN32_CMPMAX (((uint32_t)1U) << (32 - 1))  #define SN32_CMPMAX (((uint32_t)1U) << (32 - 1))
 #define SN32_LT(S1,S2) \  #define SN32_LT(S1,S2) \
Line 83 Line 88
                 || ((uint32_t)(S1) > (uint32_t)(S2)                     \                  || ((uint32_t)(S1) > (uint32_t)(S2)                     \
                     && ((uint32_t)(S1) - (uint32_t)(S2) < SN32_CMPMAX))))                      && ((uint32_t)(S1) - (uint32_t)(S2) < SN32_CMPMAX))))
   
#define POLLWAIT 3000#define POLLWAIT 5000
 #define MAX_MCSREVWAIT (10 * 1000)  #define MAX_MCSREVWAIT (10 * 1000)
 #define ISCMDQ 8  #define ISCMDQ 8
   
Line 112  static void istgt_remove_conn(CONN_Ptr conn); Line 117  static void istgt_remove_conn(CONN_Ptr conn);
 static int istgt_iscsi_drop_all_conns(CONN_Ptr conn);  static int istgt_iscsi_drop_all_conns(CONN_Ptr conn);
 static int istgt_iscsi_drop_old_conns(CONN_Ptr conn);  static int istgt_iscsi_drop_old_conns(CONN_Ptr conn);
   
   /* Switch to use readv/writev (assume blocking) */
   #define ISTGT_USE_IOVEC
   
   #if defined (ISTGT_USE_IOVEC)
   #include <sys/uio.h>
   #endif
   
   #if !defined (ISTGT_USE_IOVEC)
 #if 0  #if 0
 #define ISTGT_USE_RECVBLOCK  #define ISTGT_USE_RECVBLOCK
 #define ISTGT_USE_SENDBLOCK  #define ISTGT_USE_SENDBLOCK
Line 157  istgt_iscsi_read(CONN_Ptr conn, void *buf, size_t nbyt Line 170  istgt_iscsi_read(CONN_Ptr conn, void *buf, size_t nbyt
         } while (total < nbytes);          } while (total < nbytes);
         if (total != (nbytes + pad_bytes)) {          if (total != (nbytes + pad_bytes)) {
                 /* incomplete bytes */                  /* incomplete bytes */
                ISTGT_TRACELOG(ISTGT_TRACE_NET, "Read %d/%d+%d bytes\n",                ISTGT_TRACELOG(ISTGT_TRACE_NET, "Read %zd/%zd+%zd bytes\n",
                     total, nbytes, pad_bytes);                      total, nbytes, pad_bytes);
                 if (total > nbytes) {                  if (total > nbytes) {
                         total = nbytes;                          total = nbytes;
Line 167  istgt_iscsi_read(CONN_Ptr conn, void *buf, size_t nbyt Line 180  istgt_iscsi_read(CONN_Ptr conn, void *buf, size_t nbyt
   
         if (pad_bytes != 0) {          if (pad_bytes != 0) {
                 /* complete padding */                  /* complete padding */
                ISTGT_TRACELOG(ISTGT_TRACE_NET, "Read %d bytes (padding %d)\n",                ISTGT_TRACELOG(ISTGT_TRACE_NET, "Read %zd bytes (padding %zd)\n",
                     nbytes, pad_bytes);                      nbytes, pad_bytes);
         } else {          } else {
                 /* just aligned */                  /* just aligned */
                ISTGT_TRACELOG(ISTGT_TRACE_NET, "Read %d bytes (no padding)\n",                ISTGT_TRACELOG(ISTGT_TRACE_NET, "Read %zd bytes (no padding)\n",
                     nbytes);                      nbytes);
         }          }
 #else /* !ISTGT_USE_RECVBLOCK */  #else /* !ISTGT_USE_RECVBLOCK */
Line 197  istgt_iscsi_read(CONN_Ptr conn, void *buf, size_t nbyt Line 210  istgt_iscsi_read(CONN_Ptr conn, void *buf, size_t nbyt
   
         if (total != nbytes) {          if (total != nbytes) {
                 /* incomplete bytes */                  /* incomplete bytes */
                ISTGT_TRACELOG(ISTGT_TRACE_NET, "Read %d/%d bytes\n",                ISTGT_TRACELOG(ISTGT_TRACE_NET, "Read %zd/%zd bytes\n",
                     total, nbytes);                      total, nbytes);
                 return total;                  return total;
         }          }
Line 213  istgt_iscsi_read(CONN_Ptr conn, void *buf, size_t nbyt Line 226  istgt_iscsi_read(CONN_Ptr conn, void *buf, size_t nbyt
                         if (r < 0) {                          if (r < 0) {
                                 /* error */                                  /* error */
                                 ISTGT_TRACELOG(ISTGT_TRACE_NET,                                  ISTGT_TRACELOG(ISTGT_TRACE_NET,
                                    "Read %d bytes (padding error) (errno=%d)\n",                                    "Read %zd bytes (padding error) (errno=%d)\n",
                                     nbytes, errno);                                      nbytes, errno);
                                 return nbytes;                                  return nbytes;
                         }                          }
                         if (r == 0) {                          if (r == 0) {
                                 /* EOF */                                  /* EOF */
                                 ISTGT_TRACELOG(ISTGT_TRACE_NET,                                  ISTGT_TRACELOG(ISTGT_TRACE_NET,
                                    "Read %d bytes (padding EOF)\n",                                    "Read %zd bytes (padding EOF)\n",
                                     nbytes);                                      nbytes);
                                 return nbytes;                                  return nbytes;
                         }                          }
Line 230  istgt_iscsi_read(CONN_Ptr conn, void *buf, size_t nbyt Line 243  istgt_iscsi_read(CONN_Ptr conn, void *buf, size_t nbyt
                 if (total != pad_bytes) {                  if (total != pad_bytes) {
                         /* incomplete padding */                          /* incomplete padding */
                         ISTGT_TRACELOG(ISTGT_TRACE_NET,                          ISTGT_TRACELOG(ISTGT_TRACE_NET,
                            "Read %d bytes (padding %d)\n",                            "Read %zd bytes (padding %zd)\n",
                             nbytes, total);                              nbytes, total);
                         return nbytes;                          return nbytes;
                 }                  }
                 /* complete padding */                  /* complete padding */
                ISTGT_TRACELOG(ISTGT_TRACE_NET, "Read %d bytes (padding %d)\n",                ISTGT_TRACELOG(ISTGT_TRACE_NET, "Read %zd bytes (padding %zd)\n",
                     nbytes, pad_bytes);                      nbytes, pad_bytes);
                 return nbytes;                  return nbytes;
         }          }
   
         /* just aligned */          /* just aligned */
        ISTGT_TRACELOG(ISTGT_TRACE_NET, "Read %d bytes (no padding)\n",        ISTGT_TRACELOG(ISTGT_TRACE_NET, "Read %zd bytes (no padding)\n",
             nbytes);              nbytes);
 #endif /* ISTGT_USE_RECVBLOCK */  #endif /* ISTGT_USE_RECVBLOCK */
         return nbytes;          return nbytes;
Line 273  istgt_iscsi_write(CONN_Ptr conn, const void *buf, size Line 286  istgt_iscsi_write(CONN_Ptr conn, const void *buf, size
   
         if (total != nbytes) {          if (total != nbytes) {
                 /* incomplete bytes */                  /* incomplete bytes */
                ISTGT_TRACELOG(ISTGT_TRACE_NET, "Write %d/%d bytes\n",                ISTGT_TRACELOG(ISTGT_TRACE_NET, "Write %zd/%zd bytes\n",
                     total, nbytes);                      total, nbytes);
                 return total;                  return total;
         }          }
Line 287  istgt_iscsi_write(CONN_Ptr conn, const void *buf, size Line 300  istgt_iscsi_write(CONN_Ptr conn, const void *buf, size
                         if (r < 0) {                          if (r < 0) {
                                 /* error */                                  /* error */
                                 ISTGT_TRACELOG(ISTGT_TRACE_NET,                                  ISTGT_TRACELOG(ISTGT_TRACE_NET,
                                    "Write %d bytes (padding error) (errno=%d)\n",                                    "Write %zd bytes (padding error) (errno=%d)\n",
                                     nbytes, errno);                                      nbytes, errno);
                                 return nbytes;                                  return nbytes;
                         }                          }
Line 297  istgt_iscsi_write(CONN_Ptr conn, const void *buf, size Line 310  istgt_iscsi_write(CONN_Ptr conn, const void *buf, size
                 if (total != pad_bytes) {                  if (total != pad_bytes) {
                         /* incomplete padding */                          /* incomplete padding */
                         ISTGT_TRACELOG(ISTGT_TRACE_NET,                          ISTGT_TRACELOG(ISTGT_TRACE_NET,
                            "Write %d bytes (padding %d)\n",                            "Write %zd bytes (padding %zd)\n",
                             nbytes, total);                              nbytes, total);
                         return nbytes;                          return nbytes;
                 }                  }
   
                 /* complete padding */                  /* complete padding */
                 ISTGT_TRACELOG(ISTGT_TRACE_NET,                  ISTGT_TRACELOG(ISTGT_TRACE_NET,
                    "Write %d bytes (padding %d)\n",                    "Write %zd bytes (padding %zd)\n",
                     nbytes, pad_bytes);                      nbytes, pad_bytes);
         } else {          } else {
                 /* just aligned */                  /* just aligned */
                 ISTGT_TRACELOG(ISTGT_TRACE_NET,                  ISTGT_TRACELOG(ISTGT_TRACE_NET,
                    "Write %d bytes (no padding)\n",                    "Write %zd bytes (no padding)\n",
                     nbytes);                      nbytes);
         }          }
 #else /* !ISTGT_USE_SENDBLOCK */  #else /* !ISTGT_USE_SENDBLOCK */
Line 327  istgt_iscsi_write(CONN_Ptr conn, const void *buf, size Line 340  istgt_iscsi_write(CONN_Ptr conn, const void *buf, size
   
         if (total != nbytes) {          if (total != nbytes) {
                 /* incomplete bytes */                  /* incomplete bytes */
                ISTGT_TRACELOG(ISTGT_TRACE_NET, "Write %d/%d bytes\n",                ISTGT_TRACELOG(ISTGT_TRACE_NET, "Write %zd/%zd bytes\n",
                     total, nbytes);                      total, nbytes);
                 return r;                  return r;
         }          }
Line 344  istgt_iscsi_write(CONN_Ptr conn, const void *buf, size Line 357  istgt_iscsi_write(CONN_Ptr conn, const void *buf, size
                         if (r < 0) {                          if (r < 0) {
                                 /* error */                                  /* error */
                                 ISTGT_TRACELOG(ISTGT_TRACE_NET,                                  ISTGT_TRACELOG(ISTGT_TRACE_NET,
                                    "Write %d bytes (padding error) (errno=%d)\n",                                    "Write %zd bytes (padding error) (errno=%d)\n",
                                     nbytes, errno);                                      nbytes, errno);
                                 return nbytes;                                  return nbytes;
                         }                          }
Line 354  istgt_iscsi_write(CONN_Ptr conn, const void *buf, size Line 367  istgt_iscsi_write(CONN_Ptr conn, const void *buf, size
                 if (total != pad_bytes) {                  if (total != pad_bytes) {
                         /* incomplete padding */                          /* incomplete padding */
                         ISTGT_TRACELOG(ISTGT_TRACE_NET,                          ISTGT_TRACELOG(ISTGT_TRACE_NET,
                            "Write %d bytes (padding %d)\n",                            "Write %zd bytes (padding %zd)\n",
                             nbytes, total);                              nbytes, total);
                         return nbytes;                          return nbytes;
                 }                  }
                 /* complete padding */                  /* complete padding */
                 ISTGT_TRACELOG(ISTGT_TRACE_NET,                  ISTGT_TRACELOG(ISTGT_TRACE_NET,
                    "Write %d bytes (padding %d)\n",                    "Write %zd bytes (padding %zd)\n",
                     nbytes, pad_bytes);                      nbytes, pad_bytes);
                 return nbytes;                  return nbytes;
         }          }
   
         /* just aligned */          /* just aligned */
        ISTGT_TRACELOG(ISTGT_TRACE_NET, "Write %d bytes (no padding)\n",        ISTGT_TRACELOG(ISTGT_TRACE_NET, "Write %zd bytes (no padding)\n",
             nbytes);              nbytes);
 #endif /* ISTGT_USE_SENDBLOCK */  #endif /* ISTGT_USE_SENDBLOCK */
         return nbytes;          return nbytes;
 }  }
   #endif /* !defined (ISTGT_USE_IOVEC) */
   
 #define MATCH_DIGEST_WORD(BUF, CRC32C) \  #define MATCH_DIGEST_WORD(BUF, CRC32C) \
         (    ((((uint32_t) *((uint8_t *)(BUF)+0)) << 0)         \          (    ((((uint32_t) *((uint8_t *)(BUF)+0)) << 0)         \
Line 412  istgt_make_digest_word(uint8_t *buf, size_t len, uint3 Line 426  istgt_make_digest_word(uint8_t *buf, size_t len, uint3
 }  }
 #endif  #endif
   
   #if !defined (ISTGT_USE_IOVEC)
 static int  static int
 istgt_iscsi_read_pdu(CONN_Ptr conn, ISCSI_PDU_Ptr pdu)  istgt_iscsi_read_pdu(CONN_Ptr conn, ISCSI_PDU_Ptr pdu)
 {  {
Line 442  istgt_iscsi_read_pdu(CONN_Ptr conn, ISCSI_PDU_Ptr pdu) Line 457  istgt_iscsi_read_pdu(CONN_Ptr conn, ISCSI_PDU_Ptr pdu)
                             conn->initiator_name);                              conn->initiator_name);
                         conn->state = CONN_STATE_EXITING;                          conn->state = CONN_STATE_EXITING;
                 } else {                  } else {
                        ISTGT_ERRLOG("iscsi_read() failed (errno=%d)\n",                        ISTGT_ERRLOG("iscsi_read() failed (errno=%d,%s)\n",
                            errno);                            errno, conn->initiator_name);
                 }                  }
                 return -1;                  return -1;
         }          }
         if (rc == 0) {          if (rc == 0) {
                ISTGT_TRACELOG(ISTGT_TRACE_NET, "iscsi_read() EOF\n");                ISTGT_TRACELOG(ISTGT_TRACE_NET, "iscsi_read() EOF (%s)\n",
                     conn->initiator_name);
                 conn->state = CONN_STATE_EXITING;                  conn->state = CONN_STATE_EXITING;
                 return -1;                  return -1;
         }          }
Line 466  istgt_iscsi_read_pdu(CONN_Ptr conn, ISCSI_PDU_Ptr pdu) Line 482  istgt_iscsi_read_pdu(CONN_Ptr conn, ISCSI_PDU_Ptr pdu)
                     (4 * total_ahs_len));                      (4 * total_ahs_len));
                 rc = istgt_iscsi_read(conn, pdu->ahs, (4 * total_ahs_len));                  rc = istgt_iscsi_read(conn, pdu->ahs, (4 * total_ahs_len));
                 if (rc < 0) {                  if (rc < 0) {
                        ISTGT_ERRLOG("iscsi_read() failed\n");                        ISTGT_ERRLOG("iscsi_read() failed (errno=%d,%s)\n",
                             errno, conn->initiator_name);
                         return -1;                          return -1;
                 }                  }
                 if (rc == 0) {                  if (rc == 0) {
Line 492  istgt_iscsi_read_pdu(CONN_Ptr conn, ISCSI_PDU_Ptr pdu) Line 509  istgt_iscsi_read_pdu(CONN_Ptr conn, ISCSI_PDU_Ptr pdu)
                 rc = istgt_iscsi_read(conn, pdu->header_digest,                  rc = istgt_iscsi_read(conn, pdu->header_digest,
                     ISCSI_DIGEST_LEN);                      ISCSI_DIGEST_LEN);
                 if (rc < 0) {                  if (rc < 0) {
                        ISTGT_ERRLOG("iscsi_read() failed\n");                        ISTGT_ERRLOG("iscsi_read() failed (errno=%d,%s)\n",
                             errno, conn->initiator_name);
                         {                          {
                                 int opcode = BGET8W(&pdu->bhs.opcode, 5, 6);                                  int opcode = BGET8W(&pdu->bhs.opcode, 5, 6);
                                 ISTGT_ERRLOG("Header Digest read error (opcode = 0x%x)\n",                                  ISTGT_ERRLOG("Header Digest read error (opcode = 0x%x)\n",
Line 535  istgt_iscsi_read_pdu(CONN_Ptr conn, ISCSI_PDU_Ptr pdu) Line 553  istgt_iscsi_read_pdu(CONN_Ptr conn, ISCSI_PDU_Ptr pdu)
                     data_len);                      data_len);
                 rc = istgt_iscsi_read(conn, pdu->data, data_len);                  rc = istgt_iscsi_read(conn, pdu->data, data_len);
                 if (rc < 0) {                  if (rc < 0) {
                        ISTGT_ERRLOG("iscsi_read() failed (%d,errno=%d)\n",                        ISTGT_ERRLOG("iscsi_read() failed (%d,errno=%d,%s)\n",
                            rc, errno);                            rc, errno, conn->initiator_name);
                         return -1;                          return -1;
                 }                  }
                 if (rc == 0) {                  if (rc == 0) {
Line 572  istgt_iscsi_read_pdu(CONN_Ptr conn, ISCSI_PDU_Ptr pdu) Line 590  istgt_iscsi_read_pdu(CONN_Ptr conn, ISCSI_PDU_Ptr pdu)
                 rc = istgt_iscsi_read(conn, pdu->data_digest,                  rc = istgt_iscsi_read(conn, pdu->data_digest,
                     ISCSI_DIGEST_LEN);                      ISCSI_DIGEST_LEN);
                 if (rc < 0) {                  if (rc < 0) {
                        ISTGT_ERRLOG("iscsi_read() failed\n");                        ISTGT_ERRLOG("iscsi_read() failed (errno=%d,%s)\n",
                             errno, conn->initiator_name);
                         return -1;                          return -1;
                 }                  }
                 if (rc == 0) {                  if (rc == 0) {
Line 606  istgt_iscsi_read_pdu(CONN_Ptr conn, ISCSI_PDU_Ptr pdu) Line 625  istgt_iscsi_read_pdu(CONN_Ptr conn, ISCSI_PDU_Ptr pdu)
                 }                  }
                 rc = MATCH_DIGEST_WORD(pdu->header_digest, crc32c);                  rc = MATCH_DIGEST_WORD(pdu->header_digest, crc32c);
                 if (rc == 0) {                  if (rc == 0) {
                        ISTGT_ERRLOG("header digest error\n");                        ISTGT_ERRLOG("header digest error (%s)\n", conn->initiator_name);
                         return -1;                          return -1;
                 }                  }
         }          }
Line 614  istgt_iscsi_read_pdu(CONN_Ptr conn, ISCSI_PDU_Ptr pdu) Line 633  istgt_iscsi_read_pdu(CONN_Ptr conn, ISCSI_PDU_Ptr pdu)
                 crc32c = istgt_crc32c(pdu->data, data_len);                  crc32c = istgt_crc32c(pdu->data, data_len);
                 rc = MATCH_DIGEST_WORD(pdu->data_digest, crc32c);                  rc = MATCH_DIGEST_WORD(pdu->data_digest, crc32c);
                 if (rc == 0) {                  if (rc == 0) {
                        ISTGT_ERRLOG("data digest error\n");                        ISTGT_ERRLOG("data digest error (%s)\n", conn->initiator_name);
                         return -1;                          return -1;
                 }                  }
         }          }
   
         return total;          return total;
 }  }
   #else /* defined (ISTGT_USE_IOVEC) */
   static int
   istgt_iscsi_read_pdu(CONN_Ptr conn, ISCSI_PDU_Ptr pdu)
   {
           struct iovec iovec[4]; /* AHS+HD+DATA+DD */
           uint32_t crc32c;
           time_t start, now;
           int nbytes;
           int total_ahs_len;
           int data_len;
           int segment_len;
           int total;
           int rc;
           int i;
   
           pdu->ahs = NULL;
           pdu->total_ahs_len = 0;
           pdu->data = NULL;
           pdu->data_segment_len = 0;
           total = 0;
   
           /* BHS (require for all PDU) */
           ISTGT_TRACELOG(ISTGT_TRACE_NET, "BHS read %d\n",
               ISCSI_BHS_LEN);
           errno = 0;
           start = time(NULL);
           rc = recv(conn->sock, &pdu->bhs, ISCSI_BHS_LEN, MSG_WAITALL);
           if (rc < 0) {
                   now = time(NULL);
                   if (errno == ECONNRESET) {
                           ISTGT_WARNLOG("Connection reset by peer (%s,time=%d)\n",
                               conn->initiator_name, (int)difftime(now, start));
                           conn->state = CONN_STATE_EXITING;
                   } else if (errno == ETIMEDOUT) {
                           ISTGT_WARNLOG("Operation timed out (%s,time=%d)\n",
                               conn->initiator_name, (int)difftime(now, start));
                           conn->state = CONN_STATE_EXITING;
                   } else {
                           ISTGT_ERRLOG("iscsi_read() failed (errno=%d,%s,time=%d)\n",
                               errno, conn->initiator_name, (int)difftime(now, start));
                   }
                   return -1;
           }
           if (rc == 0) {
                   ISTGT_TRACELOG(ISTGT_TRACE_NET, "recv() EOF (%s)\n",
                       conn->initiator_name);
                   conn->state = CONN_STATE_EXITING;
                   return -1;
           }
           if (rc != ISCSI_BHS_LEN) {
                   ISTGT_ERRLOG("invalid BHS length (%d,%s)\n", rc, conn->initiator_name);
                   return -1;
           }
           total += ISCSI_BHS_LEN;
   
           /* AHS */
           total_ahs_len = DGET8(&pdu->bhs.total_ahs_len);
           if (total_ahs_len != 0) {
                   pdu->ahs = xmalloc(ISCSI_ALIGN((4 * total_ahs_len)));
                   pdu->total_ahs_len = total_ahs_len;
                   total += (4 * total_ahs_len);
           } else {
                   pdu->ahs = NULL;
                   pdu->total_ahs_len = 0;
           }
           iovec[0].iov_base = pdu->ahs;
           iovec[0].iov_len = 4 * pdu->total_ahs_len;
   
           /* Header Digest */
           iovec[1].iov_base = pdu->header_digest;
           if (conn->header_digest) {
                   iovec[1].iov_len = ISCSI_DIGEST_LEN;
                   total += ISCSI_DIGEST_LEN;
           } else {
                   iovec[1].iov_len = 0;
           }
   
           /* Data Segment */
           data_len = DGET24(&pdu->bhs.data_segment_len[0]);
           if (data_len != 0) {
                   if (conn->sess == NULL) {
                           segment_len = DEFAULT_FIRSTBURSTLENGTH;
                   } else {
                           segment_len = conn->MaxRecvDataSegmentLength;
                   }
                   if (data_len > segment_len) {
                           ISTGT_ERRLOG("Data(%d) > Segment(%d)\n",
                               data_len, segment_len);
                           return -1;
                   }
                   if (ISCSI_ALIGN(data_len) <= ISTGT_SHORTDATASIZE) {
                           pdu->data = pdu->shortdata;
                   } else {
                           pdu->data = xmalloc(ISCSI_ALIGN(segment_len));
                   }
                   pdu->data_segment_len = data_len;
                   total += ISCSI_ALIGN(data_len);
           } else {
                   pdu->data = NULL;
                   pdu->data_segment_len = 0;
           }
           iovec[2].iov_base = pdu->data;
           iovec[2].iov_len = ISCSI_ALIGN(pdu->data_segment_len);
   
           /* Data Digest */
           iovec[3].iov_base = pdu->data_digest;
           if (conn->data_digest && data_len != 0) {
                   iovec[3].iov_len = ISCSI_DIGEST_LEN;
                   total += ISCSI_DIGEST_LEN;
           } else {
                   iovec[3].iov_len = 0;
           }
   
           /* read all bytes to iovec */
           nbytes = total - ISCSI_BHS_LEN;
           ISTGT_TRACELOG(ISTGT_TRACE_NET, "PDU read %d\n", nbytes);
           errno = 0;
           start = time(NULL);
           while (nbytes > 0) {
                   rc = readv(conn->sock, &iovec[0], 4);
                   if (rc < 0) {
                           now = time(NULL);
                           ISTGT_ERRLOG("readv() failed (%d,errno=%d,%s,time=%d)\n",
                               rc, errno, conn->initiator_name, (int)difftime(now, start));
                           return -1;
                   }
                   if (rc == 0) {
                           ISTGT_TRACELOG(ISTGT_TRACE_NET, "readv() EOF (%s)\n",
                               conn->initiator_name);
                           conn->state = CONN_STATE_EXITING;
                           return -1;
                   }
                   nbytes -= rc;
                   if (nbytes == 0)
                           break;
                   /* adjust iovec length */
                   for (i = 0; i < 4; i++) {
                           if (iovec[i].iov_len != 0 && iovec[i].iov_len > (size_t)rc) {
                                   iovec[i].iov_base
                                           = (void *) (((uintptr_t)iovec[i].iov_base) + rc);
                                   iovec[i].iov_len -= rc;
                                   break;
                           } else {
                                   rc -= iovec[i].iov_len;
                                   iovec[i].iov_len = 0;
                           }
                   }
           }
   
           /* check digest */
           if (conn->header_digest) {
                   if (total_ahs_len == 0) {
                           crc32c = istgt_crc32c((uint8_t *) &pdu->bhs,
                               ISCSI_BHS_LEN);
                   } else {
                           int upd_total = 0;
                           crc32c = ISTGT_CRC32C_INITIAL;
                           crc32c = istgt_update_crc32c((uint8_t *) &pdu->bhs,
                               ISCSI_BHS_LEN, crc32c);
                           upd_total += ISCSI_BHS_LEN;
                           crc32c = istgt_update_crc32c((uint8_t *) pdu->ahs,
                               (4 * total_ahs_len), crc32c);
                           upd_total += (4 * total_ahs_len);
                           crc32c = istgt_fixup_crc32c(upd_total, crc32c);
                           crc32c = crc32c ^ ISTGT_CRC32C_XOR;
                   }
                   rc = MATCH_DIGEST_WORD(pdu->header_digest, crc32c);
                   if (rc == 0) {
                           ISTGT_ERRLOG("header digest error (%s)\n", conn->initiator_name);
                           return -1;
                   }
           }
           if (conn->data_digest && data_len != 0) {
                   crc32c = istgt_crc32c(pdu->data, ISCSI_ALIGN(data_len));
                   rc = MATCH_DIGEST_WORD(pdu->data_digest, crc32c);
                   if (rc == 0) {
                           ISTGT_ERRLOG("data digest error (%s)\n", conn->initiator_name);
                           return -1;
                   }
           }
   
           return total;
   }
   #endif /* defined (ISTGT_USE_IOVEC) */
   
 static int istgt_iscsi_write_pdu_internal(CONN_Ptr conn, ISCSI_PDU_Ptr pdu);  static int istgt_iscsi_write_pdu_internal(CONN_Ptr conn, ISCSI_PDU_Ptr pdu);
   static int istgt_iscsi_write_pdu_queue(CONN_Ptr conn, ISCSI_PDU_Ptr pdu, int req_type, int I_bit);
   
   static int istgt_update_pdu(CONN_Ptr conn, ISTGT_LU_CMD_Ptr lu_cmd)
   {
           uint8_t *rsp;
           uint32_t task_tag;
           int opcode;
           int I_bit;
   
           I_bit = lu_cmd->I_bit;
           rsp = (uint8_t *) &lu_cmd->pdu->bhs;
           opcode = BGET8W(&rsp[0], 5, 6);
           task_tag = DGET32(&rsp[16]);
           if ((opcode == ISCSI_OP_R2T)
               || (opcode == ISCSI_OP_NOPIN && task_tag == 0xffffffffU)) {
                   SESS_MTX_LOCK(conn);
                   DSET32(&rsp[24], conn->StatSN);
                   DSET32(&rsp[28], conn->sess->ExpCmdSN);
                   DSET32(&rsp[32], conn->sess->MaxCmdSN);
                   SESS_MTX_UNLOCK(conn);
           } else if ((opcode == ISCSI_OP_TASK_RSP)
               || (opcode == ISCSI_OP_NOPIN && task_tag != 0xffffffffU)) {
                   SESS_MTX_LOCK(conn);
                   DSET32(&rsp[24], conn->StatSN);
                   conn->StatSN++;
                   if (I_bit == 0) {
                           conn->sess->ExpCmdSN++;
                           conn->sess->MaxCmdSN++;
                   }
                   DSET32(&rsp[28], conn->sess->ExpCmdSN);
                   DSET32(&rsp[32], conn->sess->MaxCmdSN);
                   SESS_MTX_UNLOCK(conn);
           }
           return 0;
   }
   
 static int  static int
 istgt_iscsi_write_pdu(CONN_Ptr conn, ISCSI_PDU_Ptr pdu)  istgt_iscsi_write_pdu(CONN_Ptr conn, ISCSI_PDU_Ptr pdu)
 {  {
Line 632  istgt_iscsi_write_pdu(CONN_Ptr conn, ISCSI_PDU_Ptr pdu Line 870  istgt_iscsi_write_pdu(CONN_Ptr conn, ISCSI_PDU_Ptr pdu
         if (conn->use_sender == 0) {          if (conn->use_sender == 0) {
                 rc = istgt_iscsi_write_pdu_internal(conn, pdu);                  rc = istgt_iscsi_write_pdu_internal(conn, pdu);
         } else {          } else {
                   rc = istgt_iscsi_write_pdu_queue(conn, pdu, ISTGT_LU_TASK_REQPDU, 0);
           }
           return rc;
   }
   
   static int
   istgt_iscsi_write_pdu_upd(CONN_Ptr conn, ISCSI_PDU_Ptr pdu, int I_bit)
   {
           int rc;
   
           if (conn->use_sender == 0) {
                   rc = istgt_iscsi_write_pdu_internal(conn, pdu);
           } else {
                   rc = istgt_iscsi_write_pdu_queue(conn, pdu, ISTGT_LU_TASK_REQUPDPDU, I_bit);
           }
           return rc;
   }
   
   static int
   istgt_iscsi_write_pdu_queue(CONN_Ptr conn, ISCSI_PDU_Ptr pdu, int req_type, int I_bit)
   {
           int rc;
   
           if (conn->use_sender == 0) {
                   rc = istgt_iscsi_write_pdu_internal(conn, pdu);
           } else {
                 ISTGT_LU_TASK_Ptr lu_task;                  ISTGT_LU_TASK_Ptr lu_task;
                 ISCSI_PDU_Ptr src_pdu, dst_pdu;                  ISCSI_PDU_Ptr src_pdu, dst_pdu;
                 uint8_t *cp;                  uint8_t *cp;
Line 656  istgt_iscsi_write_pdu(CONN_Ptr conn, ISCSI_PDU_Ptr pdu Line 920  istgt_iscsi_write_pdu(CONN_Ptr conn, ISCSI_PDU_Ptr pdu
                 alloc_len += ISCSI_ALIGN(data_len);                  alloc_len += ISCSI_ALIGN(data_len);
                 lu_task = xmalloc(alloc_len);                  lu_task = xmalloc(alloc_len);
                 memset(lu_task, 0, alloc_len);                  memset(lu_task, 0, alloc_len);
                lu_task->lu_cmd.pdu = (ISCSI_PDU_Ptr) ((uint8_t *)lu_task                lu_task->lu_cmd.pdu = (ISCSI_PDU_Ptr) ((uintptr_t)lu_task
                     + ISCSI_ALIGN(sizeof *lu_task));                      + ISCSI_ALIGN(sizeof *lu_task));
                lu_task->lu_cmd.pdu->ahs = (ISCSI_AHS *) ((uint8_t *)lu_task->lu_cmd.pdu                lu_task->lu_cmd.pdu->ahs = (ISCSI_AHS *) ((uintptr_t)lu_task->lu_cmd.pdu
                     + ISCSI_ALIGN(sizeof *lu_task->lu_cmd.pdu));                      + ISCSI_ALIGN(sizeof *lu_task->lu_cmd.pdu));
                lu_task->lu_cmd.pdu->data = (uint8_t *)lu_task->lu_cmd.pdu->ahs                lu_task->lu_cmd.pdu->data = (uint8_t *) ((uintptr_t)lu_task->lu_cmd.pdu->ahs
                    + ISCSI_ALIGN(4 * total_ahs_len);                    + ISCSI_ALIGN(4 * total_ahs_len));
   
                 /* specify type and self conn */                  /* specify type and self conn */
                lu_task->type = ISTGT_LU_TASK_REQPDU;                //lu_task->type = ISTGT_LU_TASK_REQPDU;
                 lu_task->type = req_type;
                 lu_task->conn = conn;                  lu_task->conn = conn;
   
                   /* extra flags */
                   lu_task->lu_cmd.I_bit = I_bit;
   
                 /* copy PDU structure */                  /* copy PDU structure */
                 src_pdu = pdu;                  src_pdu = pdu;
                 dst_pdu = lu_task->lu_cmd.pdu;                  dst_pdu = lu_task->lu_cmd.pdu;
Line 717  istgt_iscsi_write_pdu(CONN_Ptr conn, ISCSI_PDU_Ptr pdu Line 985  istgt_iscsi_write_pdu(CONN_Ptr conn, ISCSI_PDU_Ptr pdu
         return rc;          return rc;
 }  }
   
   #if !defined (ISTGT_USE_IOVEC)
 static int  static int
 istgt_iscsi_write_pdu_internal(CONN_Ptr conn, ISCSI_PDU_Ptr pdu)  istgt_iscsi_write_pdu_internal(CONN_Ptr conn, ISCSI_PDU_Ptr pdu)
 {  {
Line 773  istgt_iscsi_write_pdu_internal(CONN_Ptr conn, ISCSI_PD Line 1042  istgt_iscsi_write_pdu_internal(CONN_Ptr conn, ISCSI_PD
                     total);                      total);
                 rc = istgt_iscsi_write(conn, spp, total);                  rc = istgt_iscsi_write(conn, spp, total);
                 if (rc < 0) {                  if (rc < 0) {
                        ISTGT_ERRLOG("iscsi_write() failed (errno=%d)\n",                        ISTGT_ERRLOG("iscsi_write() failed (errno=%d,%s)\n",
                            errno);                            errno, conn->initiator_name);
                         return -1;                          return -1;
                 }                  }
                 if (rc != total) {                  if (rc != total) {
Line 790  istgt_iscsi_write_pdu_internal(CONN_Ptr conn, ISCSI_PD Line 1059  istgt_iscsi_write_pdu_internal(CONN_Ptr conn, ISCSI_PD
             ISCSI_BHS_LEN);              ISCSI_BHS_LEN);
         rc = istgt_iscsi_write(conn, &pdu->bhs, ISCSI_BHS_LEN);          rc = istgt_iscsi_write(conn, &pdu->bhs, ISCSI_BHS_LEN);
         if (rc < 0) {          if (rc < 0) {
                ISTGT_ERRLOG("iscsi_write() failed (errno=%d)\n", errno);                ISTGT_ERRLOG("iscsi_write() failed (errno=%d,%s)\n", errno,
                     conn->initiator_name);
                 return -1;                  return -1;
         }          }
         if (rc != ISCSI_BHS_LEN) {          if (rc != ISCSI_BHS_LEN) {
Line 805  istgt_iscsi_write_pdu_internal(CONN_Ptr conn, ISCSI_PD Line 1075  istgt_iscsi_write_pdu_internal(CONN_Ptr conn, ISCSI_PD
                     (4 * total_ahs_len));                      (4 * total_ahs_len));
                 rc = istgt_iscsi_write(conn, pdu->ahs, (4 * total_ahs_len));                  rc = istgt_iscsi_write(conn, pdu->ahs, (4 * total_ahs_len));
                 if (rc < 0) {                  if (rc < 0) {
                        ISTGT_ERRLOG("iscsi_write() failed\n");                        ISTGT_ERRLOG("iscsi_write() failed (errno=%d,%s)\n",
                             errno, conn->initiator_name);
                         return -1;                          return -1;
                 }                  }
                 if (rc != (4 * total_ahs_len)) {                  if (rc != (4 * total_ahs_len)) {
Line 839  istgt_iscsi_write_pdu_internal(CONN_Ptr conn, ISCSI_PD Line 1110  istgt_iscsi_write_pdu_internal(CONN_Ptr conn, ISCSI_PD
                 rc = istgt_iscsi_write(conn, pdu->header_digest,                  rc = istgt_iscsi_write(conn, pdu->header_digest,
                     ISCSI_DIGEST_LEN);                      ISCSI_DIGEST_LEN);
                 if (rc < 0) {                  if (rc < 0) {
                        ISTGT_ERRLOG("iscsi_write() failed\n");                        ISTGT_ERRLOG("iscsi_write() failed (errno=%d,%s)\n",
                             errno, conn->initiator_name);
                         return -1;                          return -1;
                 }                  }
                 if (rc != ISCSI_DIGEST_LEN) {                  if (rc != ISCSI_DIGEST_LEN) {
Line 856  istgt_iscsi_write_pdu_internal(CONN_Ptr conn, ISCSI_PD Line 1128  istgt_iscsi_write_pdu_internal(CONN_Ptr conn, ISCSI_PD
                     data_len);                      data_len);
                 rc = istgt_iscsi_write(conn, pdu->data, data_len);                  rc = istgt_iscsi_write(conn, pdu->data, data_len);
                 if (rc < 0) {                  if (rc < 0) {
                        ISTGT_ERRLOG("iscsi_write() failed\n");                        ISTGT_ERRLOG("iscsi_write() failed (errno=%d,%s)\n",
                             errno, conn->initiator_name);
                         return -1;                          return -1;
                 }                  }
                 if (rc != data_len) {                  if (rc != data_len) {
Line 879  istgt_iscsi_write_pdu_internal(CONN_Ptr conn, ISCSI_PD Line 1152  istgt_iscsi_write_pdu_internal(CONN_Ptr conn, ISCSI_PD
                 rc = istgt_iscsi_write(conn, pdu->data_digest,                  rc = istgt_iscsi_write(conn, pdu->data_digest,
                     ISCSI_DIGEST_LEN);                      ISCSI_DIGEST_LEN);
                 if (rc < 0) {                  if (rc < 0) {
                        ISTGT_ERRLOG("iscsi_write() failed\n");                        ISTGT_ERRLOG("iscsi_write() failed (errno=%d,%s)\n",
                             errno, conn->initiator_name);
                         return -1;                          return -1;
                 }                  }
                 if (rc != ISCSI_DIGEST_LEN) {                  if (rc != ISCSI_DIGEST_LEN) {
Line 892  istgt_iscsi_write_pdu_internal(CONN_Ptr conn, ISCSI_PD Line 1166  istgt_iscsi_write_pdu_internal(CONN_Ptr conn, ISCSI_PD
   
         return total;          return total;
 }  }
   #else /* defined (ISTGT_USE_IOVEC) */
   static int
   istgt_iscsi_write_pdu_internal(CONN_Ptr conn, ISCSI_PDU_Ptr pdu)
   {
           struct iovec iovec[5]; /* BHS+AHS+HD+DATA+DD */
           uint8_t *cp;
           uint32_t crc32c;
           time_t start, now;
           int nbytes;
           int enable_digest;
           int opcode;
           int total_ahs_len;
           int data_len;
           int total;
           int rc;
           int i;
   
           cp = (uint8_t *) &pdu->bhs;
           total_ahs_len = DGET8(&cp[4]);
           data_len = DGET24(&cp[5]);
           total = 0;
   
           enable_digest = 1;
           opcode = BGET8W(&cp[0], 5, 6);
           if (opcode == ISCSI_OP_LOGIN_RSP) {
                   /* this PDU should be sent without digest */
                   enable_digest = 0;
           }
   
           /* BHS */
           iovec[0].iov_base = &pdu->bhs;
           iovec[0].iov_len = ISCSI_BHS_LEN;
           total += ISCSI_BHS_LEN;
   
           /* AHS */
           iovec[1].iov_base = pdu->ahs;
           iovec[1].iov_len = 4 * total_ahs_len;
           total += (4 * total_ahs_len);
   
           /* Header Digest */
           iovec[2].iov_base = pdu->header_digest;
           if (enable_digest && conn->header_digest) {
                   if (total_ahs_len == 0) {
                           crc32c = istgt_crc32c((uint8_t *) &pdu->bhs,
                               ISCSI_BHS_LEN);
                   } else {
                           int upd_total = 0;
                           crc32c = ISTGT_CRC32C_INITIAL;
                           crc32c = istgt_update_crc32c((uint8_t *) &pdu->bhs,
                               ISCSI_BHS_LEN, crc32c);
                           upd_total += ISCSI_BHS_LEN;
                           crc32c = istgt_update_crc32c((uint8_t *) pdu->ahs,
                               (4 * total_ahs_len), crc32c);
                           upd_total += (4 * total_ahs_len);
                           crc32c = istgt_fixup_crc32c(upd_total, crc32c);
                           crc32c = crc32c ^ ISTGT_CRC32C_XOR;
                   }
                   MAKE_DIGEST_WORD(pdu->header_digest, crc32c);
   
                   iovec[2].iov_len = ISCSI_DIGEST_LEN;
                   total += ISCSI_DIGEST_LEN;
           } else {
                   iovec[2].iov_len = 0;
           }
   
           /* Data Segment */
           iovec[3].iov_base = pdu->data;
           iovec[3].iov_len = ISCSI_ALIGN(data_len);
           total += ISCSI_ALIGN(data_len);
   
           /* Data Digest */
           iovec[4].iov_base = pdu->data_digest;
           if (enable_digest && conn->data_digest && data_len != 0) {
                   crc32c = istgt_crc32c(pdu->data, ISCSI_ALIGN(data_len));
                   MAKE_DIGEST_WORD(pdu->data_digest, crc32c);
   
                   iovec[4].iov_len = ISCSI_DIGEST_LEN;
                   total += ISCSI_DIGEST_LEN;
           } else {
                   iovec[4].iov_len = 0;
           }
   
           /* write all bytes from iovec */
           nbytes = total;
           ISTGT_TRACELOG(ISTGT_TRACE_NET, "PDU write %d\n", nbytes);
           errno = 0;
           start = time(NULL);
           while (nbytes > 0) {
                   rc = writev(conn->sock, &iovec[0], 5);
                   if (rc < 0) {
                           now = time(NULL);
                           ISTGT_ERRLOG("writev() failed (errno=%d,%s,time=%d)\n",
                               errno, conn->initiator_name, (int)difftime(now, start));
                           return -1;
                   }
                   nbytes -= rc;
                   if (nbytes == 0)
                           break;
                   /* adjust iovec length */
                   for (i = 0; i < 5; i++) {
                           if (iovec[i].iov_len != 0 && iovec[i].iov_len > (size_t)rc) {
                                   iovec[i].iov_base
                                           = (void *) (((uintptr_t)iovec[i].iov_base) + rc);
                                   iovec[i].iov_len -= rc;
                                   break;
                           } else {
                                   rc -= iovec[i].iov_len;
                                   iovec[i].iov_len = 0;
                           }
                   }
           }
   
           return total;
   }
   #endif /* defined (ISTGT_USE_IOVEC) */
   
 int  int
 istgt_iscsi_copy_pdu(ISCSI_PDU_Ptr dst_pdu, ISCSI_PDU_Ptr src_pdu)  istgt_iscsi_copy_pdu(ISCSI_PDU_Ptr dst_pdu, ISCSI_PDU_Ptr src_pdu)
 {  {
Line 1346  istgt_iscsi_negotiate_params(CONN_Ptr conn, ISCSI_PARA Line 1735  istgt_iscsi_negotiate_params(CONN_Ptr conn, ISCSI_PARA
 }  }
   
 static int  static int
istgt_iscsi_append_text(CONN_Ptr conn, const char *key, const char *val, uint8_t *data, int alloc_len, int data_len)istgt_iscsi_append_text(CONN_Ptr conn __attribute__((__unused__)), const char *key, const char *val, uint8_t *data, int alloc_len, int data_len)
 {  {
         int total;          int total;
         int len;          int len;
Line 1782  istgt_iscsi_reject(CONN_Ptr conn, ISCSI_PDU_Ptr pdu, i Line 2171  istgt_iscsi_reject(CONN_Ptr conn, ISCSI_PDU_Ptr pdu, i
   
         DSET32(&rsp[16], 0xffffffffU);          DSET32(&rsp[16], 0xffffffffU);
   
         DSET32(&rsp[24], conn->StatSN);  
         conn->StatSN++;  
         if (conn->sess != NULL) {          if (conn->sess != NULL) {
                 SESS_MTX_LOCK(conn);                  SESS_MTX_LOCK(conn);
                   DSET32(&rsp[24], conn->StatSN);
                   conn->StatSN++;
                 DSET32(&rsp[28], conn->sess->ExpCmdSN);                  DSET32(&rsp[28], conn->sess->ExpCmdSN);
                 DSET32(&rsp[32], conn->sess->MaxCmdSN);                  DSET32(&rsp[32], conn->sess->MaxCmdSN);
                 SESS_MTX_UNLOCK(conn);                  SESS_MTX_UNLOCK(conn);
         } else {          } else {
                   DSET32(&rsp[24], conn->StatSN);
                   conn->StatSN++;
                 DSET32(&rsp[28], 1);                  DSET32(&rsp[28], 1);
                 DSET32(&rsp[32], 1);                  DSET32(&rsp[32], 1);
         }          }
Line 2298  istgt_iscsi_op_login(CONN_Ptr conn, ISCSI_PDU_Ptr pdu) Line 2689  istgt_iscsi_op_login(CONN_Ptr conn, ISCSI_PDU_Ptr pdu)
                         }                          }
   
                         /* initialize parameters */                          /* initialize parameters */
                         conn->StatSN = ExpStatSN;  
                         SESS_MTX_LOCK(conn);                          SESS_MTX_LOCK(conn);
                           conn->StatSN = ExpStatSN;
                         conn->MaxOutstandingR2T                          conn->MaxOutstandingR2T
                                 = conn->sess->MaxOutstandingR2T;                                  = conn->sess->MaxOutstandingR2T;
                         conn->sess->isid = isid;                          conn->sess->isid = isid;
Line 2574  istgt_iscsi_op_login(CONN_Ptr conn, ISCSI_PDU_Ptr pdu) Line 2965  istgt_iscsi_op_login(CONN_Ptr conn, ISCSI_PDU_Ptr pdu)
         DSET16(&rsp[14], tsih);          DSET16(&rsp[14], tsih);
         DSET32(&rsp[16], task_tag);          DSET32(&rsp[16], task_tag);
   
         DSET32(&rsp[24], conn->StatSN);  
         conn->StatSN++;  
         if (conn->sess != NULL) {          if (conn->sess != NULL) {
                 SESS_MTX_LOCK(conn);                  SESS_MTX_LOCK(conn);
                   DSET32(&rsp[24], conn->StatSN);
                   conn->StatSN++;
                 DSET32(&rsp[28], conn->sess->ExpCmdSN);                  DSET32(&rsp[28], conn->sess->ExpCmdSN);
                 DSET32(&rsp[32], conn->sess->MaxCmdSN);                  DSET32(&rsp[32], conn->sess->MaxCmdSN);
                 SESS_MTX_UNLOCK(conn);                  SESS_MTX_UNLOCK(conn);
         } else {          } else {
                   DSET32(&rsp[24], conn->StatSN);
                   conn->StatSN++;
                 DSET32(&rsp[28], CmdSN);                  DSET32(&rsp[28], CmdSN);
                 DSET32(&rsp[32], CmdSN);                  DSET32(&rsp[32], CmdSN);
         }          }
Line 2683  istgt_iscsi_op_text(CONN_Ptr conn, ISCSI_PDU_Ptr pdu) Line 3076  istgt_iscsi_op_text(CONN_Ptr conn, ISCSI_PDU_Ptr pdu)
                 ISTGT_ERRLOG("CmdSN(%u) error\n", CmdSN);                  ISTGT_ERRLOG("CmdSN(%u) error\n", CmdSN);
                 return -1;                  return -1;
         }          }
         SESS_MTX_UNLOCK(conn);  
         if (SN32_GT(ExpStatSN, conn->StatSN)) {          if (SN32_GT(ExpStatSN, conn->StatSN)) {
                 ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "StatSN(%u) advanced\n",                  ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "StatSN(%u) advanced\n",
                     ExpStatSN);                      ExpStatSN);
Line 2692  istgt_iscsi_op_text(CONN_Ptr conn, ISCSI_PDU_Ptr pdu) Line 3084  istgt_iscsi_op_text(CONN_Ptr conn, ISCSI_PDU_Ptr pdu)
         if (ExpStatSN != conn->StatSN) {          if (ExpStatSN != conn->StatSN) {
 #if 0  #if 0
                 ISTGT_ERRLOG("StatSN(%u) error\n", ExpStatSN);                  ISTGT_ERRLOG("StatSN(%u) error\n", ExpStatSN);
                   SESS_MTX_UNLOCK(conn);
                 return -1;                  return -1;
 #else  #else
                 /* StarPort have a bug */                  /* StarPort have a bug */
Line 2699  istgt_iscsi_op_text(CONN_Ptr conn, ISCSI_PDU_Ptr pdu) Line 3092  istgt_iscsi_op_text(CONN_Ptr conn, ISCSI_PDU_Ptr pdu)
                 conn->StatSN = ExpStatSN;                  conn->StatSN = ExpStatSN;
 #endif  #endif
         }          }
           SESS_MTX_UNLOCK(conn);
   
         if (F_bit && C_bit) {          if (F_bit && C_bit) {
                 ISTGT_ERRLOG("final and continue\n");                  ISTGT_ERRLOG("final and continue\n");
Line 2768  istgt_iscsi_op_text(CONN_Ptr conn, ISCSI_PDU_Ptr pdu) Line 3162  istgt_iscsi_op_text(CONN_Ptr conn, ISCSI_PDU_Ptr pdu)
                 DSET32(&rsp[20], transfer_tag);                  DSET32(&rsp[20], transfer_tag);
         }          }
   
           SESS_MTX_LOCK(conn);
         DSET32(&rsp[24], conn->StatSN);          DSET32(&rsp[24], conn->StatSN);
         conn->StatSN++;          conn->StatSN++;
         SESS_MTX_LOCK(conn);  
         if (I_bit == 0) {          if (I_bit == 0) {
                 conn->sess->ExpCmdSN++;                  conn->sess->ExpCmdSN++;
                 conn->sess->MaxCmdSN++;                  conn->sess->MaxCmdSN++;
Line 2850  istgt_iscsi_op_logout(CONN_Ptr conn, ISCSI_PDU_Ptr pdu Line 3244  istgt_iscsi_op_logout(CONN_Ptr conn, ISCSI_PDU_Ptr pdu
                     "CmdSN=%u, ExpStatSN=%u, StatSN=%u\n",                      "CmdSN=%u, ExpStatSN=%u, StatSN=%u\n",
                     CmdSN, ExpStatSN, conn->StatSN);                      CmdSN, ExpStatSN, conn->StatSN);
         }          }
           if (conn->sess != NULL) {
                   SESS_MTX_LOCK(conn);
           }
         if (SN32_GT(ExpStatSN, conn->StatSN)) {          if (SN32_GT(ExpStatSN, conn->StatSN)) {
                 ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "StatSN(%u) advanced\n",                  ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "StatSN(%u) advanced\n",
                     ExpStatSN);                      ExpStatSN);
Line 2860  istgt_iscsi_op_logout(CONN_Ptr conn, ISCSI_PDU_Ptr pdu Line 3257  istgt_iscsi_op_logout(CONN_Ptr conn, ISCSI_PDU_Ptr pdu
                     ExpStatSN, conn->StatSN);                      ExpStatSN, conn->StatSN);
                 /* ignore error */                  /* ignore error */
         }          }
           if (conn->sess != NULL) {
                   SESS_MTX_UNLOCK(conn);
           }
   
         response = 0; // connection or session closed successfully          response = 0; // connection or session closed successfully
   
Line 2875  istgt_iscsi_op_logout(CONN_Ptr conn, ISCSI_PDU_Ptr pdu Line 3275  istgt_iscsi_op_logout(CONN_Ptr conn, ISCSI_PDU_Ptr pdu
   
         DSET32(&rsp[16], task_tag);          DSET32(&rsp[16], task_tag);
   
         DSET32(&rsp[24], conn->StatSN);  
         conn->StatSN++;  
         if (conn->sess != NULL) {          if (conn->sess != NULL) {
                 SESS_MTX_LOCK(conn);                  SESS_MTX_LOCK(conn);
                   DSET32(&rsp[24], conn->StatSN);
                   conn->StatSN++;
                 if (conn->sess->connections == 1) {                  if (conn->sess->connections == 1) {
                         conn->sess->ExpCmdSN++;                          conn->sess->ExpCmdSN++;
                         conn->sess->MaxCmdSN++;                          conn->sess->MaxCmdSN++;
Line 2887  istgt_iscsi_op_logout(CONN_Ptr conn, ISCSI_PDU_Ptr pdu Line 3287  istgt_iscsi_op_logout(CONN_Ptr conn, ISCSI_PDU_Ptr pdu
                 DSET32(&rsp[32], conn->sess->MaxCmdSN);                  DSET32(&rsp[32], conn->sess->MaxCmdSN);
                 SESS_MTX_UNLOCK(conn);                  SESS_MTX_UNLOCK(conn);
         } else {          } else {
                   DSET32(&rsp[24], conn->StatSN);
                   conn->StatSN++;
                 DSET32(&rsp[28], CmdSN);                  DSET32(&rsp[28], CmdSN);
                 DSET32(&rsp[32], CmdSN);                  DSET32(&rsp[32], CmdSN);
         }          }
Line 3053  istgt_iscsi_transfer_in_internal(CONN_Ptr conn, ISTGT_ Line 3455  istgt_iscsi_transfer_in_internal(CONN_Ptr conn, ISTGT_
                 DSET32(&rsp[16], task_tag);                  DSET32(&rsp[16], task_tag);
                 DSET32(&rsp[20], transfer_tag);                  DSET32(&rsp[20], transfer_tag);
   
                   SESS_MTX_LOCK(conn);
                 if (S_bit) {                  if (S_bit) {
                         DSET32(&rsp[24], conn->StatSN);                          DSET32(&rsp[24], conn->StatSN);
                         conn->StatSN++;                          conn->StatSN++;
                 } else {                  } else {
                         DSET32(&rsp[24], 0); // StatSN or Reserved                          DSET32(&rsp[24], 0); // StatSN or Reserved
                 }                  }
                 SESS_MTX_LOCK(conn);  
                 if (F_bit && S_bit && lu_cmd->I_bit == 0) {                  if (F_bit && S_bit && lu_cmd->I_bit == 0) {
                         conn->sess->MaxCmdSN++;                          conn->sess->MaxCmdSN++;
                 }                  }
Line 3104  istgt_iscsi_op_scsi(CONN_Ptr conn, ISCSI_PDU_Ptr pdu) Line 3506  istgt_iscsi_op_scsi(CONN_Ptr conn, ISCSI_PDU_Ptr pdu)
         uint32_t transfer_len;          uint32_t transfer_len;
         uint32_t CmdSN;          uint32_t CmdSN;
         uint32_t ExpStatSN;          uint32_t ExpStatSN;
           size_t bidi_residual_len;
           size_t residual_len;
           size_t data_len;
           size_t alloc_len;
         int I_bit, F_bit, R_bit, W_bit, Attr_bit;          int I_bit, F_bit, R_bit, W_bit, Attr_bit;
         int o_bit, u_bit, O_bit, U_bit;          int o_bit, u_bit, O_bit, U_bit;
         int bidi_residual_len;  
         int residual_len;  
         int data_len;  
         int alloc_len;  
         int rc;          int rc;
   
         if (!conn->full_feature) {          if (!conn->full_feature) {
Line 3156  istgt_iscsi_op_scsi(CONN_Ptr conn, ISCSI_PDU_Ptr pdu) Line 3558  istgt_iscsi_op_scsi(CONN_Ptr conn, ISCSI_PDU_Ptr pdu)
                 if (SN32_GT(CmdSN, conn->sess->ExpCmdSN)) {                  if (SN32_GT(CmdSN, conn->sess->ExpCmdSN)) {
                         if (conn->sess->connections > 1) {                          if (conn->sess->connections > 1) {
                                 struct timespec abstime;                                  struct timespec abstime;
                                time_t now;                                time_t start, now;
   
                                 SESS_MTX_UNLOCK(conn);                                  SESS_MTX_UNLOCK(conn);
                                now = time(NULL);                                start = now = time(NULL);
                                 memset(&abstime, 0, sizeof abstime);                                  memset(&abstime, 0, sizeof abstime);
                                 abstime.tv_sec = now + (MAX_MCSREVWAIT / 1000);                                  abstime.tv_sec = now + (MAX_MCSREVWAIT / 1000);
                                 abstime.tv_nsec = (MAX_MCSREVWAIT % 1000) * 1000000;                                  abstime.tv_nsec = (MAX_MCSREVWAIT % 1000) * 1000000;
Line 3186  istgt_iscsi_op_scsi(CONN_Ptr conn, ISCSI_PDU_Ptr pdu) Line 3588  istgt_iscsi_op_scsi(CONN_Ptr conn, ISCSI_PDU_Ptr pdu)
                                         }                                          }
                                 }                                  }
                                 if (rc < 0) {                                  if (rc < 0) {
                                        ISTGT_ERRLOG("MCS: CmdSN(%u) error ExpCmdSN=%u\n",                                        now = time(NULL);
                                            CmdSN, conn->sess->ExpCmdSN);                                        ISTGT_ERRLOG("MCS: CmdSN(%u) error ExpCmdSN=%u "
                                             "(time=%d)\n",
                                             CmdSN, conn->sess->ExpCmdSN,
                                             (int)difftime(now, start));
                                         SESS_MTX_UNLOCK(conn);                                          SESS_MTX_UNLOCK(conn);
                                         return -1;                                          return -1;
                                 }                                  }
Line 3219  istgt_iscsi_op_scsi(CONN_Ptr conn, ISCSI_PDU_Ptr pdu) Line 3624  istgt_iscsi_op_scsi(CONN_Ptr conn, ISCSI_PDU_Ptr pdu)
                     CmdSN, conn->sess->ExpCmdSN);                      CmdSN, conn->sess->ExpCmdSN);
                 return -1;                  return -1;
         }          }
         SESS_MTX_UNLOCK(conn);  
         if (SN32_GT(ExpStatSN, conn->StatSN)) {          if (SN32_GT(ExpStatSN, conn->StatSN)) {
                 ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "StatSN(%u) advanced\n",                  ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "StatSN(%u) advanced\n",
                     ExpStatSN);                      ExpStatSN);
Line 3227  istgt_iscsi_op_scsi(CONN_Ptr conn, ISCSI_PDU_Ptr pdu) Line 3631  istgt_iscsi_op_scsi(CONN_Ptr conn, ISCSI_PDU_Ptr pdu)
         }          }
         {          {
                 uint32_t QCmdSN;                  uint32_t QCmdSN;
                SESS_MTX_LOCK(conn);                //SESS_MTX_LOCK(conn);
                 QCmdSN = conn->sess->MaxCmdSN - conn->sess->ExpCmdSN + 1;                  QCmdSN = conn->sess->MaxCmdSN - conn->sess->ExpCmdSN + 1;
                SESS_MTX_UNLOCK(conn);                //SESS_MTX_UNLOCK(conn);
                 QCmdSN += conn->queue_depth;                  QCmdSN += conn->queue_depth;
                 if (SN32_LT(ExpStatSN + QCmdSN, conn->StatSN)) {                  if (SN32_LT(ExpStatSN + QCmdSN, conn->StatSN)) {
                         ISTGT_ERRLOG("StatSN(%u/%u) QCmdSN(%u) error\n",                          ISTGT_ERRLOG("StatSN(%u/%u) QCmdSN(%u) error\n",
                             ExpStatSN, conn->StatSN, QCmdSN);                              ExpStatSN, conn->StatSN, QCmdSN);
                           SESS_MTX_UNLOCK(conn);
                         return -1;                          return -1;
                 }                  }
         }          }
           SESS_MTX_UNLOCK(conn);
   
         lu_cmd.pdu = pdu;          lu_cmd.pdu = pdu;
         SESS_MTX_LOCK(conn);          SESS_MTX_LOCK(conn);
Line 3336  istgt_iscsi_op_scsi(CONN_Ptr conn, ISCSI_PDU_Ptr pdu) Line 3742  istgt_iscsi_op_scsi(CONN_Ptr conn, ISCSI_PDU_Ptr pdu)
                 && lu_cmd.status == ISTGT_SCSI_STATUS_GOOD) {                  && lu_cmd.status == ISTGT_SCSI_STATUS_GOOD) {
                 if (data_len < transfer_len) {                  if (data_len < transfer_len) {
                         /* underflow */                          /* underflow */
                        ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "Underflow %u/%u\n",                        ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "Underflow %zu/%u\n",
                             data_len, transfer_len);                              data_len, transfer_len);
                         residual_len = transfer_len - data_len;                          residual_len = transfer_len - data_len;
                         U_bit = 1;                          U_bit = 1;
                 } else if (data_len > transfer_len) {                  } else if (data_len > transfer_len) {
                         /* overflow */                          /* overflow */
                        ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "Overflow %u/%u\n",                        ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "Overflow %zu/%u\n",
                             data_len, transfer_len);                              data_len, transfer_len);
                         residual_len = data_len - transfer_len;                          residual_len = data_len - transfer_len;
                         O_bit = 1;                          O_bit = 1;
Line 3371  istgt_iscsi_op_scsi(CONN_Ptr conn, ISCSI_PDU_Ptr pdu) Line 3777  istgt_iscsi_op_scsi(CONN_Ptr conn, ISCSI_PDU_Ptr pdu)
         DSET32(&rsp[16], task_tag);          DSET32(&rsp[16], task_tag);
         DSET32(&rsp[20], 0); // SNACK Tag          DSET32(&rsp[20], 0); // SNACK Tag
   
           SESS_MTX_LOCK(conn);
         DSET32(&rsp[24], conn->StatSN);          DSET32(&rsp[24], conn->StatSN);
         conn->StatSN++;          conn->StatSN++;
         SESS_MTX_LOCK(conn);  
         if (I_bit == 0) {          if (I_bit == 0) {
                 conn->sess->MaxCmdSN++;                  conn->sess->MaxCmdSN++;
         }          }
Line 3418  istgt_iscsi_task_response(CONN_Ptr conn, ISTGT_LU_TASK Line 3824  istgt_iscsi_task_response(CONN_Ptr conn, ISTGT_LU_TASK
         uint32_t task_tag;          uint32_t task_tag;
         uint32_t transfer_len;          uint32_t transfer_len;
         uint32_t CmdSN;          uint32_t CmdSN;
           size_t residual_len;
           size_t data_len;
         int I_bit;          int I_bit;
         int o_bit, u_bit, O_bit, U_bit;          int o_bit, u_bit, O_bit, U_bit;
         int bidi_residual_len;          int bidi_residual_len;
         int residual_len;  
         int data_len;  
         int rc;          int rc;
   
         lu_cmd = &lu_task->lu_cmd;          lu_cmd = &lu_task->lu_cmd;
Line 3460  istgt_iscsi_task_response(CONN_Ptr conn, ISTGT_LU_TASK Line 3866  istgt_iscsi_task_response(CONN_Ptr conn, ISTGT_LU_TASK
             && lu_cmd->status == ISTGT_SCSI_STATUS_GOOD) {              && lu_cmd->status == ISTGT_SCSI_STATUS_GOOD) {
                 if (data_len < transfer_len) {                  if (data_len < transfer_len) {
                         /* underflow */                          /* underflow */
                        ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "Underflow %u/%u\n",                        ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "Underflow %zu/%u\n",
                             data_len, transfer_len);                              data_len, transfer_len);
                         residual_len = transfer_len - data_len;                          residual_len = transfer_len - data_len;
                         U_bit = 1;                          U_bit = 1;
                 } else if (data_len > transfer_len) {                  } else if (data_len > transfer_len) {
                         /* overflow */                          /* overflow */
                        ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "Overflow %u/%u\n",                        ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "Overflow %zu/%u\n",
                             data_len, transfer_len);                              data_len, transfer_len);
                         residual_len = data_len - transfer_len;                          residual_len = data_len - transfer_len;
                         O_bit = 1;                          O_bit = 1;
Line 3495  istgt_iscsi_task_response(CONN_Ptr conn, ISTGT_LU_TASK Line 3901  istgt_iscsi_task_response(CONN_Ptr conn, ISTGT_LU_TASK
         DSET32(&rsp[16], task_tag);          DSET32(&rsp[16], task_tag);
         DSET32(&rsp[20], 0); // SNACK Tag          DSET32(&rsp[20], 0); // SNACK Tag
   
           SESS_MTX_LOCK(conn);
         DSET32(&rsp[24], conn->StatSN);          DSET32(&rsp[24], conn->StatSN);
         conn->StatSN++;          conn->StatSN++;
         SESS_MTX_LOCK(conn);  
         if (I_bit == 0) {          if (I_bit == 0) {
                 conn->sess->MaxCmdSN++;                  conn->sess->MaxCmdSN++;
         }          }
Line 3570  istgt_iscsi_op_task(CONN_Ptr conn, ISCSI_PDU_Ptr pdu) Line 3976  istgt_iscsi_op_task(CONN_Ptr conn, ISCSI_PDU_Ptr pdu)
                     conn->sess->ExpCmdSN);                      conn->sess->ExpCmdSN);
                 conn->sess->ExpCmdSN = CmdSN;                  conn->sess->ExpCmdSN = CmdSN;
         }          }
         SESS_MTX_UNLOCK(conn);  
         if (SN32_GT(ExpStatSN, conn->StatSN)) {          if (SN32_GT(ExpStatSN, conn->StatSN)) {
                 ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "StatSN(%u) advanced\n",                  ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "StatSN(%u) advanced\n",
                     ExpStatSN);                      ExpStatSN);
Line 3584  istgt_iscsi_op_task(CONN_Ptr conn, ISCSI_PDU_Ptr pdu) Line 3989  istgt_iscsi_op_task(CONN_Ptr conn, ISCSI_PDU_Ptr pdu)
                 conn->StatSN = ExpStatSN;                  conn->StatSN = ExpStatSN;
         }          }
 #endif  #endif
           SESS_MTX_UNLOCK(conn);
   
         response = 0; // Function complete.          response = 0; // Function complete.
         switch (function) {          switch (function) {
Line 3675  istgt_iscsi_op_task(CONN_Ptr conn, ISCSI_PDU_Ptr pdu) Line 4081  istgt_iscsi_op_task(CONN_Ptr conn, ISCSI_PDU_Ptr pdu)
   
         DSET32(&rsp[16], task_tag);          DSET32(&rsp[16], task_tag);
   
        DSET32(&rsp[24], conn->StatSN);        if (conn->use_sender == 0) {
        conn->StatSN++;                SESS_MTX_LOCK(conn);
        SESS_MTX_LOCK(conn);                DSET32(&rsp[24], conn->StatSN);
        if (I_bit == 0) {                conn->StatSN++;
                conn->sess->ExpCmdSN++;                if (I_bit == 0) {
                conn->sess->MaxCmdSN++;                        conn->sess->ExpCmdSN++;
                         conn->sess->MaxCmdSN++;
                 }
                 DSET32(&rsp[28], conn->sess->ExpCmdSN);
                 DSET32(&rsp[32], conn->sess->MaxCmdSN);
                 SESS_MTX_UNLOCK(conn);
         } else {
                 // update by sender
         }          }
         DSET32(&rsp[28], conn->sess->ExpCmdSN);  
         DSET32(&rsp[32], conn->sess->MaxCmdSN);  
         SESS_MTX_UNLOCK(conn);  
   
        rc = istgt_iscsi_write_pdu(conn, &rsp_pdu);        rc = istgt_iscsi_write_pdu_upd(conn, &rsp_pdu, I_bit);
         if (rc < 0) {          if (rc < 0) {
                 ISTGT_ERRLOG("iscsi_write_pdu() failed\n");                  ISTGT_ERRLOG("iscsi_write_pdu() failed\n");
                 return -1;                  return -1;
Line 3752  istgt_iscsi_op_nopout(CONN_Ptr conn, ISCSI_PDU_Ptr pdu Line 4162  istgt_iscsi_op_nopout(CONN_Ptr conn, ISCSI_PDU_Ptr pdu
                 }                  }
         } else if (CmdSN != conn->sess->ExpCmdSN) {          } else if (CmdSN != conn->sess->ExpCmdSN) {
                 SESS_MTX_UNLOCK(conn);                  SESS_MTX_UNLOCK(conn);
                ISTGT_ERRLOG("CmdSN(%u) error\n", CmdSN);                ISTGT_ERRLOG("CmdSN(%u) error ExpCmdSN=%u\n",
                     CmdSN, conn->sess->ExpCmdSN);
                 return -1;                  return -1;
         }          }
         SESS_MTX_UNLOCK(conn);  
         if (SN32_GT(ExpStatSN, conn->StatSN)) {          if (SN32_GT(ExpStatSN, conn->StatSN)) {
                 ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "StatSN(%u) advanced\n",                  ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "StatSN(%u) advanced\n",
                     ExpStatSN);                      ExpStatSN);
Line 3763  istgt_iscsi_op_nopout(CONN_Ptr conn, ISCSI_PDU_Ptr pdu Line 4173  istgt_iscsi_op_nopout(CONN_Ptr conn, ISCSI_PDU_Ptr pdu
         }          }
         {          {
                 uint32_t QCmdSN;                  uint32_t QCmdSN;
                SESS_MTX_LOCK(conn);                //SESS_MTX_LOCK(conn);
                 QCmdSN = conn->sess->MaxCmdSN - conn->sess->ExpCmdSN + 1;                  QCmdSN = conn->sess->MaxCmdSN - conn->sess->ExpCmdSN + 1;
                SESS_MTX_UNLOCK(conn);                //SESS_MTX_UNLOCK(conn);
                 QCmdSN += conn->queue_depth;                  QCmdSN += conn->queue_depth;
                 if (SN32_LT(ExpStatSN + QCmdSN, conn->StatSN)) {                  if (SN32_LT(ExpStatSN + QCmdSN, conn->StatSN)) {
                         ISTGT_ERRLOG("StatSN(%u/%u) QCmdSN(%u) error\n",                          ISTGT_ERRLOG("StatSN(%u/%u) QCmdSN(%u) error\n",
                             ExpStatSN, conn->StatSN, QCmdSN);                              ExpStatSN, conn->StatSN, QCmdSN);
                           SESS_MTX_UNLOCK(conn);
                         return -1;                          return -1;
                 }                  }
         }          }
           SESS_MTX_UNLOCK(conn);
   
         if (task_tag == 0xffffffffU) {          if (task_tag == 0xffffffffU) {
                 if (I_bit == 1) {                  if (I_bit == 1) {
Line 3812  istgt_iscsi_op_nopout(CONN_Ptr conn, ISCSI_PDU_Ptr pdu Line 4224  istgt_iscsi_op_nopout(CONN_Ptr conn, ISCSI_PDU_Ptr pdu
         DSET32(&rsp[16], task_tag);          DSET32(&rsp[16], task_tag);
         DSET32(&rsp[20], transfer_tag);          DSET32(&rsp[20], transfer_tag);
   
        DSET32(&rsp[24], conn->StatSN);        if (conn->use_sender == 0) {
        conn->StatSN++;                SESS_MTX_LOCK(conn);
        SESS_MTX_LOCK(conn);                DSET32(&rsp[24], conn->StatSN);
        if (I_bit == 0) {                conn->StatSN++;
                conn->sess->ExpCmdSN++;                if (I_bit == 0) {
                conn->sess->MaxCmdSN++;                        conn->sess->ExpCmdSN++;
                         conn->sess->MaxCmdSN++;
                 }
                 DSET32(&rsp[28], conn->sess->ExpCmdSN);
                 DSET32(&rsp[32], conn->sess->MaxCmdSN);
                 SESS_MTX_UNLOCK(conn);
         } else {
                 // update by sender
         }          }
         DSET32(&rsp[28], conn->sess->ExpCmdSN);  
         DSET32(&rsp[32], conn->sess->MaxCmdSN);  
         SESS_MTX_UNLOCK(conn);  
   
        rc = istgt_iscsi_write_pdu(conn, &rsp_pdu);        rc = istgt_iscsi_write_pdu_upd(conn, &rsp_pdu, I_bit);
         if (rc < 0) {          if (rc < 0) {
                 ISTGT_ERRLOG("iscsi_write_pdu() failed\n");                  ISTGT_ERRLOG("iscsi_write_pdu() failed\n");
                 return -1;                  return -1;
Line 3890  istgt_add_transfer_task(CONN_Ptr conn, ISTGT_LU_CMD_Pt Line 4306  istgt_add_transfer_task(CONN_Ptr conn, ISTGT_LU_CMD_Pt
         ISTGT_R2T_TASK_Ptr r2t_task;          ISTGT_R2T_TASK_Ptr r2t_task;
         uint32_t transfer_len;          uint32_t transfer_len;
         uint32_t transfer_tag;          uint32_t transfer_tag;
        int first_burst_len;        size_t first_burst_len;
        int max_burst_len;        size_t max_burst_len;
        int data_len;        size_t data_len;
        int offset = 0;        size_t offset = 0;
         int len;          int len;
         int idx;          int idx;
         int rc;          int rc;
Line 4049  istgt_iscsi_op_data(CONN_Ptr conn, ISCSI_PDU_Ptr pdu) Line 4465  istgt_iscsi_op_data(CONN_Ptr conn, ISCSI_PDU_Ptr pdu)
         uint32_t ExpDataSN;          uint32_t ExpDataSN;
         uint32_t DataSN;          uint32_t DataSN;
         uint32_t buffer_offset;          uint32_t buffer_offset;
           size_t data_len;
           size_t alloc_len;
           size_t offset;
         int F_bit;          int F_bit;
         int data_len;  
         int alloc_len;  
         int offset;  
         int rc;          int rc;
   
         if (!conn->full_feature) {          if (!conn->full_feature) {
Line 4103  istgt_iscsi_op_data(CONN_Ptr conn, ISCSI_PDU_Ptr pdu) Line 4519  istgt_iscsi_op_data(CONN_Ptr conn, ISCSI_PDU_Ptr pdu)
         ExpDataSN = r2t_task->DataSN;          ExpDataSN = r2t_task->DataSN;
   
         ISTGT_TRACELOG(ISTGT_TRACE_ISCSI,          ISTGT_TRACELOG(ISTGT_TRACE_ISCSI,
            "StatSN=%u, ExpStatSN=%u, DataSN=%u, Offset=%u, Data=%d\n",            "StatSN=%u, ExpStatSN=%u, DataSN=%u, Offset=%u, Data=%zd\n",
             conn->StatSN, ExpStatSN, DataSN, buffer_offset, data_len);              conn->StatSN, ExpStatSN, DataSN, buffer_offset, data_len);
         if (DataSN != ExpDataSN) {          if (DataSN != ExpDataSN) {
                 ISTGT_ERRLOG("DataSN(%u) error\n", DataSN);                  ISTGT_ERRLOG("DataSN(%u) error\n", DataSN);
Line 4158  istgt_iscsi_send_r2t(CONN_Ptr conn, ISTGT_LU_CMD_Ptr l Line 4574  istgt_iscsi_send_r2t(CONN_Ptr conn, ISTGT_LU_CMD_Ptr l
         DSET32(&rsp[16], lu_cmd->task_tag);          DSET32(&rsp[16], lu_cmd->task_tag);
         DSET32(&rsp[20], transfer_tag);          DSET32(&rsp[20], transfer_tag);
   
        DSET32(&rsp[24], conn->StatSN);        if (conn->use_sender == 0) {
        SESS_MTX_LOCK(conn);                SESS_MTX_LOCK(conn);
        DSET32(&rsp[28], conn->sess->ExpCmdSN);                DSET32(&rsp[24], conn->StatSN);
        DSET32(&rsp[32], conn->sess->MaxCmdSN);                DSET32(&rsp[28], conn->sess->ExpCmdSN);
        SESS_MTX_UNLOCK(conn);                DSET32(&rsp[32], conn->sess->MaxCmdSN);
                 SESS_MTX_UNLOCK(conn);
         } else {
                 // update by sender
         }
   
         DSET32(&rsp[36], *R2TSN);          DSET32(&rsp[36], *R2TSN);
         *R2TSN += 1;          *R2TSN += 1;
         DSET32(&rsp[40], (uint32_t) offset);          DSET32(&rsp[40], (uint32_t) offset);
         DSET32(&rsp[44], (uint32_t) len);          DSET32(&rsp[44], (uint32_t) len);
   
        rc = istgt_iscsi_write_pdu(conn, &rsp_pdu);        rc = istgt_iscsi_write_pdu_upd(conn, &rsp_pdu, 0);
         if (rc < 0) {          if (rc < 0) {
                 ISTGT_ERRLOG("iscsi_write_pdu() failed\n");                  ISTGT_ERRLOG("iscsi_write_pdu() failed\n");
                 return -1;                  return -1;
Line 4179  istgt_iscsi_send_r2t(CONN_Ptr conn, ISTGT_LU_CMD_Ptr l Line 4599  istgt_iscsi_send_r2t(CONN_Ptr conn, ISTGT_LU_CMD_Ptr l
 }  }
   
 int  int
istgt_iscsi_transfer_out(CONN_Ptr conn, ISTGT_LU_CMD_Ptr lu_cmd, uint8_t *data, int alloc_len, int transfer_len)istgt_iscsi_transfer_out(CONN_Ptr conn, ISTGT_LU_CMD_Ptr lu_cmd, uint8_t *data, size_t alloc_len, size_t transfer_len)
 {  {
         ISTGT_R2T_TASK_Ptr r2t_task;          ISTGT_R2T_TASK_Ptr r2t_task;
         ISCSI_PDU data_pdu;          ISCSI_PDU data_pdu;
Line 4195  istgt_iscsi_transfer_out(CONN_Ptr conn, ISTGT_LU_CMD_P Line 4615  istgt_iscsi_transfer_out(CONN_Ptr conn, ISTGT_LU_CMD_P
         uint32_t DataSN;          uint32_t DataSN;
         uint32_t buffer_offset;          uint32_t buffer_offset;
         uint32_t R2TSN;          uint32_t R2TSN;
           size_t data_len;
           size_t segment_len;
           size_t first_burst_len;
           size_t max_burst_len;
           size_t offset;
         int immediate, opcode;          int immediate, opcode;
         int F_bit;          int F_bit;
         int data_len;  
         int segment_len;  
         int first_burst_len;  
         int max_burst_len;  
         int offset;  
         int len;          int len;
         int r2t_flag;          int r2t_flag;
         int r2t_offset;          int r2t_offset;
Line 4230  istgt_iscsi_transfer_out(CONN_Ptr conn, ISTGT_LU_CMD_P Line 4650  istgt_iscsi_transfer_out(CONN_Ptr conn, ISTGT_LU_CMD_P
         }          }
   
         ISTGT_TRACELOG(ISTGT_TRACE_DEBUG,           ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, 
            "Transfer=%d, First=%d, Max=%d, Segment=%d\n",            "Transfer=%zd, First=%zd, Max=%zd, Segment=%zd\n",
             transfer_len, data_len, max_burst_len, segment_len);              transfer_len, data_len, max_burst_len, segment_len);
   
         r2t_task = istgt_get_transfer_task(conn, current_transfer_tag);          r2t_task = istgt_get_transfer_task(conn, current_transfer_tag);
Line 4250  istgt_iscsi_transfer_out(CONN_Ptr conn, ISTGT_LU_CMD_P Line 4670  istgt_iscsi_transfer_out(CONN_Ptr conn, ISTGT_LU_CMD_P
                 istgt_free_transfer_task(r2t_task);                  istgt_free_transfer_task(r2t_task);
   
                 ISTGT_TRACELOG(ISTGT_TRACE_DEBUG,                  ISTGT_TRACELOG(ISTGT_TRACE_DEBUG,
                    "Using R2T(%d) offset=%d, DataSN=%d\n",                    "Using R2T(%d) offset=%zd, DataSN=%d\n",
                     conn->pending_r2t, offset, ExpDataSN);                      conn->pending_r2t, offset, ExpDataSN);
   
                 rc = istgt_queue_count(&conn->pending_pdus);                  rc = istgt_queue_count(&conn->pending_pdus);
Line 4302  istgt_iscsi_transfer_out(CONN_Ptr conn, ISTGT_LU_CMD_P Line 4722  istgt_iscsi_transfer_out(CONN_Ptr conn, ISTGT_LU_CMD_P
                 data_pdu.copy_pdu = 0;                  data_pdu.copy_pdu = 0;
                 do {                  do {
                         ISTGT_TRACELOG(ISTGT_TRACE_DEBUG,                          ISTGT_TRACELOG(ISTGT_TRACE_DEBUG,
                            "Transfer=%d, Offset=%d, Len=%d\n",                            "Transfer=%zd, Offset=%zd, Len=%d\n",
                             transfer_len, offset, len);                              transfer_len, offset, len);
                         /* send R2T if required */                          /* send R2T if required */
                         if (r2t_flag == 0                          if (r2t_flag == 0
Line 4330  istgt_iscsi_transfer_out(CONN_Ptr conn, ISTGT_LU_CMD_P Line 4750  istgt_iscsi_transfer_out(CONN_Ptr conn, ISTGT_LU_CMD_P
                                 r2t_sent = 1;                                  r2t_sent = 1;
                                 ExpDataSN = 0;                                  ExpDataSN = 0;
                                 ISTGT_TRACELOG(ISTGT_TRACE_DEBUG,                                   ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, 
                                    "R2T, Transfer=%d, Offset=%d, Len=%d\n",                                    "R2T, Transfer=%zd, Offset=%zd, Len=%d\n",
                                     transfer_len, offset, len);                                      transfer_len, offset, len);
                         } else {                          } else {
                                 r2t_sent = 0;                                  r2t_sent = 0;
Line 4434  istgt_iscsi_transfer_out(CONN_Ptr conn, ISTGT_LU_CMD_P Line 4854  istgt_iscsi_transfer_out(CONN_Ptr conn, ISTGT_LU_CMD_P
   
                         ISTGT_TRACELOG(ISTGT_TRACE_ISCSI,                          ISTGT_TRACELOG(ISTGT_TRACE_ISCSI,
                             "StatSN=%u, "                              "StatSN=%u, "
                            "ExpStatSN=%u, DataSN=%u, Offset=%u, Data=%d\n",                            "ExpStatSN=%u, DataSN=%u, Offset=%u, Data=%zd\n",
                             conn->StatSN,                              conn->StatSN,
                             ExpStatSN, DataSN, buffer_offset, data_len);                              ExpStatSN, DataSN, buffer_offset, data_len);
                         if (DataSN != ExpDataSN) {                          if (DataSN != ExpDataSN) {
Line 4488  istgt_iscsi_transfer_out(CONN_Ptr conn, ISTGT_LU_CMD_P Line 4908  istgt_iscsi_transfer_out(CONN_Ptr conn, ISTGT_LU_CMD_P
                         ExpDataSN++;                          ExpDataSN++;
   
                         if (r2t_flag == 0 && (offset > first_burst_len)) {                          if (r2t_flag == 0 && (offset > first_burst_len)) {
                                ISTGT_ERRLOG("data_len(%d) > first_burst_length(%d)",                                ISTGT_ERRLOG("data_len(%zd) > first_burst_length(%zd)",
                                     offset, first_burst_len);                                      offset, first_burst_len);
                                 goto error_return;                                  goto error_return;
                         }                          }
Line 4534  istgt_iscsi_transfer_out(CONN_Ptr conn, ISTGT_LU_CMD_P Line 4954  istgt_iscsi_transfer_out(CONN_Ptr conn, ISTGT_LU_CMD_P
         }          }
   
 r2t_return:  r2t_return:
        ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "Transfered=%d, Offset=%d\n",        ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "Transfered=%zd, Offset=%zd\n",
             transfer_len, offset);              transfer_len, offset);
   
         return 0;          return 0;
Line 4586  istgt_iscsi_send_nopin(CONN_Ptr conn) Line 5006  istgt_iscsi_send_nopin(CONN_Ptr conn)
         DSET32(&rsp[16], task_tag);          DSET32(&rsp[16], task_tag);
         DSET32(&rsp[20], transfer_tag);          DSET32(&rsp[20], transfer_tag);
   
        DSET32(&rsp[24], conn->StatSN);        if (conn->use_sender == 0) {
        SESS_MTX_LOCK(conn);                SESS_MTX_LOCK(conn);
        DSET32(&rsp[28], conn->sess->ExpCmdSN);                DSET32(&rsp[24], conn->StatSN);
        DSET32(&rsp[32], conn->sess->MaxCmdSN);                DSET32(&rsp[28], conn->sess->ExpCmdSN);
        SESS_MTX_UNLOCK(conn);                DSET32(&rsp[32], conn->sess->MaxCmdSN);
                 SESS_MTX_UNLOCK(conn);
         } else {
                 // update by sender
         }
   
        rc = istgt_iscsi_write_pdu(conn, &rsp_pdu);        rc = istgt_iscsi_write_pdu_upd(conn, &rsp_pdu, 0);
         if (rc < 0) {          if (rc < 0) {
                 ISTGT_ERRLOG("iscsi_write_pdu() failed\n");                  ISTGT_ERRLOG("iscsi_write_pdu() failed\n");
                 return -1;                  return -1;
Line 4711  wait_all_task(CONN_Ptr conn) Line 5135  wait_all_task(CONN_Ptr conn)
                 ISTGT_ERRLOG("kqueue() failed\n");                  ISTGT_ERRLOG("kqueue() failed\n");
                 return;                  return;
         }          }
        EV_SET(&kev, conn->task_pipe[0], EVFILT_READ, EV_ADD, 0, 0, NULL);        ISTGT_EV_SET(&kev, conn->task_pipe[0], EVFILT_READ, EV_ADD, 0, 0, NULL);
         rc = kevent(kq, &kev, 1, NULL, 0, NULL);          rc = kevent(kq, &kev, 1, NULL, 0, NULL);
         if (rc == -1) {          if (rc == -1) {
                 ISTGT_ERRLOG("kevent() failed\n");                  ISTGT_ERRLOG("kevent() failed\n");
Line 4761  wait_all_task(CONN_Ptr conn) Line 5185  wait_all_task(CONN_Ptr conn)
 #endif /* ISTGT_USE_KQUEUE */  #endif /* ISTGT_USE_KQUEUE */
   
 #ifdef ISTGT_USE_KQUEUE  #ifdef ISTGT_USE_KQUEUE
                if (kev.ident == conn->task_pipe[0]) {                if (kev.ident == (uintptr_t)conn->task_pipe[0]) {
                         if (kev.flags & (EV_EOF|EV_ERROR)) {                          if (kev.flags & (EV_EOF|EV_ERROR)) {
                                 break;                                  break;
                         }                          }
Line 4963  sender(void *arg) Line 5387  sender(void *arg)
                                 if (rc < 0) {                                  if (rc < 0) {
                                         lu_task->error = 1;                                          lu_task->error = 1;
                                         ISTGT_ERRLOG(                                          ISTGT_ERRLOG(
                                                "iscsi_task_response() failed on %s(%s)\n",                                                "iscsi_task_response() CmdSN=%u failed"
                                                 " on %s(%s)\n", lu_task->lu_cmd.CmdSN,
                                                 conn->target_port, conn->initiator_port);                                                  conn->target_port, conn->initiator_port);
                                           rc = write(conn->task_pipe[1], "E", 1);
                                           if(rc < 0 || rc != 1) {
                                                   ISTGT_ERRLOG("write() failed\n");
                                           }
                                         break;                                          break;
                                 }                                  }
                                 rc = istgt_lu_destroy_task(lu_task);                                  rc = istgt_lu_destroy_task(lu_task);
Line 4973  sender(void *arg) Line 5402  sender(void *arg)
                                         break;                                          break;
                                 }                                  }
                         } else if (lu_task->type == ISTGT_LU_TASK_REQPDU) {                          } else if (lu_task->type == ISTGT_LU_TASK_REQPDU) {
                           reqpdu:
                                 /* send PDU */                                  /* send PDU */
                                 rc = istgt_iscsi_write_pdu_internal(lu_task->conn,                                  rc = istgt_iscsi_write_pdu_internal(lu_task->conn,
                                     lu_task->lu_cmd.pdu);                                      lu_task->lu_cmd.pdu);
Line 4982  sender(void *arg) Line 5412  sender(void *arg)
                                                 "iscsi_write_pdu() failed on %s(%s)\n",                                                  "iscsi_write_pdu() failed on %s(%s)\n",
                                                 lu_task->conn->target_port,                                                  lu_task->conn->target_port,
                                                 lu_task->conn->initiator_port);                                                  lu_task->conn->initiator_port);
                                           rc = write(conn->task_pipe[1], "E", 1);
                                           if(rc < 0 || rc != 1) {
                                                   ISTGT_ERRLOG("write() failed\n");
                                           }
                                         break;                                          break;
                                 }                                  }
                                 /* free allocated memory by caller */                                  /* free allocated memory by caller */
                                 xfree(lu_task);                                  xfree(lu_task);
                           } else if (lu_task->type == ISTGT_LU_TASK_REQUPDPDU) {
                                   rc = istgt_update_pdu(lu_task->conn, &lu_task->lu_cmd);
                                   if (rc < 0) {
                                           lu_task->error = 1;
                                           ISTGT_ERRLOG(
                                                   "update_pdu() failed on %s(%s)\n",
                                                   lu_task->conn->target_port,
                                                   lu_task->conn->initiator_port);
                                           rc = write(conn->task_pipe[1], "E", 1);
                                           if(rc < 0 || rc != 1) {
                                                   ISTGT_ERRLOG("write() failed\n");
                                           }
                                           break;
                                   }
                                   goto reqpdu;
                         } else {                          } else {
                                 ISTGT_ERRLOG("Unknown task type %x\n", lu_task->type);                                  ISTGT_ERRLOG("Unknown task type %x\n", lu_task->type);
                                 rc = -1;                                  rc = -1;
Line 5035  worker(void *arg) Line 5484  worker(void *arg)
                 return NULL;                  return NULL;
         }          }
         conn->kq = kq;          conn->kq = kq;
        EV_SET(&kev, conn->sock, EVFILT_READ, EV_ADD, 0, 0, NULL);#if defined (ISTGT_USE_IOVEC) && defined (NOTE_LOWAT)
         ISTGT_EV_SET(&kev, conn->sock, EVFILT_READ, EV_ADD, NOTE_LOWAT, ISCSI_BHS_LEN, NULL);
 #else
         ISTGT_EV_SET(&kev, conn->sock, EVFILT_READ, EV_ADD, 0, 0, NULL);
 #endif
         rc = kevent(kq, &kev, 1, NULL, 0, NULL);          rc = kevent(kq, &kev, 1, NULL, 0, NULL);
         if (rc == -1) {          if (rc == -1) {
                 ISTGT_ERRLOG("kevent() failed\n");                  ISTGT_ERRLOG("kevent() failed\n");
                 close(kq);                  close(kq);
                 return NULL;                  return NULL;
         }          }
        EV_SET(&kev, conn->task_pipe[0], EVFILT_READ, EV_ADD, 0, 0, NULL);        ISTGT_EV_SET(&kev, conn->task_pipe[0], EVFILT_READ, EV_ADD, 0, 0, NULL);
         rc = kevent(kq, &kev, 1, NULL, 0, NULL);          rc = kevent(kq, &kev, 1, NULL, 0, NULL);
         if (rc == -1) {          if (rc == -1) {
                 ISTGT_ERRLOG("kevent() failed\n");                  ISTGT_ERRLOG("kevent() failed\n");
Line 5050  worker(void *arg) Line 5503  worker(void *arg)
                 return NULL;                  return NULL;
         }          }
   
        EV_SET(&kev, SIGINT, EVFILT_SIGNAL, EV_ADD, 0, 0, NULL);        if (!conn->istgt->daemon) {
        rc = kevent(kq, &kev, 1, NULL, 0, NULL);                ISTGT_EV_SET(&kev, SIGINT, EVFILT_SIGNAL, EV_ADD, 0, 0, NULL);
        if (rc == -1) {                rc = kevent(kq, &kev, 1, NULL, 0, NULL);
                ISTGT_ERRLOG("kevent() failed\n");                if (rc == -1) {
                close(kq);                        ISTGT_ERRLOG("kevent() failed\n");
                return NULL;                        close(kq);
                         return NULL;
                 }
                 ISTGT_EV_SET(&kev, SIGTERM, EVFILT_SIGNAL, EV_ADD, 0, 0, NULL);
                 rc = kevent(kq, &kev, 1, NULL, 0, NULL);
                 if (rc == -1) {
                         ISTGT_ERRLOG("kevent() failed\n");
                         close(kq);
                         return NULL;
                 }
         }          }
         EV_SET(&kev, SIGTERM, EVFILT_SIGNAL, EV_ADD, 0, 0, NULL);  
         rc = kevent(kq, &kev, 1, NULL, 0, NULL);  
         if (rc == -1) {  
                 ISTGT_ERRLOG("kevent() failed\n");  
                 close(kq);  
                 return NULL;  
         }  
 #else  #else
         memset(&fds, 0, sizeof fds);          memset(&fds, 0, sizeof fds);
         fds[0].fd = conn->sock;          fds[0].fd = conn->sock;
         fds[0].events = POLLIN;          fds[0].events = POLLIN;
         fds[1].fd = conn->task_pipe[0];          fds[1].fd = conn->task_pipe[0];
         fds[1].events = POLLIN;          fds[1].events = POLLIN;
   
         nopin_timer = conn->nopininterval;  
 #endif /* ISTGT_USE_KQUEUE */  #endif /* ISTGT_USE_KQUEUE */
   
         conn->pdu.ahs = NULL;          conn->pdu.ahs = NULL;
Line 5108  worker(void *arg) Line 5561  worker(void *arg)
         pthread_sigmask(SIG_UNBLOCK, &signew, &sigold);          pthread_sigmask(SIG_UNBLOCK, &signew, &sigold);
   
         ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "loop start (%d)\n", conn->id);          ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "loop start (%d)\n", conn->id);
   #ifndef ISTGT_USE_KQUEUE
           nopin_timer = conn->nopininterval;
   #endif /* !ISTGT_USE_KQUEUE */
         while (1) {          while (1) {
                 /* check exit request */                  /* check exit request */
                 if (conn->sess != NULL) {                  if (conn->sess != NULL) {
Line 5187  worker(void *arg) Line 5643  worker(void *arg)
                 }                  }
                 if (rc == 0) {                  if (rc == 0) {
                         /* no fds */                          /* no fds */
                           //ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "poll TIMEOUT\n");
                         if (nopin_timer > 0) {                          if (nopin_timer > 0) {
                                 nopin_timer -= POLLWAIT;                                  nopin_timer -= POLLWAIT;
                                 if (nopin_timer <= 0) {                                  if (nopin_timer <= 0) {
Line 5205  worker(void *arg) Line 5662  worker(void *arg)
   
                 /* on socket */                  /* on socket */
 #ifdef ISTGT_USE_KQUEUE  #ifdef ISTGT_USE_KQUEUE
                if (kev.ident == conn->sock) {                if (kev.ident == (uintptr_t)conn->sock) {
                         if (kev.flags & (EV_EOF|EV_ERROR)) {                          if (kev.flags & (EV_EOF|EV_ERROR)) {
                                 ISTGT_TRACELOG(ISTGT_TRACE_DEBUG,                                  ISTGT_TRACELOG(ISTGT_TRACE_DEBUG,
                                     "kevent EOF/ERROR\n");                                      "kevent EOF/ERROR\n");
Line 5220  worker(void *arg) Line 5677  worker(void *arg)
                         conn->pdu.copy_pdu = 0;                          conn->pdu.copy_pdu = 0;
                         rc = istgt_iscsi_read_pdu(conn, &conn->pdu);                          rc = istgt_iscsi_read_pdu(conn, &conn->pdu);
                         if (rc < 0) {                          if (rc < 0) {
                                ISTGT_ERRLOG("conn->state = %d\n", conn->state);                                if (conn->state != CONN_STATE_EXITING) {
                                         ISTGT_ERRLOG("conn->state = %d\n", conn->state);
                                 }
                                 if (conn->state != CONN_STATE_RUNNING) {                                  if (conn->state != CONN_STATE_RUNNING) {
                                         if (errno == EINPROGRESS) {                                          if (errno == EINPROGRESS) {
                                                 sleep(1);                                                  sleep(1);
Line 5317  worker(void *arg) Line 5776  worker(void *arg)
   
                 /* execute on task queue */                  /* execute on task queue */
 #ifdef ISTGT_USE_KQUEUE  #ifdef ISTGT_USE_KQUEUE
                if (kev.ident == conn->task_pipe[0]) {                if (kev.ident == (uintptr_t)conn->task_pipe[0]) {
                         if (kev.flags & (EV_EOF|EV_ERROR)) {                          if (kev.flags & (EV_EOF|EV_ERROR)) {
                                 ISTGT_TRACELOG(ISTGT_TRACE_DEBUG,                                  ISTGT_TRACELOG(ISTGT_TRACE_DEBUG,
                                     "kevent EOF/ERROR\n");                                      "kevent EOF/ERROR\n");
Line 5338  worker(void *arg) Line 5797  worker(void *arg)
                                 ISTGT_ERRLOG("read() failed\n");                                  ISTGT_ERRLOG("read() failed\n");
                                 break;                                  break;
                         }                          }
                           if (tmp[0] == 'E') {
                                   ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "exit request (%d)\n",
                                       conn->id);
                                   break;
                           }
   
                         /* DATA-IN/OUT */                          /* DATA-IN/OUT */
                         MTX_LOCK(&conn->task_queue_mutex);                          MTX_LOCK(&conn->task_queue_mutex);
Line 5378  worker(void *arg) Line 5842  worker(void *arg)
                                                 lu_task = NULL;                                                  lu_task = NULL;
                                                 conn->exec_lu_task = NULL;                                                  conn->exec_lu_task = NULL;
                                         } else {                                          } else {
                                                 MTX_LOCK(&lu_task->trans_mutex);  
                                                 //ISTGT_TRACELOG(ISTGT_TRACE_DEBUG,                                                  //ISTGT_TRACELOG(ISTGT_TRACE_DEBUG,
                                                 //    "Task Write Trans START\n");                                                  //    "Task Write Trans START\n");
                                                 rc = istgt_iscsi_task_transfer_out(conn, lu_task);                                                  rc = istgt_iscsi_task_transfer_out(conn, lu_task);
                                                 if (rc < 0) {                                                  if (rc < 0) {
                                                         lu_task->error = 1;                                                          lu_task->error = 1;
                                                         MTX_UNLOCK(&lu_task->trans_mutex);  
                                                         ISTGT_ERRLOG("iscsi_task_transfer_out() failed on %s(%s)\n",                                                          ISTGT_ERRLOG("iscsi_task_transfer_out() failed on %s(%s)\n",
                                                             conn->target_port,                                                              conn->target_port,
                                                             conn->initiator_port);                                                              conn->initiator_port);
Line 5393  worker(void *arg) Line 5855  worker(void *arg)
                                                 //ISTGT_TRACELOG(ISTGT_TRACE_DEBUG,                                                  //ISTGT_TRACELOG(ISTGT_TRACE_DEBUG,
                                                 //    "Task Write Trans END\n");                                                  //    "Task Write Trans END\n");
   
                                                   MTX_LOCK(&lu_task->trans_mutex);
                                                 lu_task->req_transfer_out = 0;                                                  lu_task->req_transfer_out = 0;
   
                                                 /* need response after execution */                                                  /* need response after execution */
Line 5400  worker(void *arg) Line 5863  worker(void *arg)
                                                 if (conn->use_sender == 0) {                                                  if (conn->use_sender == 0) {
                                                         conn->running_tasks++;                                                          conn->running_tasks++;
                                                 }                                                  }
                                                 MTX_UNLOCK(&lu_task->trans_mutex);  
   
                                                 rc = pthread_cond_broadcast(&lu_task->trans_cond);                                                  rc = pthread_cond_broadcast(&lu_task->trans_cond);
                                                   MTX_UNLOCK(&lu_task->trans_mutex);
                                                 if (rc != 0) {                                                  if (rc != 0) {
                                                         //MTX_UNLOCK(&lu_task->trans_mutex);  
                                                         ISTGT_ERRLOG("cond_broadcast() failed\n");                                                          ISTGT_ERRLOG("cond_broadcast() failed\n");
                                                         break;                                                          break;
                                                 }                                                  }
Line 5476  worker(void *arg) Line 5938  worker(void *arg)
         wait_all_task(conn);          wait_all_task(conn);
   
         if (conn->use_sender) {          if (conn->use_sender) {
                   ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "stop sender thread (%d)\n", conn->id);
                 /* stop sender thread */                  /* stop sender thread */
                   MTX_LOCK(&conn->result_queue_mutex);
                 rc = pthread_cond_broadcast(&conn->result_queue_cond);                  rc = pthread_cond_broadcast(&conn->result_queue_cond);
                   MTX_UNLOCK(&conn->result_queue_mutex);
                 if (rc != 0) {                  if (rc != 0) {
                         ISTGT_ERRLOG("cond_broadcast() failed\n");                          ISTGT_ERRLOG("cond_broadcast() failed\n");
                         /* ignore errors */                          /* ignore errors */
Line 5509  worker(void *arg) Line 5974  worker(void *arg)
 }  }
   
 int  int
istgt_create_conn(ISTGT_Ptr istgt, PORTAL_Ptr portal, int sock, struct sockaddr *sa, socklen_t salen)istgt_create_conn(ISTGT_Ptr istgt, PORTAL_Ptr portal, int sock, struct sockaddr *sa, socklen_t salen __attribute__((__unused__)))
 {  {
         char buf[MAX_TMPBUF];          char buf[MAX_TMPBUF];
         CONN_Ptr conn;          CONN_Ptr conn;
Line 5651  istgt_create_conn(ISTGT_Ptr istgt, PORTAL_Ptr portal,  Line 6116  istgt_create_conn(ISTGT_Ptr istgt, PORTAL_Ptr portal, 
                 ISTGT_ERRLOG("istgt_set_sendtimeo() failed\n");                  ISTGT_ERRLOG("istgt_set_sendtimeo() failed\n");
                 goto error_return;                  goto error_return;
         }          }
   #if defined (ISTGT_USE_IOVEC)
           /* set low water mark */
           rc = istgt_set_recvlowat(conn->sock, ISCSI_BHS_LEN);
           if (rc != 0) {
                   ISTGT_ERRLOG("istgt_set_recvlowat() failed\n");
                   goto error_return;
           }
   #endif
   
         rc = pipe(conn->task_pipe);          rc = pipe(conn->task_pipe);
         if (rc != 0) {          if (rc != 0) {
Line 5659  istgt_create_conn(ISTGT_Ptr istgt, PORTAL_Ptr portal,  Line 6132  istgt_create_conn(ISTGT_Ptr istgt, PORTAL_Ptr portal, 
                 conn->task_pipe[1] = -1;                  conn->task_pipe[1] = -1;
                 goto error_return;                  goto error_return;
         }          }
        rc = pthread_mutex_init(&conn->task_queue_mutex, NULL);        rc = pthread_mutex_init(&conn->task_queue_mutex, &istgt->mutex_attr);
         if (rc != 0) {          if (rc != 0) {
                 ISTGT_ERRLOG("mutex_init() failed\n");                  ISTGT_ERRLOG("mutex_init() failed\n");
                 goto error_return;                  goto error_return;
         }          }
        rc = pthread_mutex_init(&conn->result_queue_mutex, NULL);        rc = pthread_mutex_init(&conn->result_queue_mutex, &istgt->mutex_attr);
         if (rc != 0) {          if (rc != 0) {
                 ISTGT_ERRLOG("mutex_init() failed\n");                  ISTGT_ERRLOG("mutex_init() failed\n");
                 goto error_return;                  goto error_return;
Line 5684  istgt_create_conn(ISTGT_Ptr istgt, PORTAL_Ptr portal,  Line 6157  istgt_create_conn(ISTGT_Ptr istgt, PORTAL_Ptr portal, 
                 ISTGT_ERRLOG("cond_init() failed\n");                  ISTGT_ERRLOG("cond_init() failed\n");
                 goto error_return;                  goto error_return;
         }          }
        rc = pthread_mutex_init(&conn->r2t_mutex, NULL);        rc = pthread_mutex_init(&conn->r2t_mutex, &istgt->mutex_attr);
         if (rc != 0) {          if (rc != 0) {
                 ISTGT_ERRLOG("mutex_init() failed\n");                  ISTGT_ERRLOG("mutex_init() failed\n");
                 goto error_return;                  goto error_return;
Line 5761  istgt_create_conn(ISTGT_Ptr istgt, PORTAL_Ptr portal,  Line 6234  istgt_create_conn(ISTGT_Ptr istgt, PORTAL_Ptr portal, 
                 istgt_iscsi_param_free(conn->params);                  istgt_iscsi_param_free(conn->params);
                 istgt_queue_destroy(&conn->pending_pdus);                  istgt_queue_destroy(&conn->pending_pdus);
                 istgt_queue_destroy(&conn->task_queue);                  istgt_queue_destroy(&conn->task_queue);
                   istgt_queue_destroy(&conn->result_queue);
                 xfree(conn->portal.label);                  xfree(conn->portal.label);
                 xfree(conn->portal.host);                  xfree(conn->portal.host);
                 xfree(conn->portal.port);                  xfree(conn->portal.port);
Line 6388  istgt_get_active_conns(void) Line 6862  istgt_get_active_conns(void)
         return num;          return num;
 }  }
   
   int
   istgt_stop_conns(void)
   {
           CONN_Ptr conn;
           char tmp[1];
           int rc;
           int i;
   
           ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "istgt_stop_conns\n");
           tmp[0] = 'E';
           MTX_LOCK(&g_conns_mutex);
           for (i = 0; i < g_nconns; i++) {
                   conn = g_conns[i];
                   if (conn == NULL)
                           continue;
                   rc = write(conn->task_pipe[1], tmp, 1);
                   if(rc < 0 || rc != 1) {
                           ISTGT_ERRLOG("write() failed\n");
                           /* ignore error */
                   }
           }
           MTX_UNLOCK(&g_conns_mutex);
           return 0;
   }
   
 CONN_Ptr  CONN_Ptr
 istgt_find_conn(const char *initiator_port, const char *target_name, uint16_t tsih)  istgt_find_conn(const char *initiator_port, const char *target_name, uint16_t tsih)
 {  {
Line 6463  istgt_iscsi_init(ISTGT_Ptr istgt) Line 6962  istgt_iscsi_init(ISTGT_Ptr istgt)
 }  }
   
 int  int
istgt_iscsi_shutdown(ISTGT_Ptr istgt)istgt_iscsi_shutdown(ISTGT_Ptr istgt __attribute__((__unused__)))
 {  {
         CONN_Ptr conn;          CONN_Ptr conn;
         int retry = 10;          int retry = 10;
Line 6515  istgt_iscsi_shutdown(ISTGT_Ptr istgt) Line 7014  istgt_iscsi_shutdown(ISTGT_Ptr istgt)
         if (rc != 0) {          if (rc != 0) {
                 ISTGT_ERRLOG("mutex_destroy() failed\n");                  ISTGT_ERRLOG("mutex_destroy() failed\n");
                 return -1;                  return -1;
           }
   
           if (num == 0) {
                   xfree(g_conns);
                   g_conns = NULL;
         }          }
   
         return 0;          return 0;

Removed from v.1.1.1.1  
changed lines
  Added in v.1.1.1.3


FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>