diff options
| author | Simon Rettberg | 2025-10-06 15:00:20 +0200 |
|---|---|---|
| committer | Simon Rettberg | 2025-10-06 15:00:20 +0200 |
| commit | 688b3c61c5d12e68c281f0ade1e986572ffecfb5 (patch) | |
| tree | c2340239933919c3bdc6b2cdfd0c0a5d4e470877 /src/server/iscsi.c | |
| parent | Implemented iSCSI global and SCSI device specific INI file configuration. Als... (diff) | |
| download | dnbd3-688b3c61c5d12e68c281f0ade1e986572ffecfb5.tar.gz dnbd3-688b3c61c5d12e68c281f0ade1e986572ffecfb5.tar.xz dnbd3-688b3c61c5d12e68c281f0ade1e986572ffecfb5.zip | |
[SERVER] iscsi: Implement relaying requests to uplink servers
Diffstat (limited to 'src/server/iscsi.c')
| -rw-r--r-- | src/server/iscsi.c | 66 |
1 files changed, 63 insertions, 3 deletions
diff --git a/src/server/iscsi.c b/src/server/iscsi.c index b44f695..c634013 100644 --- a/src/server/iscsi.c +++ b/src/server/iscsi.c @@ -46,7 +46,9 @@ #include "ini.h" #include "iscsi.h" #include "locks.h" +#include "uplink.h" #include "threadpool.h" +#include "reference.h" /** * @file iscsi.c @@ -1310,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_FULL; + globvec->target_name_check = ISCSI_GLOBALS_TARGET_NAME_CHECK_RELAXED; globvec->max_sessions = 0U; globvec->header_digest = 0; globvec->data_digest = 0; @@ -5269,6 +5271,25 @@ 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 + */ +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; + + 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 ); +} + +/** * @brief Reads a number of blocks from a block offset of a DNBD3 image to a specified buffer. * * This function enqueues the I/O read @@ -5301,8 +5322,6 @@ int iscsi_scsi_emu_io_block_read(iscsi_scsi_task *scsi_task, uint8_t *buf, dnbd3 { uint64_t offset_bytes; const uint64_t num_bytes = iscsi_scsi_emu_blocks_to_bytes( &offset_bytes, offset_blocks, num_blocks, block_size ); - const int64_t len = pread( image->readFd, buf, (size_t) num_bytes, offset_bytes ); - const bool success = ((uint64_t) len == num_bytes); iscsi_connection_exec_queue *exec_queue = (iscsi_connection_exec_queue *) malloc( sizeof(struct iscsi_connection_exec_queue) ); if ( exec_queue == NULL ) { @@ -5311,6 +5330,47 @@ int iscsi_scsi_emu_io_block_read(iscsi_scsi_task *scsi_task, uint8_t *buf, dnbd3 return -ENOMEM; } + dnbd3_cache_map_t *cache = ref_get_cachemap( image ); + bool readFromFile; + + if ( cache == NULL ) { + 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); + 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 ); + 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 ); + } + } + + bool success; + if ( readFromFile ) { + const int64_t len = pread( image->readFd, buf, (size_t) num_bytes, offset_bytes ); + success = ((uint64_t) len == num_bytes); + } else { + success = true; + } + exec_queue->data.io.callback = callback; exec_queue->data.io.image = image; exec_queue->data.io.user_data = user_data; |
