diff options
| author | Sebastian Vater | 2025-10-13 09:33:18 +0200 |
|---|---|---|
| committer | Sebastian Vater | 2025-10-13 09:33:18 +0200 |
| commit | f48e7e32b7be6c645eac8f7d76bd4cdfe0cd3616 (patch) | |
| tree | 21abfd0f24b14807c6c81b0c9d1ce6e82c3cc817 | |
| parent | Fixed iSCSI SCSI INQUIRY optimal block size configuraton. Finally, added TCP_... (diff) | |
| download | dnbd3-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.
| -rw-r--r-- | Doxyfile | 2 | ||||
| -rw-r--r-- | pkg/config/iscsi.conf | 8 | ||||
| -rw-r--r-- | pkg/config/server.conf | 8 | ||||
| -rw-r--r-- | src/server/iscsi.c | 694 | ||||
| -rw-r--r-- | src/server/iscsi.h | 55 |
5 files changed, 447 insertions, 320 deletions
@@ -30,7 +30,7 @@ ENABLE_PREPROCESSING = YES MACRO_EXPANSION = YES EXPAND_ONLY_PREDEF = YES SKIP_FUNCTION_MACROS = NO -PREDEFINED = __attribute__(x)= +PREDEFINED = __attribute__(x)= UNUSED # Warnings WARN_IF_UNDOCUMENTED = YES diff --git a/pkg/config/iscsi.conf b/pkg/config/iscsi.conf index 79eab48..f01b131 100644 --- a/pkg/config/iscsi.conf +++ b/pkg/config/iscsi.conf @@ -10,11 +10,11 @@ [iscsi] ; Target name check level (warning) specifying invalid check levels will default to full -; validation!). Default is Full +; validation!). Default is Relaxed ; Full Target name is checked for full standaard compliance (recommended) ; Relaxed All invalid characters according to standard will be allowed if not an IQN, NAA or EUI. ; None No checking at all (be careful) -TargetNameCheck=Full +TargetNameCheck=Relaxed ; Header digest (warning) specifying invalid digest type will default to None!). ; Default is None @@ -37,8 +37,8 @@ DataDigest=None ; MaxBurstLength for solicited data and FirstBurstLength for unsolicited dataAn initiator MUST NOT ; send solicited PDUs exceeding MaxBurstLength nor unsolicited PDUs exceeding FirstBurstLength (or ; FirstBurstLength-Immediate Data Length if immediate data were sent). Valid values range from 512 -; to 16777215 bytes. Default is 8192 bytes (8 KiB) -MaxRecvDataSegmentLength=8192 +; to 16777215 bytes. Default is 65536 bytes (64 KiB) +MaxRecvDataSegmentLength=65536 ; Maximum number of connections allowed per session. Default is 1 MaxConnectionsPerSession=1 diff --git a/pkg/config/server.conf b/pkg/config/server.conf index 1e92963..7743579 100644 --- a/pkg/config/server.conf +++ b/pkg/config/server.conf @@ -95,11 +95,11 @@ consoleTimestamps=false [iscsi] ; Target name check level (warning) specifying invalid check levels will default to full -; validation!). Default is Full +; validation!). Default is Relaxed ; Full Target name is checked for full standaard compliance (recommended) ; Relaxed All invalid characters according to standard will be allowed if not an IQN, NAA or EUI. ; None No checking at all (be careful) -TargetNameCheck=Full +TargetNameCheck=Relaxed ; Header digest (warning) specifying invalid digest type will default to None!). ; Default is None @@ -122,8 +122,8 @@ DataDigest=None ; MaxBurstLength for solicited data and FirstBurstLength for unsolicited dataAn initiator MUST NOT ; send solicited PDUs exceeding MaxBurstLength nor unsolicited PDUs exceeding FirstBurstLength (or ; FirstBurstLength-Immediate Data Length if immediate data were sent). Valid values range from 512 -; to 16777215 bytes. Default is 8192 bytes (8 KiB) -MaxRecvDataSegmentLength=8192 +; to 16777215 bytes. Default is 65536 bytes (64 KiB) +MaxRecvDataSegmentLength=65536 ; Maximum number of connections allowed per session. Default is 1 MaxConnectionsPerSession=1 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; |
