From bde85a4b5796d3827292a641575f7bf2266c52a5 Mon Sep 17 00:00:00 2001 From: Peter Lieven Date: Tue, 6 Nov 2012 08:53:38 +0100 Subject: [PATCH 01/21] INIT allow iscsi_context = NULL in iscsi_set_error() qemu-kvm calls iscsi_parse_url_full() with iscsi = NULL. In case there is an invalid URL specified qemu-kvm segfaults when it tries to set iscsi->error_string. I tried to patch this in qemu-kvm, but the initiator_name is dirived from the target name so this seemed to be the easier approach. --- lib/init.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/lib/init.c b/lib/init.c index d7d32d2..8c489a7 100644 --- a/lib/init.c +++ b/lib/init.c @@ -251,8 +251,13 @@ iscsi_set_error(struct iscsi_context *iscsi, const char *error_string, ...) } va_end(ap); - strncpy(iscsi->error_string,errstr,MAX_STRING_SIZE); - DPRINTF(iscsi,1,"%s",iscsi->error_string); + if (iscsi != NULL) { + strncpy(iscsi->error_string,errstr,MAX_STRING_SIZE); + DPRINTF(iscsi,1,"%s",iscsi->error_string); + } + else { + fprintf(stderr,"libiscsi: %s\n", errstr); + } } void From d81bcd7b386670ee8ef0a880385a7258b62230cf Mon Sep 17 00:00:00 2001 From: Ronnie Sahlberg Date: Tue, 6 Nov 2012 06:20:11 -0800 Subject: [PATCH 02/21] Dont print to stderr from _set_error if iscsi is NULL If iscsi is NULL then just do nothing and dont log to stderr. Our caller might have closed stderr or worse, re-used fd 2 for something else. --- lib/init.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/lib/init.c b/lib/init.c index 8c489a7..56c7222 100644 --- a/lib/init.c +++ b/lib/init.c @@ -255,9 +255,6 @@ iscsi_set_error(struct iscsi_context *iscsi, const char *error_string, ...) strncpy(iscsi->error_string,errstr,MAX_STRING_SIZE); DPRINTF(iscsi,1,"%s",iscsi->error_string); } - else { - fprintf(stderr,"libiscsi: %s\n", errstr); - } } void From c10ae3ae3e59eb23584c5a24c240e935cae2c2c5 Mon Sep 17 00:00:00 2001 From: Ronnie Sahlberg Date: Tue, 6 Nov 2012 18:40:30 -0800 Subject: [PATCH 03/21] New version 1.7.0 - Lots of additional tests. - ld_iscsi updates and bugfixes. - Fix a protocol bug where we might send > FirstBurstLength amount of data as unsolicited data. - Tcp keepalive improvements. - Debugging framework. - Add support for redirection. - Fix reconnect bug where we would incorrectly re-queue DATA-OUT PDUs after reconnect. - Add a new iscsi-readcapacity16 command. - Squelch a huge number of compiler warnings. --- packaging/RPM/libiscsi.spec.in | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/packaging/RPM/libiscsi.spec.in b/packaging/RPM/libiscsi.spec.in index 3a9089a..64e2e23 100644 --- a/packaging/RPM/libiscsi.spec.in +++ b/packaging/RPM/libiscsi.spec.in @@ -1,6 +1,6 @@ Name: libiscsi Summary: iSCSI client library -Version: 1.6.0 +Version: 1.7.0 Release: 1GITHASH%{?dist} License: LGPLv2+ Group: System Environment/Libraries @@ -91,6 +91,17 @@ The libiscsi-devel package includes the header files for libiscsi. %{_libdir}/libiscsi.so %changelog +* Tue Nov 6 2012 : 1.7.0 + - Lots of additional tests. + - ld_iscsi updates and bugfixes. + - Fix a protocol bug where we might send > FirstBurstLength amount of data + as unsolicited data. + - Tcp keepalive improvements. + - Debugging framework. + - Add support for redirection. + - Fix reconnect bug where we would incorrectly re-queue DATA-OUT PDUs after reconnecting. + - Add a new iscsi-readcapacity16 command. + - Squelch a huge number of compiler warnings. * Mon Sep 3 2012 : 1.6.0 - Lots of test updates. - Fix for iscsi-ls for removable media/medium not present From 50e7c682bb42878af51213d31bc4efaca9456e5b Mon Sep 17 00:00:00 2001 From: Ronnie Sahlberg Date: Wed, 7 Nov 2012 06:34:38 -0800 Subject: [PATCH 04/21] Add a logging subsystem and change all DPRINTF to ISCSI_LOG Add a mechanism where we can set a logging subsystem that libiscsi can use. Create an example 'log to stderr' that utilities can use for convenience. --- Makefile.am | 3 +- include/iscsi-private.h | 14 ++++++++- include/iscsi.h | 23 ++++++-------- lib/connect.c | 10 +++--- lib/init.c | 17 +++++----- lib/libiscsi.def | 4 ++- lib/libiscsi.syms | 4 ++- lib/logging.c | 64 ++++++++++++++++++++++++++++++++++++++ lib/login.c | 2 +- lib/socket.c | 31 +++++++++--------- src/iscsi-inq.c | 7 +++-- src/iscsi-ls.c | 3 +- src/iscsi-readcapacity16.c | 3 +- 13 files changed, 134 insertions(+), 51 deletions(-) create mode 100644 lib/logging.c diff --git a/Makefile.am b/Makefile.am index b750cdb..9c07405 100644 --- a/Makefile.am +++ b/Makefile.am @@ -26,7 +26,8 @@ lib_LTLIBRARIES = lib/libiscsi.la lib_libiscsi_la_SOURCES = \ lib/connect.c lib/crc32c.c lib/discovery.c lib/init.c \ lib/login.c lib/md5.c lib/nop.c lib/pdu.c lib/scsi-command.c \ - lib/scsi-lowlevel.c lib/socket.c lib/sync.c lib/task_mgmt.c + lib/scsi-lowlevel.c lib/socket.c lib/sync.c lib/task_mgmt.c \ + lib/logging.c SONAME=$(firstword $(subst ., ,$(VERSION))) SOREL=$(shell printf "%d%02d%02d" $(subst ., ,$(VERSION))) diff --git a/include/iscsi-private.h b/include/iscsi-private.h index 5f71613..b34a184 100644 --- a/include/iscsi-private.h +++ b/include/iscsi-private.h @@ -127,7 +127,9 @@ struct iscsi_context { int lun; int no_auto_reconnect; int reconnect_deferred; - int debug; + + int log_level; + iscsi_log_fn log_fn; }; #define ISCSI_PDU_IMMEDIATE 0x40 @@ -284,6 +286,16 @@ struct scsi_task *iscsi_scsi_get_task_from_pdu(struct iscsi_pdu *pdu); void iscsi_set_noautoreconnect(struct iscsi_context *iscsi, int state); +#define ISCSI_LOG(iscsi, level, format, args...) \ + do { \ + if (level <= iscsi->log_level && iscsi->log_fn) { \ + iscsi_log_message(iscsi, level, format, ## args); \ + } \ + } while (0) + +void +iscsi_log_message(struct iscsi_context *iscsi, int level, const char *format, ...); + #ifdef __cplusplus } #endif diff --git a/include/iscsi.h b/include/iscsi.h index 0ab4b84..7b8db1a 100644 --- a/include/iscsi.h +++ b/include/iscsi.h @@ -966,18 +966,6 @@ iscsi_scsi_task_cancel(struct iscsi_context *iscsi, EXTERN void iscsi_scsi_cancel_all_tasks(struct iscsi_context *iscsi); -#define DPRINTF(iscsi,level,fmt,args...) \ - do { \ - if ((iscsi)->debug >= level) { \ - fprintf(stderr,"libiscsi: "); \ - fprintf(stderr, (fmt), ##args); \ - if (iscsi->target_name[0]) { \ - fprintf(stderr," [%s]",iscsi->target_name); \ - } \ - fprintf(stderr,"\n"); \ - } \ - } while (0); - /* * This function is to set the debugging level where level is * @@ -987,9 +975,18 @@ iscsi_scsi_cancel_all_tasks(struct iscsi_context *iscsi); * 3 = user set variables * 4 = function calls * 5 = ... + * 10 = everything */ EXTERN void -iscsi_set_debug(struct iscsi_context *iscsi, int level); +iscsi_set_log_level(struct iscsi_context *iscsi, int level); + +typedef void (*iscsi_log_fn)(int level, const char *mesage); + +/* Set the logging function to use */ +EXTERN void iscsi_set_log_fn(struct iscsi_context *iscsi, iscsi_log_fn fn); + +/* predefined log function that just writes to stderr */ +EXTERN void iscsi_log_to_stderr(int level, const char *message); /* * This function is to set the TCP_USER_TIMEOUT option. It has to be called after iscsi diff --git a/lib/connect.c b/lib/connect.c index 4fce89c..c43a7c6 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -177,7 +177,7 @@ int iscsi_reconnect(struct iscsi_context *old_iscsi) { struct iscsi_context *iscsi = old_iscsi; - DPRINTF(iscsi,2,"reconnect initiated"); + ISCSI_LOG(iscsi, 2, "reconnect initiated"); /* This is mainly for tests, where we do not want to automatically reconnect but rather want the commands to fail with an error @@ -235,10 +235,10 @@ try_again: iscsi->lun = old_iscsi->lun; - strncpy(iscsi->portal,old_iscsi->portal,MAX_STRING_SIZE); - - iscsi->debug = old_iscsi->debug; + strncpy(iscsi->portal,old_iscsi->portal, MAX_STRING_SIZE); + iscsi->log_level = old_iscsi->log_level; + iscsi->log_fn = old_iscsi->log_fn; iscsi->tcp_user_timeout = old_iscsi->tcp_user_timeout; iscsi->tcp_keepidle = old_iscsi->tcp_keepidle; iscsi->tcp_keepcnt = old_iscsi->tcp_keepcnt; @@ -254,7 +254,7 @@ try_again: if (backoff > 30) { backoff=30; } - DPRINTF(iscsi,1,"reconnect try %d failed, waiting %d seconds",retry,backoff); + ISCSI_LOG(iscsi, 1, "reconnect try %d failed, waiting %d seconds",retry,backoff); iscsi_destroy_context(iscsi); sleep(backoff); retry++; diff --git a/lib/init.c b/lib/init.c index 56c7222..e3b33c8 100644 --- a/lib/init.c +++ b/lib/init.c @@ -76,7 +76,8 @@ iscsi_create_context(const char *initiator_name) iscsi->tcp_keepidle=30; if (getenv("LIBISCSI_DEBUG") != NULL) { - iscsi_set_debug(iscsi,atoi(getenv("LIBISCSI_DEBUG"))); + iscsi_set_log_level(iscsi, atoi(getenv("LIBISCSI_DEBUG"))); + iscsi_set_log_fn(iscsi, iscsi_log_to_stderr); } if (getenv("LIBISCSI_TCP_USER_TIMEOUT") != NULL) { @@ -243,25 +244,25 @@ void iscsi_set_error(struct iscsi_context *iscsi, const char *error_string, ...) { va_list ap; - char errstr[MAX_STRING_SIZE+1] = {0}; + char errstr[MAX_STRING_SIZE + 1] = {0}; va_start(ap, error_string); if (vsnprintf(errstr, MAX_STRING_SIZE, error_string, ap) < 0) { - strncpy(errstr,"could not format error string!",MAX_STRING_SIZE); + strncpy(errstr, "could not format error string!", MAX_STRING_SIZE); } va_end(ap); if (iscsi != NULL) { - strncpy(iscsi->error_string,errstr,MAX_STRING_SIZE); - DPRINTF(iscsi,1,"%s",iscsi->error_string); + strncpy(iscsi->error_string, errstr,MAX_STRING_SIZE); + ISCSI_LOG(iscsi, 1, "%s",iscsi->error_string); } } void -iscsi_set_debug(struct iscsi_context *iscsi, int level) +iscsi_set_log_level(struct iscsi_context *iscsi, int level) { - iscsi->debug = level; - DPRINTF(iscsi,2,"set debug level to %d",level); + iscsi->log_level = level; + ISCSI_LOG(iscsi, 2, "set log level to %d", level); } const char * diff --git a/lib/libiscsi.def b/lib/libiscsi.def index c3a915c..dfa4838 100644 --- a/lib/libiscsi.def +++ b/lib/libiscsi.def @@ -17,6 +17,7 @@ iscsi_get_target_address iscsi_inquiry_sync iscsi_inquiry_task iscsi_is_logged_in +iscsi_log_to_stderr iscsi_login_async iscsi_login_sync iscsi_logout_async @@ -64,7 +65,8 @@ iscsi_scsi_command_sync iscsi_scsi_task_cancel iscsi_service iscsi_set_alias -iscsi_set_debug +iscsi_set_log_level +iscsi_set_log_fn iscsi_set_header_digest iscsi_set_initiator_username_pwd iscsi_set_isid_en diff --git a/lib/libiscsi.syms b/lib/libiscsi.syms index ddf3e1a..74c33fe 100644 --- a/lib/libiscsi.syms +++ b/lib/libiscsi.syms @@ -15,6 +15,7 @@ iscsi_get_target_address iscsi_inquiry_sync iscsi_inquiry_task iscsi_is_logged_in +iscsi_log_to_stderr iscsi_login_async iscsi_login_sync iscsi_logout_async @@ -62,7 +63,8 @@ iscsi_scsi_command_sync iscsi_scsi_task_cancel iscsi_service iscsi_set_alias -iscsi_set_debug +iscsi_set_log_level +iscsi_set_log_fn iscsi_set_header_digest iscsi_set_initiator_username_pwd iscsi_set_isid_en diff --git a/lib/logging.c b/lib/logging.c new file mode 100644 index 0000000..0be678a --- /dev/null +++ b/lib/logging.c @@ -0,0 +1,64 @@ +/* + Copyright (C) 2012 by Ronnie Sahlberg + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program; if not, see . +*/ + +#if defined(WIN32) +#else +#include +#endif + +#include +#include +#include +#include "iscsi.h" +#include "iscsi-private.h" +#include "scsi-lowlevel.h" + +void +iscsi_log_to_stderr(int level, const char *message) +{ + fprintf(stderr, "libiscsi:%d %s\n", level, message); +} + +void +iscsi_set_log_fn(struct iscsi_context *iscsi, iscsi_log_fn fn) +{ + iscsi->log_fn = fn; +} + +void +iscsi_log_message(struct iscsi_context *iscsi, int level, const char *format, ...) +{ + va_list ap; + static char message[1024]; + int ret; + + if (iscsi->log_fn == NULL) { + return; + } + + va_start(ap, format); + ret = vsnprintf(message, 1024, format, ap); + va_end(ap); + + if (ret < 0) { + return; + } + + iscsi->log_fn(level, message); +} + + diff --git a/lib/login.c b/lib/login.c index 5da4d21..d258337 100644 --- a/lib/login.c +++ b/lib/login.c @@ -1075,7 +1075,7 @@ iscsi_process_login_reply(struct iscsi_context *iscsi, struct iscsi_pdu *pdu, } if (status == SCSI_STATUS_REDIRECT && iscsi->target_address) { - DPRINTF(iscsi,2,"target requests redirect to %s",iscsi->target_address); + ISCSI_LOG(iscsi, 2, "target requests redirect to %s",iscsi->target_address); pdu->callback(iscsi, SCSI_STATUS_REDIRECT, NULL, pdu->private_data); return 0; diff --git a/lib/socket.c b/lib/socket.c index a4b1d49..b0274d4 100644 --- a/lib/socket.c +++ b/lib/socket.c @@ -86,7 +86,7 @@ int set_tcp_user_timeout(struct iscsi_context *iscsi) iscsi_set_error(iscsi, "TCP: Failed to set tcp user timeout. Error %s(%d)", strerror(errno), errno); return -1; } - DPRINTF(iscsi,3,"TCP_USER_TIMEOUT set to %d",iscsi->tcp_user_timeout); + ISCSI_LOG(iscsi, 3, "TCP_USER_TIMEOUT set to %d",iscsi->tcp_user_timeout); return 0; } @@ -100,7 +100,7 @@ int set_tcp_syncnt(struct iscsi_context *iscsi) iscsi_set_error(iscsi, "TCP: Failed to set tcp syn retries. Error %s(%d)", strerror(errno), errno); return -1; } - DPRINTF(iscsi,3,"TCP_SYNCNT set to %d",iscsi->tcp_syncnt); + ISCSI_LOG(iscsi, 3, "TCP_SYNCNT set to %d",iscsi->tcp_syncnt); return 0; } @@ -114,7 +114,7 @@ iscsi_connect_async(struct iscsi_context *iscsi, const char *portal, struct addrinfo *ai = NULL; int socksize; - DPRINTF(iscsi,2,"connecting to portal %s",portal); + ISCSI_LOG(iscsi, 2, "connecting to portal %s",portal); if (iscsi->fd != -1) { iscsi_set_error(iscsi, @@ -244,8 +244,9 @@ iscsi_disconnect(struct iscsi_context *iscsi) close(iscsi->fd); - if (iscsi->connected_portal[0]) - DPRINTF(iscsi,2,"disconnected from portal %s",iscsi->connected_portal); + if (iscsi->connected_portal[0]) { + ISCSI_LOG(iscsi, 2, "disconnected from portal %s",iscsi->connected_portal); + } iscsi->fd = -1; iscsi->is_connected = 0; @@ -510,7 +511,7 @@ iscsi_service(struct iscsi_context *iscsi, int revents) return iscsi_service_reconnect_if_loggedin(iscsi); } - DPRINTF(iscsi,2,"connection to %s established",iscsi->connected_portal); + ISCSI_LOG(iscsi, 2, "connection to %s established",iscsi->connected_portal); iscsi->is_connected = 1; if (iscsi->socket_status_cb) { @@ -585,31 +586,31 @@ iscsi_free_iscsi_inqueue(struct iscsi_in_pdu *inqueue) void iscsi_set_tcp_syncnt(struct iscsi_context *iscsi, int value) { iscsi->tcp_syncnt=value; - DPRINTF(iscsi,2,"TCP_SYNCNT will be set to %d on next socket creation",value); + ISCSI_LOG(iscsi, 2, "TCP_SYNCNT will be set to %d on next socket creation",value); } void iscsi_set_tcp_user_timeout(struct iscsi_context *iscsi, int value) { iscsi->tcp_user_timeout=value; - DPRINTF(iscsi,2,"TCP_USER_TIMEOUT will be set to %dms on next socket creation",value); + ISCSI_LOG(iscsi, 2, "TCP_USER_TIMEOUT will be set to %dms on next socket creation",value); } void iscsi_set_tcp_keepidle(struct iscsi_context *iscsi, int value) { iscsi->tcp_keepidle=value; - DPRINTF(iscsi,2,"TCP_KEEPIDLE will be set to %d on next socket creation",value); + ISCSI_LOG(iscsi, 2, "TCP_KEEPIDLE will be set to %d on next socket creation",value); } void iscsi_set_tcp_keepcnt(struct iscsi_context *iscsi, int value) { iscsi->tcp_keepcnt=value; - DPRINTF(iscsi,2,"TCP_KEEPCNT will be set to %d on next socket creation",value); + ISCSI_LOG(iscsi, 2, "TCP_KEEPCNT will be set to %d on next socket creation",value); } void iscsi_set_tcp_keepintvl(struct iscsi_context *iscsi, int value) { iscsi->tcp_keepintvl=value; - DPRINTF(iscsi,2,"TCP_KEEPINTVL will be set to %d on next socket creation",value); + ISCSI_LOG(iscsi, 2, "TCP_KEEPINTVL will be set to %d on next socket creation",value); } int iscsi_set_tcp_keepalive(struct iscsi_context *iscsi, int idle, int count, int interval) @@ -620,27 +621,27 @@ int iscsi_set_tcp_keepalive(struct iscsi_context *iscsi, int idle, int count, in iscsi_set_error(iscsi, "TCP: Failed to set socket option SO_KEEPALIVE. Error %s(%d)", strerror(errno), errno); return -1; } - DPRINTF(iscsi,3,"SO_KEEPALIVE set to %d",value); + ISCSI_LOG(iscsi, 3, "SO_KEEPALIVE set to %d",value); #ifdef TCP_KEEPCNT if (set_tcp_sockopt(iscsi->fd, TCP_KEEPCNT, count) != 0) { iscsi_set_error(iscsi, "TCP: Failed to set tcp keepalive count. Error %s(%d)", strerror(errno), errno); return -1; } - DPRINTF(iscsi,3,"TCP_KEEPCNT set to %d",count); + ISCSI_LOG(iscsi, 3, "TCP_KEEPCNT set to %d",count); #endif #ifdef TCP_KEEPINTVL if (set_tcp_sockopt(iscsi->fd, TCP_KEEPINTVL, interval) != 0) { iscsi_set_error(iscsi, "TCP: Failed to set tcp keepalive interval. Error %s(%d)", strerror(errno), errno); return -1; } - DPRINTF(iscsi,3,"TCP_KEEPINTVL set to %d",interval); + ISCSI_LOG(iscsi, 3, "TCP_KEEPINTVL set to %d",interval); #endif #ifdef TCP_KEEPIDLE if (set_tcp_sockopt(iscsi->fd, TCP_KEEPIDLE, idle) != 0) { iscsi_set_error(iscsi, "TCP: Failed to set tcp keepalive idle. Error %s(%d)", strerror(errno), errno); return -1; } - DPRINTF(iscsi,3,"TCP_KEEPIDLE set to %d",idle); + ISCSI_LOG(iscsi, 3, "TCP_KEEPIDLE set to %d",idle); #endif #endif diff --git a/src/iscsi-inq.c b/src/iscsi-inq.c index 031e4e3..475836b 100644 --- a/src/iscsi-inq.c +++ b/src/iscsi-inq.c @@ -265,9 +265,10 @@ int main(int argc, const char *argv[]) exit(10); } - if (debug > 0) { - iscsi_set_debug(iscsi, debug); - } + if (debug > 0) { + iscsi_set_log_level(iscsi, debug); + iscsi_set_log_fn(iscsi, iscsi_log_to_stderr); + } if (url == NULL) { fprintf(stderr, "You must specify the URL\n"); diff --git a/src/iscsi-ls.c b/src/iscsi-ls.c index b8c4b7c..94df54c 100644 --- a/src/iscsi-ls.c +++ b/src/iscsi-ls.c @@ -368,7 +368,8 @@ int main(int argc, const char *argv[]) } if (debug > 0) { - iscsi_set_debug(iscsi, debug); + iscsi_set_log_level(iscsi, debug); + iscsi_set_log_fn(iscsi, iscsi_log_to_stderr); } iscsi_url = iscsi_parse_portal_url(iscsi, url); diff --git a/src/iscsi-readcapacity16.c b/src/iscsi-readcapacity16.c index bbbc38f..15f2008 100644 --- a/src/iscsi-readcapacity16.c +++ b/src/iscsi-readcapacity16.c @@ -108,7 +108,8 @@ int main(int argc, const char *argv[]) } if (debug > 0) { - iscsi_set_debug(iscsi, debug); + iscsi_set_log_fn(iscsi, iscsi_log_to_stderr); + iscsi_set_log_level(iscsi, debug); } if (url == NULL) { From a0b9080c6c0a21b9811de85614e5158ba1c5e0ff Mon Sep 17 00:00:00 2001 From: Peter Lieven Date: Wed, 31 Oct 2012 16:46:33 +0100 Subject: [PATCH 05/21] SCSI half mallocs in scsi_malloc --- lib/scsi-lowlevel.c | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/lib/scsi-lowlevel.c b/lib/scsi-lowlevel.c index 3787072..3f8020e 100644 --- a/lib/scsi-lowlevel.c +++ b/lib/scsi-lowlevel.c @@ -47,7 +47,6 @@ scsi_free_scsi_task(struct scsi_task *task) while ((mem = task->mem)) { SLIST_REMOVE(&task->mem, mem); - free(mem->ptr); free(mem); } @@ -60,17 +59,12 @@ scsi_malloc(struct scsi_task *task, size_t size) { struct scsi_allocated_memory *mem; - mem = malloc(sizeof(struct scsi_allocated_memory)); + mem = malloc(sizeof(struct scsi_allocated_memory) + size); if (mem == NULL) { return NULL; } - memset(mem, 0, sizeof(struct scsi_allocated_memory)); - mem->ptr = malloc(size); - if (mem->ptr == NULL) { - free(mem); - return NULL; - } - memset(mem->ptr, 0, size); + memset(mem, 0, sizeof(struct scsi_allocated_memory) + size); + mem->ptr = (void *) ((uintptr_t)mem + sizeof(struct scsi_allocated_memory)); SLIST_ADD(&task->mem, mem); return mem->ptr; } From 4de36794f2ce2b443f6d32838717bb260a9c6abe Mon Sep 17 00:00:00 2001 From: Ronnie Sahlberg Date: Sun, 11 Nov 2012 08:03:44 -0800 Subject: [PATCH 06/21] Make scsi_allocated_memory private to scsi-lowlevel and remove the ptr pointer Change the list-head structure for in-task scsi memory allocations to be private to scsi-lowlevel since is is never accessed from anyehwere else and it is private to this function. Remove the pointer to the user data in the list head and replace it with a zero length buffer at the end of the header. Signed-off-by: Ronnie Sahlberg --- include/scsi-lowlevel.h | 5 ----- lib/scsi-lowlevel.c | 7 +++++-- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/include/scsi-lowlevel.h b/include/scsi-lowlevel.h index 9d25b47..53b4118 100644 --- a/include/scsi-lowlevel.h +++ b/include/scsi-lowlevel.h @@ -299,11 +299,6 @@ struct scsi_data { unsigned char *data; }; -struct scsi_allocated_memory { - struct scsi_allocated_memory *next; - void *ptr; -}; - enum scsi_residual { SCSI_RESIDUAL_NO_RESIDUAL = 0, SCSI_RESIDUAL_UNDERFLOW, diff --git a/lib/scsi-lowlevel.c b/lib/scsi-lowlevel.c index 3f8020e..45d516e 100644 --- a/lib/scsi-lowlevel.c +++ b/lib/scsi-lowlevel.c @@ -39,6 +39,10 @@ #include "scsi-lowlevel.h" #include "iscsi-private.h" +struct scsi_allocated_memory { + struct scsi_allocated_memory *next; + char buf[0]; +}; void scsi_free_scsi_task(struct scsi_task *task) @@ -64,9 +68,8 @@ scsi_malloc(struct scsi_task *task, size_t size) return NULL; } memset(mem, 0, sizeof(struct scsi_allocated_memory) + size); - mem->ptr = (void *) ((uintptr_t)mem + sizeof(struct scsi_allocated_memory)); SLIST_ADD(&task->mem, mem); - return mem->ptr; + return &mem->buf[0]; } struct value_string { From 01cd2ee42b313991b0aff1daeaf7ab835eaac756 Mon Sep 17 00:00:00 2001 From: Peter Lieven Date: Sat, 3 Nov 2012 11:09:20 +0100 Subject: [PATCH 07/21] LD_ISCSI fix segfault on reconnect iscsi_reconnect calls dup2 which is intercepted in ld_iscsi. Fix this by calling the real dup2 in this case. --- src/ld_iscsi.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/ld_iscsi.c b/src/ld_iscsi.c index b6c4aa8..cdf86e8 100644 --- a/src/ld_iscsi.c +++ b/src/ld_iscsi.c @@ -387,6 +387,10 @@ int (*real_dup2)(int oldfd, int newfd); int dup2(int oldfd, int newfd) { + if (iscsi_fd_list[newfd].is_iscsi) { + return real_dup2(oldfd, newfd); + } + close(newfd); if (iscsi_fd_list[oldfd].is_iscsi == 1) { From 59860df16aa6e32f990f2cddc1c4029372d0a58a Mon Sep 17 00:00:00 2001 From: Peter Lieven Date: Sat, 3 Nov 2012 17:36:29 +0100 Subject: [PATCH 08/21] LD_ISCSI add lseek --- src/ld_iscsi.c | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/src/ld_iscsi.c b/src/ld_iscsi.c index cdf86e8..975e800 100644 --- a/src/ld_iscsi.c +++ b/src/ld_iscsi.c @@ -275,6 +275,37 @@ int __xstat(int ver, const char *path, struct stat *buf) return __lxstat(ver, path, buf); } +off_t (*real_lseek)(int fd, off_t offset, int whence); + +off_t lseek(int fd, off_t offset, int whence) { + if (iscsi_fd_list[fd].is_iscsi == 1) { + off_t new_offset; + off_t size = iscsi_fd_list[fd].num_blocks*iscsi_fd_list[fd].block_size; + switch (whence) { + case SEEK_SET: + new_offset = offset; + break; + case SEEK_CUR: + new_offset = iscsi_fd_list[fd].offset+offset; + break; + case SEEK_END: + new_offset = size + offset; + break; + default: + errno = EINVAL; + return -1; + } + if (new_offset < 0 || new_offset > size) { + errno = EINVAL; + return -1; + } + iscsi_fd_list[fd].offset=new_offset; + return iscsi_fd_list[fd].offset; + } + + return real_lseek(fd, offset, whence); +} + ssize_t (*real_read)(int fd, void *buf, size_t count); ssize_t read(int fd, void *buf, size_t count) @@ -503,6 +534,12 @@ static void __attribute__((constructor)) _init(void) exit(10); } + real_lseek = dlsym(RTLD_NEXT, "lseek"); + if (real_lseek == NULL) { + LD_ISCSI_DPRINTF(0,"Failed to dlsym(lseek)"); + exit(10); + } + real_read = dlsym(RTLD_NEXT, "read"); if (real_read == NULL) { LD_ISCSI_DPRINTF(0,"Failed to dlsym(read)"); From bf758c7833ba922e5ddfa2c1f79fab3f609a9dd8 Mon Sep 17 00:00:00 2001 From: Peter Lieven Date: Sat, 3 Nov 2012 17:48:31 +0100 Subject: [PATCH 09/21] LD_ISCSI add pread --- src/ld_iscsi.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/src/ld_iscsi.c b/src/ld_iscsi.c index 975e800..47e7214 100644 --- a/src/ld_iscsi.c +++ b/src/ld_iscsi.c @@ -413,6 +413,26 @@ ssize_t read(int fd, void *buf, size_t count) return real_read(fd, buf, count); } +ssize_t (*real_pread)(int fd, void *buf, size_t count, off_t offset); +ssize_t pread(int fd, void *buf, size_t count, off_t offset) { + if ((iscsi_fd_list[fd].is_iscsi == 1 && iscsi_fd_list[fd].in_flight == 0)) { + off_t old_offset; + if ((old_offset = lseek(fd, 0, SEEK_CUR)) < 0) { + errno = EIO; + return -1; + } + if (lseek(fd, offset, SEEK_SET) < 0) { + return -1; + } + if (read(fd, buf, count) < 0) { + lseek(fd, old_offset, SEEK_SET); + return -1; + } + lseek(fd, old_offset, SEEK_SET); + return count; + } + return real_pread(fd, buf, count, offset); +} int (*real_dup2)(int oldfd, int newfd); @@ -546,6 +566,12 @@ static void __attribute__((constructor)) _init(void) exit(10); } + real_pread = dlsym(RTLD_NEXT, "pread"); + if (real_pread == NULL) { + LD_ISCSI_DPRINTF(0,"Failed to dlsym(pread)"); + exit(10); + } + real_dup2 = dlsym(RTLD_NEXT, "dup2"); if (real_dup2 == NULL) { LD_ISCSI_DPRINTF(0,"Failed to dlsym(dup2)"); From 6884b6eb75d402c562a9e471746471dd880dc093 Mon Sep 17 00:00:00 2001 From: Peter Lieven Date: Sat, 3 Nov 2012 18:08:12 +0100 Subject: [PATCH 10/21] LD_ISCSI add write the write command is limited in the sense that file offset and count bytes must be multiple of the targets blocksize. for most copy/dd etc. operations this is sufficient to work. --- src/ld_iscsi.c | 61 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) diff --git a/src/ld_iscsi.c b/src/ld_iscsi.c index 47e7214..7d2d5d6 100644 --- a/src/ld_iscsi.c +++ b/src/ld_iscsi.c @@ -434,6 +434,61 @@ ssize_t pread(int fd, void *buf, size_t count, off_t offset) { return real_pread(fd, buf, count, offset); } +ssize_t (*real_write)(int fd, const void *buf, size_t count); + +ssize_t write(int fd, const void *buf, size_t count) +{ + if ((iscsi_fd_list[fd].is_iscsi == 1) && (iscsi_fd_list[fd].in_flight == 0)) { + uint64_t offset; + uint64_t num_blocks, lba; + struct scsi_task *task; + + if (iscsi_fd_list[fd].dup2fd >= 0) { + return write(iscsi_fd_list[fd].dup2fd, buf, count); + } + if (iscsi_fd_list[fd].offset%iscsi_fd_list[fd].block_size) { + errno = EINVAL; + return -1; + } + if (count%iscsi_fd_list[fd].block_size) { + errno = EINVAL; + return -1; + } + + offset = iscsi_fd_list[fd].offset; + num_blocks = count/iscsi_fd_list[fd].block_size; + lba = offset / iscsi_fd_list[fd].block_size; + + /* Don't try to read beyond the last LBA */ + if (lba >= iscsi_fd_list[fd].num_blocks) { + return 0; + } + /* Trim num_blocks requested to last lba */ + if ((lba + num_blocks) > iscsi_fd_list[fd].num_blocks) { + num_blocks = iscsi_fd_list[fd].num_blocks - lba; + count = num_blocks * iscsi_fd_list[fd].block_size; + } + + iscsi_fd_list[fd].in_flight = 1; + LD_ISCSI_DPRINTF(4,"write16_sync: lun %d, lba %lu, num_blocks: %lu, block_size: %d, offset: %lu count: %lu",iscsi_fd_list[fd].lun,lba,num_blocks,iscsi_fd_list[fd].block_size,offset,count); + task = iscsi_write16_sync(iscsi_fd_list[fd].iscsi, iscsi_fd_list[fd].lun, lba, (unsigned char *) buf, count, iscsi_fd_list[fd].block_size, 0, 0, 0, 0, 0); + iscsi_fd_list[fd].in_flight = 0; + if (task == NULL || task->status != SCSI_STATUS_GOOD) { + LD_ISCSI_DPRINTF(0,"failed to send write16 command"); + errno = EIO; + return -1; + } + + iscsi_fd_list[fd].offset += count; + scsi_free_scsi_task(task); + + return count; + } + + return real_write(fd, buf, count); +} + + int (*real_dup2)(int oldfd, int newfd); int dup2(int oldfd, int newfd) @@ -572,6 +627,12 @@ static void __attribute__((constructor)) _init(void) exit(10); } + real_write = dlsym(RTLD_NEXT, "write"); + if (real_write == NULL) { + LD_ISCSI_DPRINTF(0,"Failed to dlsym(write)"); + exit(10); + } + real_dup2 = dlsym(RTLD_NEXT, "dup2"); if (real_dup2 == NULL) { LD_ISCSI_DPRINTF(0,"Failed to dlsym(dup2)"); From bd04f4bfa621f003e34cf8d8cd0523f505917f67 Mon Sep 17 00:00:00 2001 From: Peter Lieven Date: Sat, 3 Nov 2012 18:12:39 +0100 Subject: [PATCH 11/21] LD_ISCSI add pwite --- src/ld_iscsi.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/ld_iscsi.c b/src/ld_iscsi.c index 7d2d5d6..7a740f2 100644 --- a/src/ld_iscsi.c +++ b/src/ld_iscsi.c @@ -488,6 +488,26 @@ ssize_t write(int fd, const void *buf, size_t count) return real_write(fd, buf, count); } +ssize_t (*real_pwrite)(int fd, const void *buf, size_t count, off_t offset); +ssize_t pwrite(int fd, const void *buf, size_t count, off_t offset) { + if ((iscsi_fd_list[fd].is_iscsi == 1 && iscsi_fd_list[fd].in_flight == 0)) { + off_t old_offset; + if ((old_offset = lseek(fd, 0, SEEK_CUR)) < 0) { + errno = EIO; + return -1; + } + if (lseek(fd, offset, SEEK_SET) < 0) { + return -1; + } + if (write(fd, buf, count) < 0) { + lseek(fd, old_offset, SEEK_SET); + return -1; + } + lseek(fd, old_offset, SEEK_SET); + return count; + } + return real_pwrite(fd, buf, count, offset); +} int (*real_dup2)(int oldfd, int newfd); From f331556d65f642d5864dbe6155beb07ef5ed9cb1 Mon Sep 17 00:00:00 2001 From: Peter Lieven Date: Sat, 3 Nov 2012 18:15:05 +0100 Subject: [PATCH 12/21] LD_ISCSI add pwrite and dlsym it at init --- src/ld_iscsi.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/ld_iscsi.c b/src/ld_iscsi.c index 7a740f2..f9271a6 100644 --- a/src/ld_iscsi.c +++ b/src/ld_iscsi.c @@ -653,6 +653,12 @@ static void __attribute__((constructor)) _init(void) exit(10); } + real_pwrite = dlsym(RTLD_NEXT, "pwrite"); + if (real_pwrite == NULL) { + LD_ISCSI_DPRINTF(0,"Failed to dlsym(pwrite)"); + exit(10); + } + real_dup2 = dlsym(RTLD_NEXT, "dup2"); if (real_dup2 == NULL) { LD_ISCSI_DPRINTF(0,"Failed to dlsym(dup2)"); From 864a4d60a07c9226d84dc50bae329274817802c0 Mon Sep 17 00:00:00 2001 From: Peter Lieven Date: Mon, 5 Nov 2012 21:23:30 +0100 Subject: [PATCH 13/21] LD_ISCSI invalidate get_lba_status cache on write --- src/ld_iscsi.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/ld_iscsi.c b/src/ld_iscsi.c index f9271a6..144769b 100644 --- a/src/ld_iscsi.c +++ b/src/ld_iscsi.c @@ -455,6 +455,8 @@ ssize_t write(int fd, const void *buf, size_t count) return -1; } + iscsi_fd_list[fd].lbasd_cache_valid = 0; + offset = iscsi_fd_list[fd].offset; num_blocks = count/iscsi_fd_list[fd].block_size; lba = offset / iscsi_fd_list[fd].block_size; From 8512f1991189a331a13951634fd3b4e988ba6187 Mon Sep 17 00:00:00 2001 From: Peter Lieven Date: Sat, 3 Nov 2012 10:58:35 +0100 Subject: [PATCH 14/21] ISCSI-READCAPACITY16 fix missing free of scsi_task --- src/iscsi-readcapacity16.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/iscsi-readcapacity16.c b/src/iscsi-readcapacity16.c index 15f2008..512c359 100644 --- a/src/iscsi-readcapacity16.c +++ b/src/iscsi-readcapacity16.c @@ -177,6 +177,7 @@ int main(int argc, const char *argv[]) printf("%" PRIu64 "\n", rc16->block_length * (rc16->returned_lba + 1)); } + scsi_free_scsi_task(task); iscsi_destroy_url(iscsi_url); iscsi_logout_sync(iscsi); From 5722ad7e98dabd4ba86e0f82a2c03de5da476178 Mon Sep 17 00:00:00 2001 From: Peter Lieven Date: Mon, 5 Nov 2012 15:33:12 +0100 Subject: [PATCH 15/21] LOGIN change dynamic string allocations to statics --- lib/login.c | 162 +++++++++++++++++++++------------------------------- 1 file changed, 66 insertions(+), 96 deletions(-) diff --git a/lib/login.c b/lib/login.c index d258337..f37ddc0 100644 --- a/lib/login.c +++ b/lib/login.c @@ -35,7 +35,7 @@ static int iscsi_login_add_initiatorname(struct iscsi_context *iscsi, struct iscsi_pdu *pdu) { - char *str; + char str[MAX_STRING_SIZE+1]; /* We only send InitiatorName during opneg or the first leg of secneg */ if (iscsi->current_phase != ISCSI_PDU_LOGIN_CSG_OPNEG @@ -43,30 +43,26 @@ iscsi_login_add_initiatorname(struct iscsi_context *iscsi, struct iscsi_pdu *pdu return 0; } - str = malloc(1024); #if defined(WIN32) - if (_snprintf_s(str, 1024, 1024, "InitiatorName=%s", iscsi->initiator_name) == -1) { + if (_snprintf_s(str, MAX_STRING_SIZE, MAX_STRING_SIZE, "InitiatorName=%s", iscsi->initiator_name) == -1) { #else - if (snprintf(str, 1024, "InitiatorName=%s", iscsi->initiator_name) == -1) { + if (snprintf(str, MAX_STRING_SIZE, "InitiatorName=%s", iscsi->initiator_name) == -1) { #endif iscsi_set_error(iscsi, "Out-of-memory: aprintf failed."); - free(str); return -1; } if (iscsi_pdu_add_data(iscsi, pdu, (unsigned char *)str, strlen(str)+1) != 0) { iscsi_set_error(iscsi, "Out-of-memory: pdu add data failed."); - free(str); return -1; } - free(str); return 0; } static int iscsi_login_add_alias(struct iscsi_context *iscsi, struct iscsi_pdu *pdu) { - char *str; + char str[MAX_STRING_SIZE+1]; /* We only send InitiatorAlias during opneg or the first leg of secneg */ if (iscsi->current_phase != ISCSI_PDU_LOGIN_CSG_OPNEG @@ -74,31 +70,27 @@ iscsi_login_add_alias(struct iscsi_context *iscsi, struct iscsi_pdu *pdu) return 0; } - str = malloc(1024); #if defined(WIN32) - if (_snprintf_s(str, 1024, 1024, "InitiatorAlias=%s", iscsi->alias) == -1) { + if (_snprintf_s(str, MAX_STRING_SIZE, MAX_STRING_SIZE, "InitiatorAlias=%s", iscsi->alias) == -1) { #else - if (snprintf(str, 1024, "InitiatorAlias=%s", iscsi->alias) == -1) { + if (snprintf(str, MAX_STRING_SIZE, "InitiatorAlias=%s", iscsi->alias) == -1) { #endif iscsi_set_error(iscsi, "Out-of-memory: aprintf failed."); - free(str); return -1; } if (iscsi_pdu_add_data(iscsi, pdu, (unsigned char *)str, strlen(str)+1) != 0) { iscsi_set_error(iscsi, "Out-of-memory: pdu add data failed."); - free(str); return -1; } - free(str); return 0; } static int iscsi_login_add_targetname(struct iscsi_context *iscsi, struct iscsi_pdu *pdu) { - char *str; + char str[MAX_STRING_SIZE+1]; /* We only send TargetName during opneg or the first leg of secneg */ if (iscsi->current_phase != ISCSI_PDU_LOGIN_CSG_OPNEG @@ -112,31 +104,27 @@ iscsi_login_add_targetname(struct iscsi_context *iscsi, struct iscsi_pdu *pdu) return -1; } - str = malloc(1024); #if defined(WIN32) - if (_snprintf_s(str, 1024, 1024, "TargetName=%s", iscsi->target_name) == -1) { + if (_snprintf_s(str, MAX_STRING_SIZE, MAX_STRING_SIZE, "TargetName=%s", iscsi->target_name) == -1) { #else - if (snprintf(str, 1024, "TargetName=%s", iscsi->target_name) == -1) { + if (snprintf(str, MAX_STRING_SIZE, "TargetName=%s", iscsi->target_name) == -1) { #endif iscsi_set_error(iscsi, "Out-of-memory: aprintf failed."); - free(str); return -1; } if (iscsi_pdu_add_data(iscsi, pdu, (unsigned char *)str, strlen(str)+1) != 0) { iscsi_set_error(iscsi, "Out-of-memory: pdu add data failed."); - free(str); return -1; } - free(str); return 0; } static int iscsi_login_add_sessiontype(struct iscsi_context *iscsi, struct iscsi_pdu *pdu) { - char *str; + char str[MAX_STRING_SIZE+1]; /* We only send TargetName during opneg or the first leg of secneg */ if (iscsi->current_phase != ISCSI_PDU_LOGIN_CSG_OPNEG @@ -146,10 +134,10 @@ iscsi_login_add_sessiontype(struct iscsi_context *iscsi, struct iscsi_pdu *pdu) switch (iscsi->session_type) { case ISCSI_SESSION_DISCOVERY: - str = (char *)"SessionType=Discovery"; + strncpy(str,"SessionType=Discovery",MAX_STRING_SIZE); break; case ISCSI_SESSION_NORMAL: - str = (char *)"SessionType=Normal"; + strncpy(str,"SessionType=Normal",MAX_STRING_SIZE); break; default: iscsi_set_error(iscsi, "Can not handle sessions %d yet.", @@ -168,7 +156,7 @@ iscsi_login_add_sessiontype(struct iscsi_context *iscsi, struct iscsi_pdu *pdu) static int iscsi_login_add_headerdigest(struct iscsi_context *iscsi, struct iscsi_pdu *pdu) { - char *str; + char str[MAX_STRING_SIZE+1]; /* We only send HeaderDigest during opneg */ if (iscsi->current_phase != ISCSI_PDU_LOGIN_CSG_OPNEG) { @@ -177,16 +165,16 @@ iscsi_login_add_headerdigest(struct iscsi_context *iscsi, struct iscsi_pdu *pdu) switch (iscsi->want_header_digest) { case ISCSI_HEADER_DIGEST_NONE: - str = (char *)"HeaderDigest=None"; + strncpy(str,"HeaderDigest=None",MAX_STRING_SIZE); break; case ISCSI_HEADER_DIGEST_NONE_CRC32C: - str = (char *)"HeaderDigest=None,CRC32C"; + strncpy(str,"HeaderDigest=None,CRC32C",MAX_STRING_SIZE); break; case ISCSI_HEADER_DIGEST_CRC32C_NONE: - str = (char *)"HeaderDigest=CRC32C,None"; + strncpy(str,"HeaderDigest=CRC32C,None",MAX_STRING_SIZE); break; case ISCSI_HEADER_DIGEST_CRC32C: - str = (char *)"HeaderDigest=CRC32C"; + strncpy(str,"HeaderDigest=CRC32C",MAX_STRING_SIZE); break; default: iscsi_set_error(iscsi, "invalid header digest value"); @@ -205,14 +193,14 @@ iscsi_login_add_headerdigest(struct iscsi_context *iscsi, struct iscsi_pdu *pdu) static int iscsi_login_add_datadigest(struct iscsi_context *iscsi, struct iscsi_pdu *pdu) { - char *str; + char str[MAX_STRING_SIZE+1]; /* We only send DataDigest during opneg */ if (iscsi->current_phase != ISCSI_PDU_LOGIN_CSG_OPNEG) { return 0; } - str = (char *)"DataDigest=None"; + strncpy(str,"DataDigest=None",MAX_STRING_SIZE); if (iscsi_pdu_add_data(iscsi, pdu, (unsigned char *)str, strlen(str)+1) != 0) { iscsi_set_error(iscsi, "Out-of-memory: pdu add data failed."); @@ -225,32 +213,28 @@ iscsi_login_add_datadigest(struct iscsi_context *iscsi, struct iscsi_pdu *pdu) static int iscsi_login_add_initialr2t(struct iscsi_context *iscsi, struct iscsi_pdu *pdu) { - char *str; + char str[MAX_STRING_SIZE+1]; /* We only send InitialR2T during opneg */ if (iscsi->current_phase != ISCSI_PDU_LOGIN_CSG_OPNEG) { return 0; } - str = malloc(1024); #if defined(WIN32) - if (_snprintf_s(str, 1024, 1024, "InitialR2T=%s", iscsi->want_initial_r2t == ISCSI_INITIAL_R2T_NO ? + if (_snprintf_s(str, MAX_STRING_SIZE, MAX_STRING_SIZE, "InitialR2T=%s", iscsi->want_initial_r2t == ISCSI_INITIAL_R2T_NO ? #else - if (snprintf(str, 1024, "InitialR2T=%s", iscsi->want_initial_r2t == ISCSI_INITIAL_R2T_NO ? + if (snprintf(str, MAX_STRING_SIZE, "InitialR2T=%s", iscsi->want_initial_r2t == ISCSI_INITIAL_R2T_NO ? #endif "No" : "Yes") == -1) { iscsi_set_error(iscsi, "Out-of-memory: aprintf failed."); - free(str); return -1; } if (iscsi_pdu_add_data(iscsi, pdu, (unsigned char *)str, strlen(str)+1) != 0) { iscsi_set_error(iscsi, "Out-of-memory: pdu add data failed."); - free(str); return -1; } - free(str); return 0; } @@ -258,32 +242,28 @@ iscsi_login_add_initialr2t(struct iscsi_context *iscsi, struct iscsi_pdu *pdu) static int iscsi_login_add_immediatedata(struct iscsi_context *iscsi, struct iscsi_pdu *pdu) { - char *str; + char str[MAX_STRING_SIZE+1]; /* We only send ImmediateData during opneg */ if (iscsi->current_phase != ISCSI_PDU_LOGIN_CSG_OPNEG) { return 0; } - str = malloc(1024); #if defined(WIN32) - if (_snprintf_s(str, 1024, 1024, "ImmediateData=%s", iscsi->want_immediate_data == ISCSI_IMMEDIATE_DATA_NO ? + if (_snprintf_s(str, MAX_STRING_SIZE, MAX_STRING_SIZE, "ImmediateData=%s", iscsi->want_immediate_data == ISCSI_IMMEDIATE_DATA_NO ? #else - if (snprintf(str, 1024, "ImmediateData=%s", iscsi->want_immediate_data == ISCSI_IMMEDIATE_DATA_NO ? + if (snprintf(str, MAX_STRING_SIZE, "ImmediateData=%s", iscsi->want_immediate_data == ISCSI_IMMEDIATE_DATA_NO ? #endif "No" : "Yes") == -1) { iscsi_set_error(iscsi, "Out-of-memory: aprintf failed."); - free(str); return -1; } if (iscsi_pdu_add_data(iscsi, pdu, (unsigned char *)str, strlen(str)+1) != 0) { iscsi_set_error(iscsi, "Out-of-memory: pdu add data failed."); - free(str); return -1; } - free(str); return 0; } @@ -291,107 +271,95 @@ iscsi_login_add_immediatedata(struct iscsi_context *iscsi, struct iscsi_pdu *pdu static int iscsi_login_add_maxburstlength(struct iscsi_context *iscsi, struct iscsi_pdu *pdu) { - char *str; + char str[MAX_STRING_SIZE+1]; /* We only send MaxBurstLength during opneg */ if (iscsi->current_phase != ISCSI_PDU_LOGIN_CSG_OPNEG) { return 0; } - str = malloc(1024); #if defined(WIN32) - if (_snprintf_s(str, 1024, 1024, "MaxBurstLength=%d", iscsi->max_burst_length) == -1) { + if (_snprintf_s(str, MAX_STRING_SIZE, MAX_STRING_SIZE, "MaxBurstLength=%d", iscsi->max_burst_length) == -1) { #else - if (snprintf(str, 1024, "MaxBurstLength=%d", iscsi->max_burst_length) == -1) { + if (snprintf(str, MAX_STRING_SIZE, "MaxBurstLength=%d", iscsi->max_burst_length) == -1) { #endif iscsi_set_error(iscsi, "Out-of-memory: aprintf failed."); - free(str); return -1; } if (iscsi_pdu_add_data(iscsi, pdu, (unsigned char *)str, strlen(str)+1) != 0) { iscsi_set_error(iscsi, "Out-of-memory: pdu add data failed."); - free(str); return -1; } - free(str); return 0; } static int iscsi_login_add_firstburstlength(struct iscsi_context *iscsi, struct iscsi_pdu *pdu) { - char *str; + char str[MAX_STRING_SIZE+1]; /* We only send FirstBurstLength during opneg */ if (iscsi->current_phase != ISCSI_PDU_LOGIN_CSG_OPNEG) { return 0; } - str = malloc(1024); #if defined(WIN32) - if (_snprintf_s(str, 1024, 1024, "FirstBurstLength=%d", iscsi->first_burst_length) == -1) { + if (_snprintf_s(str, MAX_STRING_SIZE, MAX_STRING_SIZE, "FirstBurstLength=%d", iscsi->first_burst_length) == -1) { #else - if (snprintf(str, 1024, "FirstBurstLength=%d", iscsi->first_burst_length) == -1) { + if (snprintf(str, MAX_STRING_SIZE, "FirstBurstLength=%d", iscsi->first_burst_length) == -1) { #endif iscsi_set_error(iscsi, "Out-of-memory: aprintf failed."); - free(str); return -1; } if (iscsi_pdu_add_data(iscsi, pdu, (unsigned char *)str, strlen(str)+1) != 0) { iscsi_set_error(iscsi, "Out-of-memory: pdu add data failed."); - free(str); return -1; } - free(str); return 0; } static int iscsi_login_add_maxrecvdatasegmentlength(struct iscsi_context *iscsi, struct iscsi_pdu *pdu) { - char *str; + char str[MAX_STRING_SIZE+1]; /* We only send MaxRecvDataSegmentLength during opneg */ if (iscsi->current_phase != ISCSI_PDU_LOGIN_CSG_OPNEG) { return 0; } - str = malloc(1024); #if defined(WIN32) - if (_snprintf_s(str, 1024, 1024, "MaxRecvDataSegmentLength=%d", iscsi->initiator_max_recv_data_segment_length) == -1) { + if (_snprintf_s(str, MAX_STRING_SIZE, MAX_STRING_SIZE, "MaxRecvDataSegmentLength=%d", iscsi->initiator_max_recv_data_segment_length) == -1) { #else - if (snprintf(str, 1024, "MaxRecvDataSegmentLength=%d", iscsi->initiator_max_recv_data_segment_length) == -1) { + if (snprintf(str, MAX_STRING_SIZE, "MaxRecvDataSegmentLength=%d", iscsi->initiator_max_recv_data_segment_length) == -1) { #endif iscsi_set_error(iscsi, "Out-of-memory: aprintf failed."); - free(str); return -1; } if (iscsi_pdu_add_data(iscsi, pdu, (unsigned char *)str, strlen(str)+1) != 0) { iscsi_set_error(iscsi, "Out-of-memory: pdu add data failed."); - free(str); return -1; } - free(str); return 0; } static int iscsi_login_add_datapduinorder(struct iscsi_context *iscsi, struct iscsi_pdu *pdu) { - char *str; + char str[MAX_STRING_SIZE+1]; /* We only send DataPduInOrder during opneg */ if (iscsi->current_phase != ISCSI_PDU_LOGIN_CSG_OPNEG) { return 0; } - str = (char *)"DataPDUInOrder=Yes"; + strncpy(str,"DataPDUInOrder=Yes",MAX_STRING_SIZE); if (iscsi_pdu_add_data(iscsi, pdu, (unsigned char *)str, strlen(str)+1) != 0) { iscsi_set_error(iscsi, "Out-of-memory: pdu add data failed."); @@ -404,14 +372,14 @@ iscsi_login_add_datapduinorder(struct iscsi_context *iscsi, struct iscsi_pdu *pd static int iscsi_login_add_defaulttime2wait(struct iscsi_context *iscsi, struct iscsi_pdu *pdu) { - char *str; + char str[MAX_STRING_SIZE+1]; /* We only send DefaultTime2Wait during opneg */ if (iscsi->current_phase != ISCSI_PDU_LOGIN_CSG_OPNEG) { return 0; } - str = (char *)"DefaultTime2Wait=2"; + strncpy(str,"DefaultTime2Wait=2",MAX_STRING_SIZE); if (iscsi_pdu_add_data(iscsi, pdu, (unsigned char *)str, strlen(str)+1) != 0) { iscsi_set_error(iscsi, "Out-of-memory: pdu add data failed."); @@ -424,14 +392,14 @@ iscsi_login_add_defaulttime2wait(struct iscsi_context *iscsi, struct iscsi_pdu * static int iscsi_login_add_defaulttime2retain(struct iscsi_context *iscsi, struct iscsi_pdu *pdu) { - char *str; + char str[MAX_STRING_SIZE+1]; /* We only send DefaultTime2Retain during opneg */ if (iscsi->current_phase != ISCSI_PDU_LOGIN_CSG_OPNEG) { return 0; } - str = (char *)"DefaultTime2Retain=0"; + strncpy(str,"DefaultTime2Retain=0",MAX_STRING_SIZE); if (iscsi_pdu_add_data(iscsi, pdu, (unsigned char *)str, strlen(str)+1) != 0) { iscsi_set_error(iscsi, "Out-of-memory: pdu add data failed."); @@ -444,14 +412,14 @@ iscsi_login_add_defaulttime2retain(struct iscsi_context *iscsi, struct iscsi_pdu static int iscsi_login_add_ifmarker(struct iscsi_context *iscsi, struct iscsi_pdu *pdu) { - char *str; + char str[MAX_STRING_SIZE+1]; /* We only send IFMarker during opneg */ if (iscsi->current_phase != ISCSI_PDU_LOGIN_CSG_OPNEG) { return 0; } - str = (char *)"IFMarker=No"; + strncpy(str,"IFMarker=No",MAX_STRING_SIZE); if (iscsi_pdu_add_data(iscsi, pdu, (unsigned char *)str, strlen(str)+1) != 0) { iscsi_set_error(iscsi, "Out-of-memory: pdu add data failed."); @@ -464,14 +432,14 @@ iscsi_login_add_ifmarker(struct iscsi_context *iscsi, struct iscsi_pdu *pdu) static int iscsi_login_add_ofmarker(struct iscsi_context *iscsi, struct iscsi_pdu *pdu) { - char *str; + char str[MAX_STRING_SIZE+1]; /* We only send OFMarker during opneg */ if (iscsi->current_phase != ISCSI_PDU_LOGIN_CSG_OPNEG) { return 0; } - str = (char *)"OFMarker=No"; + strncpy(str,"OFMarker=No",MAX_STRING_SIZE); if (iscsi_pdu_add_data(iscsi, pdu, (unsigned char *)str, strlen(str)+1) != 0) { iscsi_set_error(iscsi, "Out-of-memory: pdu add data failed."); @@ -484,14 +452,14 @@ iscsi_login_add_ofmarker(struct iscsi_context *iscsi, struct iscsi_pdu *pdu) static int iscsi_login_add_maxconnections(struct iscsi_context *iscsi, struct iscsi_pdu *pdu) { - char *str; + char str[MAX_STRING_SIZE+1]; /* We only send MaxConnections during opneg */ if (iscsi->current_phase != ISCSI_PDU_LOGIN_CSG_OPNEG) { return 0; } - str = (char *)"MaxConnections=1"; + strncpy(str,"MaxConnections=1",MAX_STRING_SIZE); if (iscsi_pdu_add_data(iscsi, pdu, (unsigned char *)str, strlen(str)+1) != 0) { iscsi_set_error(iscsi, "Out-of-memory: pdu add data failed."); @@ -504,14 +472,14 @@ iscsi_login_add_maxconnections(struct iscsi_context *iscsi, struct iscsi_pdu *pd static int iscsi_login_add_maxoutstandingr2t(struct iscsi_context *iscsi, struct iscsi_pdu *pdu) { - char *str; + char str[MAX_STRING_SIZE+1]; /* We only send MaxOutstandingR2T during opneg */ if (iscsi->current_phase != ISCSI_PDU_LOGIN_CSG_OPNEG) { return 0; } - str = (char *)"MaxOutstandingR2T=1"; + strncpy(str,"MaxOutstandingR2T=1",MAX_STRING_SIZE); if (iscsi_pdu_add_data(iscsi, pdu, (unsigned char *)str, strlen(str)+1) != 0) { iscsi_set_error(iscsi, "Out-of-memory: pdu add data failed."); @@ -524,14 +492,14 @@ iscsi_login_add_maxoutstandingr2t(struct iscsi_context *iscsi, struct iscsi_pdu static int iscsi_login_add_errorrecoverylevel(struct iscsi_context *iscsi, struct iscsi_pdu *pdu) { - char *str; + char str[MAX_STRING_SIZE+1]; /* We only send ErrorRecoveryLevel during opneg */ if (iscsi->current_phase != ISCSI_PDU_LOGIN_CSG_OPNEG) { return 0; } - str = (char *)"ErrorRecoveryLevel=0"; + strncpy(str,"ErrorRecoveryLevel=0",MAX_STRING_SIZE); if (iscsi_pdu_add_data(iscsi, pdu, (unsigned char *)str, strlen(str)+1) != 0) { iscsi_set_error(iscsi, "Out-of-memory: pdu add data failed."); @@ -544,14 +512,14 @@ iscsi_login_add_errorrecoverylevel(struct iscsi_context *iscsi, struct iscsi_pdu static int iscsi_login_add_datasequenceinorder(struct iscsi_context *iscsi, struct iscsi_pdu *pdu) { - char *str; + char str[MAX_STRING_SIZE+1]; /* We only send DataSequenceInOrder during opneg */ if (iscsi->current_phase != ISCSI_PDU_LOGIN_CSG_OPNEG) { return 0; } - str = (char *)"DataSequenceInOrder=Yes"; + strncpy(str,"DataSequenceInOrder=Yes",MAX_STRING_SIZE); if (iscsi_pdu_add_data(iscsi, pdu, (unsigned char *)str, strlen(str)+1) != 0) { iscsi_set_error(iscsi, "Out-of-memory: pdu add data failed."); @@ -564,14 +532,14 @@ iscsi_login_add_datasequenceinorder(struct iscsi_context *iscsi, struct iscsi_pd static int iscsi_login_add_authmethod(struct iscsi_context *iscsi, struct iscsi_pdu *pdu) { - char *str; + char str[MAX_STRING_SIZE+1]; if (iscsi->current_phase != ISCSI_PDU_LOGIN_CSG_SECNEG || iscsi->secneg_phase != ISCSI_LOGIN_SECNEG_PHASE_OFFER_CHAP) { return 0; } - str = (char *)"AuthMethod=CHAP,None"; + strncpy(str,"AuthMethod=CHAP,None",MAX_STRING_SIZE); if (iscsi_pdu_add_data(iscsi, pdu, (unsigned char *)str, strlen(str)+1) != 0) { iscsi_set_error(iscsi, "Out-of-memory: pdu add data failed."); @@ -584,14 +552,14 @@ iscsi_login_add_authmethod(struct iscsi_context *iscsi, struct iscsi_pdu *pdu) static int iscsi_login_add_authalgorithm(struct iscsi_context *iscsi, struct iscsi_pdu *pdu) { - char *str; + char str[MAX_STRING_SIZE+1]; if (iscsi->current_phase != ISCSI_PDU_LOGIN_CSG_SECNEG || iscsi->secneg_phase != ISCSI_LOGIN_SECNEG_PHASE_SELECT_ALGORITHM) { return 0; } - str = (char *)"CHAP_A=5"; + strncpy(str,"CHAP_A=5",MAX_STRING_SIZE); if (iscsi_pdu_add_data(iscsi, pdu, (unsigned char *)str, strlen(str)+1) != 0) { iscsi_set_error(iscsi, "Out-of-memory: pdu add data failed."); @@ -604,14 +572,14 @@ iscsi_login_add_authalgorithm(struct iscsi_context *iscsi, struct iscsi_pdu *pdu static int iscsi_login_add_chap_username(struct iscsi_context *iscsi, struct iscsi_pdu *pdu) { - char *str; + char str[MAX_STRING_SIZE+1]; if (iscsi->current_phase != ISCSI_PDU_LOGIN_CSG_SECNEG || iscsi->secneg_phase != ISCSI_LOGIN_SECNEG_PHASE_SEND_RESPONSE) { return 0; } - str = (char *)"CHAP_N="; + strncpy(str,"CHAP_N=",MAX_STRING_SIZE); if (iscsi_pdu_add_data(iscsi, pdu, (unsigned char *)str, strlen(str)) != 0) { iscsi_set_error(iscsi, "Out-of-memory: pdu add data failed."); @@ -652,7 +620,8 @@ i2h(int i) static int iscsi_login_add_chap_response(struct iscsi_context *iscsi, struct iscsi_pdu *pdu) { - char *str; + char str[MAX_STRING_SIZE+1]; + char * strp; unsigned char c, cc[2]; unsigned char digest[16]; struct MD5Context ctx; @@ -671,15 +640,16 @@ iscsi_login_add_chap_response(struct iscsi_context *iscsi, struct iscsi_pdu *pdu c = iscsi->chap_i; MD5Update(&ctx, &c, 1); MD5Update(&ctx, (unsigned char *)iscsi->passwd, strlen(iscsi->passwd)); - str = iscsi->chap_c; - while (*str != 0) { - c = (h2i(str[0]) << 4) | h2i(str[1]); - str += 2; + + strp = iscsi->chap_c; + while (*strp != 0) { + c = (h2i(strp[0]) << 4) | h2i(strp[1]); + strp += 2; MD5Update(&ctx, &c, 1); } MD5Final(digest, &ctx); - str = (char *)"CHAP_R=0x"; + strncpy(str,"CHAP_R=0x",MAX_STRING_SIZE); if (iscsi_pdu_add_data(iscsi, pdu, (unsigned char *)str, strlen(str)) != 0) { iscsi_set_error(iscsi, "Out-of-memory: pdu add data failed."); From 49af416f477630f5d2e63b0c13af47953e6e9982 Mon Sep 17 00:00:00 2001 From: Ronnie Sahlberg Date: Sun, 11 Nov 2012 09:35:34 -0800 Subject: [PATCH 16/21] When we cancel a scsi task we don't need to unlink the in_buffers We dont need to unlink the in-buffers when cancelling a scsi task since the whole task structure will go away shortly anyway and all entries in the link will be automatically freed when the task is freed. --- lib/scsi-lowlevel.c | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/lib/scsi-lowlevel.c b/lib/scsi-lowlevel.c index 45d516e..e7e6da5 100644 --- a/lib/scsi-lowlevel.c +++ b/lib/scsi-lowlevel.c @@ -2566,10 +2566,6 @@ iscsi_scsi_task_cancel(struct iscsi_context *iscsi, for (pdu = iscsi->waitpdu; pdu; pdu = pdu->next) { if (pdu->itt == task->itt) { - while(task->in_buffers != NULL) { - struct scsi_data_buffer *ptr = task->in_buffers; - SLIST_REMOVE(&task->in_buffers, ptr); - } SLIST_REMOVE(&iscsi->waitpdu, pdu); if ( !(pdu->flags & ISCSI_PDU_NO_CALLBACK)) { pdu->callback(iscsi, SCSI_STATUS_CANCELLED, NULL, @@ -2581,10 +2577,6 @@ iscsi_scsi_task_cancel(struct iscsi_context *iscsi, } for (pdu = iscsi->outqueue; pdu; pdu = pdu->next) { if (pdu->itt == task->itt) { - while(task->in_buffers != NULL) { - struct scsi_data_buffer *ptr = task->in_buffers; - SLIST_REMOVE(&task->in_buffers, ptr); - } SLIST_REMOVE(&iscsi->outqueue, pdu); if ( !(pdu->flags & ISCSI_PDU_NO_CALLBACK)) { pdu->callback(iscsi, SCSI_STATUS_CANCELLED, NULL, @@ -2605,10 +2597,6 @@ iscsi_scsi_cancel_all_tasks(struct iscsi_context *iscsi) for (pdu = iscsi->waitpdu; pdu; pdu = pdu->next) { struct scsi_task *task = iscsi_scsi_get_task_from_pdu(pdu); - while(task->in_buffers != NULL) { - struct scsi_data_buffer *ptr = task->in_buffers; - SLIST_REMOVE(&task->in_buffers, ptr); - } SLIST_REMOVE(&iscsi->waitpdu, pdu); if ( !(pdu->flags & ISCSI_PDU_NO_CALLBACK)) { pdu->callback(iscsi, SCSI_STATUS_CANCELLED, NULL, @@ -2619,10 +2607,6 @@ iscsi_scsi_cancel_all_tasks(struct iscsi_context *iscsi) for (pdu = iscsi->outqueue; pdu; pdu = pdu->next) { struct scsi_task *task = iscsi_scsi_get_task_from_pdu(pdu); - while(task->in_buffers != NULL) { - struct scsi_data_buffer *ptr = task->in_buffers; - SLIST_REMOVE(&task->in_buffers, ptr); - } SLIST_REMOVE(&iscsi->outqueue, pdu); if ( !(pdu->flags & ISCSI_PDU_NO_CALLBACK)) { pdu->callback(iscsi, SCSI_STATUS_CANCELLED, NULL, From 3b05e9996fef386632de417841012e64228dde2b Mon Sep 17 00:00:00 2001 From: Ronnie Sahlberg Date: Sun, 11 Nov 2012 09:44:11 -0800 Subject: [PATCH 17/21] Move cancel_task and cancel_all_tasks from scsi-lowlevel.c to scsi-command.c These two functions belong in the iscsi layer, not the scsi layer so move them out from scsi-lowlevel.c so that we can start turning scsi-lowlevel.c to a pure scsi layer and remove all dependencies to iscsi from it. --- include/iscsi.h | 4 ++-- lib/libiscsi.def | 2 +- lib/libiscsi.syms | 2 +- lib/scsi-command.c | 54 ++++++++++++++++++++++++++++++++++++++++++ lib/scsi-lowlevel.c | 57 --------------------------------------------- lib/task_mgmt.c | 2 +- 6 files changed, 59 insertions(+), 62 deletions(-) diff --git a/include/iscsi.h b/include/iscsi.h index 7b8db1a..463f6a3 100644 --- a/include/iscsi.h +++ b/include/iscsi.h @@ -953,8 +953,8 @@ EXTERN int scsi_task_add_data_in_buffer(struct scsi_task *task, int len, unsigne * To cancel the task also a the target you need to call the task management functions. */ EXTERN int -iscsi_scsi_task_cancel(struct iscsi_context *iscsi, - struct scsi_task *task); +iscsi_scsi_cancel_task(struct iscsi_context *iscsi, + struct scsi_task *task); /* * This function is used when you want to cancel all scsi tasks. diff --git a/lib/libiscsi.def b/lib/libiscsi.def index dfa4838..6482822 100644 --- a/lib/libiscsi.def +++ b/lib/libiscsi.def @@ -62,7 +62,7 @@ iscsi_reportluns_task iscsi_scsi_cancel_all_tasks iscsi_scsi_command_async iscsi_scsi_command_sync -iscsi_scsi_task_cancel +iscsi_scsi_cancel_task iscsi_service iscsi_set_alias iscsi_set_log_level diff --git a/lib/libiscsi.syms b/lib/libiscsi.syms index 74c33fe..68d5605 100644 --- a/lib/libiscsi.syms +++ b/lib/libiscsi.syms @@ -60,7 +60,7 @@ iscsi_reportluns_task iscsi_scsi_cancel_all_tasks iscsi_scsi_command_async iscsi_scsi_command_sync -iscsi_scsi_task_cancel +iscsi_scsi_cancel_task iscsi_service iscsi_set_alias iscsi_set_log_level diff --git a/lib/scsi-command.c b/lib/scsi-command.c index f6d8d0f..d3b2fb9 100644 --- a/lib/scsi-command.c +++ b/lib/scsi-command.c @@ -1568,3 +1568,57 @@ iscsi_scsi_get_task_from_pdu(struct iscsi_pdu *pdu) { return pdu->scsi_cbdata->task; } + +int +iscsi_scsi_cancel_task(struct iscsi_context *iscsi, + struct scsi_task *task) +{ + struct iscsi_pdu *pdu; + + for (pdu = iscsi->waitpdu; pdu; pdu = pdu->next) { + if (pdu->itt == task->itt) { + SLIST_REMOVE(&iscsi->waitpdu, pdu); + if ( !(pdu->flags & ISCSI_PDU_NO_CALLBACK)) { + pdu->callback(iscsi, SCSI_STATUS_CANCELLED, NULL, + pdu->private_data); + } + iscsi_free_pdu(iscsi, pdu); + return 0; + } + } + for (pdu = iscsi->outqueue; pdu; pdu = pdu->next) { + if (pdu->itt == task->itt) { + SLIST_REMOVE(&iscsi->outqueue, pdu); + if ( !(pdu->flags & ISCSI_PDU_NO_CALLBACK)) { + pdu->callback(iscsi, SCSI_STATUS_CANCELLED, NULL, + pdu->private_data); + } + iscsi_free_pdu(iscsi, pdu); + return 0; + } + } + return -1; +} + +void +iscsi_scsi_cancel_all_tasks(struct iscsi_context *iscsi) +{ + struct iscsi_pdu *pdu; + + for (pdu = iscsi->waitpdu; pdu; pdu = pdu->next) { + SLIST_REMOVE(&iscsi->waitpdu, pdu); + if ( !(pdu->flags & ISCSI_PDU_NO_CALLBACK)) { + pdu->callback(iscsi, SCSI_STATUS_CANCELLED, NULL, + pdu->private_data); + } + iscsi_free_pdu(iscsi, pdu); + } + for (pdu = iscsi->outqueue; pdu; pdu = pdu->next) { + SLIST_REMOVE(&iscsi->outqueue, pdu); + if ( !(pdu->flags & ISCSI_PDU_NO_CALLBACK)) { + pdu->callback(iscsi, SCSI_STATUS_CANCELLED, NULL, + pdu->private_data); + } + iscsi_free_pdu(iscsi, pdu); + } +} diff --git a/lib/scsi-lowlevel.c b/lib/scsi-lowlevel.c index e7e6da5..e7697b5 100644 --- a/lib/scsi-lowlevel.c +++ b/lib/scsi-lowlevel.c @@ -2558,60 +2558,3 @@ scsi_task_get_data_in_buffer(struct scsi_task *task, uint32_t pos, ssize_t *coun return &sdb->data[pos]; } -int -iscsi_scsi_task_cancel(struct iscsi_context *iscsi, - struct scsi_task *task) -{ - struct iscsi_pdu *pdu; - - for (pdu = iscsi->waitpdu; pdu; pdu = pdu->next) { - if (pdu->itt == task->itt) { - SLIST_REMOVE(&iscsi->waitpdu, pdu); - if ( !(pdu->flags & ISCSI_PDU_NO_CALLBACK)) { - pdu->callback(iscsi, SCSI_STATUS_CANCELLED, NULL, - pdu->private_data); - } - iscsi_free_pdu(iscsi, pdu); - return 0; - } - } - for (pdu = iscsi->outqueue; pdu; pdu = pdu->next) { - if (pdu->itt == task->itt) { - SLIST_REMOVE(&iscsi->outqueue, pdu); - if ( !(pdu->flags & ISCSI_PDU_NO_CALLBACK)) { - pdu->callback(iscsi, SCSI_STATUS_CANCELLED, NULL, - pdu->private_data); - } - iscsi_free_pdu(iscsi, pdu); - return 0; - } - } - return -1; -} - -void -iscsi_scsi_cancel_all_tasks(struct iscsi_context *iscsi) -{ - struct iscsi_pdu *pdu; - - for (pdu = iscsi->waitpdu; pdu; pdu = pdu->next) { - struct scsi_task *task = iscsi_scsi_get_task_from_pdu(pdu); - - SLIST_REMOVE(&iscsi->waitpdu, pdu); - if ( !(pdu->flags & ISCSI_PDU_NO_CALLBACK)) { - pdu->callback(iscsi, SCSI_STATUS_CANCELLED, NULL, - pdu->private_data); - } - iscsi_free_pdu(iscsi, pdu); - } - for (pdu = iscsi->outqueue; pdu; pdu = pdu->next) { - struct scsi_task *task = iscsi_scsi_get_task_from_pdu(pdu); - - SLIST_REMOVE(&iscsi->outqueue, pdu); - if ( !(pdu->flags & ISCSI_PDU_NO_CALLBACK)) { - pdu->callback(iscsi, SCSI_STATUS_CANCELLED, NULL, - pdu->private_data); - } - iscsi_free_pdu(iscsi, pdu); - } -} diff --git a/lib/task_mgmt.c b/lib/task_mgmt.c index 286072d..5767aed 100644 --- a/lib/task_mgmt.c +++ b/lib/task_mgmt.c @@ -103,7 +103,7 @@ iscsi_task_mgmt_abort_task_async(struct iscsi_context *iscsi, struct scsi_task *task, iscsi_command_cb cb, void *private_data) { - iscsi_scsi_task_cancel(iscsi, task); + iscsi_scsi_cancel_task(iscsi, task); return iscsi_task_mgmt_async(iscsi, task->lun, ISCSI_TM_ABORT_TASK, From a5b8224f4e78229a42a990c06f218eadea776ae8 Mon Sep 17 00:00:00 2001 From: Ronnie Sahlberg Date: Sun, 11 Nov 2012 09:49:49 -0800 Subject: [PATCH 18/21] Dont include iscsi headers from the scsi implementation in scsi-lowlevel.c --- include/scsi-lowlevel.h | 8 +++++++- lib/scsi-lowlevel.c | 2 -- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/include/scsi-lowlevel.h b/include/scsi-lowlevel.h index 53b4118..d3d7712 100644 --- a/include/scsi-lowlevel.h +++ b/include/scsi-lowlevel.h @@ -17,6 +17,12 @@ #ifndef __scsi_lowlevel_h__ #define __scsi_lowlevel_h__ +#if defined(WIN32) +#define EXTERN __declspec( dllexport ) +#else +#define EXTERN +#endif + #ifdef __cplusplus extern "C" { #endif @@ -356,7 +362,7 @@ struct scsi_task { /* This function will free a scsi task structure. You may NOT cancel a task until the callback has been invoked - and the command has completed on the iscsi layer. + and the command has completed on the transport layer. */ EXTERN void scsi_free_scsi_task(struct scsi_task *task); diff --git a/lib/scsi-lowlevel.c b/lib/scsi-lowlevel.c index e7697b5..fa14533 100644 --- a/lib/scsi-lowlevel.c +++ b/lib/scsi-lowlevel.c @@ -35,9 +35,7 @@ #include #include #include "slist.h" -#include "iscsi.h" #include "scsi-lowlevel.h" -#include "iscsi-private.h" struct scsi_allocated_memory { struct scsi_allocated_memory *next; From 9eb26a368d4c5efec395c0441ed0c853d3d0b1b2 Mon Sep 17 00:00:00 2001 From: Ronnie Sahlberg Date: Sun, 11 Nov 2012 10:03:45 -0800 Subject: [PATCH 19/21] Fix compiler warnings related to 'const' --- examples/iscsiclient.c | 2 +- src/iscsi-inq.c | 13 +++++++++---- src/iscsi-ls.c | 12 +++++++++--- src/iscsi-readcapacity16.c | 12 +++++++++--- test-tool/iscsi-test.c | 6 +++++- 5 files changed, 33 insertions(+), 12 deletions(-) diff --git a/examples/iscsiclient.c b/examples/iscsiclient.c index 8041a39..a627716 100644 --- a/examples/iscsiclient.c +++ b/examples/iscsiclient.c @@ -52,7 +52,7 @@ WSADATA wsaData; struct client_state { int finished; - char *message; + const char *message; int has_discovered_target; char *target_name; char *target_address; diff --git a/src/iscsi-inq.c b/src/iscsi-inq.c index 475836b..cc15c90 100644 --- a/src/iscsi-inq.c +++ b/src/iscsi-inq.c @@ -24,8 +24,11 @@ #include "iscsi.h" #include "scsi-lowlevel.h" -const char *initiator = "iqn.2007-10.com.github:sahlberg:libiscsi:iscsi-inq"; +#ifndef discard_const +#define discard_const(ptr) ((void *)((intptr_t)(ptr))) +#endif +const char *initiator = "iqn.2007-10.com.github:sahlberg:libiscsi:iscsi-inq"; void inquiry_block_limits(struct scsi_inquiry_block_limits *inq) { @@ -216,7 +219,7 @@ int main(int argc, const char *argv[]) struct iscsi_context *iscsi; const char **extra_argv; int extra_argc = 0; - char *url = NULL; + const char *url = NULL; struct iscsi_url *iscsi_url = NULL; int evpd = 0, pagecode = 0; int show_help = 0, show_usage = 0, debug = 0; @@ -277,8 +280,10 @@ int main(int argc, const char *argv[]) } iscsi_url = iscsi_parse_full_url(iscsi, url); - if (url) free(url); - + if (url) { + free(discard_const(url)); + } + if (iscsi_url == NULL) { fprintf(stderr, "Failed to parse URL: %s\n", iscsi_get_error(iscsi)); diff --git a/src/iscsi-ls.c b/src/iscsi-ls.c index 94df54c..7d7ac17 100644 --- a/src/iscsi-ls.c +++ b/src/iscsi-ls.c @@ -24,6 +24,10 @@ #include "iscsi.h" #include "scsi-lowlevel.h" +#ifndef discard_const +#define discard_const(ptr) ((void *)((intptr_t)(ptr))) +#endif + int showluns; const char *initiator = "iqn.2007-10.com.github:sahlberg:libiscsi:iscsi-ls"; @@ -312,7 +316,7 @@ int main(int argc, const char *argv[]) struct client_state state; const char **extra_argv; int extra_argc = 0; - char *url = NULL; + const char *url = NULL; poptContext pc; int res; int show_help = 0, show_usage = 0, debug = 0; @@ -374,8 +378,10 @@ int main(int argc, const char *argv[]) iscsi_url = iscsi_parse_portal_url(iscsi, url); - if (url) free(url); - + if (url) { + free(discard_const(url)); + } + if (iscsi_url == NULL) { fprintf(stderr, "Failed to parse URL: %s\n", iscsi_get_error(iscsi)); diff --git a/src/iscsi-readcapacity16.c b/src/iscsi-readcapacity16.c index 512c359..31503d8 100644 --- a/src/iscsi-readcapacity16.c +++ b/src/iscsi-readcapacity16.c @@ -26,6 +26,10 @@ #include "iscsi.h" #include "scsi-lowlevel.h" +#ifndef discard_const +#define discard_const(ptr) ((void *)((intptr_t)(ptr))) +#endif + const char *initiator = "iqn.2007-10.com.github:sahlberg:libiscsi:iscsi-readcapacity16"; void print_usage(void) @@ -58,7 +62,7 @@ int main(int argc, const char *argv[]) struct iscsi_context *iscsi; const char **extra_argv; int extra_argc = 0; - char *url = NULL; + const char *url = NULL; struct iscsi_url *iscsi_url = NULL; int show_help = 0, show_usage = 0, debug = 0, size_only=0; int res; @@ -119,8 +123,10 @@ int main(int argc, const char *argv[]) } iscsi_url = iscsi_parse_full_url(iscsi, url); - if (url) free(url); - + if (url) { + free(discard_const(url)); + } + if (iscsi_url == NULL) { fprintf(stderr, "Failed to parse URL: %s\n", iscsi_get_error(iscsi)); diff --git a/test-tool/iscsi-test.c b/test-tool/iscsi-test.c index 948bbfc..1235cf1 100644 --- a/test-tool/iscsi-test.c +++ b/test-tool/iscsi-test.c @@ -34,6 +34,10 @@ #include "iscsi-private.h" #include "iscsi-test.h" +#ifndef discard_const +#define discard_const(ptr) ((void *)((intptr_t)(ptr))) +#endif + const char *initiatorname1 = "iqn.2007-10.com.github:sahlberg:libiscsi:iscsi-test"; const char *initiatorname2 = "iqn.2007-10.com.github:sahlberg:libiscsi:iscsi-test-2"; @@ -478,7 +482,7 @@ int main(int argc, const char *argv[]) free(skipname); free(testname); - free(url); + free(discard_const(url)); return num_failed ? num_failed : num_skipped ? 77 : 0; } From 5a95010b5921c2ea50349d8ac05a7f4582aebc19 Mon Sep 17 00:00:00 2001 From: Ronnie Sahlberg Date: Sun, 11 Nov 2012 10:12:39 -0800 Subject: [PATCH 20/21] Fix some compiler warnings --- test-tool/1010_datasn_invalid.c | 5 ++++- test-tool/1020_bufferoffset_invalid.c | 7 +++++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/test-tool/1010_datasn_invalid.c b/test-tool/1010_datasn_invalid.c index ec4bc3b..eea52b4 100644 --- a/test-tool/1010_datasn_invalid.c +++ b/test-tool/1010_datasn_invalid.c @@ -26,6 +26,8 @@ static int clamp_datasn; static int my_iscsi_queue_pdu(struct iscsi_context *iscsi _U_, struct iscsi_pdu *pdu) { + uint32_t datasn; + if (pdu->outdata.data[0] != ISCSI_PDU_DATA_OUT) { return 0; } @@ -44,7 +46,8 @@ static int my_iscsi_queue_pdu(struct iscsi_context *iscsi _U_, struct iscsi_pdu break; case 4: /* change datasn from (0,1) to (1,0) */ - *(uint32_t *)&pdu->outdata.data[36] = htonl(1 - ntohl(*(uint32_t *)&pdu->outdata.data[36])); + datasn = ntohl(*(uint32_t *)&pdu->outdata.data[36]); + *(uint32_t *)&pdu->outdata.data[36] = htonl(1 - datasn); break; } return 0; diff --git a/test-tool/1020_bufferoffset_invalid.c b/test-tool/1020_bufferoffset_invalid.c index 80b1025..1bc17ea 100644 --- a/test-tool/1020_bufferoffset_invalid.c +++ b/test-tool/1020_bufferoffset_invalid.c @@ -28,17 +28,20 @@ uint32_t block_size; static int my_iscsi_queue_pdu(struct iscsi_context *iscsi _U_, struct iscsi_pdu *pdu) { + uint32_t buffer_offset; + if (pdu->outdata.data[0] != ISCSI_PDU_DATA_OUT) { return 0; } + buffer_offset = ntohl(*(uint32_t *)&pdu->outdata.data[40]); switch (change_bufferoffset) { case 1: /* Add 1M to the buffer offset */ - *(uint32_t *)&pdu->outdata.data[40] = htonl(ntohl(*(uint32_t *)&pdu->outdata.data[40]) + 1024*1024); + *(uint32_t *)&pdu->outdata.data[40] = htonl(buffer_offset + 1024*1024); break; case 2: /* Add -'block_size' to the buffer offset */ - *(uint32_t *)&pdu->outdata.data[40] = htonl(ntohl(*(uint32_t *)&pdu->outdata.data[40]) - block_size); + *(uint32_t *)&pdu->outdata.data[40] = htonl(buffer_offset - block_size); break; } return 0; From 736e175e83f064dbf38fdb7c2003a515155e29aa Mon Sep 17 00:00:00 2001 From: Ronnie Sahlberg Date: Sun, 11 Nov 2012 10:15:52 -0800 Subject: [PATCH 21/21] Build with -Werror --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index bb95018..a08ca24 100644 --- a/configure.ac +++ b/configure.ac @@ -22,7 +22,7 @@ AM_CONDITIONAL(LD_ISCSI, [expr "$host_os" : linux > /dev/null 2>&1]) if test "$ac_cv_prog_gcc" = yes; then - WARN_CFLAGS="-Wall -W -Wshadow -Wstrict-prototypes -Wpointer-arith -Wcast-align -Wwrite-strings" + WARN_CFLAGS="-Wall -W -Wshadow -Wstrict-prototypes -Wpointer-arith -Wcast-align -Wwrite-strings -Werror" fi AC_SUBST(WARN_CFLAGS)