summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSebastian Vater2025-10-01 11:52:30 +0200
committerSebastian Vater2025-10-01 11:52:30 +0200
commit07cc37a77437f63f9552ddddf8d29431d5fe6256 (patch)
treefe9a7fee87e1c661f115d90877081a84ead4e6d2
parentFixed some very memory leaks in iSCSI reported by valgrind and improved sessi... (diff)
downloaddnbd3-07cc37a77437f63f9552ddddf8d29431d5fe6256.tar.gz
dnbd3-07cc37a77437f63f9552ddddf8d29431d5fe6256.tar.xz
dnbd3-07cc37a77437f63f9552ddddf8d29431d5fe6256.zip
Implemented better read/write and mutex locking in iSCSI server. Some little code cleanups and finally bug fixes again.
-rw-r--r--src/server/iscsi.c545
-rw-r--r--src/server/iscsi.h40
2 files changed, 399 insertions, 186 deletions
diff --git a/src/server/iscsi.c b/src/server/iscsi.c
index e3609d5..ef44d8e 100644
--- a/src/server/iscsi.c
+++ b/src/server/iscsi.c
@@ -18,6 +18,7 @@
*
*/
+#include "locks.h"
#include <ctype.h>
#include <errno.h>
#include <stdarg.h>
@@ -190,11 +191,34 @@ int iscsi_create()
return -1;
}
- globvec->portal_groups = iscsi_hashmap_create( 0U );
+ if ( pthread_rwlock_init( &globvec->devices_rwlock, NULL ) != 0 ) {
+ logadd( LOG_ERROR, "iscsi_create: Out of memory while initializing read/write lock for iSCSI global vector devices hash map" );
+
+ iscsi_hashmap_destroy( globvec->devices );
+ free( globvec );
+ pthread_rwlock_unlock( &iscsi_globvec_rwlock );
+
+ return -1;
+ }
+
+ globvec->portal_groups = iscsi_hashmap_create( 1U );
if ( globvec->portal_groups == NULL ) {
logadd( LOG_ERROR, "iscsi_create: Out of memory while allocating iSCSI global vector portal groups hash map" );
+ pthread_rwlock_destroy( &globvec->devices_rwlock );
+ iscsi_hashmap_destroy( globvec->devices );
+ free( globvec );
+ pthread_rwlock_unlock( &iscsi_globvec_rwlock );
+
+ return -1;
+ }
+
+ if ( pthread_rwlock_init( &globvec->portal_groups_rwlock, NULL ) != 0 ) {
+ logadd( LOG_ERROR, "iscsi_create: Out of memory while initializing read/write lock for iSCSI global vector portal groups hash map" );
+
+ iscsi_hashmap_destroy( globvec->portal_groups );
+ pthread_rwlock_destroy( &globvec->devices_rwlock );
iscsi_hashmap_destroy( globvec->devices );
free( globvec );
pthread_rwlock_unlock( &iscsi_globvec_rwlock );
@@ -207,7 +231,23 @@ int iscsi_create()
if ( globvec->target_nodes == NULL ) {
logadd( LOG_ERROR, "iscsi_create: Out of memory while allocating iSCSI global vector target nodes hash map" );
+ pthread_rwlock_destroy( &globvec->portal_groups_rwlock );
iscsi_hashmap_destroy( globvec->portal_groups );
+ pthread_rwlock_destroy( &globvec->devices_rwlock );
+ iscsi_hashmap_destroy( globvec->devices );
+ free( globvec );
+ pthread_rwlock_unlock( &iscsi_globvec_rwlock );
+
+ return -1;
+ }
+
+ if ( pthread_rwlock_init( &globvec->target_nodes_rwlock, NULL ) != 0 ) {
+ logadd( LOG_ERROR, "iscsi_create: Out of memory while initializing read/write lock for iSCSI global vector target nodes hash map" );
+
+ iscsi_hashmap_destroy( globvec->target_nodes );
+ pthread_rwlock_destroy( &globvec->portal_groups_rwlock );
+ iscsi_hashmap_destroy( globvec->portal_groups );
+ pthread_rwlock_destroy( &globvec->devices_rwlock );
iscsi_hashmap_destroy( globvec->devices );
free( globvec );
pthread_rwlock_unlock( &iscsi_globvec_rwlock );
@@ -220,8 +260,27 @@ int iscsi_create()
if ( globvec->sessions == NULL ) {
logadd( LOG_ERROR, "iscsi_create: Out of memory while allocating iSCSI global vector sessions hash map" );
+ pthread_rwlock_destroy( &globvec->target_nodes_rwlock );
+ iscsi_hashmap_destroy( globvec->target_nodes );
+ pthread_rwlock_destroy( &globvec->portal_groups_rwlock );
+ iscsi_hashmap_destroy( globvec->portal_groups );
+ pthread_rwlock_destroy( &globvec->devices_rwlock );
+ iscsi_hashmap_destroy( globvec->devices );
+ free( globvec );
+ pthread_rwlock_unlock( &iscsi_globvec_rwlock );
+
+ return -1;
+ }
+
+ if ( pthread_rwlock_init( &globvec->sessions_rwlock, NULL ) != 0 ) {
+ logadd( LOG_ERROR, "iscsi_create: Out of memory while initializing read/write lock for iSCSI global vector sessions hash map map" );
+
+ iscsi_hashmap_destroy( globvec->sessions );
+ pthread_rwlock_destroy( &globvec->target_nodes_rwlock );
iscsi_hashmap_destroy( globvec->target_nodes );
+ pthread_rwlock_destroy( &globvec->portal_groups_rwlock );
iscsi_hashmap_destroy( globvec->portal_groups );
+ pthread_rwlock_destroy( &globvec->devices_rwlock );
iscsi_hashmap_destroy( globvec->devices );
free( globvec );
pthread_rwlock_unlock( &iscsi_globvec_rwlock );
@@ -234,9 +293,13 @@ int iscsi_create()
if ( globvec->session_key_value_pairs == NULL ) {
logadd( LOG_ERROR, "iscsi_create: Out of memory while allocating iSCSI global vector session key and value pairs hash map" );
+ pthread_rwlock_destroy( &globvec->sessions_rwlock );
iscsi_hashmap_destroy( globvec->sessions );
+ pthread_rwlock_destroy( &globvec->target_nodes_rwlock );
iscsi_hashmap_destroy( globvec->target_nodes );
+ pthread_rwlock_destroy( &globvec->portal_groups_rwlock );
iscsi_hashmap_destroy( globvec->portal_groups );
+ pthread_rwlock_destroy( &globvec->devices_rwlock );
iscsi_hashmap_destroy( globvec->devices );
free( globvec );
pthread_rwlock_unlock( &iscsi_globvec_rwlock );
@@ -251,9 +314,13 @@ int iscsi_create()
iscsi_hashmap_iterate( globvec->session_key_value_pairs, iscsi_hashmap_destroy_value_callback, NULL );
iscsi_hashmap_destroy( globvec->session_key_value_pairs );
+ pthread_rwlock_destroy( &globvec->sessions_rwlock );
iscsi_hashmap_destroy( globvec->sessions );
+ pthread_rwlock_destroy( &globvec->target_nodes_rwlock );
iscsi_hashmap_destroy( globvec->target_nodes );
+ pthread_rwlock_destroy( &globvec->portal_groups_rwlock );
iscsi_hashmap_destroy( globvec->portal_groups );
+ pthread_rwlock_destroy( &globvec->devices_rwlock );
iscsi_hashmap_destroy( globvec->devices );
free( globvec );
pthread_rwlock_unlock( &iscsi_globvec_rwlock );
@@ -268,9 +335,13 @@ int iscsi_create()
iscsi_hashmap_iterate( globvec->session_key_value_pairs, iscsi_hashmap_destroy_value_callback, NULL );
iscsi_hashmap_destroy( globvec->session_key_value_pairs );
+ pthread_rwlock_destroy( &globvec->sessions_rwlock );
iscsi_hashmap_destroy( globvec->sessions );
+ pthread_rwlock_destroy( &globvec->target_nodes_rwlock );
iscsi_hashmap_destroy( globvec->target_nodes );
+ pthread_rwlock_destroy( &globvec->portal_groups_rwlock );
iscsi_hashmap_destroy( globvec->portal_groups );
+ pthread_rwlock_destroy( &globvec->devices_rwlock );
iscsi_hashmap_destroy( globvec->devices );
free( globvec );
pthread_rwlock_unlock( &iscsi_globvec_rwlock );
@@ -287,9 +358,13 @@ int iscsi_create()
iscsi_hashmap_destroy( globvec->connection_key_value_pairs );
iscsi_hashmap_iterate( globvec->session_key_value_pairs, iscsi_hashmap_destroy_value_callback, NULL );
iscsi_hashmap_destroy( globvec->session_key_value_pairs );
+ pthread_rwlock_destroy( &globvec->sessions_rwlock );
iscsi_hashmap_destroy( globvec->sessions );
+ pthread_rwlock_destroy( &globvec->target_nodes_rwlock );
iscsi_hashmap_destroy( globvec->target_nodes );
+ pthread_rwlock_destroy( &globvec->portal_groups_rwlock );
iscsi_hashmap_destroy( globvec->portal_groups );
+ pthread_rwlock_destroy( &globvec->devices_rwlock );
iscsi_hashmap_destroy( globvec->devices );
free( globvec );
pthread_rwlock_unlock( &iscsi_globvec_rwlock );
@@ -297,6 +372,8 @@ int iscsi_create()
return -1;
}
+ pthread_mutex_init( &globvec->exec_queue_mutex, NULL ); // TODO: Start: Remove after I/O sync implementation
+
globvec->flags = 0;
globvec->max_sessions = 0U;
globvec->chap_group = 0L;
@@ -329,6 +406,8 @@ void iscsi_destroy()
if ( globvec != NULL ) {
iscsi_globvec = NULL;
+ pthread_mutex_destroy( &globvec->exec_queue_mutex ); // TODO: Start: Remove after I/O sync implementation
+
iscsi_hashmap_iterate( globvec->connection_key_value_pairs, iscsi_hashmap_destroy_value_callback, NULL );
iscsi_hashmap_destroy( globvec->connection_key_value_pairs );
globvec->connection_key_value_pairs = NULL;
@@ -337,15 +416,19 @@ void iscsi_destroy()
iscsi_hashmap_destroy( globvec->session_key_value_pairs );
globvec->session_key_value_pairs = NULL;
+ pthread_rwlock_destroy( &globvec->sessions_rwlock );
iscsi_hashmap_destroy( globvec->sessions );
globvec->sessions = NULL;
+ pthread_rwlock_destroy( &globvec->target_nodes_rwlock );
iscsi_hashmap_destroy( globvec->target_nodes );
globvec->target_nodes = NULL;
+ pthread_rwlock_destroy( &globvec->portal_groups_rwlock );
iscsi_hashmap_destroy( globvec->portal_groups );
globvec->portal_groups = NULL;
+ pthread_rwlock_destroy( &globvec->devices_rwlock );
iscsi_hashmap_destroy( globvec->devices );
globvec->devices = NULL;
@@ -1611,7 +1694,7 @@ static int iscsi_add_int_key_value_pair(iscsi_hashmap *key_value_pairs, const ui
*/
static int iscsi_update_int_key_value_pair(iscsi_hashmap *key_value_pairs, const uint8_t *key, const int32_t value)
{
- const uint8_t *hash_val = iscsi_sprintf_alloc( "%" PRId32, value );
+ uint8_t *hash_val = iscsi_sprintf_alloc( "%" PRId32, value );
if ( hash_val == NULL ) {
logadd( LOG_ERROR, "iscsi_update_int_key_value_pair: Out of memory allocating integer value." );
@@ -1801,8 +1884,6 @@ void iscsi_task_destroy_callback(iscsi_scsi_task *scsi_task)
{
if ( scsi_task != NULL ) {
iscsi_task *task = (iscsi_task *) (((uint8_t *) scsi_task) - offsetof(struct iscsi_task, scsi_task));
- iscsi_task *sub_task;
- iscsi_task *tmp;
if ( task->parent != NULL ) {
if ( (task->scsi_task.flags & ISCSI_SCSI_TASK_FLAGS_XFER_READ) != 0 )
@@ -2976,7 +3057,7 @@ void iscsi_scsi_task_lun_process_abort(iscsi_scsi_task *scsi_task)
* @return Pointer to ISCSI device LUN or NULL in case
* of an error (memory exhaustion).
*/
-iscsi_scsi_lun *iscsi_scsi_lun_create(const uint id)
+iscsi_scsi_lun *iscsi_scsi_lun_create(const int lun_id)
{
iscsi_scsi_lun *lun = (iscsi_scsi_lun *) malloc( sizeof(struct iscsi_scsi_lun) );
@@ -3017,7 +3098,7 @@ iscsi_scsi_lun *iscsi_scsi_lun_create(const uint id)
lun->device = NULL;
lun->image = NULL;
- lun->id = id;
+ lun->id = lun_id;
lun->flags = 0;
lun->pr_gen = 0UL;
@@ -4032,13 +4113,15 @@ int iscsi_scsi_emu_io_blocks_read(iscsi_scsi_task *scsi_task, uint8_t *buf, dnbd
// TODO: Begin remove after I/O async implementation
uint64_t *exec_data = malloc( 64 );
- exec_data[2] = (uint64_t *) callback;
+ exec_data[2] = (uint64_t) callback;
exec_data[3] = 3ULL;
- exec_data[4] = (dnbd3_image_t *) image;
- exec_data[5] = user_data;
+ exec_data[4] = (uint64_t) image;
+ exec_data[5] = (uint64_t) user_data;
exec_data[6] = success;
+ pthread_mutex_lock( &iscsi_globvec->exec_queue_mutex );
iscsi_list_enqueue( &iscsi_globvec->exec_queue, (iscsi_node *) exec_data );
+ pthread_mutex_unlock( &iscsi_globvec->exec_queue_mutex );
// TODO: End remove after I/O async implementation
// scsi_task->xfer_pos = scsi_task->len;
@@ -4191,13 +4274,15 @@ int iscsi_scsi_emu_io_blocks_write(iscsi_scsi_task *scsi_task, uint8_t *buf, dnb
// TODO: Begin remove after I/O async implementation
uint64_t *exec_data = malloc( 64 );
- exec_data[2] = (uint64_t *) callback;
+ exec_data[2] = (uint64_t) callback;
exec_data[3] = 3ULL;
- exec_data[4] = (dnbd3_image_t *) image;
- exec_data[5] = user_data;
+ exec_data[4] = (uint64_t) image;
+ exec_data[5] = (uint64_t) user_data;
exec_data[6] = success;
+ pthread_mutex_lock( &iscsi_globvec->exec_queue_mutex );
iscsi_list_enqueue( &iscsi_globvec->exec_queue, (iscsi_node *) exec_data );
+ pthread_mutex_unlock( &iscsi_globvec->exec_queue_mutex );
// TODO: End remove after I/O async implementation
// scsi_task->xfer_pos = scsi_task->len;
@@ -6536,6 +6621,8 @@ int iscsi_port_transport_id_set(iscsi_port *port, const uint8_t *name, const uin
port->transport_id_len = (uint16_t) (offsetof(struct iscsi_transport_id, name) + len);
+ free( tmp_buf );
+
return ISCSI_CONNECT_PDU_READ_OK;
}
@@ -6547,17 +6634,13 @@ int iscsi_port_transport_id_set(iscsi_port *port, const uint8_t *name, const uin
*
* @param[in] name Pointer to name of iSCSI device,
* may NOT be NULL, so be careful.
- * @param[in] luns Maximum number of LUNs for this
- * iSCSI device.
+ * @param[in] lun_id Initial LUN identifier to create.
* @param[in] protocol_id Protocol identifier.
* @return Pointer to iSCSI device or NULL in
* case of an error.
*/
-iscsi_device *iscsi_device_create(const uint8_t *name, const uint luns, const uint8_t protocol_id)
+iscsi_device *iscsi_device_create(const uint8_t *name, const int lun_id, const uint8_t protocol_id)
{
- if ( luns == 0U )
- return NULL;
-
iscsi_device *device = (iscsi_device *) malloc( sizeof(struct iscsi_device) );
if ( device == NULL ) {
@@ -6580,7 +6663,7 @@ iscsi_device *iscsi_device_create(const uint8_t *name, const uint luns, const ui
memcpy( device->name, name, len );
- device->luns = iscsi_hashmap_create( luns );
+ device->luns = iscsi_hashmap_create( 8U );
if ( device->luns == NULL ) {
logadd( LOG_ERROR, "iscsi_device_create: Out of memory allocating iSCSI device LUN hash map" );
@@ -6591,41 +6674,53 @@ iscsi_device *iscsi_device_create(const uint8_t *name, const uint luns, const ui
return NULL;
}
- for ( uint i = 0U; i < luns; i++ ) {
- iscsi_scsi_lun *lun = iscsi_scsi_lun_create( i );
- uint8_t *hash_key = iscsi_hashmap_key_create( (uint8_t *) &i, sizeof(i) );
+ iscsi_scsi_lun *lun = iscsi_scsi_lun_create( lun_id );
- if ( hash_key == NULL ) {
- logadd( LOG_ERROR, "iscsi_device_create: Out of memory allocating iSCSI device LUN hash map" );
+ if ( lun == NULL ) {
+ logadd( LOG_ERROR, "iscsi_device_create: Out of memory allocating iSCSI device LUN hash map" );
- iscsi_hashmap_iterate( device->luns, iscsi_hashmap_key_destroy_value_callback, NULL );
- iscsi_hashmap_destroy( device->luns );
- free( device->name );
- free( device );
+ iscsi_hashmap_destroy( device->luns );
+ free( device->name );
+ free( device );
- return NULL;
- }
+ return NULL;
+ }
- const int rc = iscsi_hashmap_put( device->luns, hash_key, sizeof(i), (uint8_t *) lun );
+ const uint64_t lun_hash = lun_id;
+ uint8_t *hash_key = iscsi_hashmap_key_create( (uint8_t *) &lun_hash, sizeof(lun_hash) );
- if ( rc < 0 ) {
- iscsi_hashmap_iterate( device->luns, iscsi_hashmap_key_destroy_value_callback, NULL );
- iscsi_hashmap_destroy( device->luns );
- free( device->name );
- free( device );
+ if ( hash_key == NULL ) {
+ logadd( LOG_ERROR, "iscsi_device_create: Out of memory allocating iSCSI device LUN hash map" );
- return NULL;
- }
+ iscsi_scsi_lun_destroy( lun );
+ iscsi_hashmap_destroy( device->luns );
+ free( device->name );
+ free( device );
+
+ return NULL;
+ }
+
+ const int rc = iscsi_hashmap_put( device->luns, hash_key, sizeof(lun_hash), (uint8_t *) lun );
+
+ if ( rc < 0 ) {
+ iscsi_hashmap_key_destroy( hash_key );
+ iscsi_scsi_lun_destroy( lun );
+ iscsi_hashmap_destroy( device->luns );
+ free( device->name );
+ free( device );
- lun->device = device;
+ return NULL;
}
+ lun->device = device;
+
device->ports = iscsi_hashmap_create( 0U );
if ( device->ports == NULL ) {
logadd( LOG_ERROR, "iscsi_device_create: Out of memory allocating iSCSI device ports hash map" );
- iscsi_hashmap_iterate( device->luns, iscsi_hashmap_key_destroy_value_callback, NULL );
+ iscsi_hashmap_key_destroy( hash_key );
+ iscsi_scsi_lun_destroy( lun );
iscsi_hashmap_destroy( device->luns );
free( device->name );
free( device );
@@ -6635,6 +6730,7 @@ iscsi_device *iscsi_device_create(const uint8_t *name, const uint luns, const ui
device->id = 0;
device->flags = 0;
+ device->ref = 1UL;
device->protocol_id = protocol_id;
return device;
@@ -6652,7 +6748,7 @@ iscsi_device *iscsi_device_create(const uint8_t *name, const uint luns, const ui
*/
void iscsi_device_destroy(iscsi_device *device)
{
- if ( device != NULL ) {
+ if ( (device != NULL) && (--device->ref == 0UL) ) {
if ( device->ports != NULL ) {
iscsi_hashmap_destroy( device->ports );
@@ -6703,41 +6799,6 @@ iscsi_port *iscsi_device_find_port_by_portal_group_tag(const iscsi_device *devic
}
/**
- * @brief Finds an iSCSI LUN by LUN identifier.
- *
- * Callback function for each element while iterating
- * through the iSCSI device hash map.\n
- * LUNs about to be removed are not returned by this
- * callback.
- *
- * @param[in] key Pointer to zero padded key. NULL is
- * an invalid pointer here, so be careful.
- * @param[in] key_size Number of bytes for the key.
- * @param[in] value Value of the key, NULL creates an
- * empty key assignment.
- * @param[in,out] user_data Pointer to a data structure
- * containing the iSCSI LUN and the LUN id to be
- * searched for and may NOT be NULL, so be
- * careful.
- * @retval -1 The LUN has been found and stored
- * in the result structure. Therefore, no further
- * searching is needed.
- * @retval 0 The LUN has not been found yet.
- */
-int iscsi_device_find_lun_callback(uint8_t *key, const size_t key_size, uint8_t *value, uint8_t *user_data)
-{
- iscsi_device_find_lun_id *lun_find = (iscsi_device_find_lun_id *) user_data;
- iscsi_scsi_lun *lun = (iscsi_scsi_lun *) value;
-
- if ( (lun->id != lun_find->id) || ((lun->flags & ISCSI_SCSI_LUN_FLAGS_REMOVED) != 0) )
- return 0;
-
- lun_find->lun = lun;
-
- return -1;
-}
-
-/**
* @brief Searches an iSCSI LUN by LUN identifier.
*
* This function searches for an iSCSI LUN by
@@ -6755,11 +6816,14 @@ int iscsi_device_find_lun_callback(uint8_t *key, const size_t key_size, uint8_t
*/
iscsi_scsi_lun *iscsi_device_find_lun(iscsi_device *device, const int lun_id)
{
- iscsi_device_find_lun_id lun_find = {NULL, lun_id};
+ const uint64_t hash_key = (uint64_t) lun_id;
+ iscsi_scsi_lun *lun;
+ const int rc = iscsi_hashmap_get( device->luns, (uint8_t *) &hash_key, sizeof(hash_key), (uint8_t **) &lun );
- iscsi_hashmap_iterate( device->luns, iscsi_device_find_lun_callback, (uint8_t *) &lun_find );
+ if ( (rc < 0) || ((lun->flags & ISCSI_SCSI_LUN_FLAGS_REMOVED) != 0) )
+ return NULL;
- return lun_find.lun;
+ return lun;
}
/**
@@ -6902,7 +6966,7 @@ static int iscsi_target_node_check_flags(const int flags, const int32_t chap_gro
*/
int iscsi_target_node_create_callback(uint8_t *key, const size_t key_size, uint8_t *value, uint8_t *user_data)
{
- iscsi_target_node *target = (iscsi_target_node *) user_data;
+ iscsi_target_node *target = (iscsi_target_node *) user_data;
iscsi_portal_group *portal_group = (iscsi_portal_group *) value;
uint8_t *port_name = iscsi_sprintf_alloc( "%s,t,0x%4.4" PRIx64, target->device->name, portal_group->tag );
@@ -6922,7 +6986,7 @@ int iscsi_target_node_create_callback(uint8_t *key, const size_t key_size, uint8
* may NOT be NULL, so be careful.
* @param[in] alias Pointer to alias of IQN name.
* @param[in] index Target node index number.
- * @param[in] luns Number of LUNs for underlying SCSI device.
+ * @param[in] lun_id LUN identifier to associate with underlying SCSI device.
* @param[in] queue_depth Maximum queue depth.
* @param[in] flags Flags for this target node.
* @param[in] chap_group CHAP group to associate this node with.
@@ -6931,7 +6995,7 @@ int iscsi_target_node_create_callback(uint8_t *key, const size_t key_size, uint8
* @return Pointer to iSCSI target node on successful
* operation or NULL in case of an error.
*/
-iscsi_target_node *iscsi_target_node_create(uint8_t *name, const uint8_t *alias, const int index, const uint luns, const uint queue_depth, const int flags, const int32_t chap_group, const int header_digest, const int data_digest)
+iscsi_target_node *iscsi_target_node_create(uint8_t *name, const uint8_t *alias, const int index, const int lun_id, const uint queue_depth, const int flags, const int32_t chap_group, const int header_digest, const int data_digest)
{
if ( (name == NULL) || (iscsi_target_node_check_name( name ) < 0) || (iscsi_target_node_check_flags( flags, chap_group ) < 0) )
return NULL;
@@ -6979,14 +7043,7 @@ iscsi_target_node *iscsi_target_node_create(uint8_t *name, const uint8_t *alias,
dnbd3_image_t *image = iscsi_target_node_image_get( name );
- if ( image == NULL )
- return NULL;
-
- target->device = iscsi_device_create( (uint8_t *) image->name, luns, ISCSI_TRANSPORT_ID_PROTOCOL_ID_ISCSI );
-
- if ( target->device == NULL ) {
- logadd( LOG_ERROR, "iscsi_target_node_create: Out of memory allocating iSCSI target device" );
-
+ if ( image == NULL ) {
if ( target->alias != NULL )
free( target->alias );
@@ -6996,10 +7053,123 @@ iscsi_target_node *iscsi_target_node_create(uint8_t *name, const uint8_t *alias,
return NULL;
}
- const int rc = iscsi_hashmap_iterate( iscsi_globvec->portal_groups, iscsi_target_node_create_callback, (uint8_t *) target );
+ const uint key_len = (uint) (strlen( (char *) image->name ) + 1U);
+ 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 );
+ int rc = iscsi_hashmap_get( iscsi_globvec->devices, hash_key, key_len, (uint8_t **) &device );
+
+ if ( device != NULL ) {
+ iscsi_scsi_lun *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_create: Out of memory allocating iSCSI device LUN hash map" );
+
+ 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;
+ }
+
+ const uint64_t lun_hash = lun_id;
+ uint8_t *lun_hash_key = iscsi_hashmap_key_create( (uint8_t *) &lun_hash, sizeof(lun_hash) );
+
+ if ( lun_hash_key == NULL ) {
+ logadd( LOG_ERROR, "iscsi_target_node_create: Out of memory allocating iSCSI device LUN hash map" );
+
+ pthread_rwlock_unlock( &iscsi_globvec->devices_rwlock );
+ iscsi_scsi_lun_destroy( lun );
+ iscsi_hashmap_key_destroy( hash_key );
+
+ if ( target->alias != NULL )
+ free( target->alias );
+
+ free( target->name );
+ free( target );
+
+ return NULL;
+ }
+
+ const int rc = iscsi_hashmap_put( device->luns, lun_hash_key, sizeof(lun_hash), (uint8_t *) lun );
+
+ if ( rc < 0 ) {
+ pthread_rwlock_unlock( &iscsi_globvec->devices_rwlock );
+ iscsi_hashmap_key_destroy( lun_hash_key );
+ iscsi_scsi_lun_destroy( lun );
+ iscsi_hashmap_key_destroy( hash_key );
+
+ if ( target->alias != NULL )
+ free( target->alias );
+
+ free( target->name );
+ free( target );
+
+ return NULL;
+ }
+ }
+
+ device->ref++;
+
+ iscsi_hashmap_key_destroy( hash_key );
+ } 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;
+ }
+ }
+
+ pthread_rwlock_unlock( &iscsi_globvec->devices_rwlock );
+
+ target->device = device;
+
+ pthread_rwlock_rdlock( &iscsi_globvec->portal_groups_rwlock );
+ rc = iscsi_hashmap_iterate( iscsi_globvec->portal_groups, iscsi_target_node_create_callback, (uint8_t *) target );
+ pthread_rwlock_unlock( &iscsi_globvec->portal_groups_rwlock );
if ( rc < 0 ) {
- iscsi_device_destroy( target->device );
+ pthread_rwlock_wrlock( &iscsi_globvec->devices_rwlock );
+ iscsi_hashmap_remove( iscsi_globvec->devices, hash_key, key_len );
+ pthread_rwlock_unlock( &iscsi_globvec->devices_rwlock );
+ iscsi_device_destroy( device );
+ iscsi_hashmap_key_destroy( hash_key );
if ( target->alias != NULL )
free( target->alias );
@@ -7082,38 +7252,6 @@ int32_t iscsi_target_node_send(iscsi_connection *conn, const uint8_t *dst_iqn, c
}
/**
- * @brief Finds an iSCSI target node by case insensitive name search.
- *
- * Callback function for each element while iterating
- * through the iSCSI target nodes.
- *
- * @param[in] key Pointer to zero padded key. NULL is
- * an invalid pointer here, so be careful.
- * @param[in] key_size Number of bytes for the key.
- * @param[in] value Value of the key, NULL creates an
- * empty key assignment.
- * @param[in,out] user_data Pointer to a data structure
- * containing the iSCSI target node and the name to be
- * searched for and may NOT be NULL, so be careful.
- * @retval -1 The target node has been found and stored
- * in the result structure. Therefore, no further
- * 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)
-{
- iscsi_target_node_find_name *target_find = (iscsi_target_node_find_name *) user_data;
- iscsi_target_node *target = (iscsi_target_node *) value;
-
- if ( strcasecmp( (char *) target->name, (char *) target_find->name ) != 0 )
- return 0;
-
- target_find->target = target;
-
- return -1;
-}
-
-/**
* @brief Calculates the WWN using 64-bit IEEE Extended NAA for a name.
*
* @param[in] name Pointer to string containing the
@@ -7219,6 +7357,38 @@ dnbd3_image_t *iscsi_target_node_image_get(uint8_t *iqn)
}
/**
+ * @brief Finds an iSCSI target node by case insensitive name search.
+ *
+ * Callback function for each element while iterating
+ * through the iSCSI target nodes.
+ *
+ * @param[in] key Pointer to zero padded key. NULL is
+ * an invalid pointer here, so be careful.
+ * @param[in] key_size Number of bytes for the key.
+ * @param[in] value Value of the key, NULL creates an
+ * empty key assignment.
+ * @param[in,out] user_data Pointer to a data structure
+ * containing the iSCSI target node and the name to be
+ * searched for and may NOT be NULL, so be careful.
+ * @retval -1 The target node has been found and stored
+ * in the result structure. Therefore, no further
+ * 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)
+{
+ iscsi_target_node_find_name *target_find = (iscsi_target_node_find_name *) user_data;
+ iscsi_target_node *target = (iscsi_target_node *) value;
+
+ if ( strcasecmp( (char *) target->name, (char *) target_find->name ) != 0 )
+ return 0;
+
+ target_find->target = target;
+
+ return -1;
+}
+
+/**
* @brief Searches an iSCSI target node by name using case insensitive search.
*
* This function searches for an iSCSI target node
@@ -7237,44 +7407,56 @@ 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 );
iscsi_hashmap_iterate( iscsi_globvec->target_nodes, iscsi_target_node_find_callback, (uint8_t *) &target_find );
- if ( target_find.target == NULL ) {
+ iscsi_target_node *target = target_find.target;
+
+ if ( target == NULL ) {
dnbd3_image_t *image = iscsi_target_node_image_get( target_name );
- if ( image == NULL )
+ if ( image == NULL ) {
+ pthread_rwlock_unlock( &iscsi_globvec->target_nodes_rwlock );
+
return NULL;
+ }
- target_find.target = iscsi_target_node_create( target_name, NULL, 0, 8U, 16U, 0, 0L, 0, 0 );
+ target = iscsi_target_node_create( target_name, NULL, 0, image->rid, 16U, 0, 0L, 0, 0 );
- if ( target_find.target == NULL ) {
+ if ( target == NULL ) {
logadd( LOG_ERROR, "iscsi_target_node_find: Out of memory while allocating iSCSI target node" );
+ pthread_rwlock_unlock( &iscsi_globvec->target_nodes_rwlock );
+
return NULL;
}
const uint key_len = (uint) (strlen( (char *) target_name ) + 1U);
- uint8_t *hash_key = iscsi_hashmap_key_create( target_name, key_len );
+ 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" );
- iscsi_target_node_destroy( target_find.target );
+ 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, sizeof(key_len), (uint8_t *) target_find.target );
+ int rc = iscsi_hashmap_put( iscsi_globvec->target_nodes, (uint8_t *) hash_key, sizeof(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_find.target );
+ iscsi_target_node_destroy( target );
return NULL;
}
}
- return target_find.target;
+ pthread_rwlock_unlock( &iscsi_globvec->target_nodes_rwlock );
+
+ return target;
}
/**
@@ -9034,8 +9216,13 @@ static iscsi_session *iscsi_session_get_by_tsih(const uint16_t tsih)
const uint64_t hash_key = tsih;
iscsi_session *session;
+
+ pthread_rwlock_rdlock( &iscsi_globvec->sessions_rwlock );
+
int rc = iscsi_hashmap_get( iscsi_globvec->sessions, (uint8_t *) &hash_key, sizeof(hash_key), (uint8_t **) &session );
+ pthread_rwlock_unlock( &iscsi_globvec->sessions_rwlock );
+
return (rc == 0) ? session : NULL;
}
@@ -9050,12 +9237,11 @@ static iscsi_session *iscsi_session_get_by_tsih(const uint16_t tsih)
* @param[in] init_port_name Pointer to initiator port name,
* may NOT be NULL, so take caution.
* @param[in] tsih Target Session Identifying Handle (TSIH).
- * @param[in] cid Connection ID (CID).
* @return Upper 8 bits of contain status class, lower 8
* bits status detail. All 16 bits set to zero
* indicate success.
*/
-static uint16_t iscsi_session_append(iscsi_connection *conn, const uint8_t *init_port_name, const uint16_t tsih, const uint16_t cid)
+static uint16_t iscsi_session_append(iscsi_connection *conn, const uint8_t *init_port_name, const uint16_t tsih)
{
iscsi_session *session = iscsi_session_get_by_tsih( tsih );
@@ -9096,7 +9282,7 @@ static int iscsi_connection_login_check_session(iscsi_connection *conn, iscsi_pd
int rc = 0;
if ( login_response_pkt->tsih != 0U ) {
- rc = iscsi_session_append( conn, init_port_name, iscsi_get_be16(login_response_pkt->tsih), (uint16_t) cid );
+ rc = iscsi_session_append( conn, init_port_name, iscsi_get_be16(login_response_pkt->tsih) );
if ( rc != 0 ) {
login_response_pkt->status_class = (uint8_t) (rc >> 8U);
@@ -9667,23 +9853,27 @@ void iscsi_connection_pdu_write(iscsi_connection *conn, iscsi_pdu *pdu, iscsi_co
uint64_t *exec_data = malloc( 64 );
- exec_data[2] = (uint64_t *) iscsi_connection_pdu_write_complete;
+ exec_data[2] = (uint64_t) iscsi_connection_pdu_write_complete;
exec_data[3] = 2ULL;
- exec_data[4] = pdu;
+ exec_data[4] = (uint64_t) pdu;
exec_data[5] = (rc == (int32_t) len) ? 0 : -1;
+ pthread_mutex_lock( &iscsi_globvec->exec_queue_mutex );
iscsi_list_enqueue( &iscsi_globvec->exec_queue, (iscsi_node *) exec_data );
+ pthread_mutex_unlock( &iscsi_globvec->exec_queue_mutex );
if ( callback == NULL )
return;
exec_data = malloc( 64 );
- exec_data[2] = (uint64_t *) callback;
+ exec_data[2] = (uint64_t) callback;
exec_data[3] = 1ULL;
- exec_data[4] = user_data;
+ exec_data[4] = (uint64_t) user_data;
+ pthread_mutex_lock( &iscsi_globvec->exec_queue_mutex );
iscsi_list_enqueue( &iscsi_globvec->exec_queue, (iscsi_node *) exec_data );
+ pthread_mutex_unlock( &iscsi_globvec->exec_queue_mutex );
// TODO: End remove after I/O async implementation
// iscsi_connection_pdu_write_complete( (uint8_t *) pdu, (rc == (int32_t) len) ? 0 : -1 );
@@ -9964,7 +10154,7 @@ static int iscsi_connection_pdu_header_handle_scsi_cmd(iscsi_connection *conn, i
iscsi_scsi_cmd_packet *stat_scsi_cmd_pkt = (iscsi_scsi_cmd_packet *) pdu->bhs_pkt;
uint64_t stat_opcode = (uint64_t) stat_scsi_cmd_pkt->scsi_cdb.opcode;
uint64_t *stat_value = NULL;
- int stat_rc = iscsi_hashmap_get( conn->stat_scsi_opcodes, (uint8_t *) &stat_opcode, sizeof(stat_opcode), (uint8_t *) &stat_value );
+ int stat_rc = iscsi_hashmap_get( conn->stat_scsi_opcodes, (uint8_t *) &stat_opcode, sizeof(stat_opcode), (uint8_t **) &stat_value );
if ( stat_value == NULL ) {
stat_value = malloc( sizeof(uint64_t) );
@@ -10020,6 +10210,7 @@ static int iscsi_connection_pdu_header_handle_scsi_cmd(iscsi_connection *conn, i
const uint64_t lun = iscsi_get_be64(scsi_cmd_pkt->lun);
const int lun_id = iscsi_scsi_lun_get_from_iscsi( lun );
+ task->lun_id = lun_id;
task->scsi_task.lun = iscsi_device_find_lun( conn->device, lun_id );
if ( task->scsi_task.lun == NULL ) {
@@ -11089,9 +11280,13 @@ static int iscsi_connection_login_set_info(iscsi_connection *conn, iscsi_pdu *lo
conn->stat_sn = iscsi_get_be32(login_response_pkt->stat_sn);
conn->session->isid = isid;
+ pthread_rwlock_wrlock( &iscsi_globvec->sessions_rwlock );
iscsi_hashmap_key_create_id( iscsi_globvec->sessions, &conn->session->tsih );
+
int rc = iscsi_hashmap_put( iscsi_globvec->sessions, (uint8_t *) &conn->session->tsih, sizeof(conn->session->tsih), (uint8_t *) conn->session );
+ pthread_rwlock_unlock( &iscsi_globvec->sessions_rwlock );
+
if ( rc < 0 ) {
iscsi_session_destroy( conn->session );
conn->session = NULL;
@@ -11964,7 +12159,7 @@ static int iscsi_connection_pdu_read(iscsi_connection *conn)
uint64_t stat_opcode = (uint64_t) ISCSI_GET_OPCODE(bhs_pkt->opcode);
uint64_t *stat_value = NULL;
- int stat_rc = iscsi_hashmap_get( conn->stat_iscsi_opcodes, (uint8_t *) &stat_opcode, sizeof(stat_opcode), (uint8_t *) &stat_value );
+ int stat_rc = iscsi_hashmap_get( conn->stat_iscsi_opcodes, (uint8_t *) &stat_opcode, sizeof(stat_opcode), (uint8_t **) &stat_value );
if ( stat_value == NULL ) {
stat_value = malloc( sizeof(uint64_t) );
@@ -12103,29 +12298,32 @@ int iscsi_connection_pdu_handle(iscsi_connection *conn)
int i;
for ( i = 0; i < ISCSI_PDU_HANDLE_COUNT; i++ ) {
- pthread_rwlock_wrlock( &iscsi_globvec_rwlock );
-
- if ( iscsi_globvec == NULL ) {
- pthread_rwlock_unlock( &iscsi_globvec_rwlock );
-
- return ISCSI_CONNECT_PDU_READ_ERR_FATAL;
- }
-
// TODO: Remove after I/O sync implementation
+ pthread_mutex_lock( &iscsi_globvec->exec_queue_mutex );
iscsi_list_create( &iscsi_globvec->exec_queue );
+ pthread_mutex_unlock( &iscsi_globvec->exec_queue_mutex );
const int rc = iscsi_connection_pdu_read( conn );
// TODO: Start: Remove after I/O sync implementation
- while ( !iscsi_list_empty( &iscsi_globvec->exec_queue ) ) {
+ for ( ;; ) {
+ pthread_mutex_lock( &iscsi_globvec->exec_queue_mutex );
+
+ if ( iscsi_list_empty( &iscsi_globvec->exec_queue ) ) {
+ pthread_mutex_unlock( &iscsi_globvec->exec_queue_mutex );
+
+ break;
+ }
+
uint64_t *exec_data = (uint64_t *) iscsi_list_peek( &iscsi_globvec->exec_queue );
iscsi_list_remove( (iscsi_node *) exec_data );
+ pthread_mutex_unlock( &iscsi_globvec->exec_queue_mutex );
if ( exec_data[3] == 1ULL ) {
iscsi_scsi_task_xfer_complete_callback callback = (iscsi_scsi_task_xfer_complete_callback) exec_data[2];
- callback( (uint8_t *) exec_data[4] );
+ callback( (iscsi_scsi_task *) exec_data[4] );
} else if ( exec_data[3] == 2ULL ) {
iscsi_connection_write_complete_callback callback = (iscsi_connection_write_complete_callback) exec_data[2];
callback( (uint8_t *) exec_data[4], (int) exec_data[5] );
@@ -12139,8 +12337,6 @@ int iscsi_connection_pdu_handle(iscsi_connection *conn)
// TODO: End: Remove after I/O sync implementation
- pthread_rwlock_unlock( &iscsi_globvec_rwlock );
-
if ( rc == ISCSI_CONNECT_PDU_READ_OK )
break;
else if ( rc == ISCSI_CONNECT_PDU_READ_ERR_FATAL )
@@ -12172,13 +12368,16 @@ 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
- pthread_rwlock_wrlock( &iscsi_globvec_rwlock );
+ pthread_rwlock_rdlock( &iscsi_globvec_rwlock );
if ( iscsi_globvec == NULL )
return;
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 );
if ( portal_group == NULL ) {
@@ -12187,6 +12386,7 @@ void iscsi_connection_handle(dnbd3_client_t *client, const dnbd3_request_t *requ
if ( hash_key == NULL ) {
logadd( LOG_ERROR, "iscsi_connection_handle: Out of memory while allocating iSCSI portal group" );
+ pthread_rwlock_unlock( &iscsi_globvec->portal_groups_rwlock );
pthread_rwlock_unlock( &iscsi_globvec_rwlock );
return;
@@ -12199,6 +12399,7 @@ 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 portal group" );
iscsi_hashmap_key_destroy( (uint8_t *) hash_key );
+ pthread_rwlock_unlock( &iscsi_globvec->portal_groups_rwlock );
pthread_rwlock_unlock( &iscsi_globvec_rwlock );
return;
@@ -12212,12 +12413,14 @@ void iscsi_connection_handle(dnbd3_client_t *client, const dnbd3_request_t *requ
if ( rc < 0 ) {
iscsi_portal_group_destroy( portal_group );
+ pthread_rwlock_unlock( &iscsi_globvec->portal_groups_rwlock );
pthread_rwlock_unlock( &iscsi_globvec_rwlock );
return;
}
}
+ pthread_rwlock_unlock( &iscsi_globvec->portal_groups_rwlock );
host_to_string( &client->host, client->hostName, HOSTNAMELEN );
const uint8_t *port = memchr( client->hostName, ':', HOSTNAMELEN );
@@ -12267,6 +12470,8 @@ void iscsi_connection_handle(dnbd3_client_t *client, const dnbd3_request_t *requ
}
iscsi_portal *portal = NULL;
+
+ pthread_rwlock_wrlock( &iscsi_globvec->portal_groups_rwlock );
rc = iscsi_hashmap_get( portal_group->portals, (uint8_t *) hash_key, key_len, (uint8_t **) &portal );
if ( portal == NULL ) {
@@ -12280,7 +12485,8 @@ void iscsi_connection_handle(dnbd3_client_t *client, const dnbd3_request_t *requ
if ( portal == NULL ) {
logadd( LOG_ERROR, "iscsi_connection_handle: Out of memory while allocating iSCSI portal" );
- iscsi_hashmap_key_destroy( hash_key );
+ pthread_rwlock_unlock( &iscsi_globvec->portal_groups_rwlock );
+ iscsi_hashmap_key_destroy( (uint8_t *) hash_key );
free( host );
pthread_rwlock_unlock( &iscsi_globvec_rwlock );
@@ -12290,8 +12496,9 @@ void iscsi_connection_handle(dnbd3_client_t *client, const dnbd3_request_t *requ
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( hash_key );
+ iscsi_hashmap_key_destroy( (uint8_t *) hash_key );
free( host );
pthread_rwlock_unlock( &iscsi_globvec_rwlock );
@@ -12299,7 +12506,7 @@ void iscsi_connection_handle(dnbd3_client_t *client, const dnbd3_request_t *requ
}
}
- iscsi_hashmap_key_destroy( hash_key );
+ iscsi_hashmap_key_destroy( (uint8_t *) hash_key );
free( host );
iscsi_connection *conn = iscsi_connection_create( portal, client->sock );
@@ -12314,11 +12521,15 @@ void iscsi_connection_handle(dnbd3_client_t *client, const dnbd3_request_t *requ
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 );
pthread_rwlock_unlock( &iscsi_globvec_rwlock );
@@ -12328,30 +12539,28 @@ void iscsi_connection_handle(dnbd3_client_t *client, const dnbd3_request_t *requ
memcpy( conn->pdu_processing->bhs_pkt, request, len );
conn->pdu_processing->bhs_pos = len;
- conn->pdu_recv_state = ISCSI_CONNECT_PDU_RECV_STATE_WAIT_PDU_HDR;
+ conn->pdu_recv_state = ISCSI_CONNECT_PDU_RECV_STATE_WAIT_PDU_HDR;
- pthread_rwlock_unlock( &iscsi_globvec_rwlock );
+ logadd( LOG_INFO, "" );
+ logadd( LOG_INFO, "iSCSI connection opened for device %s from initiator %s using port %s and portal %s:%s", (conn->device != NULL ? (char *) conn->device->name : "(null)"), (char *) conn->init_name, ((conn->init_port != NULL) ? (char *) conn->init_port->name : "(null)"), (char *) portal->host, (char *) portal->port );
while ( iscsi_connection_pdu_handle( conn ) >= ISCSI_CONNECT_PDU_READ_OK ) {
}
- pthread_rwlock_wrlock( &iscsi_globvec_rwlock );
-
- if ( iscsi_globvec == NULL )
- return;
-
iscsi_hashmap_bucket *stat_bucket;
+ logadd( LOG_INFO, "iSCSI connection closed for device %s from initiator %s using port %s and portal %s:%s", (conn->device != NULL ? (char *) conn->device->name : "(null)"), (char *) conn->init_name, ((conn->init_port != NULL) ? (char *) conn->init_port->name : "(null)"), (char *) portal->host, (char *) portal->port );
+
iscsi_list_foreach_node ( &conn->stat_iscsi_opcodes->list, stat_bucket ) {
uint64_t *stat_opcode = (uint64_t *) stat_bucket->value;
- logadd( LOG_INFO, "iSCSI opcode usage statistics for device %s from initiator %s using port %s and portal %s:%s: Opcode 0x%02" PRIX64 " has been received %" PRIu64 " times until connection drop.", (conn->device != NULL ? conn->device->name : "(null)"), conn->init_name, ((conn->init_port != NULL) ? conn->init_port->name : "(null)"), portal->host, portal->port, *(uint64_t *) stat_bucket->key, *stat_opcode );
+ logadd( LOG_INFO, "iSCSI opcode usage statistics for device %s from initiator %s using port %s and portal %s:%s: Opcode 0x%02" PRIX64 " has been received %" PRIu64 " times until connection drop.", (conn->device != NULL ? (char *) conn->device->name : "(null)"), (char *) conn->init_name, ((conn->init_port != NULL) ? (char *) conn->init_port->name : "(null)"), (char *) portal->host, (char *) portal->port, *(uint64_t *) stat_bucket->key, *stat_opcode );
}
iscsi_list_foreach_node ( &conn->stat_scsi_opcodes->list, stat_bucket ) {
uint64_t *stat_opcode = (uint64_t *) stat_bucket->value;
- logadd( LOG_INFO, "iSCSI SCSI CDB opcode usage statistics for device %s from initiator %s using port %s and portal %s:%s: SCSI CDB opcode 0x%02" PRIX64 " has been received %" PRIu64 " times until connection drop.", (conn->device != NULL ? conn->device->name : "(null)"), conn->init_name, ((conn->init_port != NULL) ? conn->init_port->name : "(null)"), portal->host, portal->port, *(uint64_t *) stat_bucket->key, *stat_opcode );
+ logadd( LOG_INFO, "iSCSI SCSI CDB opcode usage statistics for device %s from initiator %s using port %s and portal %s:%s: SCSI CDB opcode 0x%02" PRIX64 " has been received %" PRIu64 " times until connection drop.", (conn->device != NULL ? (char *) conn->device->name : "(null)"), (char *) conn->init_name, ((conn->init_port != NULL) ? (char *) conn->init_port->name : "(null)"), (char *) portal->host, (char *) portal->port, *(uint64_t *) stat_bucket->key, *stat_opcode );
}
iscsi_session *session = conn->session;
@@ -12369,8 +12578,10 @@ void iscsi_connection_handle(dnbd3_client_t *client, const dnbd3_request_t *requ
iscsi_connection_destroy( conn );
+ pthread_rwlock_wrlock( &iscsi_globvec->portal_groups_rwlock );
iscsi_portal_group_del_portal( portal_group, portal );
iscsi_portal_destroy( portal );
+ pthread_rwlock_unlock( &iscsi_globvec->portal_groups_rwlock );
pthread_rwlock_unlock( &iscsi_globvec_rwlock );
}
diff --git a/src/server/iscsi.h b/src/server/iscsi.h
index 33346af..b45772f 100644
--- a/src/server/iscsi.h
+++ b/src/server/iscsi.h
@@ -9917,15 +9917,27 @@ typedef struct iscsi_globals {
/// Hash map containing all iSCSI devices.
iscsi_hashmap *devices;
+ /// Read/write lock for hash map containing all iSCSI devices. MUST be initialized with iscsi_create before any iSCSI functions are used.
+ pthread_rwlock_t devices_rwlock;
+
/// Hash map containing all registered iSCSI portal groups.
iscsi_hashmap *portal_groups;
+ /// Read/write lock for hash map containing all iSCSI portal_groups. MUST be initialized with iscsi_create before any iSCSI functions are used.
+ pthread_rwlock_t portal_groups_rwlock;
+
/// iSCSI target nodes.
iscsi_hashmap *target_nodes;
+ /// Read/write lock for hash map containing all iSCSI target nodes. MUST be initialized with iscsi_create before any iSCSI functions are used.
+ pthread_rwlock_t target_nodes_rwlock;
+
/// Hash map containing all iSCSI sessions.
iscsi_hashmap *sessions;
+ /// Read/write lock for hash map containing all iSCSI sessions. MUST be initialized with iscsi_create before any iSCSI functions are used.
+ pthread_rwlock_t sessions_rwlock;
+
/// Hash map containing session key and value pair types and allowed values or ranges.
iscsi_hashmap *session_key_value_pairs;
@@ -9935,6 +9947,9 @@ typedef struct iscsi_globals {
// TODO: Remove after async I/O implementation
iscsi_list exec_queue;
+ // TODO: Remove after async I/O implementation
+ pthread_mutex_t exec_queue_mutex;
+
/// Global flags.
int flags;
@@ -10524,7 +10539,7 @@ int iscsi_scsi_task_status_copy(iscsi_scsi_task *dst_scsi_task, const iscsi_scsi
void iscsi_scsi_task_lun_process_none(iscsi_scsi_task *scsi_task); // Processes a iSCSI SCSI task with no LUN identifier
void iscsi_scsi_task_lun_process_abort(iscsi_scsi_task *scsi_task); // Processes a iSCSI SCSI aborted task
-iscsi_scsi_lun *iscsi_scsi_lun_create(const uint id); // Allocates and initializes an iSCSI LUN structure for linkage with a DNBD3 image
+iscsi_scsi_lun *iscsi_scsi_lun_create(const int lun_id); // Allocates and initializes an iSCSI LUN structure for linkage with a DNBD3 image
void iscsi_scsi_lun_destroy(iscsi_scsi_lun *lun); // Deallocates all resources acquired by iscsi_scsi_lun_create
uint64_t iscsi_scsi_lun_get_from_scsi(const int lun_id); // Converts an internal representation of a LUN identifier to an iSCSI LUN required for packet data
@@ -10682,26 +10697,14 @@ typedef struct iscsi_device {
/// Flags.
int flags;
+ /// Reference counter.
+ uint32_t ref;
+
/// Protocol identifier.
uint8_t protocol_id;
} iscsi_device;
-/**
- * @brief iSCSI device search by LUN identifier.
- *
- * This structure is used by iterating through
- * all iSCSI LUNs finding by LUN identifier.
- */
-typedef struct iscsi_device_find_lun_id {
- /// Found iSCSI LUN is stored here, should be initialized to NULL.
- iscsi_scsi_lun *lun;
-
- /// The LUN identifier to search for (always MUST be between 0 and 7).
- int id;
-} iscsi_device_find_lun_id;
-
-
/// iSCSI target node WWN identifier prefix string.
#define ISCSI_TARGET_NODE_WWN_NAME_PREFIX "wwn-0x"
@@ -11363,11 +11366,10 @@ void iscsi_task_xfer_complete_process_other(iscsi_connection *conn, iscsi_task *
void iscsi_task_response(iscsi_connection *conn, iscsi_task *task); // Creates, initializes and sends an iSCSI task reponse PDU.
-iscsi_device *iscsi_device_create(const uint8_t *name, const uint luns, const uint8_t protocol_id); // Creates and initializes an iSCSI device with a maximum number of LUNs
+iscsi_device *iscsi_device_create(const uint8_t *name, const int lun_id, const uint8_t protocol_id); // Creates and initializes an iSCSI device with a maximum number of LUNs
void iscsi_device_destroy(iscsi_device *device); // Deallocates all resources acquired by iscsi_device_create
iscsi_port *iscsi_device_find_port_by_portal_group_tag(const iscsi_device *device, const uint64_t id); // Gets an iSCSI device being in use by portal group identifier
-int iscsi_device_find_lun_callback(uint8_t *key, const size_t key_size, uint8_t *value, uint8_t *user_data); // Finds an iSCSI LUN by LUN identifier
iscsi_scsi_lun *iscsi_device_find_lun(iscsi_device *device, const int lun_id); // Searches an iSCSI LUN by LUN identifier
int iscsi_device_port_add(iscsi_device *device, const uint8_t *name, const uint64_t id); // Creates, initializes and adds an iSCSI target port to an iSCSI device
@@ -11375,7 +11377,7 @@ int iscsi_device_port_add(iscsi_device *device, const uint8_t *name, const uint6
void iscsi_device_scsi_task_queue(iscsi_device *device, iscsi_scsi_task *scsi_task); // Enqueues an iSCSI SCSI task to the first LUN of an iSCSI device
int iscsi_target_node_create_callback(uint8_t *key, const size_t key_size, uint8_t *value, uint8_t *user_data); // Creates, initializes and adds a portal group to an iSCSI target node
-iscsi_target_node *iscsi_target_node_create(uint8_t *name, const uint8_t *alias, const int index, const uint luns, const uint queue_depth, const int flags, const int32_t chap_group, const int header_digest, const int data_digest); // Creates and initializes an iSCSI target node
+iscsi_target_node *iscsi_target_node_create(uint8_t *name, const uint8_t *alias, const int index, const int lun_id, const uint queue_depth, const int flags, const int32_t chap_group, const int header_digest, const int data_digest); // Creates and initializes an iSCSI target node
void iscsi_target_node_destroy(iscsi_target_node *target); // Deallocates all resources acquired by iscsi_target_node_create
int32_t iscsi_target_node_send(iscsi_connection *conn, const uint8_t *dst_iqn, const uint8_t *src_iqn, uint8_t *buf, const uint32_t pos, const uint32_t len); // Sends a buffer from a source iSCSI IQN to target iSCSI IQNs