summaryrefslogtreecommitdiffstats
path: root/src/server
diff options
context:
space:
mode:
authorSebastian Vater2025-10-13 09:33:18 +0200
committerSebastian Vater2025-10-13 09:33:18 +0200
commitf48e7e32b7be6c645eac8f7d76bd4cdfe0cd3616 (patch)
tree21abfd0f24b14807c6c81b0c9d1ce6e82c3cc817 /src/server
parentFixed iSCSI SCSI INQUIRY optimal block size configuraton. Finally, added TCP_... (diff)
downloaddnbd3-f48e7e32b7be6c645eac8f7d76bd4cdfe0cd3616.tar.gz
dnbd3-f48e7e32b7be6c645eac8f7d76bd4cdfe0cd3616.tar.xz
dnbd3-f48e7e32b7be6c645eac8f7d76bd4cdfe0cd3616.zip
iSCSI Release candiate. Fixed iSCSI (some critical) bugs encountered during testing phase. Also, with a MaxRecvDataSegmentLength at least of 64k, which is the new default, iSCSI now works smoothly on boot even with no TCP_NODELAY. Finally, huge performance gains with parallel sessions by optimizing multithreading by using pthreads rwlock for read caches.
Diffstat (limited to 'src/server')
-rw-r--r--src/server/iscsi.c694
-rw-r--r--src/server/iscsi.h55
2 files changed, 438 insertions, 311 deletions
diff --git a/src/server/iscsi.c b/src/server/iscsi.c
index f0cea53..2ca2225 100644
--- a/src/server/iscsi.c
+++ b/src/server/iscsi.c
@@ -362,7 +362,7 @@ void iscsi_hashmap_key_destroy(uint8_t *key)
* there is a possibility for future usage.
* @return Always returns 0 as this function cannot fail.
*/
-int iscsi_hashmap_key_destroy_callback(uint8_t *key, const size_t key_size, uint8_t *value, uint8_t *user_data)
+int iscsi_hashmap_key_destroy_callback(uint8_t *key, const size_t key_size UNUSED, uint8_t *value UNUSED, uint8_t *user_data UNUSED)
{
iscsi_hashmap_key_destroy( key );
@@ -385,7 +385,7 @@ int iscsi_hashmap_key_destroy_callback(uint8_t *key, const size_t key_size, uint
* there is a possibility for future usage.
* @return Always returns 0 as this function cannot fail.
*/
-int iscsi_hashmap_destroy_value_callback(uint8_t *key, const size_t key_size, uint8_t *value, uint8_t *user_data)
+int iscsi_hashmap_destroy_value_callback(uint8_t *key UNUSED, const size_t key_size UNUSED, uint8_t *value, uint8_t *user_data UNUSED)
{
if ( value != NULL )
free( value );
@@ -409,7 +409,7 @@ int iscsi_hashmap_destroy_value_callback(uint8_t *key, const size_t key_size, ui
* there is a possibility for future usage.
* @return Always returns 0 as this function cannot fail.
*/
-int iscsi_hashmap_key_destroy_value_callback(uint8_t *key, const size_t key_size, uint8_t *value, uint8_t *user_data)
+int iscsi_hashmap_key_destroy_value_callback(uint8_t *key, const size_t key_size UNUSED, uint8_t *value, uint8_t *user_data UNUSED)
{
if ( value != NULL )
free( value );
@@ -963,7 +963,7 @@ pthread_rwlock_t iscsi_globvec_rwlock;
static const iscsi_key_value_pair_lut_entry iscsi_connection_key_value_pair_lut[] = {
{ ISCSI_LOGIN_AUTH_SESSION_TEXT_KEY_HEADER_DIGEST, (uint8_t *) "None", (uint8_t *) "CRC32C\0None\0", ISCSI_TEXT_KEY_VALUE_PAIR_TYPE_LIST, 0 },
{ ISCSI_LOGIN_AUTH_SESSION_TEXT_KEY_DATA_DIGEST, (uint8_t *) "None", (uint8_t *) "CRC32C\0None\0", ISCSI_TEXT_KEY_VALUE_PAIR_TYPE_LIST, 0 },
- { ISCSI_LOGIN_AUTH_SESSION_TEXT_KEY_MAX_RECV_DS_LEN, (uint8_t *) "8192", (uint8_t *) "512\016777215\0", ISCSI_TEXT_KEY_VALUE_PAIR_TYPE_NUM_DECLARATIVE, ISCSI_TEXT_KEY_VALUE_PAIR_FLAGS_MULTI_NEGOTIATION | ISCSI_TEXT_KEY_VALUE_PAIR_FLAGS_OVERRIDE_DEFAULT },
+ { ISCSI_LOGIN_AUTH_SESSION_TEXT_KEY_MAX_RECV_DS_LEN, (uint8_t *) "8192", (uint8_t *) "512\0""16777215\0", ISCSI_TEXT_KEY_VALUE_PAIR_TYPE_NUM_DECLARATIVE, ISCSI_TEXT_KEY_VALUE_PAIR_FLAGS_MULTI_NEGOTIATION | ISCSI_TEXT_KEY_VALUE_PAIR_FLAGS_OVERRIDE_DEFAULT },
{ ISCSI_LOGIN_AUTH_SESSION_TEXT_KEY_OF_MARKER, (uint8_t *) "No", (uint8_t *) "Yes\0No\0", ISCSI_TEXT_KEY_VALUE_PAIR_TYPE_BOOL_AND, 0 },
{ ISCSI_LOGIN_AUTH_SESSION_TEXT_KEY_IF_MARKER, (uint8_t *) "No", (uint8_t *) "Yes\0No\0", ISCSI_TEXT_KEY_VALUE_PAIR_TYPE_BOOL_AND, 0 },
{ ISCSI_LOGIN_AUTH_SESSION_TEXT_KEY_OF_MARK_INT, (uint8_t *) "1", (uint8_t *) "1\0""65535\0", ISCSI_TEXT_KEY_VALUE_PAIR_TYPE_NUM_MIN, 0 },
@@ -1289,8 +1289,8 @@ int iscsi_create()
return -1;
}
- if ( pthread_mutex_init( &globvec->scsi_device_config_mutex, NULL ) != 0 ) {
- logadd( LOG_ERROR, "iscsi_create: Out of memory while initializing mutex for iSCSI global vector SCSI device configuration" );
+ if ( pthread_rwlock_init( &globvec->scsi_device_config_rwlock, NULL ) != 0 ) {
+ logadd( LOG_ERROR, "iscsi_create: Out of memory while initializing read/write lock for iSCSI global vector SCSI device configuration" );
iscsi_hashmap_destroy( globvec->scsi_device_config );
iscsi_hashmap_iterate( globvec->connection_key_value_pairs, iscsi_hashmap_key_destroy_value_callback, NULL );
@@ -1312,12 +1312,12 @@ int iscsi_create()
}
globvec->flags = (ISCSI_GLOBALS_FLAGS_INIT_R2T | ISCSI_GLOBALS_FLAGS_IMMEDIATE_DATA | ISCSI_GLOBALS_FLAGS_DATA_PDU_IN_ORDER | ISCSI_GLOBALS_FLAGS_DATA_SEQ_IN_ORDER | ISCSI_GLOBALS_FLAGS_SCSI_IO_REMOVABLE | ISCSI_GLOBALS_FLAGS_SCSI_IO_WRITE_PROTECT);
- globvec->target_name_check = ISCSI_GLOBALS_TARGET_NAME_CHECK_FULL;
+ globvec->target_name_check = ISCSI_GLOBALS_TARGET_NAME_CHECK_RELAXED;
globvec->max_sessions = 0U;
globvec->header_digest = 0;
globvec->data_digest = 0;
globvec->scsi_device_type = ISCSI_SCSI_BASIC_INQUIRY_DATA_PERIPHERAL_TYPE_DIRECT;
- globvec->max_recv_ds_len = ISCSI_DEFAULT_RECV_DS_LEN;
+ globvec->max_recv_ds_len = ISCSI_DEFAULT_MAX_RECV_DS_LEN;
globvec->max_session_conns = ISCSI_GLOBALS_DEFAULT_MAX_CONNECTIONS;
globvec->max_outstanding_r2t = ISCSI_GLOBALS_DEFAULT_MAX_OUTSTANDING_R2T;
globvec->default_time_to_wait = ISCSI_GLOBALS_DEFAULT_TIME_TO_WAIT;
@@ -1361,7 +1361,7 @@ void iscsi_destroy()
if ( globvec != NULL ) {
iscsi_globvec = NULL;
- pthread_mutex_destroy( &globvec->scsi_device_config_mutex );
+ pthread_rwlock_destroy( &globvec->scsi_device_config_rwlock );
iscsi_hashmap_iterate( globvec->scsi_device_config, iscsi_hashmap_key_destroy_value_callback, NULL );
iscsi_hashmap_destroy( globvec->scsi_device_config );
globvec->scsi_device_config = NULL;
@@ -1425,7 +1425,7 @@ void iscsi_destroy()
static int32_t iscsi_config_parse_int(const uint8_t *value)
{
if ( *value == '\0' )
- return -2147483648L;
+ return ISCSI_GLOBALS_CONFIG_TYPE_VALUE_ERROR;
if ( (strcasecmp( (char *) value, "true" ) == 0) || (strcasecmp( (char *) value, "yes" ) == 0) || (strcasecmp( (char *) value, "on" ) == 0) || (strcasecmp( (char *) value, "enabled" ) == 0) || (strcasecmp( (char *) value, "activated" ) == 0) )
return 1L;
@@ -1436,7 +1436,7 @@ static int32_t iscsi_config_parse_int(const uint8_t *value)
int64_t rc = (int64_t) strtoll( (char *) value, (char **) &val_end, 10 );
if ( value == val_end )
- return -2147483648L;
+ return ISCSI_GLOBALS_CONFIG_TYPE_VALUE_ERROR;
while ( (*val_end == '\t') || (*val_end == ' ') ) {
val_end++;
@@ -1500,7 +1500,7 @@ static int32_t iscsi_config_parse_int(const uint8_t *value)
break;
}
default : {
- return -2147483648L;
+ return ISCSI_GLOBALS_CONFIG_TYPE_VALUE_ERROR;
break;
}
@@ -1514,7 +1514,7 @@ static int32_t iscsi_config_parse_int(const uint8_t *value)
}
if ( *val_end != '\0' )
- return -2147483648L;
+ return ISCSI_GLOBALS_CONFIG_TYPE_VALUE_ERROR;
if ( rc < -2147483647LL )
rc = -2147483647LL;
@@ -1558,10 +1558,10 @@ static int iscsi_config_load_from_ini(void *user_data, const char *section, cons
if ( strcasecmp( key, ISCSI_GLOBALS_SECTION_ISCSI_KEY_TARGET_NAME_CHECK ) == 0 ) {
if ( strcasecmp( value, "None" ) == 0 )
globvec->target_name_check = ISCSI_GLOBALS_TARGET_NAME_CHECK_NONE;
- else if ( strcasecmp( value, "Relaxed" ) == 0 )
- globvec->target_name_check = ISCSI_GLOBALS_TARGET_NAME_CHECK_RELAXED;
- else
+ else if ( strcasecmp( value, "Full" ) == 0 )
globvec->target_name_check = ISCSI_GLOBALS_TARGET_NAME_CHECK_FULL;
+ else
+ globvec->target_name_check = ISCSI_GLOBALS_TARGET_NAME_CHECK_RELAXED;
} else if ( strcasecmp( key, ISCSI_GLOBALS_SECTION_ISCSI_KEY_MAX_SESSIONS ) == 0 ) {
globvec->max_sessions = (uint) num_value;
} else if ( strcasecmp( key, (char *) ISCSI_LOGIN_AUTH_SESSION_TEXT_KEY_HEADER_DIGEST ) == 0 ) {
@@ -1590,28 +1590,28 @@ static int iscsi_config_load_from_ini(void *user_data, const char *section, cons
if ( (num_value >= 512L) && (num_value <= (int32_t) ISCSI_MAX_DS_SIZE) )
globvec->max_burst_len = num_value;
} else if ( strcasecmp( key, (char *) ISCSI_LOGIN_AUTH_SESSION_TEXT_KEY_INITIAL_R2T ) == 0 ) {
- if ( num_value != -2147483648L ) {
+ if ( num_value != ISCSI_GLOBALS_CONFIG_TYPE_VALUE_ERROR ) {
if ( num_value != 0L )
globvec->flags |= ISCSI_GLOBALS_FLAGS_INIT_R2T;
else
globvec->flags &= ~ISCSI_GLOBALS_FLAGS_INIT_R2T;
}
} else if ( strcasecmp( key, (char *) ISCSI_LOGIN_AUTH_SESSION_TEXT_KEY_IMMEDIATE_DATA ) == 0 ) {
- if ( num_value != -2147483648L ) {
+ if ( num_value != ISCSI_GLOBALS_CONFIG_TYPE_VALUE_ERROR ) {
if ( num_value != 0L )
globvec->flags |= ISCSI_GLOBALS_FLAGS_IMMEDIATE_DATA;
else
globvec->flags &= ~ISCSI_GLOBALS_FLAGS_IMMEDIATE_DATA;
}
} else if ( strcasecmp( key, (char *) ISCSI_LOGIN_AUTH_SESSION_TEXT_KEY_DATA_PDU_IN_ORDER ) == 0 ) {
- if ( num_value != -2147483648L ) {
+ if ( num_value != ISCSI_GLOBALS_CONFIG_TYPE_VALUE_ERROR ) {
if ( num_value != 0L )
globvec->flags |= ISCSI_GLOBALS_FLAGS_DATA_PDU_IN_ORDER;
else
globvec->flags &= ~ISCSI_GLOBALS_FLAGS_DATA_PDU_IN_ORDER;
}
} else if ( strcasecmp( key, (char *) ISCSI_LOGIN_AUTH_SESSION_TEXT_KEY_DATA_SEQ_IN_ORDER ) == 0 ) {
- if ( num_value != -2147483648L ) {
+ if ( num_value != ISCSI_GLOBALS_CONFIG_TYPE_VALUE_ERROR ) {
if ( num_value != 0L )
globvec->flags |= ISCSI_GLOBALS_FLAGS_DATA_SEQ_IN_ORDER;
else
@@ -1652,42 +1652,42 @@ static int iscsi_config_load_from_ini(void *user_data, const char *section, cons
globvec->scsi_logical_block_size_shift = iscsi_get_log2_of_pow2( num_value );
}
} else if ( strcasecmp( key, ISCSI_GLOBALS_SECTION_SCSI_KEY_REMOVABLE ) == 0 ) {
- if ( num_value != -2147483648L ) {
+ if ( num_value != ISCSI_GLOBALS_CONFIG_TYPE_VALUE_ERROR ) {
if ( num_value != 0L )
globvec->flags |= ISCSI_GLOBALS_FLAGS_SCSI_IO_REMOVABLE;
else
globvec->flags &= ~ISCSI_GLOBALS_FLAGS_SCSI_IO_REMOVABLE;
}
} else if ( strcasecmp( key, ISCSI_GLOBALS_SECTION_SCSI_KEY_UNMAP ) == 0 ) {
- if ( num_value != -2147483648L ) {
+ if ( num_value != ISCSI_GLOBALS_CONFIG_TYPE_VALUE_ERROR ) {
if ( num_value != 0L )
globvec->flags |= ISCSI_GLOBALS_FLAGS_SCSI_IO_UNMAP;
else
globvec->flags &= ~ISCSI_GLOBALS_FLAGS_SCSI_IO_UNMAP;
}
} else if ( strcasecmp( key, ISCSI_GLOBALS_SECTION_SCSI_KEY_NO_ROTATION ) == 0 ) {
- if ( num_value != -2147483648L ) {
+ if ( num_value != ISCSI_GLOBALS_CONFIG_TYPE_VALUE_ERROR ) {
if ( num_value != 0L )
globvec->flags |= ISCSI_GLOBALS_FLAGS_SCSI_IO_NO_ROTATION;
else
globvec->flags &= ~ISCSI_GLOBALS_FLAGS_SCSI_IO_NO_ROTATION;
}
} else if ( strcasecmp( key, ISCSI_GLOBALS_SECTION_SCSI_KEY_PHYSICAL_READ_ONLY ) == 0 ) {
- if ( num_value != -2147483648L ) {
+ if ( num_value != ISCSI_GLOBALS_CONFIG_TYPE_VALUE_ERROR ) {
if ( num_value != 0L )
globvec->flags |= ISCSI_GLOBALS_FLAGS_SCSI_IO_PHYSICAL_READ_ONLY;
else
globvec->flags &= ~ISCSI_GLOBALS_FLAGS_SCSI_IO_PHYSICAL_READ_ONLY;
}
} else if ( strcasecmp( key, ISCSI_GLOBALS_SECTION_SCSI_KEY_WRITE_PROTECT ) == 0 ) {
- if ( num_value != -2147483648L ) {
+ if ( num_value != ISCSI_GLOBALS_CONFIG_TYPE_VALUE_ERROR ) {
if ( num_value != 0L )
globvec->flags |= ISCSI_GLOBALS_FLAGS_SCSI_IO_WRITE_PROTECT;
else
globvec->flags &= ~ISCSI_GLOBALS_FLAGS_SCSI_IO_WRITE_PROTECT;
}
} else if ( strcasecmp( key, ISCSI_GLOBALS_SECTION_SCSI_KEY_WRITE_CACHE ) == 0 ) {
- if ( num_value != -2147483648L ) {
+ if ( num_value != ISCSI_GLOBALS_CONFIG_TYPE_VALUE_ERROR ) {
if ( num_value != 0L )
globvec->flags |= ISCSI_GLOBALS_FLAGS_SCSI_IO_WRITE_CACHE;
else
@@ -1811,28 +1811,28 @@ static int iscsi_config_load_from_ini(void *user_data, const char *section, cons
if ( (num_value >= 512L) && (num_value <= (int32_t) ISCSI_MAX_DS_SIZE) )
scsi_device_config->max_burst_len = num_value;
} else if ( strcasecmp( key, (char *) ISCSI_LOGIN_AUTH_SESSION_TEXT_KEY_INITIAL_R2T ) == 0 ) {
- if ( num_value != -2147483648L ) {
+ if ( num_value != ISCSI_GLOBALS_CONFIG_TYPE_VALUE_ERROR ) {
if ( num_value != 0L )
scsi_device_config->flags |= ISCSI_GLOBALS_FLAGS_INIT_R2T;
else
scsi_device_config->flags &= ~ISCSI_GLOBALS_FLAGS_INIT_R2T;
}
} else if ( strcasecmp( key, (char *) ISCSI_LOGIN_AUTH_SESSION_TEXT_KEY_IMMEDIATE_DATA ) == 0 ) {
- if ( num_value != -2147483648L ) {
+ if ( num_value != ISCSI_GLOBALS_CONFIG_TYPE_VALUE_ERROR ) {
if ( num_value != 0L )
scsi_device_config->flags |= ISCSI_GLOBALS_FLAGS_IMMEDIATE_DATA;
else
scsi_device_config->flags &= ~ISCSI_GLOBALS_FLAGS_IMMEDIATE_DATA;
}
} else if ( strcasecmp( key, (char *) ISCSI_LOGIN_AUTH_SESSION_TEXT_KEY_DATA_PDU_IN_ORDER ) == 0 ) {
- if ( num_value != -2147483648L ) {
+ if ( num_value != ISCSI_GLOBALS_CONFIG_TYPE_VALUE_ERROR ) {
if ( num_value != 0L )
scsi_device_config->flags |= ISCSI_GLOBALS_FLAGS_DATA_PDU_IN_ORDER;
else
scsi_device_config->flags &= ~ISCSI_GLOBALS_FLAGS_DATA_PDU_IN_ORDER;
}
} else if ( strcasecmp( key, (char *) ISCSI_LOGIN_AUTH_SESSION_TEXT_KEY_DATA_SEQ_IN_ORDER ) == 0 ) {
- if ( num_value != -2147483648L ) {
+ if ( num_value != ISCSI_GLOBALS_CONFIG_TYPE_VALUE_ERROR ) {
if ( num_value != 0L )
scsi_device_config->flags |= ISCSI_GLOBALS_FLAGS_DATA_SEQ_IN_ORDER;
else
@@ -1869,42 +1869,42 @@ static int iscsi_config_load_from_ini(void *user_data, const char *section, cons
scsi_device_config->scsi_logical_block_size_shift = iscsi_get_log2_of_pow2( num_value );
}
} else if ( strcasecmp( key, ISCSI_GLOBALS_SECTION_SCSI_KEY_REMOVABLE ) == 0 ) {
- if ( num_value != -2147483648L ) {
+ if ( num_value != ISCSI_GLOBALS_CONFIG_TYPE_VALUE_ERROR ) {
if ( num_value != 0L )
scsi_device_config->flags |= ISCSI_GLOBALS_SCSI_DEVICE_CONFIG_FLAGS_SCSI_IO_REMOVABLE;
else
scsi_device_config->flags &= ~ISCSI_GLOBALS_SCSI_DEVICE_CONFIG_FLAGS_SCSI_IO_REMOVABLE;
}
} else if ( strcasecmp( key, ISCSI_GLOBALS_SECTION_SCSI_KEY_UNMAP ) == 0 ) {
- if ( num_value != -2147483648L ) {
+ if ( num_value != ISCSI_GLOBALS_CONFIG_TYPE_VALUE_ERROR ) {
if ( num_value != 0L )
scsi_device_config->flags |= ISCSI_GLOBALS_SCSI_DEVICE_CONFIG_FLAGS_SCSI_IO_UNMAP;
else
scsi_device_config->flags &= ~ISCSI_GLOBALS_SCSI_DEVICE_CONFIG_FLAGS_SCSI_IO_UNMAP;
}
} else if ( strcasecmp( key, ISCSI_GLOBALS_SECTION_SCSI_KEY_NO_ROTATION ) == 0 ) {
- if ( num_value != -2147483648L ) {
+ if ( num_value != ISCSI_GLOBALS_CONFIG_TYPE_VALUE_ERROR ) {
if ( num_value != 0L )
scsi_device_config->flags |= ISCSI_GLOBALS_SCSI_DEVICE_CONFIG_FLAGS_SCSI_IO_NO_ROTATION;
else
scsi_device_config->flags &= ~ISCSI_GLOBALS_SCSI_DEVICE_CONFIG_FLAGS_SCSI_IO_NO_ROTATION;
}
} else if ( strcasecmp( key, ISCSI_GLOBALS_SECTION_SCSI_KEY_PHYSICAL_READ_ONLY ) == 0 ) {
- if ( num_value != -2147483648L ) {
+ if ( num_value != ISCSI_GLOBALS_CONFIG_TYPE_VALUE_ERROR ) {
if ( num_value != 0L )
scsi_device_config->flags |= ISCSI_GLOBALS_SCSI_DEVICE_CONFIG_FLAGS_SCSI_IO_PHYSICAL_READ_ONLY;
else
scsi_device_config->flags &= ~ISCSI_GLOBALS_SCSI_DEVICE_CONFIG_FLAGS_SCSI_IO_PHYSICAL_READ_ONLY;
}
} else if ( strcasecmp( key, ISCSI_GLOBALS_SECTION_SCSI_KEY_WRITE_PROTECT ) == 0 ) {
- if ( num_value != -2147483648L ) {
+ if ( num_value != ISCSI_GLOBALS_CONFIG_TYPE_VALUE_ERROR ) {
if ( num_value != 0L )
scsi_device_config->flags |= ISCSI_GLOBALS_SCSI_DEVICE_CONFIG_FLAGS_SCSI_IO_WRITE_PROTECT;
else
scsi_device_config->flags &= ~ISCSI_GLOBALS_SCSI_DEVICE_CONFIG_FLAGS_SCSI_IO_WRITE_PROTECT;
}
} else if ( strcasecmp( key, ISCSI_GLOBALS_SECTION_SCSI_KEY_WRITE_CACHE ) == 0 ) {
- if ( num_value != -2147483648L ) {
+ if ( num_value != ISCSI_GLOBALS_CONFIG_TYPE_VALUE_ERROR ) {
if ( num_value != 0L )
scsi_device_config->flags |= ISCSI_GLOBALS_SCSI_DEVICE_CONFIG_FLAGS_SCSI_IO_WRITE_CACHE;
else
@@ -1943,7 +1943,7 @@ int iscsi_config_load(iscsi_globals *globvec)
return 0;
}
- pthread_mutex_lock( &globvec->scsi_device_config_mutex );
+ pthread_rwlock_wrlock( &globvec->scsi_device_config_rwlock );
iscsi_hashmap_iterate( globvec->scsi_device_config, iscsi_hashmap_key_destroy_value_callback, NULL );
ini_parse( name, iscsi_config_load_from_ini, (void *) globvec );
free( name );
@@ -1951,20 +1951,20 @@ int iscsi_config_load(iscsi_globals *globvec)
name = (char *) iscsi_sprintf_alloc( "%s/%s", _configDir, ISCSI_GLOBALS_CONFIG_FILENAME );
if ( name == NULL ) {
- pthread_mutex_unlock( &globvec->scsi_device_config_mutex );
+ pthread_rwlock_unlock( &globvec->scsi_device_config_rwlock );
return -1;
}
if ( !file_isReadable( name ) ) {
- pthread_mutex_unlock( &globvec->scsi_device_config_mutex );
+ pthread_rwlock_unlock( &globvec->scsi_device_config_rwlock );
free( name );
return 0;
}
ini_parse( name, iscsi_config_load_from_ini, (void *) globvec );
- pthread_mutex_unlock( &globvec->scsi_device_config_mutex );
+ pthread_rwlock_unlock( &globvec->scsi_device_config_rwlock );
free( name );
return 1;
@@ -1994,7 +1994,7 @@ int iscsi_config_load(iscsi_globals *globvec)
* @retval 0 The SCSI device configuration has not been found
* yet.
*/
-int iscsi_config_get_callback(uint8_t *key, const size_t key_size, uint8_t *value, uint8_t *user_data)
+int iscsi_config_get_callback(uint8_t *key, const size_t key_size UNUSED, uint8_t *value, uint8_t *user_data)
{
iscsi_scsi_device_config_find *scsi_device_config_find = (iscsi_scsi_device_config_find *) user_data;
const int rc = fnmatch( (char *) key, (char *) scsi_device_config_find->name, (FNM_PATHNAME | FNM_PERIOD) );
@@ -2023,8 +2023,8 @@ int iscsi_config_get_callback(uint8_t *key, const size_t key_size, uint8_t *valu
* be accessed instead.
* @param[in] type Type of configuration to be
* retrieved.
- * @return The requested configuration value or a
- * negative error code otherwise.
+ * @return The requested configuration value or
+ * -2147483648 as an error code otherwise.
*/
int32_t iscsi_config_get(uint8_t *name, const int type)
{
@@ -2035,50 +2035,45 @@ int32_t iscsi_config_get(uint8_t *name, const int type)
if ( hash_key == NULL ) {
logadd( LOG_ERROR, "iscsi_config_get: Out of memory allocating memory for iSCSI SCSI device configuration key" );
- return -1L;
+ return ISCSI_GLOBALS_CONFIG_TYPE_VALUE_ERROR;
}
- pthread_mutex_lock( &iscsi_globvec->scsi_device_config_mutex );
+ pthread_rwlock_rdlock( &iscsi_globvec->scsi_device_config_rwlock );
iscsi_scsi_device_config *scsi_device_config = NULL;
int rc = iscsi_hashmap_get( iscsi_globvec->scsi_device_config, hash_key, key_len, (uint8_t **) &scsi_device_config );
- if ( rc < 0 ) {
- iscsi_scsi_device_config_find scsi_device_config_find = {NULL, name};
-
- rc = iscsi_hashmap_iterate(iscsi_globvec->scsi_device_config, iscsi_config_get_callback, (uint8_t *) &scsi_device_config_find );
-
- scsi_device_config = scsi_device_config_find.scsi_device_config;
-
- if ( scsi_device_config != NULL ) {
- iscsi_scsi_device_config *new_scsi_device_config = (iscsi_scsi_device_config *) malloc( sizeof(struct iscsi_scsi_device_config) );
+ if ( scsi_device_config == NULL ) {
+ pthread_rwlock_unlock( &iscsi_globvec->scsi_device_config_rwlock );
+ pthread_rwlock_wrlock( &iscsi_globvec->scsi_device_config_rwlock );
+ rc = iscsi_hashmap_get( iscsi_globvec->scsi_device_config, hash_key, key_len, (uint8_t **) &scsi_device_config );
- if ( new_scsi_device_config == NULL ) {
- logadd( LOG_ERROR, "iscsi_config_get: Out of memory allocating memory for new iSCSI SCSI device configuration" );
+ if ( scsi_device_config == NULL ) {
+ iscsi_scsi_device_config_find scsi_device_config_find = {NULL, name};
- pthread_mutex_unlock( &iscsi_globvec->scsi_device_config_mutex );
- iscsi_hashmap_key_destroy( hash_key );
+ rc = iscsi_hashmap_iterate(iscsi_globvec->scsi_device_config, iscsi_config_get_callback, (uint8_t *) &scsi_device_config_find );
- return -1L;
- }
+ scsi_device_config = scsi_device_config_find.scsi_device_config;
- memcpy( new_scsi_device_config, scsi_device_config, sizeof(struct iscsi_scsi_device_config) );
- rc = iscsi_hashmap_put( iscsi_globvec->scsi_device_config, hash_key, key_len, (uint8_t *) new_scsi_device_config );
+ if ( scsi_device_config != NULL ) {
+ iscsi_scsi_device_config *new_scsi_device_config = (iscsi_scsi_device_config *) malloc( sizeof(struct iscsi_scsi_device_config) );
- if ( rc < 0 ) {
- pthread_mutex_unlock( &iscsi_globvec->scsi_device_config_mutex );
- free( new_scsi_device_config );
- iscsi_hashmap_key_destroy( hash_key );
+ if ( new_scsi_device_config != NULL ) {
+ memcpy( new_scsi_device_config, scsi_device_config, sizeof(struct iscsi_scsi_device_config) );
+ rc = iscsi_hashmap_put( iscsi_globvec->scsi_device_config, hash_key, key_len, (uint8_t *) new_scsi_device_config );
- return -1L;
+ if ( rc >= 0 ) {
+ scsi_device_config = new_scsi_device_config;
+ hash_key = NULL;
+ } else {
+ free( new_scsi_device_config );
+ }
+ }
}
-
- scsi_device_config = new_scsi_device_config;
- hash_key = NULL;
}
}
- pthread_mutex_unlock( &iscsi_globvec->scsi_device_config_mutex );
+ pthread_rwlock_unlock( &iscsi_globvec->scsi_device_config_rwlock );
if ( hash_key != NULL )
iscsi_hashmap_key_destroy( hash_key );
@@ -2211,8 +2206,6 @@ int32_t iscsi_config_get(uint8_t *name, const int type)
break;
}
default : {
- return -1L;
-
break;
}
}
@@ -2270,6 +2263,11 @@ int32_t iscsi_config_get(uint8_t *name, const int type)
break;
}
+ case ISCSI_GLOBALS_CONFIG_TYPE_CHAP_GROUP : {
+ return iscsi_globvec->chap_group;
+
+ break;
+ }
case ISCSI_GLOBALS_CONFIG_TYPE_SCSI_DEVICE_TYPE : {
return iscsi_globvec->scsi_device_type;
@@ -2295,6 +2293,21 @@ int32_t iscsi_config_get(uint8_t *name, const int type)
break;
}
+ case ISCSI_GLOBALS_CONFIG_TYPE_FLAGS_CHAP_DISABLE : {
+ return (((iscsi_globvec->flags & ISCSI_GLOBALS_FLAGS_CHAP_DISABLE) != 0) ? 1L : 0L);
+
+ break;
+ }
+ case ISCSI_GLOBALS_CONFIG_TYPE_FLAGS_CHAP_REQUIRE : {
+ return (((iscsi_globvec->flags & ISCSI_GLOBALS_FLAGS_CHAP_REQUIRE) != 0) ? 1L : 0L);
+
+ break;
+ }
+ case ISCSI_GLOBALS_CONFIG_TYPE_FLAGS_CHAP_MUTUAL : {
+ return (((iscsi_globvec->flags & ISCSI_GLOBALS_FLAGS_CHAP_MUTUAL) != 0) ? 1L : 0L);
+
+ break;
+ }
case ISCSI_GLOBALS_CONFIG_TYPE_FLAGS_INIT_R2T : {
return (((iscsi_globvec->flags & ISCSI_GLOBALS_FLAGS_INIT_R2T) != 0) ? 1L : 0L);
@@ -2346,13 +2359,11 @@ int32_t iscsi_config_get(uint8_t *name, const int type)
break;
}
default : {
- return -1L;
-
break;
}
}
- return -1L;
+ return ISCSI_GLOBALS_CONFIG_TYPE_VALUE_ERROR;
}
/**
@@ -3111,7 +3122,7 @@ static int iscsi_task_xfer_add(iscsi_connection *conn, iscsi_task *task)
{
const uint32_t xfer_len = task->scsi_task.xfer_len;
uint32_t ds_len = task->pdu->ds_len;
- const uint32_t seg_len = ISCSI_DEFAULT_MAX_RECV_DS_LEN;
+ const uint32_t seg_len = (uint32_t) iscsi_config_get( NULL, ISCSI_GLOBALS_CONFIG_TYPE_MAX_RECV_DS_LEN );
const uint32_t data_out_req = (uint32_t) (iscsi_is_pow2( seg_len ) ? (((xfer_len - ds_len - 1UL) >> iscsi_get_log2_of_pow2( seg_len )) + 1UL) : (((xfer_len - ds_len - 1UL) / seg_len) + 1UL));
task->scsi_data_out_cnt = data_out_req;
@@ -3604,7 +3615,7 @@ iscsi_portal_group *iscsi_portal_group_create(const uint64_t tag, const int flag
* there is a possibility for future usage.
* @return Always returns 0 as this function cannot fail.
*/
-int iscsi_portal_group_destroy_callback(uint8_t *key, const size_t key_size, uint8_t *value, uint8_t *user_data)
+int iscsi_portal_group_destroy_callback(uint8_t *key UNUSED, const size_t key_size UNUSED, uint8_t *value, uint8_t *user_data UNUSED)
{
iscsi_portal_group_destroy( (iscsi_portal_group *) value );
@@ -3794,7 +3805,7 @@ iscsi_portal *iscsi_portal_create(const uint8_t *host, const uint8_t *port)
* there is a possibility for future usage.
* @return Always returns 0 as this function cannot fail.
*/
-int iscsi_portal_destroy_callback(uint8_t *key, const size_t key_size, uint8_t *value, uint8_t *user_data)
+int iscsi_portal_destroy_callback(uint8_t *key, const size_t key_size UNUSED, uint8_t *value, uint8_t *user_data UNUSED)
{
iscsi_portal_destroy( (iscsi_portal *) value );
iscsi_hashmap_key_destroy( key );
@@ -4214,7 +4225,7 @@ iscsi_scsi_lun *iscsi_scsi_lun_create(const int lun_id)
* there is a possibility for future usage.
* @return Always returns 0 as this function cannot fail.
*/
-int iscsi_scsi_lun_destroy_callback(uint8_t *key, const size_t key_size, uint8_t *value, uint8_t *user_data)
+int iscsi_scsi_lun_destroy_callback(uint8_t *key, const size_t key_size UNUSED, uint8_t *value, uint8_t *user_data UNUSED)
{
iscsi_scsi_lun_destroy( (iscsi_scsi_lun *) value );
iscsi_hashmap_key_destroy( key );
@@ -4579,7 +4590,7 @@ int iscsi_scsi_pr_check_scsi2(iscsi_scsi_task *scsi_task)
* searching is needed.
* @retval 0 The registrant has not been found yet.
*/
-int iscsi_scsi_pr_registrant_get_callback(uint8_t *key, const size_t key_size, uint8_t *value, uint8_t *user_data)
+int iscsi_scsi_pr_registrant_get_callback(uint8_t *key UNUSED, const size_t key_size UNUSED, uint8_t *value, uint8_t *user_data)
{
iscsi_scsi_pr_registrant_get_reg *reg_find = (iscsi_scsi_pr_registrant_get_reg *) user_data;
iscsi_scsi_pr_registrant *reg = (iscsi_scsi_pr_registrant *) value;
@@ -5035,7 +5046,7 @@ static inline uint64_t iscsi_scsi_emu_physical_block_get_count(const dnbd3_image
{
int32_t block_size_shift = iscsi_config_get( (uint8_t *) image->name, ISCSI_GLOBALS_CONFIG_TYPE_SCSI_PHYSICAL_BLOCK_SIZE_SHIFT );
- if ( block_size_shift < 0L )
+ if ( block_size_shift <= 0L )
block_size_shift = iscsi_config_get( NULL, ISCSI_GLOBALS_CONFIG_TYPE_SCSI_PHYSICAL_BLOCK_SIZE_SHIFT );
return (image->virtualFilesize >> (uint32_t) block_size_shift);
@@ -5057,7 +5068,7 @@ static inline uint32_t iscsi_scsi_emu_physical_block_get_size_shift(const dnbd3_
{
int32_t block_size_shift = iscsi_config_get( (uint8_t *) image->name, ISCSI_GLOBALS_CONFIG_TYPE_SCSI_PHYSICAL_BLOCK_SIZE_SHIFT );
- if ( block_size_shift < 0L )
+ if ( block_size_shift <= 0L )
block_size_shift = iscsi_config_get( NULL, ISCSI_GLOBALS_CONFIG_TYPE_SCSI_PHYSICAL_BLOCK_SIZE_SHIFT );
return block_size_shift;
@@ -5078,7 +5089,7 @@ static inline uint32_t iscsi_scsi_emu_physical_block_get_size(const dnbd3_image_
{
int32_t block_size = iscsi_config_get( (uint8_t *) image->name, ISCSI_GLOBALS_CONFIG_TYPE_SCSI_PHYSICAL_BLOCK_SIZE );
- if ( block_size < 0L )
+ if ( block_size <= 0L )
block_size = iscsi_config_get( NULL, ISCSI_GLOBALS_CONFIG_TYPE_SCSI_PHYSICAL_BLOCK_SIZE );
return block_size;
@@ -5099,7 +5110,7 @@ static inline uint64_t iscsi_scsi_emu_block_get_count(const dnbd3_image_t *image
{
int32_t block_size_shift = iscsi_config_get( (uint8_t *) image->name, ISCSI_GLOBALS_CONFIG_TYPE_SCSI_LOGICAL_BLOCK_SIZE_SHIFT );
- if ( block_size_shift < 0L )
+ if ( block_size_shift <= 0L )
block_size_shift = iscsi_config_get( NULL, ISCSI_GLOBALS_CONFIG_TYPE_SCSI_LOGICAL_BLOCK_SIZE_SHIFT );
return (image->virtualFilesize >> (uint32_t) block_size_shift);
@@ -5121,7 +5132,7 @@ static inline uint32_t iscsi_scsi_emu_block_get_size_shift(const dnbd3_image_t *
{
int32_t block_size_shift = iscsi_config_get( (uint8_t *) image->name, ISCSI_GLOBALS_CONFIG_TYPE_SCSI_LOGICAL_BLOCK_SIZE_SHIFT );
- if ( block_size_shift < 0L )
+ if ( block_size_shift <= 0L )
block_size_shift = iscsi_config_get( NULL, ISCSI_GLOBALS_CONFIG_TYPE_SCSI_LOGICAL_BLOCK_SIZE_SHIFT );
return block_size_shift;
@@ -5142,7 +5153,7 @@ static inline uint32_t iscsi_scsi_emu_block_get_size(const dnbd3_image_t *image)
{
int32_t block_size = iscsi_config_get( (uint8_t *) image->name, ISCSI_GLOBALS_CONFIG_TYPE_SCSI_LOGICAL_BLOCK_SIZE );
- if ( block_size < 0L )
+ if ( block_size <= 0L )
block_size = iscsi_config_get( NULL, ISCSI_GLOBALS_CONFIG_TYPE_SCSI_LOGICAL_BLOCK_SIZE );
return block_size;
@@ -5293,15 +5304,21 @@ static uint64_t iscsi_scsi_emu_blocks_to_bytes(uint64_t *offset_bytes, const uin
* @param[in] start Start of range in bytes.
* @param[in] length Length of range in bytes, as passed to
* uplink_request().
- * @param[in] buffer Data for requested range.
+ * @param[in] buffer Data for requested range or NULL on
+ * an uplink error.
*/
static void iscsi_uplink_callback(void *data, uint64_t handle UNUSED, uint64_t start UNUSED, uint32_t length, const char *buffer)
{
iscsi_scsi_task *scsi_task = (iscsi_scsi_task *) data;
+ const bool success = ((buffer != NULL) && (length > 0UL));
- memcpy( scsi_task->buf, buffer, length );
+ if ( success )
+ memcpy( scsi_task->buf, buffer, length );
pthread_mutex_lock( &scsi_task->uplink_mutex );
+
+ scsi_task->status = (success ? ISCSI_SCSI_STATUS_GOOD : ISCSI_SCSI_STATUS_CHECK_COND);
+
pthread_cond_signal( &scsi_task->uplink_cond );
pthread_mutex_unlock( &scsi_task->uplink_mutex );
}
@@ -5344,7 +5361,7 @@ int iscsi_scsi_emu_io_block_read(iscsi_scsi_task *scsi_task, dnbd3_image_t *imag
readFromFile = true;
} else {
// This is a proxyed image, check if we need to relay the request...
- const uint64_t start = (offset_bytes & ~(uint64_t)(DNBD3_BLOCK_SIZE - 1));
+ const uint64_t start = (offset_bytes & ~(uint64_t) (DNBD3_BLOCK_SIZE - 1));
const uint64_t end = ((offset_bytes + num_bytes + DNBD3_BLOCK_SIZE - 1) & ~(uint64_t) (DNBD3_BLOCK_SIZE - 1));
readFromFile = image_isRangeCachedUnsafe( cache, start, end );
@@ -5370,9 +5387,12 @@ int iscsi_scsi_emu_io_block_read(iscsi_scsi_task *scsi_task, dnbd3_image_t *imag
pthread_mutex_lock( &scsi_task->uplink_mutex );
success = uplink_request( image, (void *) scsi_task, iscsi_uplink_callback, 0ULL, offset_bytes, (uint32_t) num_bytes );
- if ( success )
+ if ( success ) {
pthread_cond_wait( &scsi_task->uplink_cond, &scsi_task->uplink_mutex );
+ success = (scsi_task->status == ISCSI_SCSI_STATUS_GOOD);
+ }
+
pthread_mutex_unlock( &scsi_task->uplink_mutex );
pthread_cond_destroy( &scsi_task->uplink_cond );
pthread_mutex_destroy( &scsi_task->uplink_mutex );
@@ -5422,7 +5442,7 @@ int iscsi_scsi_emu_io_block_read(iscsi_scsi_task *scsi_task, dnbd3_image_t *imag
* completed successfully, false otherwise.
* @return Pointer to passed user data.
*/
-uint8_t *iscsi_scsi_emu_block_read_complete_callback(dnbd3_image_t *image, uint8_t *user_data, const bool success)
+uint8_t *iscsi_scsi_emu_block_read_complete_callback(dnbd3_image_t *image UNUSED, uint8_t *user_data, const bool success)
{
iscsi_scsi_task *scsi_task = (iscsi_scsi_task *) user_data;
@@ -5490,7 +5510,7 @@ int iscsi_scsi_emu_io_block_cmp_write(iscsi_scsi_task *scsi_task, uint8_t *cmp_b
* completed successfully, false otherwise.
* @return Pointer to passed user data.
*/
-uint8_t *iscsi_scsi_emu_block_write_complete_callback(dnbd3_image_t *image, uint8_t *user_data, const bool success)
+uint8_t *iscsi_scsi_emu_block_write_complete_callback(dnbd3_image_t *image UNUSED, uint8_t *user_data, const bool success)
{
iscsi_scsi_task *scsi_task = (iscsi_scsi_task *) user_data;
@@ -6268,7 +6288,7 @@ static size_t iscsi_scsi_emu_pad_scsi_name(uint8_t *buf, const uint8_t *name)
* reported Vital Product Data (VPD) SCSI Port
* Designation Descriptor entry.
*/
-int iscsi_scsi_emu_primary_inquiry_callback(uint8_t *key, const size_t key_size, uint8_t *value, uint8_t *user_data)
+int iscsi_scsi_emu_primary_inquiry_callback(uint8_t *key UNUSED, const size_t key_size UNUSED, uint8_t *value, uint8_t *user_data)
{
iscsi_scsi_emu_primary_inquiry_ports_fill *port_report_fill = (iscsi_scsi_emu_primary_inquiry_ports_fill *) user_data;
iscsi_port *port = (iscsi_port *) value;
@@ -6696,7 +6716,6 @@ static int iscsi_scsi_emu_primary_inquiry(dnbd3_image_t *image, iscsi_scsi_task
return (int) (alloc_len + sizeof(struct iscsi_scsi_vpd_page_inquiry_data_packet));
} else {
int32_t scsi_device_type = iscsi_config_get( (uint8_t *) image->name, ISCSI_GLOBALS_CONFIG_TYPE_SCSI_DEVICE_TYPE );
- uint alloc_len;
if ( scsi_device_type < 0L )
scsi_device_type = iscsi_config_get( NULL, ISCSI_GLOBALS_CONFIG_TYPE_SCSI_DEVICE_TYPE );
@@ -6808,7 +6827,7 @@ static int iscsi_scsi_emu_primary_inquiry(dnbd3_image_t *image, iscsi_scsi_task
* allocation space to store this
* reported LUN entry.
*/
-int iscsi_scsi_emu_primary_report_luns_callback(uint8_t *key, const size_t key_size, uint8_t *value, uint8_t *user_data)
+int iscsi_scsi_emu_primary_report_luns_callback(uint8_t *key UNUSED, const size_t key_size UNUSED, uint8_t *value, uint8_t *user_data)
{
iscsi_scsi_emu_primary_report_luns_fill *lun_report_fill = (iscsi_scsi_emu_primary_report_luns_fill *) user_data;
iscsi_scsi_lun *scsi_lun = (iscsi_scsi_lun *) value;
@@ -7821,7 +7840,7 @@ iscsi_port *iscsi_port_create(const uint8_t *name, const uint64_t id, const uint
* there is a possibility for future usage.
* @return Always returns 0 as this function cannot fail.
*/
-int iscsi_port_destroy_callback(uint8_t *key, const size_t key_size, uint8_t *value, uint8_t *user_data)
+int iscsi_port_destroy_callback(uint8_t *key UNUSED, const size_t key_size UNUSED, uint8_t *value, uint8_t *user_data UNUSED)
{
iscsi_port_destroy( (iscsi_port *) value );
@@ -8074,7 +8093,7 @@ iscsi_device *iscsi_device_create(const uint8_t *name, const int lun_id, const u
* there is a possibility for future usage.
* @return Always returns 0 as this function cannot fail.
*/
-int iscsi_device_destroy_callback(uint8_t *key, const size_t key_size, uint8_t *value, uint8_t *user_data)
+int iscsi_device_destroy_callback(uint8_t *key, const size_t key_size UNUSED, uint8_t *value, uint8_t *user_data UNUSED)
{
iscsi_device_destroy( (iscsi_device *) value );
iscsi_hashmap_key_destroy( key );
@@ -8230,7 +8249,7 @@ int iscsi_device_port_add(iscsi_device *device, const uint8_t *name, const uint6
* to the associated device. NULL is not
* allowed here, take caution.
*/
-void iscsi_device_scsi_task_queue(iscsi_device *device, iscsi_scsi_task *scsi_task)
+void iscsi_device_scsi_task_queue(iscsi_device *device UNUSED, iscsi_scsi_task *scsi_task)
{
iscsi_scsi_lun_task_exec( scsi_task->lun, scsi_task );
}
@@ -8354,7 +8373,7 @@ static int iscsi_target_node_check_flags(const int flags, const int32_t chap_gro
* @retval 0 The iSCSI portal group has been
* added successfully.
*/
-int iscsi_target_node_create_callback(uint8_t *key, const size_t key_size, uint8_t *value, uint8_t *user_data)
+int iscsi_target_node_create_callback(uint8_t *key UNUSED, const size_t key_size UNUSED, uint8_t *value, uint8_t *user_data)
{
iscsi_target_node *target = (iscsi_target_node *) user_data;
iscsi_portal_group *portal_group = (iscsi_portal_group *) value;
@@ -8371,6 +8390,73 @@ int iscsi_target_node_create_callback(uint8_t *key, const size_t key_size, uint8
}
/**
+ * @brief Finds an already existing iSCSI SCSI LUN or creates and adds a new LUN in a specified SCSI device.
+ *
+ * This function is thread safe.
+ *
+ * @param[in] device Pointer to SCSI device to find the LUN
+ * identifier of and NULL is NOT allowed here,
+ * so be careful.
+ * @param[in] lun_id LUN identifier to find in underlying SCSI
+ * device.
+ * @return Pointer to either newly created SCSI LUN or the
+ * already existing one and NULL in case SCSI
+ * LUN creation failed.
+ */
+static iscsi_scsi_lun *iscsi_target_node_device_lun_find(iscsi_device *device, const int lun_id)
+{
+ pthread_rwlock_rdlock( &device->luns_rwlock );
+
+ iscsi_scsi_lun *lun = iscsi_device_find_lun( device, lun_id );
+
+ if ( lun == NULL ) {
+ pthread_rwlock_unlock( &device->luns_rwlock );
+ pthread_rwlock_wrlock( &device->luns_rwlock );
+ lun = iscsi_device_find_lun( device, lun_id );
+
+ if ( lun == NULL ) {
+ lun = iscsi_scsi_lun_create( lun_id );
+
+ if ( lun == NULL ) {
+ logadd( LOG_ERROR, "iscsi_target_node_device_lun_find: Out of memory allocating iSCSI device LUN hash map" );
+
+ pthread_rwlock_unlock( &device->luns_rwlock );
+
+ return NULL;
+ }
+
+ const uint64_t lun_hash = lun_id;
+ uint8_t *hash_key = iscsi_hashmap_key_create( (uint8_t *) &lun_hash, sizeof(lun_hash) );
+
+ if ( hash_key == NULL ) {
+ logadd( LOG_ERROR, "iscsi_target_node_device_lun_find: Out of memory allocating iSCSI device LUN hash map" );
+
+ pthread_rwlock_unlock( &device->luns_rwlock );
+ iscsi_scsi_lun_destroy( lun );
+
+ return NULL;
+ }
+
+ const int rc = iscsi_hashmap_put( device->luns, hash_key, sizeof(lun_hash), (uint8_t *) lun );
+
+ if ( rc < 0 ) {
+ pthread_rwlock_unlock( &device->luns_rwlock );
+ iscsi_hashmap_key_destroy( hash_key );
+ iscsi_scsi_lun_destroy( lun );
+
+ return NULL;
+ }
+
+ lun->device = device;
+ }
+ }
+
+ pthread_rwlock_unlock( &device->luns_rwlock );
+
+ return lun;
+}
+
+/**
* @brief Creates and initializes an iSCSI target node.
*
* This function also allocates the underlying SCSI
@@ -8451,23 +8537,39 @@ iscsi_target_node *iscsi_target_node_create(uint8_t *name, const uint8_t *alias,
uint8_t *hash_key = iscsi_hashmap_key_create( (uint8_t *) image->name, key_len );
iscsi_device *device = NULL;
- pthread_rwlock_wrlock( &iscsi_globvec->devices_rwlock );
+ pthread_rwlock_rdlock( &iscsi_globvec->devices_rwlock );
int rc = iscsi_hashmap_get( iscsi_globvec->devices, hash_key, key_len, (uint8_t **) &device );
if ( device != NULL ) {
- pthread_rwlock_wrlock( &device->luns_rwlock );
+ iscsi_scsi_lun *lun = iscsi_target_node_device_lun_find( device, lun_id );
- iscsi_scsi_lun *lun = iscsi_device_find_lun( device, lun_id );
+ iscsi_hashmap_key_destroy( hash_key );
if ( lun == NULL ) {
- lun = iscsi_scsi_lun_create( lun_id );
+ pthread_rwlock_unlock( &iscsi_globvec->devices_rwlock );
- if ( lun == NULL ) {
- logadd( LOG_ERROR, "iscsi_target_node_create: Out of memory allocating iSCSI device LUN hash map" );
+ if ( target->alias != NULL )
+ free( target->alias );
- pthread_rwlock_unlock( &device->luns_rwlock );
+ free( target->name );
+ free( target );
+
+ return NULL;
+ }
+
+ hash_key = NULL;
+ } else {
+ pthread_rwlock_unlock( &iscsi_globvec->devices_rwlock );
+ pthread_rwlock_wrlock( &iscsi_globvec->devices_rwlock );
+ rc = iscsi_hashmap_get( iscsi_globvec->devices, hash_key, key_len, (uint8_t **) &device );
+
+ if ( device != NULL ) {
+ iscsi_scsi_lun *lun = iscsi_target_node_device_lun_find( device, lun_id );
+
+ iscsi_hashmap_key_destroy( hash_key );
+
+ if ( lun == NULL ) {
pthread_rwlock_unlock( &iscsi_globvec->devices_rwlock );
- iscsi_hashmap_key_destroy( hash_key );
if ( target->alias != NULL )
free( target->alias );
@@ -8478,15 +8580,14 @@ iscsi_target_node *iscsi_target_node_create(uint8_t *name, const uint8_t *alias,
return NULL;
}
- const uint64_t lun_hash = lun_id;
- uint8_t *lun_hash_key = iscsi_hashmap_key_create( (uint8_t *) &lun_hash, sizeof(lun_hash) );
+ hash_key = NULL;
+ } else {
+ device = iscsi_device_create( (uint8_t *) image->name, lun_id, ISCSI_TRANSPORT_ID_PROTOCOL_ID_ISCSI );
- if ( lun_hash_key == NULL ) {
- logadd( LOG_ERROR, "iscsi_target_node_create: Out of memory allocating iSCSI device LUN hash map" );
+ if ( device == NULL ) {
+ logadd( LOG_ERROR, "iscsi_target_node_create: Out of memory allocating iSCSI target device" );
- pthread_rwlock_unlock( &device->luns_rwlock );
pthread_rwlock_unlock( &iscsi_globvec->devices_rwlock );
- iscsi_scsi_lun_destroy( lun );
iscsi_hashmap_key_destroy( hash_key );
if ( target->alias != NULL )
@@ -8498,13 +8599,11 @@ iscsi_target_node *iscsi_target_node_create(uint8_t *name, const uint8_t *alias,
return NULL;
}
- const int rc = iscsi_hashmap_put( device->luns, lun_hash_key, sizeof(lun_hash), (uint8_t *) lun );
+ rc = iscsi_hashmap_put( iscsi_globvec->devices, hash_key, key_len, (uint8_t *) device );
if ( rc < 0 ) {
- pthread_rwlock_unlock( &device->luns_rwlock );
pthread_rwlock_unlock( &iscsi_globvec->devices_rwlock );
- iscsi_hashmap_key_destroy( lun_hash_key );
- iscsi_scsi_lun_destroy( lun );
+ iscsi_device_destroy( device );
iscsi_hashmap_key_destroy( hash_key );
if ( target->alias != NULL )
@@ -8516,47 +8615,9 @@ iscsi_target_node *iscsi_target_node_create(uint8_t *name, const uint8_t *alias,
return NULL;
}
}
-
- pthread_rwlock_unlock( &device->luns_rwlock );
- iscsi_hashmap_key_destroy( hash_key );
-
- hash_key = NULL;
- } else {
- device = iscsi_device_create( (uint8_t *) image->name, lun_id, ISCSI_TRANSPORT_ID_PROTOCOL_ID_ISCSI );
-
- if ( device == NULL ) {
- logadd( LOG_ERROR, "iscsi_target_node_create: Out of memory allocating iSCSI target device" );
-
- pthread_rwlock_unlock( &iscsi_globvec->devices_rwlock );
- iscsi_hashmap_key_destroy( hash_key );
-
- if ( target->alias != NULL )
- free( target->alias );
-
- free( target->name );
- free( target );
-
- return NULL;
- }
-
- rc = iscsi_hashmap_put( iscsi_globvec->devices, hash_key, key_len, (uint8_t *) device );
-
- if ( rc < 0 ) {
- pthread_rwlock_unlock( &iscsi_globvec->devices_rwlock );
- iscsi_device_destroy( device );
- iscsi_hashmap_key_destroy( hash_key );
-
- if ( target->alias != NULL )
- free( target->alias );
-
- free( target->name );
- free( target );
-
- return NULL;
- }
}
- device->active_conns++;
+ device->active_conns++; // TODO: Use this actually
pthread_rwlock_unlock( &iscsi_globvec->devices_rwlock );
@@ -8617,7 +8678,7 @@ iscsi_target_node *iscsi_target_node_create(uint8_t *name, const uint8_t *alias,
* there is a possibility for future usage.
* @return Always returns 0 as this function cannot fail.
*/
-int iscsi_target_node_destroy_callback(uint8_t *key, const size_t key_size, uint8_t *value, uint8_t *user_data)
+int iscsi_target_node_destroy_callback(uint8_t *key, const size_t key_size UNUSED, uint8_t *value, uint8_t *user_data UNUSED)
{
iscsi_target_node_destroy( (iscsi_target_node *) value );
iscsi_hashmap_key_destroy( key );
@@ -8825,7 +8886,7 @@ dnbd3_image_t *iscsi_target_node_image_get(uint8_t *iqn)
* searching is needed.
* @retval 0 The target node has not been found yet.
*/
-int iscsi_target_node_find_callback(uint8_t *key, const size_t key_size, uint8_t *value, uint8_t *user_data)
+int iscsi_target_node_find_callback(uint8_t *key UNUSED, const size_t key_size UNUSED, uint8_t *value, uint8_t *user_data)
{
iscsi_target_node_find_name *target_find = (iscsi_target_node_find_name *) user_data;
iscsi_target_node *target = (iscsi_target_node *) value;
@@ -8857,54 +8918,72 @@ iscsi_target_node *iscsi_target_node_find(uint8_t *target_name)
iscsi_target_node_find_name target_find = {NULL, target_name};
- pthread_rwlock_wrlock( &iscsi_globvec->target_nodes_rwlock );
+ pthread_rwlock_rdlock( &iscsi_globvec->target_nodes_rwlock );
iscsi_hashmap_iterate( iscsi_globvec->target_nodes, iscsi_target_node_find_callback, (uint8_t *) &target_find );
iscsi_target_node *target = target_find.target;
if ( target == NULL ) {
- dnbd3_image_t *image = iscsi_target_node_image_get( target_name );
+ pthread_rwlock_unlock( &iscsi_globvec->target_nodes_rwlock );
+ pthread_rwlock_wrlock( &iscsi_globvec->target_nodes_rwlock );
+ iscsi_hashmap_iterate( iscsi_globvec->target_nodes, iscsi_target_node_find_callback, (uint8_t *) &target_find );
- if ( image == NULL ) {
- pthread_rwlock_unlock( &iscsi_globvec->target_nodes_rwlock );
+ target = target_find.target;
- return NULL;
- }
+ if ( target == NULL ) {
+ dnbd3_image_t *image = iscsi_target_node_image_get( target_name );
- target = iscsi_target_node_create( target_name, NULL, 0, image->rid, 16U, 0, 0L, 0, 0 );
+ if ( image == NULL ) {
+ pthread_rwlock_unlock( &iscsi_globvec->target_nodes_rwlock );
- if ( target == NULL ) {
- logadd( LOG_ERROR, "iscsi_target_node_find: iSCSI target node not found" );
+ return NULL;
+ }
- pthread_rwlock_unlock( &iscsi_globvec->target_nodes_rwlock );
+ int32_t header_digest = iscsi_config_get( (uint8_t *) image->name, ISCSI_GLOBALS_CONFIG_TYPE_HEADER_DIGEST );
- return NULL;
- }
+ if ( header_digest < 0L )
+ header_digest = iscsi_config_get( NULL, ISCSI_GLOBALS_CONFIG_TYPE_HEADER_DIGEST );
- const uint key_len = (uint) (strlen( (char *) target_name ) + 1U);
- uint8_t *hash_key = iscsi_hashmap_key_create( target_name, key_len );
+ int32_t data_digest = iscsi_config_get( (uint8_t *) image->name, ISCSI_GLOBALS_CONFIG_TYPE_DATA_DIGEST );
- if ( hash_key == NULL ) {
- logadd( LOG_ERROR, "iscsi_target_node_find: Out of memory while allocating iSCSI target node" );
+ if ( data_digest < 0L )
+ data_digest = iscsi_config_get( NULL, ISCSI_GLOBALS_CONFIG_TYPE_DATA_DIGEST );
- pthread_rwlock_unlock( &iscsi_globvec->target_nodes_rwlock );
- iscsi_target_node_destroy( target );
+ target = iscsi_target_node_create( target_name, NULL, 0, image->rid, 16U, 0, 0L, (int) header_digest, (int) data_digest );
- return NULL;
- }
+ if ( target == NULL ) {
+ logadd( LOG_ERROR, "iscsi_target_node_find: iSCSI target node not found" );
- int rc = iscsi_hashmap_put( iscsi_globvec->target_nodes, (uint8_t *) hash_key, key_len, (uint8_t *) target );
+ pthread_rwlock_unlock( &iscsi_globvec->target_nodes_rwlock );
- if ( rc < 0 ) {
- pthread_rwlock_unlock( &iscsi_globvec->target_nodes_rwlock );
- iscsi_hashmap_key_destroy( (uint8_t *) hash_key );
- iscsi_target_node_destroy( target );
+ return NULL;
+ }
- return NULL;
+ const uint key_len = (uint) (strlen( (char *) target_name ) + 1U);
+ uint8_t *hash_key = iscsi_hashmap_key_create( target_name, key_len );
+
+ if ( hash_key == NULL ) {
+ logadd( LOG_ERROR, "iscsi_target_node_find: Out of memory while allocating iSCSI target node" );
+
+ pthread_rwlock_unlock( &iscsi_globvec->target_nodes_rwlock );
+ iscsi_target_node_destroy( target );
+
+ return NULL;
+ }
+
+ int rc = iscsi_hashmap_put( iscsi_globvec->target_nodes, (uint8_t *) hash_key, key_len, (uint8_t *) target );
+
+ if ( rc < 0 ) {
+ pthread_rwlock_unlock( &iscsi_globvec->target_nodes_rwlock );
+ iscsi_hashmap_key_destroy( (uint8_t *) hash_key );
+ iscsi_target_node_destroy( target );
+
+ return NULL;
+ }
}
}
- target->active_conns++;
+ target->active_conns++; // TODO: Use this actually.
pthread_rwlock_unlock( &iscsi_globvec->target_nodes_rwlock );
@@ -8982,28 +9061,28 @@ iscsi_session *iscsi_session_create(iscsi_connection *conn, iscsi_target_node *t
}
session->tag = conn->pg_tag;
- session->flags = 0;
+ session->flags = (ISCSI_SESSION_FLAGS_INIT_R2T | ISCSI_SESSION_FLAGS_IMMEDIATE_DATA | ISCSI_SESSION_FLAGS_DATA_PDU_IN_ORDER | ISCSI_SESSION_FLAGS_DATA_SEQ_IN_ORDER);
- if ( (iscsi_globvec->flags & ISCSI_GLOBALS_FLAGS_INIT_R2T) != 0 )
- session->flags |= ISCSI_SESSION_FLAGS_INIT_R2T;
+ if ( iscsi_config_get( NULL, ISCSI_GLOBALS_CONFIG_TYPE_FLAGS_INIT_R2T ) == 0L )
+ session->flags &= ~ISCSI_SESSION_FLAGS_INIT_R2T;
- if ( (iscsi_globvec->flags & ISCSI_GLOBALS_FLAGS_IMMEDIATE_DATA) != 0 )
- session->flags |= ISCSI_SESSION_FLAGS_IMMEDIATE_DATA;
+ if ( iscsi_config_get( NULL, ISCSI_GLOBALS_CONFIG_TYPE_FLAGS_IMMEDIATE_DATA ) == 0L )
+ session->flags &= ~ISCSI_SESSION_FLAGS_IMMEDIATE_DATA;
- if ( (iscsi_globvec->flags & ISCSI_GLOBALS_FLAGS_DATA_PDU_IN_ORDER) != 0 )
- session->flags |= ISCSI_SESSION_FLAGS_DATA_PDU_IN_ORDER;
+ if ( iscsi_config_get( NULL, ISCSI_GLOBALS_CONFIG_TYPE_FLAGS_DATA_PDU_IN_ORDER ) == 0L )
+ session->flags &= ~ISCSI_SESSION_FLAGS_DATA_PDU_IN_ORDER;
- if ( (iscsi_globvec->flags & ISCSI_GLOBALS_FLAGS_DATA_SEQ_IN_ORDER) != 0 )
- session->flags |= ISCSI_SESSION_FLAGS_DATA_SEQ_IN_ORDER;
+ if ( iscsi_config_get( NULL, ISCSI_GLOBALS_CONFIG_TYPE_FLAGS_DATA_SEQ_IN_ORDER ) == 0L )
+ session->flags &= ~ISCSI_SESSION_FLAGS_DATA_SEQ_IN_ORDER;
session->conns = 1UL;
- session->max_conns = iscsi_globvec->max_session_conns;
- session->max_outstanding_r2t = iscsi_globvec->max_outstanding_r2t;
- session->default_time_to_wait = iscsi_globvec->default_time_to_wait;
- session->default_time_to_retain = iscsi_globvec->default_time_to_retain;
- session->first_burst_len = iscsi_globvec->first_burst_len;
- session->max_burst_len = iscsi_globvec->max_burst_len;
- session->err_recovery_level = iscsi_globvec->err_recovery_level;
+ session->max_conns = (uint32_t) iscsi_config_get( NULL, ISCSI_GLOBALS_CONFIG_TYPE_MAX_SESSION_CONNS );
+ session->max_outstanding_r2t = (uint32_t) iscsi_config_get( NULL, ISCSI_GLOBALS_CONFIG_TYPE_MAX_OUTSTANDING_R2T );
+ session->default_time_to_wait = (uint32_t) iscsi_config_get( NULL, ISCSI_GLOBALS_CONFIG_TYPE_DEFAULT_TIME_TO_WAIT );
+ session->default_time_to_retain = (uint32_t) iscsi_config_get( NULL, ISCSI_GLOBALS_CONFIG_TYPE_DEFAULT_TIME_TO_RETAIN );
+ session->first_burst_len = (uint32_t) iscsi_config_get( NULL, ISCSI_GLOBALS_CONFIG_TYPE_FIRST_BURST_LEN );
+ session->max_burst_len = (uint32_t) iscsi_config_get( NULL, ISCSI_GLOBALS_CONFIG_TYPE_MAX_BURST_LEN );
+ session->err_recovery_level = (uint32_t) iscsi_config_get( NULL, ISCSI_GLOBALS_CONFIG_TYPE_ERR_RECOVERY_LEVEL );
iscsi_list_create( &session->conn_list );
iscsi_list_enqueue( &session->conn_list, &conn->node );
@@ -9070,7 +9149,7 @@ iscsi_session *iscsi_session_create(iscsi_connection *conn, iscsi_target_node *t
* there is a possibility for future usage.
* @return Always returns 0 as this function cannot fail.
*/
-int iscsi_session_destroy_callback(uint8_t *key, const size_t key_size, uint8_t *value, uint8_t *user_data)
+int iscsi_session_destroy_callback(uint8_t *key, const size_t key_size UNUSED, uint8_t *value, uint8_t *user_data UNUSED)
{
iscsi_session_destroy( (iscsi_session *) value );
iscsi_hashmap_key_destroy( key );
@@ -9358,7 +9437,7 @@ static int iscsi_connection_tasks_destroy(iscsi_connection *conn)
* there is a possibility for future usage.
* @return Always returns 0 as this function cannot fail.
*/
-int iscsi_connection_destroy_callback(uint8_t *key, const size_t key_size, uint8_t *value, uint8_t *user_data)
+int iscsi_connection_destroy_callback(uint8_t *key, const size_t key_size UNUSED, uint8_t *value, uint8_t *user_data UNUSED)
{
iscsi_connection_destroy( (iscsi_connection *) value );
iscsi_hashmap_key_destroy( key );
@@ -9607,7 +9686,9 @@ int iscsi_connection_handle_scsi_data_in_queued_tasks(iscsi_connection *conn)
pthread_rwlock_unlock( &conn->device->luns_rwlock );
- sub_task->scsi_task.len = ((len < ISCSI_DEFAULT_MAX_RECV_DS_LEN) ? len : ISCSI_DEFAULT_MAX_RECV_DS_LEN);
+ const uint32_t max_recv_ds_len = (uint32_t) iscsi_config_get( NULL, ISCSI_GLOBALS_CONFIG_TYPE_MAX_RECV_DS_LEN );
+
+ sub_task->scsi_task.len = ((len < max_recv_ds_len) ? len : max_recv_ds_len);
task->pos += sub_task->scsi_task.len;
iscsi_task_queue( conn, sub_task );
@@ -9659,10 +9740,12 @@ int iscsi_connection_init_key_value_pairs(iscsi_hashmap *key_value_pairs)
* @param[in] pos Position of buffer in bytes to start
* writing to.
* @param[in] len Total length of buffer in bytes.
+ * @param[in] first_burst_len Set if first burst length
+ * has been specified by the initiator.
* @return New buffer position in bytes or a negative
* error code.
*/
-static int32_t iscsi_append_special_key_value_pair_packet(iscsi_connection *conn, iscsi_key_value_pair *key_value_pair, const uint8_t *key, uint8_t *buf, uint32_t pos, const uint32_t len)
+static int32_t iscsi_append_special_key_value_pair_packet(iscsi_connection *conn, iscsi_key_value_pair *key_value_pair, const uint8_t *key, uint8_t *buf, uint32_t pos, const uint32_t len, const bool first_burst_len)
{
if ( key_value_pair == NULL )
return pos;
@@ -9671,20 +9754,20 @@ static int32_t iscsi_append_special_key_value_pair_packet(iscsi_connection *conn
if ( pos >= len )
return -1L;
- pos += (uint32_t) (snprintf( (char *) (buf + pos), (len - pos), "%s=%" PRId32, key, (uint32_t) ISCSI_DEFAULT_MAX_RECV_DS_LEN ) + 1);
+ pos += (uint32_t) (snprintf( (char *) (buf + pos), (len - pos), "%s=%" PRId32, ISCSI_LOGIN_AUTH_SESSION_TEXT_KEY_MAX_RECV_DS_LEN, (uint32_t) iscsi_config_get( NULL, ISCSI_GLOBALS_CONFIG_TYPE_MAX_RECV_DS_LEN ) ) + 1);
}
- if ( (key_value_pair->flags & ISCSI_TEXT_KEY_VALUE_PAIR_FLAGS_USE_OTHER_MAX_VALUE) != 0 ) {
+ if ( ((key_value_pair->flags & ISCSI_TEXT_KEY_VALUE_PAIR_FLAGS_USE_OTHER_MAX_VALUE) != 0) && !first_burst_len ) {
if ( pos >= len )
return -1L;
uint8_t *first_burst_len_val = NULL;
int rc = iscsi_get_key_value_pair( conn->session->key_value_pairs, ISCSI_LOGIN_AUTH_SESSION_TEXT_KEY_FIRST_BURST_LEN, &first_burst_len_val );
- uint32_t first_burst_len = ((rc < 0) ? iscsi_globvec->first_burst_len : (uint32_t) atol( (char *) first_burst_len_val ));
+ uint32_t first_burst_len = ((rc < 0) ? (uint32_t) iscsi_config_get( NULL, ISCSI_GLOBALS_CONFIG_TYPE_FIRST_BURST_LEN ) : (uint32_t) atol( (char *) first_burst_len_val ));
uint8_t *max_burst_len_val;
rc = iscsi_get_key_value_pair( conn->session->key_value_pairs, ISCSI_LOGIN_AUTH_SESSION_TEXT_KEY_MAX_BURST_LEN, &max_burst_len_val );
- uint32_t max_burst_len = ((rc < 0) ? iscsi_globvec->max_burst_len : (uint32_t) atol( (char *) max_burst_len_val ));
+ uint32_t max_burst_len = ((rc < 0) ? (uint32_t) iscsi_config_get( NULL, ISCSI_GLOBALS_CONFIG_TYPE_MAX_BURST_LEN ) : (uint32_t) atol( (char *) max_burst_len_val ));
if ( first_burst_len > max_burst_len ) {
first_burst_len = max_burst_len;
@@ -9694,7 +9777,7 @@ static int32_t iscsi_append_special_key_value_pair_packet(iscsi_connection *conn
}
}
- pos += (uint32_t) (snprintf( (char *) (buf + pos), (len - pos), "%s=%" PRId32, key, first_burst_len ) + 1);
+ pos += (uint32_t) (snprintf( (char *) (buf + pos), (len - pos), "%s=%" PRId32, ISCSI_LOGIN_AUTH_SESSION_TEXT_KEY_FIRST_BURST_LEN, first_burst_len ) + 1);
}
return pos;
@@ -10032,7 +10115,7 @@ int iscsi_negotiate_key_value_pair_callback(uint8_t *key, const size_t key_size,
rc = iscsi_get_key_value_pair( key_value_pairs, ISCSI_LOGIN_AUTH_SESSION_TEXT_KEY_MAX_BURST_LEN, &max_burst_len_val );
- max_burst_len = ((rc < 0) ? iscsi_globvec->max_burst_len : (uint32_t) atol( (char *) max_burst_len_val ));
+ max_burst_len = ((rc < 0) ? (uint32_t) iscsi_config_get( NULL, ISCSI_GLOBALS_CONFIG_TYPE_MAX_BURST_LEN ) : (uint32_t) atol( (char *) max_burst_len_val ));
if ( (first_burst_len < ISCSI_MAX_DS_SIZE) && (first_burst_len > max_burst_len) )
sprintf( (char *) value, "%" PRId32, first_burst_len );
@@ -10053,7 +10136,7 @@ int iscsi_negotiate_key_value_pair_callback(uint8_t *key, const size_t key_size,
if ( (int32_t) key_value_pair_packet->pos < 0L )
return key_value_pair_packet->pos;
- key_value_pair_packet->pos = iscsi_append_special_key_value_pair_packet( conn, key_value_pair, key, key_value_pair_packet->buf, key_value_pair_packet->pos, key_value_pair_packet->len );
+ key_value_pair_packet->pos = iscsi_append_special_key_value_pair_packet( conn, key_value_pair, key, key_value_pair_packet->buf, key_value_pair_packet->pos, key_value_pair_packet->len, key_value_pair_packet->first_burst_len );
if ( (int32_t) key_value_pair_packet->pos < 0L )
return key_value_pair_packet->pos;
@@ -10094,7 +10177,10 @@ int32_t iscsi_negotiate_key_value_pairs(iscsi_connection *conn, iscsi_hashmap *k
const int discovery = (((rc == 0) && (strcasecmp( (char *) type, "Discovery" ) == 0)) ? 1 : 0);
- iscsi_key_value_pair_packet key_value_pair_packet = {conn, buf, pos, len, discovery};
+ uint8_t *first_burst_len;
+ rc = iscsi_get_key_value_pair( key_value_pairs, ISCSI_LOGIN_AUTH_SESSION_TEXT_KEY_FIRST_BURST_LEN, &first_burst_len );
+
+ iscsi_key_value_pair_packet key_value_pair_packet = {conn, buf, pos, len, discovery, (rc == 0) };
iscsi_hashmap_iterate( key_value_pairs, iscsi_negotiate_key_value_pair_callback, (uint8_t *) &key_value_pair_packet );
return key_value_pair_packet.pos;
@@ -10121,8 +10207,10 @@ int iscsi_connection_copy_key_value_pairs(iscsi_connection *conn)
if ( rc != 0 )
return rc;
- if ( (int_val <= 0L) || (int_val > (int32_t) ISCSI_DEFAULT_MAX_RECV_DS_LEN) )
- int_val = ISCSI_DEFAULT_MAX_RECV_DS_LEN;
+ const uint32_t max_recv_ds_len = (uint32_t) iscsi_config_get( NULL, ISCSI_GLOBALS_CONFIG_TYPE_MAX_RECV_DS_LEN );
+
+ if ( (int_val <= 0L) || (int_val > (int32_t) max_recv_ds_len) )
+ int_val = max_recv_ds_len;
conn->max_recv_ds_len = int_val;
@@ -10237,7 +10325,7 @@ static int32_t iscsi_connection_auth_key_value_pairs(iscsi_connection *conn, isc
*/
static int iscsi_connection_check_key_value_pairs(iscsi_connection *conn)
{
- if ( (conn->session->first_burst_len > conn->session->max_burst_len) || (conn->session->first_burst_len < 512UL) || (conn->session->max_burst_len < 512UL) || (conn->session->max_burst_len > iscsi_globvec->max_burst_len) || (conn->max_recv_ds_len < 512UL) || (conn->max_recv_ds_len > iscsi_globvec->max_burst_len) )
+ if ( (conn->session->first_burst_len > conn->session->max_burst_len) || (conn->session->first_burst_len < 512UL) || (conn->session->first_burst_len > (uint32_t) iscsi_config_get( NULL, ISCSI_GLOBALS_CONFIG_TYPE_FIRST_BURST_LEN )) || (conn->session->max_burst_len < 512UL) || (conn->session->max_burst_len > (uint32_t) iscsi_config_get( NULL, ISCSI_GLOBALS_CONFIG_TYPE_MAX_BURST_LEN )) || (conn->session->max_burst_len > ISCSI_MAX_DS_SIZE) || (conn->max_recv_ds_len < 512UL) || (conn->max_recv_ds_len > ISCSI_MAX_DS_SIZE) )
return -1;
return 0;
@@ -10291,6 +10379,9 @@ static int iscsi_connection_update_key_value_pairs(iscsi_connection *conn)
setsockopt( conn->sock, SOL_SOCKET, SO_RCVBUF, &recv_buf_len, sizeof(recv_buf_len)); // Not being able to set the buffer is NOT fatal, so ignore error.
+ recv_buf_len += (uint) ((uint32_t) iscsi_config_get( NULL, ISCSI_GLOBALS_CONFIG_TYPE_MAX_RECV_DS_LEN ) << 2UL);
+ setsockopt( conn->sock, SOL_SOCKET, SO_SNDBUF, &recv_buf_len, sizeof(recv_buf_len)); // Not being able to set the buffer is NOT fatal, so ignore error.
+
return rc;
}
@@ -10781,7 +10872,7 @@ static uint16_t iscsi_session_append(iscsi_connection *conn, const uint8_t *init
* @return 0 if valid session, a negative error code
* otherwise.
*/
-static int iscsi_connection_login_check_session(iscsi_connection *conn, iscsi_pdu *login_response_pdu, uint8_t *init_port_name, uint cid)
+static int iscsi_connection_login_check_session(iscsi_connection *conn, iscsi_pdu *login_response_pdu, uint8_t *init_port_name, uint cid UNUSED)
{
iscsi_login_response_packet *login_response_pkt = (iscsi_login_response_packet *) login_response_pdu->bhs_pkt;
int rc = 0;
@@ -11017,7 +11108,7 @@ iscsi_bhs_packet *iscsi_connection_pdu_append(iscsi_pdu *pdu, const uint ahs_len
* freed. NULL is NOT allowed here, so take
* caution.
*/
-void iscsi_connection_pdu_free(iscsi_connection *conn, iscsi_pdu *pdu)
+void iscsi_connection_pdu_free(iscsi_connection *conn UNUSED, iscsi_pdu *pdu)
{
iscsi_connection_xfer_complete_callback callback = pdu->xfer_complete_callback;
uint8_t *user_data = pdu->xfer_complete_user_data;
@@ -11605,7 +11696,7 @@ static int iscsi_connection_pdu_header_handle_nop_out(iscsi_connection *conn, is
if ( conn->session->type == ISCSI_SESSION_TYPE_DISCOVERY )
return ISCSI_CONNECT_PDU_READ_ERR_FATAL;
- if ( pdu->ds_len > ISCSI_DEFAULT_MAX_RECV_DS_LEN )
+ if ( pdu->ds_len > (uint32_t) iscsi_config_get( NULL, ISCSI_GLOBALS_CONFIG_TYPE_MAX_RECV_DS_LEN ) )
return iscsi_connection_handle_reject( conn, pdu, ISCSI_REJECT_REASON_PROTOCOL_ERR );
iscsi_nop_out_packet *nop_out_pkt = (iscsi_nop_out_packet *) pdu->bhs_pkt;
@@ -11730,7 +11821,7 @@ static int iscsi_connection_pdu_header_handle_scsi_cmd(iscsi_connection *conn, i
return ISCSI_CONNECT_PDU_READ_OK;
}
- if ( pdu->ds_len > (uint) (sizeof(struct iscsi_bhs_packet) + ISCSI_MAX_AHS_SIZE + conn->header_digest + iscsi_globvec->first_burst_len + conn->data_digest) ) {
+ if ( pdu->ds_len > (uint) (sizeof(struct iscsi_bhs_packet) + ISCSI_MAX_AHS_SIZE + conn->header_digest + (uint32_t) iscsi_config_get( NULL, ISCSI_GLOBALS_CONFIG_TYPE_FIRST_BURST_LEN ) + conn->data_digest) ) {
iscsi_task_destroy( task );
return iscsi_connection_handle_reject( conn, pdu, ISCSI_REJECT_REASON_PROTOCOL_ERR );
@@ -11749,8 +11840,10 @@ static int iscsi_connection_pdu_header_handle_scsi_cmd(iscsi_connection *conn, i
}
if ( ((scsi_cmd_pkt->flags_task & ISCSI_SCSI_CMD_FLAGS_FINAL) != 0) && (pdu->ds_len < exp_xfer_len) ) {
- if ( exp_xfer_len > ISCSI_DEFAULT_MAX_RECV_DS_LEN )
- exp_xfer_len = ISCSI_DEFAULT_MAX_RECV_DS_LEN;
+ const uint32_t max_recv_ds_len = (uint32_t) iscsi_config_get( NULL, ISCSI_GLOBALS_CONFIG_TYPE_MAX_RECV_DS_LEN );
+
+ if ( exp_xfer_len > max_recv_ds_len )
+ exp_xfer_len = max_recv_ds_len;
pdu->len = exp_xfer_len;
}
@@ -11800,7 +11893,7 @@ static int iscsi_connection_pdu_header_handle_task_func_req(iscsi_connection *co
*/
static int iscsi_connection_pdu_header_handle_text_req(iscsi_connection *conn, iscsi_pdu *pdu)
{
- if ( pdu->ds_len > (uint) (sizeof(struct iscsi_bhs_packet) + ISCSI_MAX_AHS_SIZE + conn->header_digest + iscsi_globvec->first_burst_len + conn->data_digest) )
+ if ( pdu->ds_len > (uint) (sizeof(struct iscsi_bhs_packet) + ISCSI_MAX_AHS_SIZE + conn->header_digest + (uint32_t) iscsi_config_get( NULL, ISCSI_GLOBALS_CONFIG_TYPE_FIRST_BURST_LEN ) + conn->data_digest) )
return iscsi_connection_handle_reject( conn, pdu, ISCSI_REJECT_REASON_PROTOCOL_ERR );
iscsi_text_req_packet *text_req_pkt = (iscsi_text_req_packet *) pdu->bhs_pkt;
@@ -12038,7 +12131,7 @@ static int iscsi_connection_pdu_header_handle_scsi_data_out(iscsi_connection *co
if ( conn->session->type == ISCSI_SESSION_TYPE_DISCOVERY )
return ISCSI_CONNECT_PDU_READ_ERR_FATAL;
- if ( pdu->ds_len > ISCSI_DEFAULT_MAX_RECV_DS_LEN )
+ if ( pdu->ds_len > (uint32_t) iscsi_config_get( NULL, ISCSI_GLOBALS_CONFIG_TYPE_MAX_RECV_DS_LEN ) )
return iscsi_connection_handle_reject( conn, pdu, ISCSI_REJECT_REASON_PROTOCOL_ERR );
iscsi_scsi_data_out_req_packet *scsi_data_out_req_pkt = (iscsi_scsi_data_out_req_packet *) pdu->bhs_pkt;
@@ -12055,9 +12148,6 @@ static int iscsi_connection_pdu_header_handle_scsi_data_out(iscsi_connection *co
pthread_rwlock_unlock( &conn->device->luns_rwlock );
- if ( pdu->ds_len > ISCSI_DEFAULT_MAX_RECV_DS_LEN )
- return iscsi_connection_handle_reject( conn, pdu, ISCSI_REJECT_REASON_PROTOCOL_ERR );
-
const uint32_t init_task_tag = iscsi_get_be32(scsi_data_out_req_pkt->init_task_tag);
if ( task->init_task_tag != init_task_tag )
@@ -12116,7 +12206,7 @@ static int iscsi_connection_pdu_header_handle_scsi_data_out(iscsi_connection *co
if ( task->scsi_task.buf != NULL ) {
pdu->ds_cmd_data = (iscsi_scsi_ds_cmd_data *) (task->scsi_task.buf + task->len);
- pdu->ds_len = ISCSI_DEFAULT_MAX_RECV_DS_LEN;
+ pdu->ds_len = (uint32_t) iscsi_config_get( NULL, ISCSI_GLOBALS_CONFIG_TYPE_MAX_RECV_DS_LEN );
}
return ISCSI_CONNECT_PDU_READ_OK;
@@ -12395,7 +12485,7 @@ static int iscsi_connection_pdu_data_handle_nop_out(iscsi_connection *conn, iscs
*/
static int iscsi_connection_pdu_data_handle_scsi_cmd_read(iscsi_connection *conn, iscsi_task *task)
{
- if ( task->scsi_task.xfer_len <= ISCSI_DEFAULT_MAX_RECV_DS_LEN ) {
+ if ( task->scsi_task.xfer_len <= (uint32_t) iscsi_config_get( NULL, ISCSI_GLOBALS_CONFIG_TYPE_MAX_RECV_DS_LEN ) ) {
task->parent = NULL;
task->scsi_task.buf = NULL;
task->scsi_task.pos = 0UL;
@@ -12599,16 +12689,16 @@ static int iscsi_connection_login_session_chap_discovery(iscsi_connection *conn)
{
conn->flags &= ~(ISCSI_CONNECT_FLAGS_CHAP_DISABLE | ISCSI_CONNECT_FLAGS_CHAP_REQUIRE | ISCSI_CONNECT_FLAGS_CHAP_MUTUAL);
- if ( (iscsi_globvec->flags & ISCSI_GLOBALS_FLAGS_CHAP_DISABLE) != 0 )
+ if ( iscsi_config_get( NULL, ISCSI_GLOBALS_CONFIG_TYPE_FLAGS_CHAP_DISABLE ) != 0L )
conn->flags |= ISCSI_CONNECT_FLAGS_CHAP_DISABLE;
- if ( (iscsi_globvec->flags & ISCSI_GLOBALS_FLAGS_CHAP_REQUIRE) != 0 )
+ if ( iscsi_config_get( NULL, ISCSI_GLOBALS_CONFIG_TYPE_FLAGS_CHAP_REQUIRE ) > 0L )
conn->flags |= ISCSI_CONNECT_FLAGS_CHAP_REQUIRE;
- if ( (iscsi_globvec->flags & ISCSI_GLOBALS_FLAGS_CHAP_MUTUAL) != 0 )
+ if ( iscsi_config_get( NULL, ISCSI_GLOBALS_CONFIG_TYPE_FLAGS_CHAP_MUTUAL ) > 0L )
conn->flags |= ISCSI_CONNECT_FLAGS_CHAP_MUTUAL;
- conn->chap_group = iscsi_globvec->chap_group;
+ conn->chap_group = iscsi_config_get( NULL, ISCSI_GLOBALS_CONFIG_TYPE_CHAP_GROUP );
return iscsi_connection_chap_negotiate( conn );
}
@@ -13196,7 +13286,7 @@ static int iscsi_connecction_handle_login_response_t_bit(iscsi_connection *conn,
static int iscsi_connecction_handle_login_response(iscsi_connection *conn, iscsi_pdu *login_response_pdu, iscsi_hashmap *key_value_pairs)
{
iscsi_login_response_packet *login_response_pkt = (iscsi_login_response_packet *) login_response_pdu->bhs_pkt;
- const int32_t ds_len = iscsi_negotiate_key_value_pairs( conn, key_value_pairs, (uint8_t *) login_response_pdu->ds_cmd_data, login_response_pdu->ds_len, login_response_pdu->len );
+ const int32_t ds_len = iscsi_negotiate_key_value_pairs( conn, key_value_pairs, (uint8_t *) login_response_pdu->ds_cmd_data, login_response_pdu->ds_len, login_response_pdu->len );
if ( ds_len < 0L ) {
login_response_pkt->status_class = ISCSI_LOGIN_RESPONSE_STATUS_CLASS_CLIENT_ERR;
@@ -13871,55 +13961,79 @@ void iscsi_connection_handle(dnbd3_client_t *client, const dnbd3_request_t *requ
_Static_assert( sizeof(dnbd3_request_t) <= sizeof(struct iscsi_bhs_packet), "DNBD3 request size larger than iSCSI BHS packet data size - Manual intervention required!" );
// sock_setTimeout( client->sock, 1000L * 3600L ); // TODO: Remove after finishing iSCSI implementation
+ uint recv_buf_len = (uint) iscsi_config_get( NULL, ISCSI_GLOBALS_CONFIG_TYPE_FIRST_BURST_LEN );
+
+ if ( recv_buf_len < 4096U )
+ recv_buf_len = 4096U;
+ else if ( recv_buf_len > 8192U )
+ recv_buf_len = 8192U;
+
+ recv_buf_len += (uint) (sizeof(struct iscsi_bhs_packet) + ISCSI_MAX_AHS_SIZE + ISCSI_DIGEST_SIZE + ISCSI_DIGEST_SIZE); // BHS + maximum AHS size + header and data digest overhead
+ recv_buf_len <<= 2U; // Receive up to four streams at once.
+
+ setsockopt( client->sock, SOL_SOCKET, SO_RCVBUF, &recv_buf_len, sizeof(recv_buf_len)); // Not being able to set the buffer is NOT fatal, so ignore error.
+
+ recv_buf_len += (uint) (ISCSI_DEFAULT_RECV_DS_LEN << 2UL);
+ setsockopt( client->sock, SOL_SOCKET, SO_SNDBUF, &recv_buf_len, sizeof(recv_buf_len)); // Not being able to set the buffer is NOT fatal, so ignore error.
+
pthread_rwlock_rdlock( &iscsi_globvec_rwlock );
- if ( iscsi_globvec == NULL )
+ if ( iscsi_globvec == NULL ) {
+ pthread_rwlock_unlock( &iscsi_globvec_rwlock );
+
return;
+ }
+
+ pthread_rwlock_rdlock( &iscsi_globvec->portal_groups_rwlock );
uint64_t *hash_key;
iscsi_portal_group *portal_group = NULL;
-
- pthread_rwlock_wrlock( &iscsi_globvec->portal_groups_rwlock );
-
- int rc = iscsi_hashmap_get( iscsi_globvec->portal_groups, (uint8_t *) &iscsi_globvec->portal_groups->last_insert_id, sizeof(iscsi_globvec->portal_groups->last_insert_id), (uint8_t **) &portal_group );
+ const uint64_t pg_tag = 1ULL;
+ int rc = iscsi_hashmap_get( iscsi_globvec->portal_groups, (uint8_t *) &pg_tag, sizeof(pg_tag), (uint8_t **) &portal_group );
if ( portal_group == NULL ) {
- hash_key = (uint64_t *) malloc( sizeof(uint64_t) );
+ pthread_rwlock_unlock( &iscsi_globvec->portal_groups_rwlock );
+ pthread_rwlock_wrlock( &iscsi_globvec->portal_groups_rwlock );
+ rc = iscsi_hashmap_get( iscsi_globvec->portal_groups, (uint8_t *) &pg_tag, sizeof(pg_tag), (uint8_t **) &portal_group );
- if ( hash_key == NULL ) {
- logadd( LOG_ERROR, "iscsi_connection_handle: Out of memory while allocating iSCSI portal group" );
+ if ( portal_group == NULL ) {
+ hash_key = (uint64_t *) malloc( sizeof(uint64_t) );
- pthread_rwlock_unlock( &iscsi_globvec->portal_groups_rwlock );
- pthread_rwlock_unlock( &iscsi_globvec_rwlock );
+ if ( hash_key == NULL ) {
+ logadd( LOG_ERROR, "iscsi_connection_handle: Out of memory while allocating iSCSI portal group" );
- return;
- }
+ pthread_rwlock_unlock( &iscsi_globvec->portal_groups_rwlock );
+ pthread_rwlock_unlock( &iscsi_globvec_rwlock );
- iscsi_hashmap_key_create_id( iscsi_globvec->portal_groups, hash_key );
- portal_group = iscsi_portal_group_create( *hash_key, 0 );
+ return;
+ }
- if ( portal_group == NULL ) {
- logadd( LOG_ERROR, "iscsi_connection_handle: Out of memory while allocating iSCSI portal group" );
+ iscsi_hashmap_key_create_id( iscsi_globvec->portal_groups, hash_key );
+ portal_group = iscsi_portal_group_create( *hash_key, 0 );
- iscsi_hashmap_key_destroy( (uint8_t *) hash_key );
- pthread_rwlock_unlock( &iscsi_globvec->portal_groups_rwlock );
- pthread_rwlock_unlock( &iscsi_globvec_rwlock );
+ if ( portal_group == NULL ) {
+ logadd( LOG_ERROR, "iscsi_connection_handle: Out of memory while allocating iSCSI portal group" );
- return;
- }
+ iscsi_hashmap_key_destroy( (uint8_t *) hash_key );
+ pthread_rwlock_unlock( &iscsi_globvec->portal_groups_rwlock );
+ pthread_rwlock_unlock( &iscsi_globvec_rwlock );
- portal_group->tag = *hash_key;
+ return;
+ }
- iscsi_hashmap_key_destroy( (uint8_t *) hash_key );
+ portal_group->tag = *hash_key;
+
+ iscsi_hashmap_key_destroy( (uint8_t *) hash_key );
- rc = iscsi_hashmap_put( iscsi_globvec->portal_groups, (uint8_t *) &portal_group->tag, sizeof(portal_group->tag), (uint8_t *) portal_group );
+ rc = iscsi_hashmap_put( iscsi_globvec->portal_groups, (uint8_t *) &portal_group->tag, sizeof(portal_group->tag), (uint8_t *) portal_group );
- if ( rc < 0 ) {
- iscsi_portal_group_destroy( portal_group );
- pthread_rwlock_unlock( &iscsi_globvec->portal_groups_rwlock );
- pthread_rwlock_unlock( &iscsi_globvec_rwlock );
+ if ( rc < 0 ) {
+ iscsi_portal_group_destroy( portal_group );
+ pthread_rwlock_unlock( &iscsi_globvec->portal_groups_rwlock );
+ pthread_rwlock_unlock( &iscsi_globvec_rwlock );
- return;
+ return;
+ }
}
}
@@ -13972,41 +14086,35 @@ void iscsi_connection_handle(dnbd3_client_t *client, const dnbd3_request_t *requ
return;
}
- iscsi_portal *portal = NULL;
+ if ( port == NULL ) {
+ port = (uint8_t *) strchr( (char *) hash_key, ':' );
+ port++;
+ }
- pthread_rwlock_wrlock( &iscsi_globvec->portal_groups_rwlock );
- rc = iscsi_hashmap_get( portal_group->portals, (uint8_t *) hash_key, key_len, (uint8_t **) &portal );
+ iscsi_portal *portal = iscsi_portal_create( host, port );
if ( portal == NULL ) {
- if ( port == NULL ) {
- port = (uint8_t *) strchr( (char *) hash_key, ':' );
- port++;
- }
-
- portal = iscsi_portal_create( host, port );
+ logadd( LOG_ERROR, "iscsi_connection_handle: Out of memory while allocating iSCSI portal" );
- if ( portal == NULL ) {
- logadd( LOG_ERROR, "iscsi_connection_handle: Out of memory while allocating iSCSI portal" );
+ iscsi_hashmap_key_destroy( (uint8_t *) hash_key );
+ free( host );
+ pthread_rwlock_unlock( &iscsi_globvec_rwlock );
- pthread_rwlock_unlock( &iscsi_globvec->portal_groups_rwlock );
- iscsi_hashmap_key_destroy( (uint8_t *) hash_key );
- free( host );
- pthread_rwlock_unlock( &iscsi_globvec_rwlock );
+ return;
+ }
- return;
- }
+ pthread_rwlock_wrlock( &iscsi_globvec->portal_groups_rwlock );
- rc = iscsi_portal_group_add_portal( portal_group, portal );
+ rc = iscsi_portal_group_add_portal( portal_group, portal );
- if ( rc < 0 ) {
- pthread_rwlock_unlock( &iscsi_globvec->portal_groups_rwlock );
- iscsi_portal_destroy( portal );
- iscsi_hashmap_key_destroy( (uint8_t *) hash_key );
- free( host );
- pthread_rwlock_unlock( &iscsi_globvec_rwlock );
+ if ( rc < 0 ) {
+ pthread_rwlock_unlock( &iscsi_globvec->portal_groups_rwlock );
+ iscsi_portal_destroy( portal );
+ iscsi_hashmap_key_destroy( (uint8_t *) hash_key );
+ free( host );
+ pthread_rwlock_unlock( &iscsi_globvec_rwlock );
- return;
- }
+ return;
}
iscsi_hashmap_key_destroy( (uint8_t *) hash_key );
@@ -14018,19 +14126,17 @@ void iscsi_connection_handle(dnbd3_client_t *client, const dnbd3_request_t *requ
logadd( LOG_ERROR, "iscsi_connection_handle: Out of memory while allocating iSCSI connection" );
iscsi_portal_group_del_portal( portal_group, portal );
+ pthread_rwlock_unlock( &iscsi_globvec->portal_groups_rwlock );
iscsi_portal_destroy( portal );
pthread_rwlock_unlock( &iscsi_globvec_rwlock );
return;
}
- pthread_rwlock_unlock( &iscsi_globvec->portal_groups_rwlock );
-
conn->pdu_processing = iscsi_connection_pdu_create( conn, 0U, 0, 0UL, 0 );
if ( conn->pdu_processing == NULL ) {
iscsi_connection_destroy( conn );
- pthread_rwlock_wrlock( &iscsi_globvec->portal_groups_rwlock );
iscsi_portal_group_del_portal( portal_group, portal );
pthread_rwlock_unlock( &iscsi_globvec->portal_groups_rwlock );
iscsi_portal_destroy( portal );
@@ -14039,6 +14145,8 @@ void iscsi_connection_handle(dnbd3_client_t *client, const dnbd3_request_t *requ
return;
}
+ pthread_rwlock_unlock( &iscsi_globvec->portal_groups_rwlock );
+
memcpy( conn->pdu_processing->bhs_pkt, request, len );
conn->pdu_processing->bhs_pos = len;
diff --git a/src/server/iscsi.h b/src/server/iscsi.h
index ded2d1d..f247621 100644
--- a/src/server/iscsi.h
+++ b/src/server/iscsi.h
@@ -9918,6 +9918,9 @@ typedef struct iscsi_key_value_pair_packet {
/// Discovery mode.
int discovery;
+
+ /// First burst length has been passed by the initiator.
+ bool first_burst_len;
} iscsi_key_value_pair_packet;
int iscsi_parse_key_value_pairs(iscsi_hashmap *key_value_pairs, const uint8_t *packet_data, uint len, int c_bit, uint8_t **partial_pairs); // Extracts all text key / value pairs out of an iSCSI packet into a hash map
@@ -9976,7 +9979,7 @@ int iscsi_parse_key_value_pairs(iscsi_hashmap *key_value_pairs, const uint8_t *p
#define ISCSI_GLOBALS_SECTION_SCSI_DEVICE_PREFIX "scsi-device-"
-/// iSCSI main global data config type: iHeader digest (CRC32), always MUST be 0 or 4 for now.
+/// iSCSI main global data config type: Header digest (CRC32), always MUST be 0 or 4 for now.
#define ISCSI_GLOBALS_CONFIG_TYPE_HEADER_DIGEST 0
/// iSCSI main global data config type: Data digest (CRC32), always MUST be 0 or 4 for now.
@@ -10006,50 +10009,66 @@ int iscsi_parse_key_value_pairs(iscsi_hashmap *key_value_pairs, const uint8_t *p
/// iSCSI main global data config type: Error recovery level.
#define ISCSI_GLOBALS_CONFIG_TYPE_ERR_RECOVERY_LEVEL 9
+/// iSCSI main global data config type: CHAP authentication group.
+#define ISCSI_GLOBALS_CONFIG_TYPE_CHAP_GROUP 10
+
/// iSCSI main global data config type: SCSI emulation for device type.
-#define ISCSI_GLOBALS_CONFIG_TYPE_SCSI_DEVICE_TYPE 10
+#define ISCSI_GLOBALS_CONFIG_TYPE_SCSI_DEVICE_TYPE 11
/// iSCSI main global data config type: SCSI emulation for physical block size.
-#define ISCSI_GLOBALS_CONFIG_TYPE_SCSI_PHYSICAL_BLOCK_SIZE 11
+#define ISCSI_GLOBALS_CONFIG_TYPE_SCSI_PHYSICAL_BLOCK_SIZE 12
/// iSCSI main global data config type: SCSI emulation for physical block size shift count.
-#define ISCSI_GLOBALS_CONFIG_TYPE_SCSI_PHYSICAL_BLOCK_SIZE_SHIFT 12
+#define ISCSI_GLOBALS_CONFIG_TYPE_SCSI_PHYSICAL_BLOCK_SIZE_SHIFT 13
/// iSCSI main global data config type: SCSI emulation for logical block size.
-#define ISCSI_GLOBALS_CONFIG_TYPE_SCSI_LOGICAL_BLOCK_SIZE 13
+#define ISCSI_GLOBALS_CONFIG_TYPE_SCSI_LOGICAL_BLOCK_SIZE 14
/// iSCSI main global data config type: SCSI emulation for logical block size shift count.
-#define ISCSI_GLOBALS_CONFIG_TYPE_SCSI_LOGICAL_BLOCK_SIZE_SHIFT 14
+#define ISCSI_GLOBALS_CONFIG_TYPE_SCSI_LOGICAL_BLOCK_SIZE_SHIFT 15
+
+/// iSCSI main global data config type: CHAP authentication is disabled.
+#define ISCSI_GLOBALS_CONFIG_TYPE_FLAGS_CHAP_DISABLE 16
+
+/// iSCSI main global data config type: CHAP authentication is required.
+#define ISCSI_GLOBALS_CONFIG_TYPE_FLAGS_CHAP_REQUIRE 17
+
+/// iSCSI main global data config type: CHAP authentication is mutual.
+#define ISCSI_GLOBALS_CONFIG_TYPE_FLAGS_CHAP_MUTUAL 18
/// iSCSI main global data config type: Initial ready to transfer.
-#define ISCSI_GLOBALS_CONFIG_TYPE_FLAGS_INIT_R2T 15
+#define ISCSI_GLOBALS_CONFIG_TYPE_FLAGS_INIT_R2T 19
/// iSCSI main global data config type: Immediate data.
-#define ISCSI_GLOBALS_CONFIG_TYPE_FLAGS_IMMEDIATE_DATA 16
+#define ISCSI_GLOBALS_CONFIG_TYPE_FLAGS_IMMEDIATE_DATA 20
/// iSCSI main global data config type: Data PDU in order.
-#define ISCSI_GLOBALS_CONFIG_TYPE_FLAGS_DATA_PDU_IN_ORDER 17
+#define ISCSI_GLOBALS_CONFIG_TYPE_FLAGS_DATA_PDU_IN_ORDER 21
/// iSCSI main global data config type: Data sequence in order.
-#define ISCSI_GLOBALS_CONFIG_TYPE_FLAGS_DATA_SEQ_IN_ORDER 18
+#define ISCSI_GLOBALS_CONFIG_TYPE_FLAGS_DATA_SEQ_IN_ORDER 22
/// iSCSI main global data config type: SCSI emulation for I/O removable device.
-#define ISCSI_GLOBALS_CONFIG_TYPE_FLAGS_SCSI_IO_REMOVABLE 19
+#define ISCSI_GLOBALS_CONFIG_TYPE_FLAGS_SCSI_IO_REMOVABLE 23
/// iSCSI main global data config type: SCSI emulation for I/O UNMAP supporting device.
-#define ISCSI_GLOBALS_CONFIG_TYPE_FLAGS_SCSI_IO_UNMAP 20
+#define ISCSI_GLOBALS_CONFIG_TYPE_FLAGS_SCSI_IO_UNMAP 24
/// iSCSI main global data config type: SCSI emulation for I/O non-rotating device.
-#define ISCSI_GLOBALS_CONFIG_TYPE_FLAGS_SCSI_IO_NO_ROTATION 21
+#define ISCSI_GLOBALS_CONFIG_TYPE_FLAGS_SCSI_IO_NO_ROTATION 25
/// iSCSI main global data config type: SCSI emulation for I/O physical read only device.
-#define ISCSI_GLOBALS_CONFIG_TYPE_FLAGS_SCSI_IO_PHYSICAL_READ_ONLY 22
+#define ISCSI_GLOBALS_CONFIG_TYPE_FLAGS_SCSI_IO_PHYSICAL_READ_ONLY 26
/// iSCSI main global data config type: SCSI emulation for I/O write protected device.
-#define ISCSI_GLOBALS_CONFIG_TYPE_FLAGS_SCSI_IO_WRITE_PROTECT 23
+#define ISCSI_GLOBALS_CONFIG_TYPE_FLAGS_SCSI_IO_WRITE_PROTECT 27
/// iSCSI main global data config type: SCSI emulation for I/O write cache device.
-#define ISCSI_GLOBALS_CONFIG_TYPE_FLAGS_SCSI_IO_WRITE_CACHE 24
+#define ISCSI_GLOBALS_CONFIG_TYPE_FLAGS_SCSI_IO_WRITE_CACHE 28
+
+
+/// iSCSI main global data config type: Value error result.
+#define ISCSI_GLOBALS_CONFIG_TYPE_VALUE_ERROR -2147483648L
/// iSCSI main global data SCSI device configuration flags: Initial ready to transfer.
@@ -10274,8 +10293,8 @@ typedef struct iscsi_globals {
/// Hash map containing iSCSI SCSI device specific configuration.
iscsi_hashmap *scsi_device_config;
- /// Mutex for hash map containing iSCSI SCSI device specific configuration.
- pthread_mutex_t scsi_device_config_mutex;
+ /// Read/write lock for hash map containing iSCSI SCSI device specific configuration.
+ pthread_rwlock_t scsi_device_config_rwlock;
/// Global flags.
int flags;