Diff for /embedaddon/istgt/src/istgt_lu_disk.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 59 Line 59
 #include "istgt_scsi.h"  #include "istgt_scsi.h"
 #include "istgt_queue.h"  #include "istgt_queue.h"
   
   #if !defined(__GNUC__)
   #undef __attribute__
   #define __attribute__(x)
   #endif
   
 #ifndef O_FSYNC  #ifndef O_FSYNC
 #define O_FSYNC O_SYNC  #define O_FSYNC O_SYNC
 #endif  #endif
Line 83  typedef enum { Line 88  typedef enum {
 #define PR_ALLOW_WERR  0x0002  #define PR_ALLOW_WERR  0x0002
 #define PR_ALLOW_EARR  0x0001  #define PR_ALLOW_EARR  0x0001
   
 typedef struct istgt_lu_pr_key_t {  
         uint64_t key;  
   
         /* transport IDs */  
         char *registered_initiator_port;  
         char *registered_target_port;  
         /* PERSISTENT RESERVE OUT received from */  
         int pg_idx; /* relative target port */  
         int pg_tag; /* target port group */  
   
         int ninitiator_ports;  
         char **initiator_ports;  
         int all_tpg;  
 } ISTGT_LU_PR_KEY;  
   
 typedef struct istgt_lu_disk_t {  
         ISTGT_LU_Ptr lu;  
         int num;  
         int lun;  
   
         int fd;  
         const char *file;  
         uint64_t fsize;  
         uint64_t foffset;  
         uint64_t size;  
         uint64_t blocklen;  
         uint64_t blockcnt;  
   
 #ifdef HAVE_UUID_H  
         uuid_t uuid;  
 #endif /* HAVE_UUID_H */  
   
         /* cache flags */  
         int read_cache;  
         int write_cache;  
         /* parts for cache */  
         int wbufsize;  
         uint8_t *wbuf;  
         uint64_t woffset;  
         uint64_t wnbytes;  
         int req_write_cache;  
         int err_write_cache;  
   
         /* thin provisioning */  
         int thin_provisioning;  
   
         /* for ats */  
         pthread_mutex_t ats_mutex;  
   
         int queue_depth;  
         pthread_mutex_t cmd_queue_mutex;  
         ISTGT_QUEUE cmd_queue;  
         pthread_mutex_t wait_lu_task_mutex;  
         ISTGT_LU_TASK_Ptr wait_lu_task;  
   
         /* PERSISTENT RESERVE */  
         int npr_keys;  
         ISTGT_LU_PR_KEY pr_keys[MAX_LU_RESERVE];  
         uint32_t pr_generation;  
   
         char *rsv_port;  
         uint64_t rsv_key;  
         int rsv_scope;  
         int rsv_type;  
   
         /* SCSI sense code */  
         volatile int sense;  
 } ISTGT_LU_DISK;  
   
 #define BUILD_SENSE(SK,ASC,ASCQ)                                        \  #define BUILD_SENSE(SK,ASC,ASCQ)                                        \
         do {                                                            \          do {                                                            \
                 *sense_len =                                            \                  *sense_len =                                            \
Line 172  static int istgt_lu_disk_build_sense_data(ISTGT_LU_DIS Line 108  static int istgt_lu_disk_build_sense_data(ISTGT_LU_DIS
 static int istgt_lu_disk_queue_abort_ITL(ISTGT_LU_DISK *spec, const char *initiator_port);  static int istgt_lu_disk_queue_abort_ITL(ISTGT_LU_DISK *spec, const char *initiator_port);
   
 static int  static int
istgt_lu_disk_open(ISTGT_LU_DISK *spec, int flags, int mode)istgt_lu_disk_open_raw(ISTGT_LU_DISK *spec, int flags, int mode)
 {  {
         int rc;          int rc;
   
Line 186  istgt_lu_disk_open(ISTGT_LU_DISK *spec, int flags, int Line 122  istgt_lu_disk_open(ISTGT_LU_DISK *spec, int flags, int
 }  }
   
 static int  static int
istgt_lu_disk_close(ISTGT_LU_DISK *spec)istgt_lu_disk_close_raw(ISTGT_LU_DISK *spec)
 {  {
         int rc;          int rc;
   
Line 203  istgt_lu_disk_close(ISTGT_LU_DISK *spec) Line 139  istgt_lu_disk_close(ISTGT_LU_DISK *spec)
   
 #if 0  #if 0
 static off_t  static off_t
istgt_lu_disk_lseek(ISTGT_LU_DISK *spec, off_t offset, int whence)istgt_lu_disk_lseek_raw(ISTGT_LU_DISK *spec, off_t offset, int whence)
 {  {
         off_t rc;          off_t rc;
   
Line 217  istgt_lu_disk_lseek(ISTGT_LU_DISK *spec, off_t offset, Line 153  istgt_lu_disk_lseek(ISTGT_LU_DISK *spec, off_t offset,
 #endif  #endif
   
 static int64_t  static int64_t
istgt_lu_disk_seek(ISTGT_LU_DISK *spec, uint64_t offset)istgt_lu_disk_seek_raw(ISTGT_LU_DISK *spec, uint64_t offset)
 {  {
         off_t rc;          off_t rc;
   
Line 230  istgt_lu_disk_seek(ISTGT_LU_DISK *spec, uint64_t offse Line 166  istgt_lu_disk_seek(ISTGT_LU_DISK *spec, uint64_t offse
 }  }
   
 static int64_t  static int64_t
istgt_lu_disk_read(ISTGT_LU_DISK *spec, void *buf, uint64_t nbytes)istgt_lu_disk_read_raw(ISTGT_LU_DISK *spec, void *buf, uint64_t nbytes)
 {  {
         int64_t rc;          int64_t rc;
   
Line 256  istgt_lu_disk_read(ISTGT_LU_DISK *spec, void *buf, uin Line 192  istgt_lu_disk_read(ISTGT_LU_DISK *spec, void *buf, uin
                         if (rc < 0) {                          if (rc < 0) {
                                 return -1;                                  return -1;
                         }                          }
                        if (rc != request) {                        if ((uint64_t) rc != request) {
                                 /* read size < request */                                  /* read size < request */
                                 if (spec->foffset + rc >= spec->size) {                                  if (spec->foffset + rc >= spec->size) {
                                         rc = spec->size - spec->foffset;                                          rc = spec->size - spec->foffset;
Line 286  istgt_lu_disk_read(ISTGT_LU_DISK *spec, void *buf, uin Line 222  istgt_lu_disk_read(ISTGT_LU_DISK *spec, void *buf, uin
 }  }
   
 static int64_t  static int64_t
istgt_lu_disk_write(ISTGT_LU_DISK *spec, const void *buf, uint64_t nbytes)istgt_lu_disk_write_raw(ISTGT_LU_DISK *spec, const void *buf, uint64_t nbytes)
 {  {
         int64_t rc;          int64_t rc;
   
Line 345  istgt_lu_disk_write(ISTGT_LU_DISK *spec, const void *b Line 281  istgt_lu_disk_write(ISTGT_LU_DISK *spec, const void *b
 }  }
   
 static int64_t  static int64_t
istgt_lu_disk_sync(ISTGT_LU_DISK *spec, uint64_t offset, uint64_t nbytes)istgt_lu_disk_sync_raw(ISTGT_LU_DISK *spec, uint64_t offset, uint64_t nbytes)
 {  {
         int64_t rc;          int64_t rc;
   
Line 358  istgt_lu_disk_sync(ISTGT_LU_DISK *spec, uint64_t offse Line 294  istgt_lu_disk_sync(ISTGT_LU_DISK *spec, uint64_t offse
 }  }
   
 static int  static int
istgt_lu_disk_allocate(ISTGT_LU_DISK *spec)istgt_lu_disk_allocate_raw(ISTGT_LU_DISK *spec)
 {  {
         uint8_t *data;          uint8_t *data;
         uint64_t fsize;          uint64_t fsize;
Line 382  istgt_lu_disk_allocate(ISTGT_LU_DISK *spec) Line 318  istgt_lu_disk_allocate(ISTGT_LU_DISK *spec)
         spec->fsize = fsize;          spec->fsize = fsize;
   
         offset = size - nbytes;          offset = size - nbytes;
        rc = istgt_lu_disk_seek(spec, offset);        rc = istgt_lu_disk_seek_raw(spec, offset);
         if (rc == -1) {          if (rc == -1) {
                 ISTGT_ERRLOG("lu_disk_seek() failed\n");                  ISTGT_ERRLOG("lu_disk_seek() failed\n");
                 xfree(data);                  xfree(data);
                 return -1;                  return -1;
         }          }
        rc = istgt_lu_disk_read(spec, data, nbytes);        rc = istgt_lu_disk_read_raw(spec, data, nbytes);
         /* EOF is OK */          /* EOF is OK */
         if (rc == -1) {          if (rc == -1) {
                 ISTGT_ERRLOG("lu_disk_read() failed\n");                  ISTGT_ERRLOG("lu_disk_read() failed\n");
Line 403  istgt_lu_disk_allocate(ISTGT_LU_DISK *spec) Line 339  istgt_lu_disk_allocate(ISTGT_LU_DISK *spec)
                                 fsize = size;                                  fsize = size;
                         }                          }
                         offset = fsize - nbytes;                          offset = fsize - nbytes;
                        rc = istgt_lu_disk_seek(spec, offset);                        rc = istgt_lu_disk_seek_raw(spec, offset);
                         if (rc == -1) {                          if (rc == -1) {
                                 ISTGT_ERRLOG("lu_disk_seek() failed\n");                                  ISTGT_ERRLOG("lu_disk_seek() failed\n");
                                 xfree(data);                                  xfree(data);
                                 return -1;                                  return -1;
                         }                          }
                        rc = istgt_lu_disk_write(spec, data, nbytes);                        rc = istgt_lu_disk_write_raw(spec, data, nbytes);
                        if (rc == -1 || rc != nbytes) {                        if (rc == -1 || (uint64_t) rc != nbytes) {
                                 ISTGT_ERRLOG("lu_disk_write() failed\n");                                  ISTGT_ERRLOG("lu_disk_write() failed\n");
                                 xfree(data);                                  xfree(data);
                                 return -1;                                  return -1;
Line 420  istgt_lu_disk_allocate(ISTGT_LU_DISK *spec) Line 356  istgt_lu_disk_allocate(ISTGT_LU_DISK *spec)
                 }                  }
         } else {          } else {
                 /* allocate complete size */                  /* allocate complete size */
                rc = istgt_lu_disk_seek(spec, offset);                rc = istgt_lu_disk_seek_raw(spec, offset);
                 if (rc == -1) {                  if (rc == -1) {
                         ISTGT_ERRLOG("lu_disk_seek() failed\n");                          ISTGT_ERRLOG("lu_disk_seek() failed\n");
                         xfree(data);                          xfree(data);
                         return -1;                          return -1;
                 }                  }
                rc = istgt_lu_disk_write(spec, data, nbytes);                rc = istgt_lu_disk_write_raw(spec, data, nbytes);
                if (rc == -1 || rc != nbytes) {                if (rc == -1 || (uint64_t) rc != nbytes) {
                         ISTGT_ERRLOG("lu_disk_write() failed\n");                          ISTGT_ERRLOG("lu_disk_write() failed\n");
                         xfree(data);                          xfree(data);
                         return -1;                          return -1;
Line 440  istgt_lu_disk_allocate(ISTGT_LU_DISK *spec) Line 376  istgt_lu_disk_allocate(ISTGT_LU_DISK *spec)
 }  }
   
 static int  static int
istgt_lu_disk_setcache(ISTGT_LU_DISK *spec)istgt_lu_disk_setcache_raw(ISTGT_LU_DISK *spec)
 {  {
         int flags;          int flags;
         int rc;          int rc;
Line 478  istgt_lu_disk_setcache(ISTGT_LU_DISK *spec) Line 414  istgt_lu_disk_setcache(ISTGT_LU_DISK *spec)
         return 0;          return 0;
 }  }
   
   static const char *
   istgt_get_disktype_by_ext(const char *file)
   {
           size_t n;
   
           if (file == NULL || file[0] == '\n')
                   return "RAW";
   
           n = strlen(file);
           if (n > 4 && strcasecmp(file + (n - 4), ".vdi") == 0)
                   return "VDI";
           if (n > 4 && strcasecmp(file + (n - 4), ".vhd") == 0)
                   return "VHD";
           if (n > 5 && strcasecmp(file + (n - 5), ".vmdk") == 0)
                   return "VMDK";
   
           if (n > 5 && strcasecmp(file + (n - 5), ".qcow") == 0)
                   return "QCOW";
           if (n > 6 && strcasecmp(file + (n - 6), ".qcow2") == 0)
                   return "QCOW";
           if (n > 4 && strcasecmp(file + (n - 4), ".qed") == 0)
                   return "QED";
           if (n > 5 && strcasecmp(file + (n - 5), ".vhdx") == 0)
                   return "VHDX";
   
           return "RAW";
   }
   
 int  int
istgt_lu_disk_init(ISTGT_Ptr istgt, ISTGT_LU_Ptr lu)istgt_lu_disk_init(ISTGT_Ptr istgt __attribute__((__unused__)), ISTGT_LU_Ptr lu)
 {  {
         ISTGT_LU_DISK *spec;          ISTGT_LU_DISK *spec;
         uint64_t gb_size;          uint64_t gb_size;
Line 541  istgt_lu_disk_init(ISTGT_Ptr istgt, ISTGT_LU_Ptr lu) Line 505  istgt_lu_disk_init(ISTGT_Ptr istgt, ISTGT_LU_Ptr lu)
                 spec->req_write_cache = 0;                  spec->req_write_cache = 0;
                 spec->err_write_cache = 0;                  spec->err_write_cache = 0;
                 spec->thin_provisioning = 0;                  spec->thin_provisioning = 0;
                   spec->watssize = 0;
                   spec->watsbuf = NULL;
   
                 rc = pthread_mutex_init(&spec->ats_mutex, NULL);                  rc = pthread_mutex_init(&spec->ats_mutex, NULL);
                 if (rc != 0) {                  if (rc != 0) {
Line 549  istgt_lu_disk_init(ISTGT_Ptr istgt, ISTGT_LU_Ptr lu) Line 515  istgt_lu_disk_init(ISTGT_Ptr istgt, ISTGT_LU_Ptr lu)
                 }                  }
   
                 spec->queue_depth = lu->queue_depth;                  spec->queue_depth = lu->queue_depth;
                rc = pthread_mutex_init(&spec->cmd_queue_mutex, NULL);                rc = pthread_mutex_init(&spec->cmd_queue_mutex, &istgt->mutex_attr);
                 if (rc != 0) {                  if (rc != 0) {
                         ISTGT_ERRLOG("LU%d: mutex_init() failed\n", lu->num);                          ISTGT_ERRLOG("LU%d: mutex_init() failed\n", lu->num);
                         return -1;                          return -1;
Line 588  istgt_lu_disk_init(ISTGT_Ptr istgt, ISTGT_LU_Ptr lu) Line 554  istgt_lu_disk_init(ISTGT_Ptr istgt, ISTGT_LU_Ptr lu)
                 uuid_create(&spec->uuid, &status);                  uuid_create(&spec->uuid, &status);
                 if (status != uuid_s_ok) {                  if (status != uuid_s_ok) {
                         ISTGT_ERRLOG("LU%d: LUN%d: uuid_create() failed\n", lu->num, i);                          ISTGT_ERRLOG("LU%d: LUN%d: uuid_create() failed\n", lu->num, i);
                           (void) pthread_mutex_destroy(&spec->wait_lu_task_mutex);
                         (void) pthread_mutex_destroy(&spec->cmd_queue_mutex);                          (void) pthread_mutex_destroy(&spec->cmd_queue_mutex);
                           (void) pthread_mutex_destroy(&spec->ats_mutex);
                         istgt_queue_destroy(&spec->cmd_queue);                          istgt_queue_destroy(&spec->cmd_queue);
                         xfree(spec);                          xfree(spec);
                         return -1;                          return -1;
Line 597  istgt_lu_disk_init(ISTGT_Ptr istgt, ISTGT_LU_Ptr lu) Line 565  istgt_lu_disk_init(ISTGT_Ptr istgt, ISTGT_LU_Ptr lu)
   
                 spec->file = lu->lun[i].u.storage.file;                  spec->file = lu->lun[i].u.storage.file;
                 spec->size = lu->lun[i].u.storage.size;                  spec->size = lu->lun[i].u.storage.size;
                spec->blocklen = lu->blocklen;                spec->disktype = istgt_get_disktype_by_ext(spec->file);
                if (spec->blocklen != 512                if (strcasecmp(spec->disktype, "VDI") == 0
                    && spec->blocklen != 1024                    || strcasecmp(spec->disktype, "VHD") == 0
                    && spec->blocklen != 2048                    || strcasecmp(spec->disktype, "VMDK") == 0
                    && spec->blocklen != 4096                    || strcasecmp(spec->disktype, "QCOW") == 0
                    && spec->blocklen != 8192                    || strcasecmp(spec->disktype, "QED") == 0
                    && spec->blocklen != 16384                    || strcasecmp(spec->disktype, "VHDX") == 0) {
                    && spec->blocklen != 32768                        rc = istgt_lu_disk_vbox_lun_init(spec, istgt, lu);
                    && spec->blocklen != 65536                        if (rc < 0) {
                    && spec->blocklen != 131072                                ISTGT_ERRLOG("LU%d: LUN%d: lu_disk_vbox_lun_init() failed\n",
                    && spec->blocklen != 262144                                    lu->num, i);
                    && spec->blocklen != 524288) {                                goto error_return;
                        ISTGT_ERRLOG("LU%d: LUN%d: invalid blocklen %"PRIu64"\n",                        }
                            lu->num, i, spec->blocklen);                } else if (strcasecmp(spec->disktype, "RAW") == 0) {
                error_return:                        spec->open = istgt_lu_disk_open_raw;
                        (void) pthread_mutex_destroy(&spec->cmd_queue_mutex);                        spec->close = istgt_lu_disk_close_raw;
                        istgt_queue_destroy(&spec->cmd_queue);                        spec->seek = istgt_lu_disk_seek_raw;
                        xfree(spec);                        spec->read = istgt_lu_disk_read_raw;
                        return -1;                        spec->write = istgt_lu_disk_write_raw;
                }                        spec->sync = istgt_lu_disk_sync_raw;
                spec->blockcnt = spec->size / spec->blocklen;                        spec->allocate = istgt_lu_disk_allocate_raw;
                if (spec->blockcnt == 0) {                        spec->setcache = istgt_lu_disk_setcache_raw;
                        ISTGT_ERRLOG("LU%d: LUN%d: size zero\n", lu->num, i); 
                        goto error_return; 
                } 
   
                           spec->blocklen = lu->blocklen;
                           if (spec->blocklen != 512
                               && spec->blocklen != 1024
                               && spec->blocklen != 2048
                               && spec->blocklen != 4096
                               && spec->blocklen != 8192
                               && spec->blocklen != 16384
                               && spec->blocklen != 32768
                               && spec->blocklen != 65536
                               && spec->blocklen != 131072
                               && spec->blocklen != 262144
                               && spec->blocklen != 524288) {
                                   ISTGT_ERRLOG("LU%d: LUN%d: invalid blocklen %"PRIu64"\n",
                                       lu->num, i, spec->blocklen);
                           error_return:
                                   (void) pthread_mutex_destroy(&spec->wait_lu_task_mutex);
                                   (void) pthread_mutex_destroy(&spec->cmd_queue_mutex);
                                   (void) pthread_mutex_destroy(&spec->ats_mutex);
                                   istgt_queue_destroy(&spec->cmd_queue);
                                   xfree(spec);
                                   return -1;
                           }
                           spec->blockcnt = spec->size / spec->blocklen;
                           if (spec->blockcnt == 0) {
                                   ISTGT_ERRLOG("LU%d: LUN%d: size zero\n", lu->num, i);
                                   goto error_return;
                           }
   
 #if 0  #if 0
                ISTGT_TRACELOG(ISTGT_TRACE_DEBUG,                        ISTGT_TRACELOG(ISTGT_TRACE_DEBUG,
                    "LU%d: LUN%d file=%s, size=%"PRIu64"\n",                            "LU%d: LUN%d file=%s, size=%"PRIu64"\n",
                    lu->num, i, spec->file, spec->size);                            lu->num, i, spec->file, spec->size);
                ISTGT_TRACELOG(ISTGT_TRACE_DEBUG,                        ISTGT_TRACELOG(ISTGT_TRACE_DEBUG,
                    "LU%d: LUN%d %"PRIu64" blocks, %"                            "LU%d: LUN%d %"PRIu64" blocks, %"
                    PRIu64" bytes/block\n",                            PRIu64" bytes/block\n",
                    lu->num, i, spec->blockcnt, spec->blocklen);                            lu->num, i, spec->blockcnt, spec->blocklen);
 #endif  #endif
                printf("LU%d: LUN%d file=%s, size=%"PRIu64"\n",                        printf("LU%d: LUN%d file=%s, size=%"PRIu64"\n",
                    lu->num, i, spec->file, spec->size);                            lu->num, i, spec->file, spec->size);
                printf("LU%d: LUN%d %"PRIu64" blocks, %"PRIu64" bytes/block\n",                        printf("LU%d: LUN%d %"PRIu64" blocks, %"PRIu64" bytes/block\n",
                    lu->num, i, spec->blockcnt, spec->blocklen);                            lu->num, i, spec->blockcnt, spec->blocklen);
                        
                flags = lu->readonly ? O_RDONLY : O_RDWR;                        flags = lu->readonly ? O_RDONLY : O_RDWR;
                newfile = 0;                        newfile = 0;
                rc = istgt_lu_disk_open(spec, flags, 0666);                        rc = spec->open(spec, flags, 0666);
                if (rc < 0) { 
                        newfile = 1; 
                        flags = lu->readonly ? O_RDONLY : (O_CREAT | O_EXCL | O_RDWR); 
                        rc = istgt_lu_disk_open(spec, flags, 0666); 
                         if (rc < 0) {                          if (rc < 0) {
                                ISTGT_ERRLOG("LU%d: LUN%d: open error\n", lu->num, i);                                newfile = 1;
                                goto error_return;                                flags = lu->readonly ? O_RDONLY : (O_CREAT | O_EXCL | O_RDWR);
                                 rc = spec->open(spec, flags, 0666);
                                 if (rc < 0) {
                                         ISTGT_ERRLOG("LU%d: LUN%d: open error(errno=%d)\n",
                                             lu->num, i, errno);
                                         goto error_return;
                                 }
                         }                          }
                }                        if (!lu->readonly) {
                if (!lu->readonly) {                                rc = spec->allocate(spec);
                        rc = istgt_lu_disk_allocate(spec);                                if (rc < 0) {
                                         ISTGT_ERRLOG("LU%d: LUN%d: allocate error\n",
                                             lu->num, i);
                                         goto error_return;
                                 }
                         }
                         rc = spec->setcache(spec);
                         if (rc < 0) {                          if (rc < 0) {
                                ISTGT_ERRLOG("LU%d: LUN%d: allocate error\n", lu->num, i);                                ISTGT_ERRLOG("LU%d: LUN%d: setcache error\n", lu->num, i);
                                 goto error_return;                                  goto error_return;
                         }                          }
                }                } else {
                rc = istgt_lu_disk_setcache(spec);                        ISTGT_ERRLOG("LU%d: LUN%d: unsupported format\n", lu->num, i);
                if (rc < 0) { 
                        ISTGT_ERRLOG("LU%d: LUN%d: setcache error\n", lu->num, i); 
                         goto error_return;                          goto error_return;
                 }                  }
   
Line 728  istgt_lu_disk_init(ISTGT_Ptr istgt, ISTGT_LU_Ptr lu) Line 727  istgt_lu_disk_init(ISTGT_Ptr istgt, ISTGT_LU_Ptr lu)
 }  }
   
 int  int
istgt_lu_disk_shutdown(ISTGT_Ptr istgt, ISTGT_LU_Ptr lu)istgt_lu_disk_shutdown(ISTGT_Ptr istgt __attribute__((__unused__)), ISTGT_LU_Ptr lu)
 {  {
         ISTGT_LU_DISK *spec;          ISTGT_LU_DISK *spec;
         ISTGT_LU_PR_KEY *prkey;          ISTGT_LU_PR_KEY *prkey;
Line 751  istgt_lu_disk_shutdown(ISTGT_Ptr istgt, ISTGT_LU_Ptr l Line 750  istgt_lu_disk_shutdown(ISTGT_Ptr istgt, ISTGT_LU_Ptr l
                 }                  }
                 spec = (ISTGT_LU_DISK *) lu->lun[i].spec;                  spec = (ISTGT_LU_DISK *) lu->lun[i].spec;
   
                if (!spec->lu->readonly) {                if (strcasecmp(spec->disktype, "VDI") == 0
                        rc = istgt_lu_disk_sync(spec, 0, spec->size);                    || strcasecmp(spec->disktype, "VHD") == 0
                     || strcasecmp(spec->disktype, "VMDK") == 0
                     || strcasecmp(spec->disktype, "QCOW") == 0
                     || strcasecmp(spec->disktype, "QED") == 0
                     || strcasecmp(spec->disktype, "VHDX") == 0) {
                         rc = istgt_lu_disk_vbox_lun_shutdown(spec, istgt, lu);
                         if (rc < 0) {                          if (rc < 0) {
                                //ISTGT_ERRLOG("LU%d: lu_disk_sync() failed\n", lu->num);                                ISTGT_ERRLOG("LU%d: lu_disk_vbox_lun_shutdown() failed\n",
                                     lu->num);
                                 /* ignore error */                                  /* ignore error */
                         }                          }
                   } else if (strcasecmp(spec->disktype, "RAW") == 0) {
                           if (!spec->lu->readonly) {
                                   rc = spec->sync(spec, 0, spec->size);
                                   if (rc < 0) {
                                           //ISTGT_ERRLOG("LU%d: lu_disk_sync() failed\n", lu->num);
                                           /* ignore error */
                                   }
                           }
                           rc = spec->close(spec);
                           if (rc < 0) {
                                   //ISTGT_ERRLOG("LU%d: lu_disk_close() failed\n", lu->num);
                                   /* ignore error */
                           }
                   } else {
                           ISTGT_ERRLOG("LU%d: LUN%d: unsupported format\n", lu->num, i);
                           return -1;
                 }                  }
                 rc = istgt_lu_disk_close(spec);  
                 if (rc < 0) {  
                         //ISTGT_ERRLOG("LU%d: lu_disk_close() failed\n", lu->num);  
                         /* ignore error */  
                 }  
   
                 for (j = 0; j < spec->npr_keys; j++) {                  for (j = 0; j < spec->npr_keys; j++) {
                         prkey = &spec->pr_keys[j];                          prkey = &spec->pr_keys[j];
Line 790  istgt_lu_disk_shutdown(ISTGT_Ptr istgt, ISTGT_LU_Ptr l Line 806  istgt_lu_disk_shutdown(ISTGT_Ptr istgt, ISTGT_LU_Ptr l
                         //ISTGT_ERRLOG("LU%d: mutex_destroy() failed\n", lu->num);                          //ISTGT_ERRLOG("LU%d: mutex_destroy() failed\n", lu->num);
                         /* ignore error */                          /* ignore error */
                 }                  }
                   xfree(spec->watsbuf);
                 xfree(spec->wbuf);                  xfree(spec->wbuf);
                 xfree(spec);                  xfree(spec);
                 lu->lun[i].spec = NULL;                  lu->lun[i].spec = NULL;
Line 1000  istgt_lu_set_extid(uint8_t *buf, uint64_t vid, uint64_ Line 1017  istgt_lu_set_extid(uint8_t *buf, uint64_t vid, uint64_
 }  }
   
 static int  static int
istgt_lu_disk_scsi_report_luns(ISTGT_LU_Ptr lu, CONN_Ptr conn, uint8_t *cdb, int sel, uint8_t *data, int alloc_len)istgt_lu_disk_scsi_report_luns(ISTGT_LU_Ptr lu, CONN_Ptr conn __attribute__((__unused__)), uint8_t *cdb __attribute__((__unused__)), int sel, uint8_t *data, int alloc_len)
 {  {
         uint64_t fmt_lun, lun, method;          uint64_t fmt_lun, lun, method;
         int hlen = 0, len = 0;          int hlen = 0, len = 0;
Line 1043  istgt_lu_disk_scsi_report_luns(ISTGT_LU_Ptr lu, CONN_P Line 1060  istgt_lu_disk_scsi_report_luns(ISTGT_LU_Ptr lu, CONN_P
                         method = 0x00U;                          method = 0x00U;
                         fmt_lun = (method & 0x03U) << 62;                          fmt_lun = (method & 0x03U) << 62;
                         fmt_lun |= (lun & 0x00ffU) << 48;                          fmt_lun |= (lun & 0x00ffU) << 48;
                } else if (lu->maxlun <= 0x4000U) {                } else if (lu->maxlun <= 0x4000) {
                         /* below 16384 */                          /* below 16384 */
                         method = 0x01U;                          method = 0x01U;
                         fmt_lun = (method & 0x03U) << 62;                          fmt_lun = (method & 0x03U) << 62;
Line 1249  istgt_lu_disk_scsi_inquiry(ISTGT_LU_DISK *spec, CONN_P Line 1266  istgt_lu_disk_scsi_inquiry(ISTGT_LU_DISK *spec, CONN_P
   
                         /* IDENTIFIER */                          /* IDENTIFIER */
                         plen = snprintf((char *) &cp[4], MAX_TARGET_NAME,                          plen = snprintf((char *) &cp[4], MAX_TARGET_NAME,
                            "%s",                            "%s", spec->lu->name);
                            spec->lu->name); 
                         cp[3] = plen;                          cp[3] = plen;
                         len += 4 + plen;                          len += 4 + plen;
   
Line 1272  istgt_lu_disk_scsi_inquiry(ISTGT_LU_DISK *spec, CONN_P Line 1288  istgt_lu_disk_scsi_inquiry(ISTGT_LU_DISK *spec, CONN_P
   
                         /* IDENTIFIER */                          /* IDENTIFIER */
                         plen = snprintf((char *) &cp[4], MAX_TARGET_NAME,                          plen = snprintf((char *) &cp[4], MAX_TARGET_NAME,
                            "%s"",t,0x""%4.4x",                            "%s"",t,0x""%4.4x", spec->lu->name, conn->portal.tag);
                            spec->lu->name, 
                            conn->portal.tag); 
                         cp[3] = plen;                          cp[3] = plen;
                         len += 4 + plen;                          len += 4 + plen;
   
Line 1525  istgt_lu_disk_scsi_inquiry(ISTGT_LU_DISK *spec, CONN_P Line 1539  istgt_lu_disk_scsi_inquiry(ISTGT_LU_DISK *spec, CONN_P
   
                                 /* IDENTIFIER */                                  /* IDENTIFIER */
                                 plen = snprintf((char *) &cp2[4], MAX_TARGET_NAME,                                  plen = snprintf((char *) &cp2[4], MAX_TARGET_NAME,
                                    "%s"",t,0x""%4.4x",                                    "%s"",t,0x""%4.4x", spec->lu->name, pg_tag);
                                    spec->lu->name, 
                                    pg_tag); 
                                 cp2[3] = plen;                                  cp2[3] = plen;
                                 plen2 += 4 + plen;                                  plen2 += 4 + plen;
   
Line 1558  istgt_lu_disk_scsi_inquiry(ISTGT_LU_DISK *spec, CONN_P Line 1570  istgt_lu_disk_scsi_inquiry(ISTGT_LU_DISK *spec, CONN_P
                         /* WSNZ(0) */                          /* WSNZ(0) */
                         BDSET8(&data[4], 0, 0); /* support zero length in WRITE SAME */                          BDSET8(&data[4], 0, 0); /* support zero length in WRITE SAME */
                         /* MAXIMUM COMPARE AND WRITE LENGTH */                          /* MAXIMUM COMPARE AND WRITE LENGTH */
                        blocks = ISTGT_LU_WORK_BLOCK_SIZE / (uint32_t) spec->blocklen;                        blocks = ISTGT_LU_WORK_ATS_BLOCK_SIZE / (uint32_t) spec->blocklen;
                         if (blocks > 0xff) {                          if (blocks > 0xff) {
                                 blocks = 0xff;                                  blocks = 0xff;
                         }                          }
Line 1791  istgt_lu_disk_scsi_mode_sense_page(ISTGT_LU_DISK *spec Line 1803  istgt_lu_disk_scsi_mode_sense_page(ISTGT_LU_DISK *spec
                 /* Changeable values */                  /* Changeable values */
                 if (page != 0x08) {                  if (page != 0x08) {
                         /* not supported */                          /* not supported */
                        return 0;                        return -1;
                 }                  }
         } else if (pc == 0x02) {          } else if (pc == 0x02) {
                 /* Default values */                  /* Default values */
Line 1852  istgt_lu_disk_scsi_mode_sense_page(ISTGT_LU_DISK *spec Line 1864  istgt_lu_disk_scsi_mode_sense_page(ISTGT_LU_DISK *spec
                 plen = 0x12 + 2;                  plen = 0x12 + 2;
                 MODE_SENSE_PAGE_INIT(cp, plen, page, subpage);                  MODE_SENSE_PAGE_INIT(cp, plen, page, subpage);
                 BDADD8(&cp[0], 1, 7); /* PS */                  BDADD8(&cp[0], 1, 7); /* PS */
                   if (pc == 0x01) {
                           // Changeable values
                           BDADD8(&cp[2], 1, 2); /* WCE */
                           BDADD8(&cp[2], 1, 0); /* RCD */
                           len += plen;
                           break;
                   }
                 BDADD8(&cp[2], 1, 2); /* WCE */                  BDADD8(&cp[2], 1, 2); /* WCE */
                 //BDADD8(&cp[2], 1, 0); /* RCD */                  //BDADD8(&cp[2], 1, 0); /* RCD */
                 {                  {
Line 2088  istgt_lu_disk_scsi_mode_sense6(ISTGT_LU_DISK *spec, CO Line 2107  istgt_lu_disk_scsi_mode_sense6(ISTGT_LU_DISK *spec, CO
         data[3] = len;                  /* Block Descripter Length */          data[3] = len;                  /* Block Descripter Length */
   
         plen = istgt_lu_disk_scsi_mode_sense_page(spec, conn, cdb, pc, page, subpage, &cp[0], alloc_len);          plen = istgt_lu_disk_scsi_mode_sense_page(spec, conn, cdb, pc, page, subpage, &cp[0], alloc_len);
           if (plen < 0) {
                   return -1;
           }
         cp += plen;          cp += plen;
   
         total = hlen + len + plen;          total = hlen + len + plen;
Line 2146  istgt_lu_disk_scsi_mode_sense10(ISTGT_LU_DISK *spec, C Line 2168  istgt_lu_disk_scsi_mode_sense10(ISTGT_LU_DISK *spec, C
         DSET16(&data[6], len);          /* Block Descripter Length */          DSET16(&data[6], len);          /* Block Descripter Length */
   
         plen = istgt_lu_disk_scsi_mode_sense_page(spec, conn, cdb, pc, page, subpage, &cp[0], alloc_len);          plen = istgt_lu_disk_scsi_mode_sense_page(spec, conn, cdb, pc, page, subpage, &cp[0], alloc_len);
           if (plen < 0) {
                   return -1;
           }
         cp += plen;          cp += plen;
   
         total = hlen + len + plen;          total = hlen + len + plen;
Line 2161  istgt_lu_disk_transfer_data(CONN_Ptr conn, ISTGT_LU_CM Line 2186  istgt_lu_disk_transfer_data(CONN_Ptr conn, ISTGT_LU_CM
   
         if (lu_cmd->lu->queue_depth == 0) {          if (lu_cmd->lu->queue_depth == 0) {
                 if (len > bufsize) {                  if (len > bufsize) {
                        ISTGT_ERRLOG("bufsize(%d) too small\n", bufsize);                        ISTGT_ERRLOG("bufsize(%zd) too small\n", bufsize);
                         return -1;                          return -1;
                 }                  }
                 rc = istgt_iscsi_transfer_out(conn, lu_cmd, buf, bufsize, len);                  rc = istgt_iscsi_transfer_out(conn, lu_cmd, buf, bufsize, len);
Line 2176  istgt_lu_disk_transfer_data(CONN_Ptr conn, ISTGT_LU_CM Line 2201  istgt_lu_disk_transfer_data(CONN_Ptr conn, ISTGT_LU_CM
 static int  static int
 istgt_lu_disk_scsi_mode_select_page(ISTGT_LU_DISK *spec, CONN_Ptr conn, uint8_t *cdb, int pf, int sp, uint8_t *data, size_t len)  istgt_lu_disk_scsi_mode_select_page(ISTGT_LU_DISK *spec, CONN_Ptr conn, uint8_t *cdb, int pf, int sp, uint8_t *data, size_t len)
 {  {
           size_t hlen, plen;
         int ps, spf, page, subpage;          int ps, spf, page, subpage;
         int hlen, plen;  
         int rc;          int rc;
   
         if (pf == 0) {          if (pf == 0) {
Line 2271  istgt_lu_disk_scsi_mode_select_page(ISTGT_LU_DISK *spe Line 2296  istgt_lu_disk_scsi_mode_select_page(ISTGT_LU_DISK *spe
         return 0;          return 0;
 }  }
   
   static int
   istgt_lu_disk_scsi_read_defect10(ISTGT_LU_DISK *spec __attribute__((__unused__)), CONN_Ptr conn __attribute__((__unused__)), uint8_t *cdb __attribute__((__unused__)), int req_plist, int req_glist, int list_format, uint8_t *data, int alloc_len)
   {
           uint8_t *cp;
           int hlen = 0, len = 0;
           int total;
   
           if (alloc_len < 4) {
                   return -1;
           }
   
           data[0] = 0;                            /* Reserved */
           data[1] = 0;
           if (req_plist) {
                   BDADD8(&data[1], 1, 4);         /* PLISTV */
           }
           if (req_glist) {
                   BDADD8(&data[1], 1, 3);         /* GLISTV */
           }
           BDADD8W(&data[1], list_format, 2, 3);   /* DEFECT LIST FORMAT */
           DSET16(&data[2], 0);                    /* DEFECT LIST LENGTH */
           hlen = 4;
   
           cp = &data[4];
           /* defect list (if any) */
           len = 0;
   
           total = hlen + len;
           DSET16(&data[2], total - hlen);         /* DEFECT LIST LENGTH */
           return total;
   }
   
   static int
   istgt_lu_disk_scsi_read_defect12(ISTGT_LU_DISK *spec __attribute__((__unused__)), CONN_Ptr conn __attribute__((__unused__)), uint8_t *cdb __attribute__((__unused__)), int req_plist, int req_glist, int list_format, uint8_t *data, int alloc_len)
   {
           uint8_t *cp;
           int hlen = 0, len = 0;
           int total;
   
           if (alloc_len < 8) {
                   return -1;
           }
   
           data[0] = 0;                            /* Reserved */
           data[1] = 0;
           if (req_plist) {
                   BDADD8(&data[1], 1, 4);         /* PLISTV */
           }
           if (req_glist) {
                   BDADD8(&data[1], 1, 3);         /* GLISTV */
           }
           BDADD8W(&data[1], list_format, 2, 3);   /* DEFECT LIST FORMAT */
           data[2] = 0;                            /* Reserved */
           data[3] = 0;                            /* Reserved */
           DSET32(&data[4], 0);                    /* DEFECT LIST LENGTH */
           hlen = 8;
   
           cp = &data[8];
           /* defect list (if any) */
           len = 0;
   
           total = hlen + len;
           DSET32(&data[4], total - hlen);         /* DEFECT LIST LENGTH */
           return total;
   }
   
 #if 0  #if 0
 static int  static int
 istgt_lu_disk_scsi_request_sense(ISTGT_LU_DISK *spec, CONN_Ptr conn, uint8_t *cdb, int desc, uint8_t *data, int alloc_len)  istgt_lu_disk_scsi_request_sense(ISTGT_LU_DISK *spec, CONN_Ptr conn, uint8_t *cdb, int desc, uint8_t *data, int alloc_len)
Line 2349  istgt_lu_disk_scsi_request_sense(ISTGT_LU_DISK *spec,  Line 2440  istgt_lu_disk_scsi_request_sense(ISTGT_LU_DISK *spec, 
 #endif  #endif
   
 static int  static int
istgt_lu_disk_scsi_report_target_port_groups(ISTGT_LU_DISK *spec, CONN_Ptr conn, uint8_t *cdb, uint8_t *data, int alloc_len)istgt_lu_disk_scsi_report_target_port_groups(ISTGT_LU_DISK *spec, CONN_Ptr conn, uint8_t *cdb __attribute__((__unused__)), uint8_t *data, int alloc_len)
 {  {
         ISTGT_Ptr istgt;          ISTGT_Ptr istgt;
         ISTGT_LU_Ptr lu;          ISTGT_LU_Ptr lu;
Line 2359  istgt_lu_disk_scsi_report_target_port_groups(ISTGT_LU_ Line 2450  istgt_lu_disk_scsi_report_target_port_groups(ISTGT_LU_
         int total;          int total;
         int pg_tag;          int pg_tag;
         int nports;          int nports;
        int i, j;        int i, j, k;
         int ridx;
   
         if (alloc_len < 0xfff) {          if (alloc_len < 0xfff) {
                 return -1;                  return -1;
Line 2436  istgt_lu_disk_scsi_report_target_port_groups(ISTGT_LU_ Line 2528  istgt_lu_disk_scsi_report_target_port_groups(ISTGT_LU_
                 len += plen;                  len += plen;
   
                 nports = 0;                  nports = 0;
                for (j = 0; j < istgt->nportal; j ++) {                ridx = 0;
                        if (istgt->portal[j].tag != pg_tag)                MTX_LOCK(&istgt->mutex);
                                continue;                for (j = 0; j < istgt->nportal_group; j++) {
                        /* Target port descriptor(s) */                        if (istgt->portal_group[j].tag == pg_tag) {
                        cp = &data[hlen + len];                                for (k = 0; k < istgt->portal_group[j].nportals; k++) {
                        /* Obsolete */                                        /* Target port descriptor(s) */
                        DSET16(&cp[0], 0);                                        cp = &data[hlen + len];
                        /* RELATIVE TARGET PORT IDENTIFIER */                                        /* Obsolete */
                        DSET16(&cp[2], (uint16_t) (1 + istgt->portal[j].idx));                                        DSET16(&cp[0], 0);
                        plen = 4;                                        /* RELATIVE TARGET PORT IDENTIFIER */
                        len += plen;                                        DSET16(&cp[2], (uint16_t) (1 + ridx));
                        nports++;                                        plen = 4;
                                         len += plen;
                                         nports++;
                                         ridx++;
                                 }
                         } else {
                                 ridx += istgt->portal_group[j].nportals;
                         }
                 }                  }
                   MTX_UNLOCK(&istgt->mutex);
   
                 if (nports > 0xff) {                  if (nports > 0xff) {
                         ISTGT_ERRLOG("too many portals in portal group\n");                          ISTGT_ERRLOG("too many portals in portal group\n");
Line 2611  istgt_lu_disk_find_pr_key(ISTGT_LU_DISK *spec, const c Line 2711  istgt_lu_disk_find_pr_key(ISTGT_LU_DISK *spec, const c
 }  }
   
 static int  static int
istgt_lu_disk_remove_other_pr_key(ISTGT_LU_DISK *spec, CONN_Ptr conn, const char *initiator_port, const char *target_port, uint64_t key)istgt_lu_disk_remove_other_pr_key(ISTGT_LU_DISK *spec, CONN_Ptr conn __attribute__((__unused__)), const char *initiator_port, const char *target_port, uint64_t key)
 {  {
         ISTGT_LU_PR_KEY *prkey, *prkey1, *prkey2;          ISTGT_LU_PR_KEY *prkey, *prkey1, *prkey2;
         int i, j;          int i, j;
Line 2664  istgt_lu_disk_remove_other_pr_key(ISTGT_LU_DISK *spec, Line 2764  istgt_lu_disk_remove_other_pr_key(ISTGT_LU_DISK *spec,
 }  }
   
 static int  static int
istgt_lu_disk_remove_pr_key(ISTGT_LU_DISK *spec, CONN_Ptr conn, const char *initiator_port, const char *target_port, uint64_t key)istgt_lu_disk_remove_pr_key(ISTGT_LU_DISK *spec, CONN_Ptr conn __attribute__((__unused__)), const char *initiator_port, const char *target_port, uint64_t key)
 {  {
         ISTGT_LU_PR_KEY *prkey, *prkey1, *prkey2;          ISTGT_LU_PR_KEY *prkey, *prkey1, *prkey2;
         int i, j;          int i, j;
Line 2763  istgt_lu_parse_transport_id(char **tid, uint8_t *data, Line 2863  istgt_lu_parse_transport_id(char **tid, uint8_t *data,
 }  }
   
 static int  static int
istgt_lu_disk_scsi_persistent_reserve_in(ISTGT_LU_DISK *spec, CONN_Ptr conn, ISTGT_LU_CMD_Ptr lu_cmd, int sa, uint8_t *data, int alloc_len)istgt_lu_disk_scsi_persistent_reserve_in(ISTGT_LU_DISK *spec, CONN_Ptr conn __attribute__((__unused__)), ISTGT_LU_CMD_Ptr lu_cmd, int sa, uint8_t *data, int alloc_len __attribute__((__unused__)))
 {  {
         ISTGT_LU_PR_KEY *prkey;          ISTGT_LU_PR_KEY *prkey;
           size_t hlen = 0, len = 0, plen;
         uint8_t *sense_data;          uint8_t *sense_data;
        int *sense_len;        size_t *sense_len;
         uint8_t *cp;          uint8_t *cp;
         int hlen = 0, len = 0, plen;  
         int total;          int total;
         int i;          int i;
   
Line 2925  istgt_lu_disk_scsi_persistent_reserve_out(ISTGT_LU_DIS Line 3025  istgt_lu_disk_scsi_persistent_reserve_out(ISTGT_LU_DIS
 {  {
         ISTGT_LU_PR_KEY *prkey;          ISTGT_LU_PR_KEY *prkey;
         uint8_t *sense_data;          uint8_t *sense_data;
        int *sense_len;        size_t *sense_len;
         char *old_rsv_port = NULL;          char *old_rsv_port = NULL;
         char **initiator_ports;          char **initiator_ports;
         int maxports, nports;          int maxports, nports;
Line 2998  istgt_lu_disk_scsi_persistent_reserve_out(ISTGT_LU_DIS Line 3098  istgt_lu_disk_scsi_persistent_reserve_out(ISTGT_LU_DIS
                         }                          }
                         /* remove existing keys */                          /* remove existing keys */
                         rc = istgt_lu_disk_remove_pr_key(spec, conn,                          rc = istgt_lu_disk_remove_pr_key(spec, conn,
                            conn->initiator_port, conn->target_port, rkey);                            conn->initiator_port, conn->target_port, 0);
                         if (rc < 0) {                          if (rc < 0) {
                                 ISTGT_ERRLOG("lu_disk_remove_pr_key() failed\n");                                  ISTGT_ERRLOG("lu_disk_remove_pr_key() failed\n");
                                 /* INTERNAL TARGET FAILURE */                                  /* INTERNAL TARGET FAILURE */
Line 3461  istgt_lu_disk_scsi_persistent_reserve_out(ISTGT_LU_DIS Line 3561  istgt_lu_disk_scsi_persistent_reserve_out(ISTGT_LU_DIS
                                         return -1;                                          return -1;
                                 }                                  }
                         }                          }
                           /* unregister? */
                           if (sarkey == 0) {
                                   lu_cmd->status = ISTGT_SCSI_STATUS_GOOD;
                                   return 0;
                           }
                 } else {                  } else {
                         /* registered port */                          /* registered port */
                         if (spec_i_pt) {                          if (spec_i_pt) {
Line 3735  istgt_lu_disk_scsi_release(ISTGT_LU_DISK *spec, CONN_P Line 3840  istgt_lu_disk_scsi_release(ISTGT_LU_DISK *spec, CONN_P
 {  {
         ISTGT_LU_CMD lu_cmd2;          ISTGT_LU_CMD lu_cmd2;
         uint8_t *sense_data;          uint8_t *sense_data;
        int *sense_len;        size_t *sense_len;
         uint64_t LUI;          uint64_t LUI;
         uint64_t rkey;          uint64_t rkey;
         uint8_t cdb[10];          uint8_t cdb[10];
Line 3822  istgt_lu_disk_scsi_reserve(ISTGT_LU_DISK *spec, CONN_P Line 3927  istgt_lu_disk_scsi_reserve(ISTGT_LU_DISK *spec, CONN_P
 {  {
         ISTGT_LU_CMD lu_cmd2;          ISTGT_LU_CMD lu_cmd2;
         uint8_t *sense_data;          uint8_t *sense_data;
        int *sense_len;        size_t *sense_len;
         uint64_t LUI;          uint64_t LUI;
         uint64_t rkey;          uint64_t rkey;
         uint8_t cdb[10];          uint8_t cdb[10];
Line 3905  istgt_lu_disk_scsi_reserve(ISTGT_LU_DISK *spec, CONN_P Line 4010  istgt_lu_disk_scsi_reserve(ISTGT_LU_DISK *spec, CONN_P
 }  }
   
 static int  static int
istgt_lu_disk_lbread(ISTGT_LU_DISK *spec, CONN_Ptr conn, ISTGT_LU_CMD_Ptr lu_cmd, uint64_t lba, uint32_t len)istgt_lu_disk_lbread(ISTGT_LU_DISK *spec, CONN_Ptr conn __attribute__((__unused__)), ISTGT_LU_CMD_Ptr lu_cmd, uint64_t lba, uint32_t len)
 {  {
         uint8_t *data;          uint8_t *data;
         uint64_t maxlba;          uint64_t maxlba;
Line 3937  istgt_lu_disk_lbread(ISTGT_LU_DISK *spec, CONN_Ptr con Line 4042  istgt_lu_disk_lbread(ISTGT_LU_DISK *spec, CONN_Ptr con
         }          }
   
         if (nbytes > lu_cmd->iobufsize) {          if (nbytes > lu_cmd->iobufsize) {
                ISTGT_ERRLOG("nbytes(%u) > iobufsize(%u)\n",                ISTGT_ERRLOG("nbytes(%zu) > iobufsize(%zu)\n",
                    nbytes, lu_cmd->iobufsize);                    (size_t) nbytes, lu_cmd->iobufsize);
                 return -1;                  return -1;
         }          }
         data = lu_cmd->iobuf;          data = lu_cmd->iobuf;
   
        rc = istgt_lu_disk_seek(spec, offset);        rc = spec->seek(spec, offset);
         if (rc < 0) {          if (rc < 0) {
                 ISTGT_ERRLOG("lu_disk_seek() failed\n");                  ISTGT_ERRLOG("lu_disk_seek() failed\n");
                 return -1;                  return -1;
         }          }
   
        rc = istgt_lu_disk_read(spec, data, nbytes);        rc = spec->read(spec, data, nbytes);
         if (rc < 0) {          if (rc < 0) {
                 ISTGT_ERRLOG("lu_disk_read() failed\n");                  ISTGT_ERRLOG("lu_disk_read() failed\n");
                 return -1;                  return -1;
Line 3995  istgt_lu_disk_lbwrite(ISTGT_LU_DISK *spec, CONN_Ptr co Line 4100  istgt_lu_disk_lbwrite(ISTGT_LU_DISK *spec, CONN_Ptr co
         }          }
   
         if (nbytes > lu_cmd->iobufsize) {          if (nbytes > lu_cmd->iobufsize) {
                ISTGT_ERRLOG("nbytes(%u) > iobufsize(%u)\n",                ISTGT_ERRLOG("nbytes(%zu) > iobufsize(%zu)\n",
                    nbytes, lu_cmd->iobufsize);                    (size_t) nbytes, lu_cmd->iobufsize);
                 return -1;                  return -1;
         }          }
         data = lu_cmd->iobuf;          data = lu_cmd->iobuf;
Line 4014  istgt_lu_disk_lbwrite(ISTGT_LU_DISK *spec, CONN_Ptr co Line 4119  istgt_lu_disk_lbwrite(ISTGT_LU_DISK *spec, CONN_Ptr co
         }          }
   
         spec->req_write_cache = 0;          spec->req_write_cache = 0;
        rc = istgt_lu_disk_seek(spec, offset);        rc = spec->seek(spec, offset);
         if (rc < 0) {          if (rc < 0) {
                 ISTGT_ERRLOG("lu_disk_seek() failed\n");                  ISTGT_ERRLOG("lu_disk_seek() failed\n");
                 return -1;                  return -1;
         }          }
   
        rc = istgt_lu_disk_write(spec, data, nbytes);        rc = spec->write(spec, data, nbytes);
        if (rc < 0 || rc != nbytes) {        if (rc < 0 || (uint64_t) rc != nbytes) {
                 ISTGT_ERRLOG("lu_disk_write() failed\n");                  ISTGT_ERRLOG("lu_disk_write() failed\n");
                 return -1;                  return -1;
         }          }
Line 4069  istgt_lu_disk_lbwrite_same(ISTGT_LU_DISK *spec, CONN_P Line 4174  istgt_lu_disk_lbwrite_same(ISTGT_LU_DISK *spec, CONN_P
         }          }
   
         if (nbytes > lu_cmd->iobufsize) {          if (nbytes > lu_cmd->iobufsize) {
                ISTGT_ERRLOG("nbytes(%u) > iobufsize(%u)\n",                ISTGT_ERRLOG("nbytes(%zu) > iobufsize(%zu)\n",
                    nbytes, lu_cmd->iobufsize);                    (size_t) nbytes, lu_cmd->iobufsize);
                 return -1;                  return -1;
         }          }
         data = lu_cmd->iobuf;          data = lu_cmd->iobuf;
Line 4098  istgt_lu_disk_lbwrite_same(ISTGT_LU_DISK *spec, CONN_P Line 4203  istgt_lu_disk_lbwrite_same(ISTGT_LU_DISK *spec, CONN_P
         }          }
   
         spec->req_write_cache = 0;          spec->req_write_cache = 0;
        rc = istgt_lu_disk_seek(spec, offset);        rc = spec->seek(spec, offset);
         if (rc < 0) {          if (rc < 0) {
                 ISTGT_ERRLOG("lu_disk_seek() failed\n");                  ISTGT_ERRLOG("lu_disk_seek() failed\n");
                 return -1;                  return -1;
Line 4107  istgt_lu_disk_lbwrite_same(ISTGT_LU_DISK *spec, CONN_P Line 4212  istgt_lu_disk_lbwrite_same(ISTGT_LU_DISK *spec, CONN_P
 #if 0  #if 0
         nblocks = 0;          nblocks = 0;
         while (nblocks < llen) {          while (nblocks < llen) {
                rc = istgt_lu_disk_write(spec, data, nbytes);                rc = spec->write(spec, data, nbytes);
                 if (rc < 0 || rc != nbytes) {                  if (rc < 0 || rc != nbytes) {
                         ISTGT_ERRLOG("lu_disk_write() failed\n");                          ISTGT_ERRLOG("lu_disk_write() failed\n");
                         return -1;                          return -1;
Line 4124  istgt_lu_disk_lbwrite_same(ISTGT_LU_DISK *spec, CONN_P Line 4229  istgt_lu_disk_lbwrite_same(ISTGT_LU_DISK *spec, CONN_P
         nblocks = 0;          nblocks = 0;
         while (nblocks < llen) {          while (nblocks < llen) {
                 uint64_t reqblocks = DMIN64(wblocks, (llen - nblocks));                  uint64_t reqblocks = DMIN64(wblocks, (llen - nblocks));
                rc = istgt_lu_disk_write(spec, conn->workbuf, (reqblocks * nbytes));                rc = spec->write(spec, conn->workbuf, (reqblocks * nbytes));
                if (rc < 0 || rc != (reqblocks * nbytes)) {                if (rc < 0 || (uint64_t) rc != (reqblocks * nbytes)) {
                         ISTGT_ERRLOG("lu_disk_write() failed\n");                          ISTGT_ERRLOG("lu_disk_write() failed\n");
                         return -1;                          return -1;
                 }                  }
Line 4143  istgt_lu_disk_lbwrite_same(ISTGT_LU_DISK *spec, CONN_P Line 4248  istgt_lu_disk_lbwrite_same(ISTGT_LU_DISK *spec, CONN_P
 static int  static int
 istgt_lu_disk_lbwrite_ats(ISTGT_LU_DISK *spec, CONN_Ptr conn, ISTGT_LU_CMD_Ptr lu_cmd, uint64_t lba, uint32_t len)  istgt_lu_disk_lbwrite_ats(ISTGT_LU_DISK *spec, CONN_Ptr conn, ISTGT_LU_CMD_Ptr lu_cmd, uint64_t lba, uint32_t len)
 {  {
         uint8_t *tmp;  
         uint8_t *data;          uint8_t *data;
         uint64_t maxlba;          uint64_t maxlba;
         uint64_t llen;          uint64_t llen;
Line 4152  istgt_lu_disk_lbwrite_ats(ISTGT_LU_DISK *spec, CONN_Pt Line 4256  istgt_lu_disk_lbwrite_ats(ISTGT_LU_DISK *spec, CONN_Pt
         uint64_t nbytes;          uint64_t nbytes;
         int64_t rc;          int64_t rc;
         uint8_t *sense_data;          uint8_t *sense_data;
        int *sense_len;        size_t *sense_len;
   
         if (len == 0) {          if (len == 0) {
                 lu_cmd->data_len = 0;                  lu_cmd->data_len = 0;
Line 4179  istgt_lu_disk_lbwrite_ats(ISTGT_LU_DISK *spec, CONN_Pt Line 4283  istgt_lu_disk_lbwrite_ats(ISTGT_LU_DISK *spec, CONN_Pt
         }          }
   
         if (nbytes > lu_cmd->iobufsize) {          if (nbytes > lu_cmd->iobufsize) {
                ISTGT_ERRLOG("nbytes(%u) > iobufsize(%u)\n",                ISTGT_ERRLOG("nbytes(%zu) > iobufsize(%zu)\n",
                    nbytes, lu_cmd->iobufsize);                    (size_t) nbytes, lu_cmd->iobufsize);
                 return -1;                  return -1;
         }          }
         data = lu_cmd->iobuf;          data = lu_cmd->iobuf;
Line 4197  istgt_lu_disk_lbwrite_ats(ISTGT_LU_DISK *spec, CONN_Pt Line 4301  istgt_lu_disk_lbwrite_ats(ISTGT_LU_DISK *spec, CONN_Pt
                 return -1;                  return -1;
         }          }
   
        tmp = xmalloc(nbytes);        if (spec->watsbuf == NULL) {
                 spec->watssize = ISTGT_LU_WORK_ATS_BLOCK_SIZE;
                 spec->watsbuf = xmalloc(spec->watssize);
         }
         if (nbytes > (uint64_t) spec->watssize) {
                 ISTGT_ERRLOG("nbytes(%zu) > watssize(%zu)\n",
                     (size_t) nbytes, (size_t) spec->watssize);
                 return -1;
         }
 
         spec->req_write_cache = 0;          spec->req_write_cache = 0;
         /* start atomic test and set */          /* start atomic test and set */
         MTX_LOCK(&spec->ats_mutex);          MTX_LOCK(&spec->ats_mutex);
   
        rc = istgt_lu_disk_seek(spec, offset);        rc = spec->seek(spec, offset);
         if (rc < 0) {          if (rc < 0) {
                 MTX_UNLOCK(&spec->ats_mutex);                  MTX_UNLOCK(&spec->ats_mutex);
                 ISTGT_ERRLOG("lu_disk_seek() failed\n");                  ISTGT_ERRLOG("lu_disk_seek() failed\n");
                 xfree(tmp);  
                 return -1;                  return -1;
         }          }
   
        rc = istgt_lu_disk_read(spec, tmp, nbytes);        rc = spec->read(spec, spec->watsbuf, nbytes);
        if (rc < 0 || rc != nbytes) {        if (rc < 0 || (uint64_t) rc != nbytes) {
                 MTX_UNLOCK(&spec->ats_mutex);                  MTX_UNLOCK(&spec->ats_mutex);
                 ISTGT_ERRLOG("lu_disk_read() failed\n");                  ISTGT_ERRLOG("lu_disk_read() failed\n");
                 xfree(tmp);  
                 return -1;                  return -1;
         }          }
   
 #if 0  #if 0
         ISTGT_TRACEDUMP(ISTGT_TRACE_DEBUG, "ATS VERIFY", data, nbytes);          ISTGT_TRACEDUMP(ISTGT_TRACE_DEBUG, "ATS VERIFY", data, nbytes);
         ISTGT_TRACEDUMP(ISTGT_TRACE_DEBUG, "ATS WRITE", data + nbytes, nbytes);          ISTGT_TRACEDUMP(ISTGT_TRACE_DEBUG, "ATS WRITE", data + nbytes, nbytes);
        ISTGT_TRACEDUMP(ISTGT_TRACE_DEBUG, "ATS DATA", tmp, nbytes);        ISTGT_TRACEDUMP(ISTGT_TRACE_DEBUG, "ATS DATA", spec->watsbuf, nbytes);
 #endif  #endif
        if (memcmp(tmp, data, nbytes) != 0) {        if (memcmp(spec->watsbuf, data, nbytes) != 0) {
                 MTX_UNLOCK(&spec->ats_mutex);                  MTX_UNLOCK(&spec->ats_mutex);
                 //ISTGT_ERRLOG("compare failed\n");                  //ISTGT_ERRLOG("compare failed\n");
                 xfree(tmp);  
                 /* MISCOMPARE DURING VERIFY OPERATION */                  /* MISCOMPARE DURING VERIFY OPERATION */
                 BUILD_SENSE(MISCOMPARE, 0x1d, 0x00);                  BUILD_SENSE(MISCOMPARE, 0x1d, 0x00);
                 return -1;                  return -1;
         }          }
   
        rc = istgt_lu_disk_seek(spec, offset);        rc = spec->seek(spec, offset);
         if (rc < 0) {          if (rc < 0) {
                 MTX_UNLOCK(&spec->ats_mutex);                  MTX_UNLOCK(&spec->ats_mutex);
                 ISTGT_ERRLOG("lu_disk_seek() failed\n");                  ISTGT_ERRLOG("lu_disk_seek() failed\n");
                 xfree(tmp);  
                 return -1;                  return -1;
         }          }
        rc = istgt_lu_disk_write(spec, data + nbytes, nbytes);        rc = spec->write(spec, data + nbytes, nbytes);
        if (rc < 0 || rc != nbytes) {        if (rc < 0 || (uint64_t) rc != nbytes) {
                 MTX_UNLOCK(&spec->ats_mutex);                  MTX_UNLOCK(&spec->ats_mutex);
                 ISTGT_ERRLOG("lu_disk_write() failed\n");                  ISTGT_ERRLOG("lu_disk_write() failed\n");
                 xfree(tmp);  
                 return -1;                  return -1;
         }          }
         ISTGT_TRACELOG(ISTGT_TRACE_SCSI, "Wrote %"PRId64"/%"PRIu64" bytes\n",          ISTGT_TRACELOG(ISTGT_TRACE_SCSI, "Wrote %"PRId64"/%"PRIu64" bytes\n",
Line 4251  istgt_lu_disk_lbwrite_ats(ISTGT_LU_DISK *spec, CONN_Pt Line 4359  istgt_lu_disk_lbwrite_ats(ISTGT_LU_DISK *spec, CONN_Pt
   
         MTX_UNLOCK(&spec->ats_mutex);          MTX_UNLOCK(&spec->ats_mutex);
         /* end atomic test and set */          /* end atomic test and set */
         xfree(tmp);  
   
         lu_cmd->data_len = nbytes * 2;          lu_cmd->data_len = nbytes * 2;
   
Line 4259  istgt_lu_disk_lbwrite_ats(ISTGT_LU_DISK *spec, CONN_Pt Line 4366  istgt_lu_disk_lbwrite_ats(ISTGT_LU_DISK *spec, CONN_Pt
 }  }
   
 static int  static int
istgt_lu_disk_lbsync(ISTGT_LU_DISK *spec, CONN_Ptr conn, ISTGT_LU_CMD_Ptr lu_cmd, uint64_t lba, uint32_t len)istgt_lu_disk_lbsync(ISTGT_LU_DISK *spec, CONN_Ptr conn __attribute__((__unused__)), ISTGT_LU_CMD_Ptr lu_cmd __attribute__((__unused__)), uint64_t lba, uint32_t len)
 {  {
         uint64_t maxlba;          uint64_t maxlba;
         uint64_t llen;          uint64_t llen;
Line 4287  istgt_lu_disk_lbsync(ISTGT_LU_DISK *spec, CONN_Ptr con Line 4394  istgt_lu_disk_lbsync(ISTGT_LU_DISK *spec, CONN_Ptr con
                 return -1;                  return -1;
         }          }
   
        rc = istgt_lu_disk_sync(spec, offset, nbytes);        rc = spec->sync(spec, offset, nbytes);
         if (rc < 0) {          if (rc < 0) {
                 ISTGT_ERRLOG("lu_disk_sync() failed\n");                  ISTGT_ERRLOG("lu_disk_sync() failed\n");
                 return -1;                  return -1;
Line 4354  istgt_lu_scsi_build_sense_data(uint8_t *data, int sk,  Line 4461  istgt_lu_scsi_build_sense_data(uint8_t *data, int sk, 
 }  }
   
 static int  static int
istgt_lu_disk_build_sense_data(ISTGT_LU_DISK *spec, uint8_t *data, int sk, int asc, int ascq)istgt_lu_disk_build_sense_data(ISTGT_LU_DISK *spec __attribute__((__unused__)), uint8_t *data, int sk, int asc, int ascq)
 {  {
         int rc;          int rc;
   
Line 4423  istgt_lu_scsi_build_sense_data2(uint8_t *data, int sk, Line 4530  istgt_lu_scsi_build_sense_data2(uint8_t *data, int sk,
 }  }
   
 static int  static int
istgt_lu_disk_build_sense_data2(ISTGT_LU_DISK *spec, uint8_t *data, int sk, int asc, int ascq)istgt_lu_disk_build_sense_data2(ISTGT_LU_DISK *spec __attribute__((__unused__)), uint8_t *data, int sk, int asc, int ascq)
 {  {
         int rc;          int rc;
   
Line 4472  istgt_lu_disk_reset(ISTGT_LU_Ptr lu, int lun) Line 4579  istgt_lu_disk_reset(ISTGT_LU_Ptr lu, int lun)
   
         /* re-open file */          /* re-open file */
         if (!spec->lu->readonly) {          if (!spec->lu->readonly) {
                rc = istgt_lu_disk_sync(spec, 0, spec->size);                rc = spec->sync(spec, 0, spec->size);
                 if (rc < 0) {                  if (rc < 0) {
                         ISTGT_ERRLOG("LU%d: LUN%d: lu_disk_sync() failed\n",                          ISTGT_ERRLOG("LU%d: LUN%d: lu_disk_sync() failed\n",
                             lu->num, lun);                              lu->num, lun);
                         /* ignore error */                          /* ignore error */
                 }                  }
         }          }
        rc = istgt_lu_disk_close(spec);        rc = spec->close(spec);
         if (rc < 0) {          if (rc < 0) {
                 ISTGT_ERRLOG("LU%d: LUN%d: lu_disk_close() failed\n",                  ISTGT_ERRLOG("LU%d: LUN%d: lu_disk_close() failed\n",
                     lu->num, lun);                      lu->num, lun);
                 /* ignore error */                  /* ignore error */
         }          }
         flags = lu->readonly ? O_RDONLY : O_RDWR;          flags = lu->readonly ? O_RDONLY : O_RDWR;
        rc = istgt_lu_disk_open(spec, flags, 0666);        rc = spec->open(spec, flags, 0666);
         if (rc < 0) {          if (rc < 0) {
                 ISTGT_ERRLOG("LU%d: LUN%d: lu_disk_open() failed\n",                  ISTGT_ERRLOG("LU%d: LUN%d: lu_disk_open() failed\n",
                     lu->num, lun);                      lu->num, lun);
Line 4526  istgt_lu_disk_queue_clear_internal(ISTGT_LU_DISK *spec Line 4633  istgt_lu_disk_queue_clear_internal(ISTGT_LU_DISK *spec
                 if (((all_cmds != 0) || (lu_task->lu_cmd.CmdSN == CmdSN))                  if (((all_cmds != 0) || (lu_task->lu_cmd.CmdSN == CmdSN))
                     && (strcasecmp(lu_task->initiator_port,                      && (strcasecmp(lu_task->initiator_port,
                             initiator_port) == 0)) {                              initiator_port) == 0)) {
                        ISTGT_LOG("CmdSN(%u), OP=0x%x, ElapsedTime=%u cleared\n",                        ISTGT_LOG("CmdSN(%u), OP=0x%x, ElapsedTime=%lu cleared\n",
                             lu_task->lu_cmd.CmdSN,                              lu_task->lu_cmd.CmdSN,
                             lu_task->lu_cmd.cdb[0],                              lu_task->lu_cmd.cdb[0],
                            (now - lu_task->create_time));                            (unsigned long) (now - lu_task->create_time));
                         rc = istgt_lu_destroy_task(lu_task);                          rc = istgt_lu_destroy_task(lu_task);
                         if (rc < 0) {                          if (rc < 0) {
                                 MTX_UNLOCK(&spec->cmd_queue_mutex);                                  MTX_UNLOCK(&spec->cmd_queue_mutex);
Line 4568  istgt_lu_disk_queue_clear_internal(ISTGT_LU_DISK *spec Line 4675  istgt_lu_disk_queue_clear_internal(ISTGT_LU_DISK *spec
                         /* conn had gone? */                          /* conn had gone? */
                         rc = pthread_mutex_trylock(&lu_task->trans_mutex);                          rc = pthread_mutex_trylock(&lu_task->trans_mutex);
                         if (rc == 0) {                          if (rc == 0) {
                                ISTGT_LOG("CmdSN(%u), OP=0x%x, ElapsedTime=%u aborted\n",                                ISTGT_LOG("CmdSN(%u), OP=0x%x, ElapsedTime=%lu aborted\n",
                                     lu_task->lu_cmd.CmdSN,                                      lu_task->lu_cmd.CmdSN,
                                     lu_task->lu_cmd.cdb[0],                                      lu_task->lu_cmd.cdb[0],
                                    (now - lu_task->create_time));                                    (unsigned long) (now - lu_task->create_time));
                                 /* force error */                                  /* force error */
                                 lu_task->error = 1;                                  lu_task->error = 1;
                                 lu_task->abort = 1;                                  lu_task->abort = 1;
Line 4723  istgt_lu_disk_queue_clear_all(ISTGT_LU_Ptr lu, int lun Line 4830  istgt_lu_disk_queue_clear_all(ISTGT_LU_Ptr lu, int lun
                 lu_task = istgt_queue_dequeue(&spec->cmd_queue);                  lu_task = istgt_queue_dequeue(&spec->cmd_queue);
                 if (lu_task == NULL)                  if (lu_task == NULL)
                         break;                          break;
                ISTGT_LOG("CmdSN(%u), OP=0x%x, ElapsedTime=%u cleared\n",                ISTGT_LOG("CmdSN(%u), OP=0x%x, ElapsedTime=%lu cleared\n",
                     lu_task->lu_cmd.CmdSN,                      lu_task->lu_cmd.CmdSN,
                     lu_task->lu_cmd.cdb[0],                      lu_task->lu_cmd.cdb[0],
                    (now - lu_task->create_time));                    (unsigned long) (now - lu_task->create_time));
                 rc = istgt_lu_destroy_task(lu_task);                  rc = istgt_lu_destroy_task(lu_task);
                 if (rc < 0) {                  if (rc < 0) {
                         MTX_UNLOCK(&spec->cmd_queue_mutex);                          MTX_UNLOCK(&spec->cmd_queue_mutex);
Line 4743  istgt_lu_disk_queue_clear_all(ISTGT_LU_Ptr lu, int lun Line 4850  istgt_lu_disk_queue_clear_all(ISTGT_LU_Ptr lu, int lun
                 /* conn had gone? */                  /* conn had gone? */
                 rc = pthread_mutex_trylock(&lu_task->trans_mutex);                  rc = pthread_mutex_trylock(&lu_task->trans_mutex);
                 if (rc == 0) {                  if (rc == 0) {
                        ISTGT_LOG("CmdSN(%u), OP=0x%x, ElapsedTime=%u aborted\n",                        ISTGT_LOG("CmdSN(%u), OP=0x%x, ElapsedTime=%lu aborted\n",
                             lu_task->lu_cmd.CmdSN,                              lu_task->lu_cmd.CmdSN,
                             lu_task->lu_cmd.cdb[0],                              lu_task->lu_cmd.cdb[0],
                            (now - lu_task->create_time));                            (unsigned long) (now - lu_task->create_time));
                         /* force error */                          /* force error */
                         lu_task->error = 1;                          lu_task->error = 1;
                         lu_task->abort = 1;                          lu_task->abort = 1;
Line 4782  istgt_lu_disk_queue(CONN_Ptr conn, ISTGT_LU_CMD_Ptr lu Line 4889  istgt_lu_disk_queue(CONN_Ptr conn, ISTGT_LU_CMD_Ptr lu
         int data_len;          int data_len;
         int data_alloc_len;          int data_alloc_len;
         uint8_t *sense_data;          uint8_t *sense_data;
        int *sense_len;        size_t *sense_len;
         int lun_i;          int lun_i;
         int maxq;          int maxq;
         int qcnt;          int qcnt;
Line 4811  istgt_lu_disk_queue(CONN_Ptr conn, ISTGT_LU_CMD_Ptr lu Line 4918  istgt_lu_disk_queue(CONN_Ptr conn, ISTGT_LU_CMD_Ptr lu
 #endif /* ISTGT_TRACE_DISK */  #endif /* ISTGT_TRACE_DISK */
                 if (cdb[0] == SPC_INQUIRY) {                  if (cdb[0] == SPC_INQUIRY) {
                         allocation_len = DGET16(&cdb[3]);                          allocation_len = DGET16(&cdb[3]);
                        if (allocation_len > data_alloc_len) {                        if (allocation_len > (size_t) data_alloc_len) {
                                 ISTGT_ERRLOG("data_alloc_len(%d) too small\n",                                  ISTGT_ERRLOG("data_alloc_len(%d) too small\n",
                                     data_alloc_len);                                      data_alloc_len);
                                 lu_cmd->status = ISTGT_SCSI_STATUS_CHECK_CONDITION;                                  lu_cmd->status = ISTGT_SCSI_STATUS_CHECK_CONDITION;
Line 4825  istgt_lu_disk_queue(CONN_Ptr conn, ISTGT_LU_CMD_Ptr lu Line 4932  istgt_lu_disk_queue(CONN_Ptr conn, ISTGT_LU_CMD_Ptr lu
                         memset(&data[1], 0, data_len - 1);                          memset(&data[1], 0, data_len - 1);
                         /* ADDITIONAL LENGTH */                          /* ADDITIONAL LENGTH */
                         data[4] = data_len - 5;                          data[4] = data_len - 5;
                        lu_cmd->data_len = DMIN32(data_len, lu_cmd->transfer_len);                        lu_cmd->data_len = DMIN32((size_t)data_len, lu_cmd->transfer_len);
                         lu_cmd->status = ISTGT_SCSI_STATUS_GOOD;                          lu_cmd->status = ISTGT_SCSI_STATUS_GOOD;
                         return ISTGT_LU_TASK_RESULT_IMMEDIATE;                          return ISTGT_LU_TASK_RESULT_IMMEDIATE;
                 } else {                  } else {
Line 4856  istgt_lu_disk_queue(CONN_Ptr conn, ISTGT_LU_CMD_Ptr lu Line 4963  istgt_lu_disk_queue(CONN_Ptr conn, ISTGT_LU_CMD_Ptr lu
                 return -1;                  return -1;
         }          }
   
         MTX_LOCK(&lu->queue_mutex);  
         /* enqueue SCSI command */          /* enqueue SCSI command */
         MTX_LOCK(&spec->cmd_queue_mutex);          MTX_LOCK(&spec->cmd_queue_mutex);
         rc = istgt_queue_count(&spec->cmd_queue);          rc = istgt_queue_count(&spec->cmd_queue);
         maxq = spec->queue_depth * lu->istgt->MaxSessions;          maxq = spec->queue_depth * lu->istgt->MaxSessions;
         if (rc > maxq) {          if (rc > maxq) {
                 MTX_UNLOCK(&spec->cmd_queue_mutex);                  MTX_UNLOCK(&spec->cmd_queue_mutex);
                 MTX_UNLOCK(&lu->queue_mutex);  
                 lu_cmd->data_len = 0;                  lu_cmd->data_len = 0;
                 lu_cmd->status = ISTGT_SCSI_STATUS_TASK_SET_FULL;                  lu_cmd->status = ISTGT_SCSI_STATUS_TASK_SET_FULL;
                 rc = istgt_lu_destroy_task(lu_task);                  rc = istgt_lu_destroy_task(lu_task);
Line 4907  istgt_lu_disk_queue(CONN_Ptr conn, ISTGT_LU_CMD_Ptr lu Line 5012  istgt_lu_disk_queue(CONN_Ptr conn, ISTGT_LU_CMD_Ptr lu
         }          }
         MTX_UNLOCK(&spec->cmd_queue_mutex);          MTX_UNLOCK(&spec->cmd_queue_mutex);
         if (rc < 0) {          if (rc < 0) {
                 MTX_UNLOCK(&lu->queue_mutex);  
                 ISTGT_ERRLOG("queue_enqueue() failed\n");                  ISTGT_ERRLOG("queue_enqueue() failed\n");
         error_return:          error_return:
                 rc = istgt_lu_destroy_task(lu_task);                  rc = istgt_lu_destroy_task(lu_task);
Line 4919  istgt_lu_disk_queue(CONN_Ptr conn, ISTGT_LU_CMD_Ptr lu Line 5023  istgt_lu_disk_queue(CONN_Ptr conn, ISTGT_LU_CMD_Ptr lu
         }          }
   
         /* notify LUN thread */          /* notify LUN thread */
           MTX_LOCK(&lu->queue_mutex);
           lu->queue_check = 1;
         rc = pthread_cond_broadcast(&lu->queue_cond);          rc = pthread_cond_broadcast(&lu->queue_cond);
         MTX_UNLOCK(&lu->queue_mutex);          MTX_UNLOCK(&lu->queue_mutex);
         if (rc != 0) {          if (rc != 0) {
Line 4989  istgt_lu_disk_queue_start(ISTGT_LU_Ptr lu, int lun) Line 5095  istgt_lu_disk_queue_start(ISTGT_LU_Ptr lu, int lun)
         CONN_Ptr conn;          CONN_Ptr conn;
         ISTGT_LU_CMD_Ptr lu_cmd;          ISTGT_LU_CMD_Ptr lu_cmd;
         struct timespec abstime;          struct timespec abstime;
        time_t now;        time_t start, now;
         uint8_t *iobuf;          uint8_t *iobuf;
         char tmp[1];          char tmp[1];
         int abort_task = 0;          int abort_task = 0;
Line 5143  istgt_lu_disk_queue_start(ISTGT_LU_Ptr lu, int lun) Line 5249  istgt_lu_disk_queue_start(ISTGT_LU_Ptr lu, int lun)
                         abstime.tv_sec = 0;                          abstime.tv_sec = 0;
                         abstime.tv_nsec = 0;                          abstime.tv_nsec = 0;
   
                         MTX_LOCK(&lu_task->trans_mutex);  
                         MTX_LOCK(&conn->task_queue_mutex);                          MTX_LOCK(&conn->task_queue_mutex);
                         rc = istgt_queue_enqueue(&conn->task_queue, lu_task);                          rc = istgt_queue_enqueue(&conn->task_queue, lu_task);
                         MTX_UNLOCK(&conn->task_queue_mutex);                          MTX_UNLOCK(&conn->task_queue_mutex);
Line 5159  istgt_lu_disk_queue_start(ISTGT_LU_Ptr lu, int lun) Line 5264  istgt_lu_disk_queue_start(ISTGT_LU_Ptr lu, int lun)
                                 goto error_return;                                  goto error_return;
                         }                          }
   
                        now = time(NULL);                        start = now = time(NULL);
                         abstime.tv_sec = now + (lu_task->condwait / 1000);                          abstime.tv_sec = now + (lu_task->condwait / 1000);
                         abstime.tv_nsec = (lu_task->condwait % 1000) * 1000000;                          abstime.tv_nsec = (lu_task->condwait % 1000) * 1000000;
 #if 0  #if 0
                         ISTGT_LOG("wait CmdSN=%u\n", lu_task->lu_cmd.CmdSN);                          ISTGT_LOG("wait CmdSN=%u\n", lu_task->lu_cmd.CmdSN);
 #endif  #endif
                           MTX_LOCK(&lu_task->trans_mutex);
                         MTX_LOCK(&spec->wait_lu_task_mutex);                          MTX_LOCK(&spec->wait_lu_task_mutex);
                         spec->wait_lu_task = lu_task;                          spec->wait_lu_task = lu_task;
                         MTX_UNLOCK(&spec->wait_lu_task_mutex);                          MTX_UNLOCK(&spec->wait_lu_task_mutex);
                           rc = 0;
                         while (lu_task->req_transfer_out == 1) {                          while (lu_task->req_transfer_out == 1) {
                                 rc = pthread_cond_timedwait(&lu_task->trans_cond,                                  rc = pthread_cond_timedwait(&lu_task->trans_cond,
                                     &lu_task->trans_mutex,                                      &lu_task->trans_mutex,
Line 5179  istgt_lu_disk_queue_start(ISTGT_LU_Ptr lu, int lun) Line 5286  istgt_lu_disk_queue_start(ISTGT_LU_Ptr lu, int lun)
                                                 spec->wait_lu_task = NULL;                                                  spec->wait_lu_task = NULL;
                                                 MTX_UNLOCK(&spec->wait_lu_task_mutex);                                                  MTX_UNLOCK(&spec->wait_lu_task_mutex);
                                                 MTX_UNLOCK(&lu_task->trans_mutex);                                                  MTX_UNLOCK(&lu_task->trans_mutex);
                                                ISTGT_ERRLOG("timeout trans_cond CmdSN=%u\n",                                                now = time(NULL);
                                                    lu_task->lu_cmd.CmdSN);                                                ISTGT_ERRLOG("timeout trans_cond CmdSN=%u "
                                                     "(time=%d)\n",
                                                     lu_task->lu_cmd.CmdSN,
                                                     (int)difftime(now, start));
                                                 /* timeout */                                                  /* timeout */
                                                 return -1;                                                  return -1;
                                         }                                          }
Line 5215  istgt_lu_disk_queue_start(ISTGT_LU_Ptr lu, int lun) Line 5325  istgt_lu_disk_queue_start(ISTGT_LU_Ptr lu, int lun)
                                 }                                  }
                                 if (rc == ETIMEDOUT) {                                  if (rc == ETIMEDOUT) {
                                         lu_task->error = 1;                                          lu_task->error = 1;
                                        ISTGT_ERRLOG("timeout trans_cond CmdSN=%u\n",                                        now = time(NULL);
                                            lu_task->lu_cmd.CmdSN);                                        ISTGT_ERRLOG("timeout trans_cond CmdSN=%u (time=%d)\n",
                                             lu_task->lu_cmd.CmdSN, (int)difftime(now, start));
                                         return -1;                                          return -1;
                                 }                                  }
                                 lu_task->error = 1;                                  lu_task->error = 1;
Line 5359  istgt_lu_disk_execute(CONN_Ptr conn, ISTGT_LU_CMD_Ptr  Line 5470  istgt_lu_disk_execute(CONN_Ptr conn, ISTGT_LU_CMD_Ptr 
         uint32_t transfer_len;          uint32_t transfer_len;
         uint32_t parameter_len;          uint32_t parameter_len;
         uint8_t *sense_data;          uint8_t *sense_data;
        int *sense_len;        size_t *sense_len;
         int lun_i;          int lun_i;
         int rc;          int rc;
   
Line 5386  istgt_lu_disk_execute(CONN_Ptr conn, ISTGT_LU_CMD_Ptr  Line 5497  istgt_lu_disk_execute(CONN_Ptr conn, ISTGT_LU_CMD_Ptr 
 #endif /* ISTGT_TRACE_DISK */  #endif /* ISTGT_TRACE_DISK */
                 if (cdb[0] == SPC_INQUIRY) {                  if (cdb[0] == SPC_INQUIRY) {
                         allocation_len = DGET16(&cdb[3]);                          allocation_len = DGET16(&cdb[3]);
                        if (allocation_len > data_alloc_len) {                        if (allocation_len > (size_t) data_alloc_len) {
                                 ISTGT_ERRLOG("data_alloc_len(%d) too small\n",                                  ISTGT_ERRLOG("data_alloc_len(%d) too small\n",
                                     data_alloc_len);                                      data_alloc_len);
                                 lu_cmd->status = ISTGT_SCSI_STATUS_CHECK_CONDITION;                                  lu_cmd->status = ISTGT_SCSI_STATUS_CHECK_CONDITION;
Line 5400  istgt_lu_disk_execute(CONN_Ptr conn, ISTGT_LU_CMD_Ptr  Line 5511  istgt_lu_disk_execute(CONN_Ptr conn, ISTGT_LU_CMD_Ptr 
                         memset(&data[1], 0, data_len - 1);                          memset(&data[1], 0, data_len - 1);
                         /* ADDITIONAL LENGTH */                          /* ADDITIONAL LENGTH */
                         data[4] = data_len - 5;                          data[4] = data_len - 5;
                        lu_cmd->data_len = DMIN32(data_len, lu_cmd->transfer_len);                        lu_cmd->data_len = DMIN32((size_t)data_len, lu_cmd->transfer_len);
                         lu_cmd->status = ISTGT_SCSI_STATUS_GOOD;                          lu_cmd->status = ISTGT_SCSI_STATUS_GOOD;
                         return 0;                          return 0;
                 } else {                  } else {
Line 5478  istgt_lu_disk_execute(CONN_Ptr conn, ISTGT_LU_CMD_Ptr  Line 5589  istgt_lu_disk_execute(CONN_Ptr conn, ISTGT_LU_CMD_Ptr 
                         return -1;                          return -1;
                 }                  }
                 allocation_len = DGET16(&cdb[3]);                  allocation_len = DGET16(&cdb[3]);
                if (allocation_len > data_alloc_len) {                if (allocation_len > (size_t) data_alloc_len) {
                         ISTGT_ERRLOG("data_alloc_len(%d) too small\n",                          ISTGT_ERRLOG("data_alloc_len(%d) too small\n",
                             data_alloc_len);                              data_alloc_len);
                         lu_cmd->status = ISTGT_SCSI_STATUS_CHECK_CONDITION;                          lu_cmd->status = ISTGT_SCSI_STATUS_CHECK_CONDITION;
Line 5492  istgt_lu_disk_execute(CONN_Ptr conn, ISTGT_LU_CMD_Ptr  Line 5603  istgt_lu_disk_execute(CONN_Ptr conn, ISTGT_LU_CMD_Ptr 
                         break;                          break;
                 }                  }
                 ISTGT_TRACEDUMP(ISTGT_TRACE_DEBUG, "INQUIRY", data, data_len);                  ISTGT_TRACEDUMP(ISTGT_TRACE_DEBUG, "INQUIRY", data, data_len);
                lu_cmd->data_len = DMIN32(data_len, lu_cmd->transfer_len);                lu_cmd->data_len = DMIN32((size_t)data_len, lu_cmd->transfer_len);
                 lu_cmd->status = ISTGT_SCSI_STATUS_GOOD;                  lu_cmd->status = ISTGT_SCSI_STATUS_GOOD;
                 break;                  break;
   
Line 5510  istgt_lu_disk_execute(CONN_Ptr conn, ISTGT_LU_CMD_Ptr  Line 5621  istgt_lu_disk_execute(CONN_Ptr conn, ISTGT_LU_CMD_Ptr 
                         ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "sel=%x\n", sel);                          ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "sel=%x\n", sel);
   
                         allocation_len = DGET32(&cdb[6]);                          allocation_len = DGET32(&cdb[6]);
                        if (allocation_len > data_alloc_len) {                        if (allocation_len > (size_t) data_alloc_len) {
                                 ISTGT_ERRLOG("data_alloc_len(%d) too small\n",                                  ISTGT_ERRLOG("data_alloc_len(%d) too small\n",
                                                         data_alloc_len);                                    data_alloc_len);
                                 lu_cmd->status = ISTGT_SCSI_STATUS_CHECK_CONDITION;                                  lu_cmd->status = ISTGT_SCSI_STATUS_CHECK_CONDITION;
                                 return -1;                                  return -1;
                         }                          }
Line 5530  istgt_lu_disk_execute(CONN_Ptr conn, ISTGT_LU_CMD_Ptr  Line 5641  istgt_lu_disk_execute(CONN_Ptr conn, ISTGT_LU_CMD_Ptr 
                                 break;                                  break;
                         }                          }
                         ISTGT_TRACEDUMP(ISTGT_TRACE_DEBUG, "REPORT LUNS", data, data_len);                          ISTGT_TRACEDUMP(ISTGT_TRACE_DEBUG, "REPORT LUNS", data, data_len);
                        lu_cmd->data_len = DMIN32(data_len, lu_cmd->transfer_len);                        lu_cmd->data_len = DMIN32((size_t)data_len, lu_cmd->transfer_len);
                         lu_cmd->status = ISTGT_SCSI_STATUS_GOOD;                          lu_cmd->status = ISTGT_SCSI_STATUS_GOOD;
                 }                  }
                 break;                  break;
Line 5597  istgt_lu_disk_execute(CONN_Ptr conn, ISTGT_LU_CMD_Ptr  Line 5708  istgt_lu_disk_execute(CONN_Ptr conn, ISTGT_LU_CMD_Ptr 
                                 return -1;                                  return -1;
                         }                          }
                         allocation_len = DGET32(&cdb[10]);                          allocation_len = DGET32(&cdb[10]);
                        if (allocation_len > data_alloc_len) {                        if (allocation_len > (size_t) data_alloc_len) {
                                 ISTGT_ERRLOG("data_alloc_len(%d) too small\n",                                  ISTGT_ERRLOG("data_alloc_len(%d) too small\n",
                                     data_alloc_len);                                      data_alloc_len);
                                 lu_cmd->status = ISTGT_SCSI_STATUS_CHECK_CONDITION;                                  lu_cmd->status = ISTGT_SCSI_STATUS_CHECK_CONDITION;
Line 5609  istgt_lu_disk_execute(CONN_Ptr conn, ISTGT_LU_CMD_Ptr  Line 5720  istgt_lu_disk_execute(CONN_Ptr conn, ISTGT_LU_CMD_Ptr 
                         data[12] = 0;                   /* RTO_EN(1) PROT_EN(0) */                          data[12] = 0;                   /* RTO_EN(1) PROT_EN(0) */
                         memset(&data[13], 0, 32 - (8 + 4 + 1));     /* Reserved */                          memset(&data[13], 0, 32 - (8 + 4 + 1));     /* Reserved */
                         data_len = 32;                          data_len = 32;
                        lu_cmd->data_len = DMIN32(data_len, lu_cmd->transfer_len);                        lu_cmd->data_len = DMIN32((size_t)data_len, lu_cmd->transfer_len);
                         lu_cmd->status = ISTGT_SCSI_STATUS_GOOD;                          lu_cmd->status = ISTGT_SCSI_STATUS_GOOD;
                         break;                          break;
                 case SBC_SAI_READ_LONG_16:                  case SBC_SAI_READ_LONG_16:
Line 5783  istgt_lu_disk_execute(CONN_Ptr conn, ISTGT_LU_CMD_Ptr  Line 5894  istgt_lu_disk_execute(CONN_Ptr conn, ISTGT_LU_CMD_Ptr 
                         subpage = cdb[3];                          subpage = cdb[3];
   
                         allocation_len = cdb[4];                          allocation_len = cdb[4];
                        if (allocation_len > data_alloc_len) {                        if (allocation_len > (size_t) data_alloc_len) {
                                 ISTGT_ERRLOG("data_alloc_len(%d) too small\n",                                  ISTGT_ERRLOG("data_alloc_len(%d) too small\n",
                                     data_alloc_len);                                      data_alloc_len);
                                 lu_cmd->status = ISTGT_SCSI_STATUS_CHECK_CONDITION;                                  lu_cmd->status = ISTGT_SCSI_STATUS_CHECK_CONDITION;
Line 5793  istgt_lu_disk_execute(CONN_Ptr conn, ISTGT_LU_CMD_Ptr  Line 5904  istgt_lu_disk_execute(CONN_Ptr conn, ISTGT_LU_CMD_Ptr 
   
                         data_len = istgt_lu_disk_scsi_mode_sense6(spec, conn, cdb, dbd, pc, page, subpage, data, data_alloc_len);                          data_len = istgt_lu_disk_scsi_mode_sense6(spec, conn, cdb, dbd, pc, page, subpage, data, data_alloc_len);
                         if (data_len < 0) {                          if (data_len < 0) {
                                   /* INVALID FIELD IN CDB */
                                   BUILD_SENSE(ILLEGAL_REQUEST, 0x24, 0x00);
                                 lu_cmd->status = ISTGT_SCSI_STATUS_CHECK_CONDITION;                                  lu_cmd->status = ISTGT_SCSI_STATUS_CHECK_CONDITION;
                                 break;                                  break;
                         }                          }
 #if 0  #if 0
                         istgt_dump("MODE SENSE(6)", data, data_len);                          istgt_dump("MODE SENSE(6)", data, data_len);
 #endif  #endif
                        lu_cmd->data_len = DMIN32(data_len, lu_cmd->transfer_len);                        lu_cmd->data_len = DMIN32((size_t)data_len, lu_cmd->transfer_len);
                         lu_cmd->status = ISTGT_SCSI_STATUS_GOOD;                          lu_cmd->status = ISTGT_SCSI_STATUS_GOOD;
                         break;                          break;
                 }                  }
Line 5833  istgt_lu_disk_execute(CONN_Ptr conn, ISTGT_LU_CMD_Ptr  Line 5946  istgt_lu_disk_execute(CONN_Ptr conn, ISTGT_LU_CMD_Ptr 
                         subpage = cdb[3];                          subpage = cdb[3];
   
                         allocation_len = DGET16(&cdb[7]);                          allocation_len = DGET16(&cdb[7]);
                        if (allocation_len > data_alloc_len) {                        if (allocation_len > (size_t) data_alloc_len) {
                                 ISTGT_ERRLOG("data_alloc_len(%d) too small\n",                                  ISTGT_ERRLOG("data_alloc_len(%d) too small\n",
                                     data_alloc_len);                                      data_alloc_len);
                                 lu_cmd->status = ISTGT_SCSI_STATUS_CHECK_CONDITION;                                  lu_cmd->status = ISTGT_SCSI_STATUS_CHECK_CONDITION;
Line 5843  istgt_lu_disk_execute(CONN_Ptr conn, ISTGT_LU_CMD_Ptr  Line 5956  istgt_lu_disk_execute(CONN_Ptr conn, ISTGT_LU_CMD_Ptr 
   
                         data_len = istgt_lu_disk_scsi_mode_sense10(spec, conn, cdb, llbaa, dbd, pc, page, subpage, data, data_alloc_len);                          data_len = istgt_lu_disk_scsi_mode_sense10(spec, conn, cdb, llbaa, dbd, pc, page, subpage, data, data_alloc_len);
                         if (data_len < 0) {                          if (data_len < 0) {
                                   /* INVALID FIELD IN CDB */
                                   BUILD_SENSE(ILLEGAL_REQUEST, 0x24, 0x00);
                                 lu_cmd->status = ISTGT_SCSI_STATUS_CHECK_CONDITION;                                  lu_cmd->status = ISTGT_SCSI_STATUS_CHECK_CONDITION;
                                 break;                                  break;
                         }                          }
 #if 0  #if 0
                         istgt_dump("MODE SENSE(10)", data, data_len);                          istgt_dump("MODE SENSE(10)", data, data_len);
 #endif  #endif
                        lu_cmd->data_len = DMIN32(data_len, lu_cmd->transfer_len);                        lu_cmd->data_len = DMIN32((size_t)data_len, lu_cmd->transfer_len);
                         lu_cmd->status = ISTGT_SCSI_STATUS_GOOD;                          lu_cmd->status = ISTGT_SCSI_STATUS_GOOD;
                         break;                          break;
                 }                  }
   
 #if 0  
         case SPC_LOG_SELECT:          case SPC_LOG_SELECT:
         case SPC_LOG_SENSE:          case SPC_LOG_SENSE:
                 /* INVALID COMMAND OPERATION CODE */                  /* INVALID COMMAND OPERATION CODE */
                 BUILD_SENSE(ILLEGAL_REQUEST, 0x20, 0x00);                  BUILD_SENSE(ILLEGAL_REQUEST, 0x20, 0x00);
                 lu_cmd->status = ISTGT_SCSI_STATUS_CHECK_CONDITION;                  lu_cmd->status = ISTGT_SCSI_STATUS_CHECK_CONDITION;
                 break;                  break;
 #endif  
   
         case SPC_REQUEST_SENSE:          case SPC_REQUEST_SENSE:
                 {                  {
Line 5883  istgt_lu_disk_execute(CONN_Ptr conn, ISTGT_LU_CMD_Ptr  Line 5996  istgt_lu_disk_execute(CONN_Ptr conn, ISTGT_LU_CMD_Ptr 
                         }                          }
   
                         allocation_len = cdb[4];                          allocation_len = cdb[4];
                        if (allocation_len > data_alloc_len) {                        if (allocation_len > (size_t) data_alloc_len) {
                                 ISTGT_ERRLOG("data_alloc_len(%d) too small\n",                                  ISTGT_ERRLOG("data_alloc_len(%d) too small\n",
                                     data_alloc_len);                                      data_alloc_len);
                                 lu_cmd->status = ISTGT_SCSI_STATUS_CHECK_CONDITION;                                  lu_cmd->status = ISTGT_SCSI_STATUS_CHECK_CONDITION;
Line 5913  istgt_lu_disk_execute(CONN_Ptr conn, ISTGT_LU_CMD_Ptr  Line 6026  istgt_lu_disk_execute(CONN_Ptr conn, ISTGT_LU_CMD_Ptr 
 #if 0  #if 0
                         istgt_dump("REQUEST SENSE", data, data_len);                          istgt_dump("REQUEST SENSE", data, data_len);
 #endif  #endif
                        lu_cmd->data_len = DMIN32(data_len, lu_cmd->transfer_len);                        lu_cmd->data_len = DMIN32((size_t)data_len, lu_cmd->transfer_len);
                         lu_cmd->status = ISTGT_SCSI_STATUS_GOOD;                          lu_cmd->status = ISTGT_SCSI_STATUS_GOOD;
                         break;                          break;
                 }                  }
Line 6416  istgt_lu_disk_execute(CONN_Ptr conn, ISTGT_LU_CMD_Ptr  Line 6529  istgt_lu_disk_execute(CONN_Ptr conn, ISTGT_LU_CMD_Ptr 
                         transfer_len = (uint32_t) DGET8(&cdb[13]);                          transfer_len = (uint32_t) DGET8(&cdb[13]);
                         group_no = BGET8W(&cdb[14], 4, 5);                          group_no = BGET8W(&cdb[14], 4, 5);
   
                        maxlen = ISTGT_LU_WORK_BLOCK_SIZE / spec->blocklen;                        maxlen = ISTGT_LU_WORK_ATS_BLOCK_SIZE / spec->blocklen;
                         if (maxlen > 0xff) {                          if (maxlen > 0xff) {
                                 maxlen = 0xff;                                  maxlen = 0xff;
                         }                          }
Line 6509  istgt_lu_disk_execute(CONN_Ptr conn, ISTGT_LU_CMD_Ptr  Line 6622  istgt_lu_disk_execute(CONN_Ptr conn, ISTGT_LU_CMD_Ptr 
                         break;                          break;
                 }                  }
   
           case SBC_READ_DEFECT_DATA_10:
                   {
                           int req_plist, req_glist, list_format;
   
                           if (lu_cmd->R_bit == 0) {
                                   ISTGT_ERRLOG("R_bit == 0\n");
                                   lu_cmd->status = ISTGT_SCSI_STATUS_CHECK_CONDITION;
                                   return -1;
                           }
   
                           req_plist = BGET8(&cdb[2], 4);
                           req_glist = BGET8(&cdb[2], 3);
                           list_format = BGET8W(&cdb[2], 2, 3);
   
                           allocation_len = (uint32_t) DGET16(&cdb[7]);
                           if (allocation_len > (size_t) data_alloc_len) {
                                   ISTGT_ERRLOG("data_alloc_len(%d) too small\n",
                                       data_alloc_len);
                                   lu_cmd->status = ISTGT_SCSI_STATUS_CHECK_CONDITION;
                                   return -1;
                           }
                           memset(data, 0, allocation_len);
   
                           data_len = istgt_lu_disk_scsi_read_defect10(spec, conn, cdb,
                               req_plist, req_glist, list_format, data, data_alloc_len);
                           if (data_len < 0) {
                                   lu_cmd->status = ISTGT_SCSI_STATUS_CHECK_CONDITION;
                                   break;
                           }
                           lu_cmd->data_len = DMIN32((size_t)data_len, lu_cmd->transfer_len);
                           lu_cmd->status = ISTGT_SCSI_STATUS_GOOD;
                           break;
                   }
   
           case SBC_READ_DEFECT_DATA_12:
                   {
                           int req_plist, req_glist, list_format;
   
                           if (lu_cmd->R_bit == 0) {
                                   ISTGT_ERRLOG("R_bit == 0\n");
                                   lu_cmd->status = ISTGT_SCSI_STATUS_CHECK_CONDITION;
                                   return -1;
                           }
   
                           req_plist = BGET8(&cdb[2], 4);
                           req_glist = BGET8(&cdb[2], 3);
                           list_format = BGET8W(&cdb[2], 2, 3);
   
                           allocation_len = DGET32(&cdb[6]);
                           if (allocation_len > (size_t) data_alloc_len) {
                                   ISTGT_ERRLOG("data_alloc_len(%d) too small\n",
                                       data_alloc_len);
                                   lu_cmd->status = ISTGT_SCSI_STATUS_CHECK_CONDITION;
                                   return -1;
                           }
                           memset(data, 0, allocation_len);
   
                           data_len = istgt_lu_disk_scsi_read_defect12(spec, conn, cdb,
                               req_plist, req_glist, list_format, data, data_alloc_len);
                           if (data_len < 0) {
                                   lu_cmd->status = ISTGT_SCSI_STATUS_CHECK_CONDITION;
                                   break;
                           }
                           lu_cmd->data_len = DMIN32((size_t)data_len, lu_cmd->transfer_len);
                           lu_cmd->status = ISTGT_SCSI_STATUS_GOOD;
                           break;
                   }
   
         case SCC_MAINTENANCE_IN:          case SCC_MAINTENANCE_IN:
                 ISTGT_TRACELOG(ISTGT_TRACE_SCSI, "MAINTENANCE_IN\n");                  ISTGT_TRACELOG(ISTGT_TRACE_SCSI, "MAINTENANCE_IN\n");
                 switch (BGET8W(&cdb[1], 4, 5)) { /* SERVICE ACTION */                  switch (BGET8W(&cdb[1], 4, 5)) { /* SERVICE ACTION */
Line 6520  istgt_lu_disk_execute(CONN_Ptr conn, ISTGT_LU_CMD_Ptr  Line 6701  istgt_lu_disk_execute(CONN_Ptr conn, ISTGT_LU_CMD_Ptr 
                                 return -1;                                  return -1;
                         }                          }
                         allocation_len = DGET32(&cdb[6]);                          allocation_len = DGET32(&cdb[6]);
                        if (allocation_len > data_alloc_len) {                        if (allocation_len > (size_t) data_alloc_len) {
                                 ISTGT_ERRLOG("data_alloc_len(%d) too small\n",                                  ISTGT_ERRLOG("data_alloc_len(%d) too small\n",
                                     data_alloc_len);                                      data_alloc_len);
                                 lu_cmd->status = ISTGT_SCSI_STATUS_CHECK_CONDITION;                                  lu_cmd->status = ISTGT_SCSI_STATUS_CHECK_CONDITION;
Line 6534  istgt_lu_disk_execute(CONN_Ptr conn, ISTGT_LU_CMD_Ptr  Line 6715  istgt_lu_disk_execute(CONN_Ptr conn, ISTGT_LU_CMD_Ptr 
                         }                          }
                         ISTGT_TRACEDUMP(ISTGT_TRACE_DEBUG,                          ISTGT_TRACEDUMP(ISTGT_TRACE_DEBUG,
                             "REPORT_TARGET_PORT_GROUPS", data, data_len);                              "REPORT_TARGET_PORT_GROUPS", data, data_len);
                        lu_cmd->data_len = DMIN32(data_len, lu_cmd->transfer_len);                        lu_cmd->data_len = DMIN32((size_t)data_len, lu_cmd->transfer_len);
                         lu_cmd->status = ISTGT_SCSI_STATUS_GOOD;                          lu_cmd->status = ISTGT_SCSI_STATUS_GOOD;
                         break;                          break;
                 default:                  default:
Line 6623  istgt_lu_disk_execute(CONN_Ptr conn, ISTGT_LU_CMD_Ptr  Line 6804  istgt_lu_disk_execute(CONN_Ptr conn, ISTGT_LU_CMD_Ptr 
   
                         sa = BGET8W(&cdb[1], 4, 5);                          sa = BGET8W(&cdb[1], 4, 5);
                         allocation_len = DGET16(&cdb[7]);                          allocation_len = DGET16(&cdb[7]);
                        if (allocation_len > data_alloc_len) {                        if (allocation_len > (size_t) data_alloc_len) {
                                 ISTGT_ERRLOG("data_alloc_len(%d) too small\n",                                  ISTGT_ERRLOG("data_alloc_len(%d) too small\n",
                                     data_alloc_len);                                      data_alloc_len);
                                 lu_cmd->status = ISTGT_SCSI_STATUS_CHECK_CONDITION;                                  lu_cmd->status = ISTGT_SCSI_STATUS_CHECK_CONDITION;
Line 6638  istgt_lu_disk_execute(CONN_Ptr conn, ISTGT_LU_CMD_Ptr  Line 6819  istgt_lu_disk_execute(CONN_Ptr conn, ISTGT_LU_CMD_Ptr 
                         }                          }
                         ISTGT_TRACEDUMP(ISTGT_TRACE_DEBUG,                          ISTGT_TRACEDUMP(ISTGT_TRACE_DEBUG,
                             "PERSISTENT_RESERVE_IN", data, data_len);                              "PERSISTENT_RESERVE_IN", data, data_len);
                        lu_cmd->data_len = DMIN32(data_len, lu_cmd->transfer_len);                        lu_cmd->data_len = DMIN32((size_t)data_len, lu_cmd->transfer_len);
                         lu_cmd->status = ISTGT_SCSI_STATUS_GOOD;                          lu_cmd->status = ISTGT_SCSI_STATUS_GOOD;
                 }                  }
                 break;                  break;
Line 6690  istgt_lu_disk_execute(CONN_Ptr conn, ISTGT_LU_CMD_Ptr  Line 6871  istgt_lu_disk_execute(CONN_Ptr conn, ISTGT_LU_CMD_Ptr 
                 break;                  break;
   
         /* XXX TODO: fix */          /* XXX TODO: fix */
           case 0x85: /* ATA PASS-THROUGH(16) */
           case 0xA1: /* ATA PASS-THROUGH(12) */
                   /* INVALID COMMAND OPERATION CODE */
                   BUILD_SENSE(ILLEGAL_REQUEST, 0x20, 0x00);
                   lu_cmd->status = ISTGT_SCSI_STATUS_CHECK_CONDITION;
                   break;
         case SPC_EXTENDED_COPY:          case SPC_EXTENDED_COPY:
                 /* INVALID COMMAND OPERATION CODE */                  /* INVALID COMMAND OPERATION CODE */
                 BUILD_SENSE(ILLEGAL_REQUEST, 0x20, 0x00);                  BUILD_SENSE(ILLEGAL_REQUEST, 0x20, 0x00);

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


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