diff options
| author | Sebastian Vater | 2025-10-06 15:42:16 +0200 |
|---|---|---|
| committer | Sebastian Vater | 2025-10-06 15:42:16 +0200 |
| commit | 539c05839d6126f592fd06e364c75cb9ac2da96f (patch) | |
| tree | f88194f9153c7f539d791e3f1f807107a2ffebb0 /src | |
| parent | [SERVER] iscsi: Implement relaying requests to uplink servers (diff) | |
| download | dnbd3-539c05839d6126f592fd06e364c75cb9ac2da96f.tar.gz dnbd3-539c05839d6126f592fd06e364c75cb9ac2da96f.tar.xz dnbd3-539c05839d6126f592fd06e364c75cb9ac2da96f.zip | |
Moved uplink mutex / condition init and destroy to task creation and destruction functions. Finally, some small code refactoring.
Diffstat (limited to 'src')
| -rw-r--r-- | src/server/iscsi.c | 87 | ||||
| -rw-r--r-- | src/server/iscsi.h | 12 |
2 files changed, 62 insertions, 37 deletions
diff --git a/src/server/iscsi.c b/src/server/iscsi.c index c634013..afb1e6c 100644 --- a/src/server/iscsi.c +++ b/src/server/iscsi.c @@ -1312,7 +1312,7 @@ 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_RELAXED; + globvec->target_name_check = ISCSI_GLOBALS_TARGET_NAME_CHECK_FULL; globvec->max_sessions = 0U; globvec->header_digest = 0; globvec->data_digest = 0; @@ -2871,6 +2871,20 @@ iscsi_task *iscsi_task_create(iscsi_connection *conn, iscsi_task *parent, iscsi_ iscsi_scsi_task_create( &task->scsi_task, callback, iscsi_task_destroy_callback ); + if ( pthread_mutex_init( &task->scsi_task.uplink_mutex, NULL ) != 0 ) { + logadd( LOG_ERROR, "iscsi_task_create: Error while initializing DNBD3 uplink mutex for iSCSI SCSI task" ); + + return NULL; + } + + if ( pthread_cond_init( &task->scsi_task.uplink_cond, NULL ) != 0 ) { + logadd( LOG_ERROR, "iscsi_task_create: Error while initializing DNBD3 uplink condition for iSCSI SCSI task" ); + + pthread_mutex_destroy( &task->scsi_task.uplink_mutex ); + + return NULL; + } + if ( parent != NULL ) { parent->scsi_task.ref++; @@ -2917,6 +2931,9 @@ void iscsi_task_destroy_callback(iscsi_scsi_task *scsi_task) task->parent = NULL; } + pthread_cond_destroy( &task->scsi_task.uplink_cond ); + pthread_mutex_destroy( &task->scsi_task.uplink_mutex ); + if ( task->pdu != NULL ) { iscsi_connection_pdu_destroy( task->pdu ); @@ -3852,13 +3869,13 @@ void iscsi_scsi_task_create(iscsi_scsi_task *scsi_task, iscsi_scsi_task_xfer_com scsi_task->target_port = NULL; scsi_task->init_port = NULL; scsi_task->cdb = NULL; + scsi_task->sense_data = NULL; scsi_task->xfer_complete_callback = xfer_complete_callback; scsi_task->destroy_callback = destroy_callback; scsi_task->io_complete_callback = NULL; scsi_task->io_wait.image = NULL; scsi_task->io_wait.callback = NULL; scsi_task->io_wait.user_data = NULL; - scsi_task->sense_data = NULL; scsi_task->buf = NULL; scsi_task->pos = 0UL; scsi_task->len = 0UL; @@ -5273,20 +5290,28 @@ static uint64_t iscsi_scsi_emu_blocks_to_bytes(uint64_t *offset_bytes, const uin /** * @brief Called when data requested via an uplink server has arrived. * - * @param[in] data related scsi_task - * @param[in] handle pointer to destination buffer, as passed to iscsi_scsi_emu_io_block_read() - * @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 + * This function is used to retrieve + * block data which is NOT locally + * available. + * + * @param[in] data Pointer to related scsi_task. May NOT + * be NULL, so be careful. + * @param[in] handle Pointer to destination buffer, as passed to + * iscsi_scsi_emu_io_block_read(). + * @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. */ static void iscsi_uplink_callback(void *data, uint64_t handle, uint64_t start UNUSED, uint32_t length, const char *buffer) { - iscsi_scsi_task *scsi_task = (iscsi_scsi_task*)data; + iscsi_scsi_task *scsi_task = (iscsi_scsi_task *) data; - memcpy( (uint8_t*)handle, buffer, length ); - pthread_mutex_lock( &scsi_task->up_mutex ); - pthread_cond_signal( &scsi_task->up_cond ); - pthread_mutex_unlock( &scsi_task->up_mutex ); + memcpy( (uint8_t *) handle, buffer, length ); + + pthread_mutex_lock( &scsi_task->uplink_mutex ); + pthread_cond_signal( &scsi_task->uplink_cond ); + pthread_mutex_unlock( &scsi_task->uplink_mutex ); } /** @@ -5325,7 +5350,7 @@ int iscsi_scsi_emu_io_block_read(iscsi_scsi_task *scsi_task, uint8_t *buf, dnbd3 iscsi_connection_exec_queue *exec_queue = (iscsi_connection_exec_queue *) malloc( sizeof(struct iscsi_connection_exec_queue) ); if ( exec_queue == NULL ) { - logadd( LOG_ERROR, "iscsi_scsi_emu_io_block_read: Out of memory while allocating execution queue for async I/O" ); + logadd( LOG_ERROR, "iscsi_scsi_emu_io_block_read: Out of memory while allocating execution queue for I/O read" ); return -ENOMEM; } @@ -5337,38 +5362,38 @@ int iscsi_scsi_emu_io_block_read(iscsi_scsi_task *scsi_task, uint8_t *buf, dnbd3 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 end = (offset_bytes + num_bytes + DNBD3_BLOCK_SIZE - 1) & ~(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 ); ref_put( &cache->reference ); if ( !readFromFile ) { // Not cached, request via uplink - pthread_mutex_init( &scsi_task->up_mutex, NULL ); - pthread_cond_init( &scsi_task->up_cond, NULL ); - pthread_mutex_lock( &scsi_task->up_mutex ); - if ( !uplink_request( image, scsi_task, &iscsi_uplink_callback, (uint64_t)buf, offset_bytes, num_bytes ) ) { - pthread_mutex_unlock( &scsi_task->up_mutex ); - pthread_cond_destroy( &scsi_task->up_cond ); - pthread_mutex_destroy( &scsi_task->up_mutex ); + pthread_mutex_lock( &scsi_task->uplink_mutex ); + + if ( !uplink_request( image, scsi_task, iscsi_uplink_callback, (uint64_t) buf, offset_bytes, num_bytes ) ) { + pthread_mutex_unlock( &scsi_task->uplink_mutex ); + logadd( LOG_DEBUG1, "Could not relay uncached request to upstream proxy for image %s:%d", image->name, image->rid ); + return -EIO; } + // Wait sync (Maybe use pthread_cond_timedwait to detect unavailable uplink instead of hanging...) - pthread_cond_wait( &scsi_task->up_cond, &scsi_task->up_mutex ); - pthread_mutex_unlock( &scsi_task->up_mutex ); - pthread_cond_destroy( &scsi_task->up_cond ); - pthread_mutex_destroy( &scsi_task->up_mutex ); + pthread_cond_wait( &scsi_task->uplink_cond, &scsi_task->uplink_mutex ); + pthread_mutex_unlock( &scsi_task->uplink_mutex ); } } bool success; + if ( readFromFile ) { - const int64_t len = pread( image->readFd, buf, (size_t) num_bytes, offset_bytes ); - success = ((uint64_t) len == num_bytes); + const int64_t len = pread( image->readFd, buf, (size_t) num_bytes, offset_bytes ); + success = ((uint64_t) len == num_bytes); } else { - success = true; + success = true; } exec_queue->data.io.callback = callback; @@ -5527,7 +5552,7 @@ int iscsi_scsi_emu_io_block_write(iscsi_scsi_task *scsi_task, uint8_t *buf, dnbd iscsi_connection_exec_queue *exec_queue = (iscsi_connection_exec_queue *) malloc( sizeof(struct iscsi_connection_exec_queue) ); if ( exec_queue == NULL ) { - logadd( LOG_ERROR, "iscsi_scsi_emu_io_block_read: Out of memory while allocating execution queue for async I/O" ); + logadd( LOG_ERROR, "iscsi_scsi_emu_io_block_read: Out of memory while allocating execution queue for I/O write" ); return -ENOMEM; } @@ -5786,7 +5811,7 @@ static int iscsi_scsi_emu_block_write_same(dnbd3_image_t *image, iscsi_scsi_task * @retval true The DNBD3 image has been initialized * successfully and is readable. * @retval false The DNBD3 image has NOT been - * successfully and is read is not possible. + * successfully and reading is not possible. */ static bool iscsi_scsi_emu_image_init(iscsi_scsi_task *scsi_task, const bool access) { diff --git a/src/server/iscsi.h b/src/server/iscsi.h index 4c284e0..7ce4122 100644 --- a/src/server/iscsi.h +++ b/src/server/iscsi.h @@ -10823,6 +10823,12 @@ typedef struct iscsi_scsi_task { /// I/O task wait. iscsi_scsi_emu_io_wait io_wait; + /// Uplink read mutex for sync + pthread_mutex_t uplink_mutex; + + /// Conditional to signal uplink read complete + pthread_cond_t uplink_cond; + /// Output buffer. uint8_t *buf; @@ -10858,12 +10864,6 @@ typedef struct iscsi_scsi_task { /// Task management response code. uint8_t task_mgmt_response; - - /// Uplink read mutex for sync - pthread_mutex_t up_mutex; - - /// Conditional to signal uplink read complete - pthread_cond_t up_cond; } iscsi_scsi_task; |
