summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--README.md123
-rw-r--r--src/server/iscsi.c111
-rw-r--r--src/server/iscsi.h12
3 files changed, 220 insertions, 26 deletions
diff --git a/README.md b/README.md
index 5fad3ae..a77a64d 100644
--- a/README.md
+++ b/README.md
@@ -67,6 +67,7 @@ apt-get install git \
linux-headers-generic \
libfuse-dev \
libjansson-dev \
+ libcurl4-openssl-dev \
rpm
```
@@ -82,6 +83,7 @@ apt-get install git \
linux-headers-generic \
libfuse-dev \
libjansson-dev \
+ libcurl4-openssl-dev \
afl \
rpm
```
@@ -455,3 +457,124 @@ if (clientA)
if (clientB)
unlock(clientB.lock);
```
+
+
+## iSCSI server
+DNBD3 partially supports the _Internet Small Computer Systems Interface (iSCSI)_ protocol based on [RFC 7143](https://www.rfc-editor.org/rfc/rfc7143) and the [Storage Performance Development Kit (SPDK)](https://spdk.io) implementation.
+
+The iSCSI server can be enabled in the configuration file _server.conf_ by:
+
+```ini
+[dnbd3]
+; Specifies whether the iSCSI server should be initialized, enabled and used upon start of DNBD3 server.
+iSCSIServer=true
+```
+
+
+The valid configuration options of _iscsi.conf_ (see below) can be used in _server.conf_ as well, but _iscsi.conf_ will override any present settings. It is recommended to use _server.conf_ for default settings and _iscsi.conf_ for specific settings.
+
+
+### Configuration file _iscsi.conf_
+The _iscsi.conf_ file is the main configuration file for the iSCSI implementation of _dnbd3-server_. The configuration in the file is specified the INI file format as shown in the following:
+
+```ini
+; Using this file is recommended for actual iSCSI and SCSI emulation settings. This file will be
+; parsed after server.conf and all values here will override the ones in server.conf.
+; Also it is strictly recommended to set SCSI device specific details here.
+; All SCSI device specific details start with a section scsi-device- following a pattern which
+; can either be the full image name or a matching pattern like debian*.iso, e.g.
+; [scsi-device-debian*.iso] will match all images starting with debian and end with the .iso
+; file extension.
+; scsi-device- sections will be processed in order, always inherit from the [iscsi] and [scsi]
+; sections and are matched case sensitive
+
+[iscsi]
+; Target name check level (warning) specifying invalid check levels will default to full
+; validation!). Default is Full
+; 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
+
+...
+
+[scsi]
+; Valid devices types for emulated device (warning) specifying invalid types will default to direct
+; access device!). Default is Direct
+; Direct Direct access device (e.g. hard drive)
+; Sequential Sequential access device (e.g. tape)
+; WriteOnce Write once device (WORM)
+; ReadOnlyDirect Read only direct access device
+; OpticalMemory Optical memory device (e.g. CD-ROM, DVD, BluRay)
+; MediaChanger Media changer device
+DeviceType=Direct
+
+; Physical block size of emulated device, rounded up to nearest power of two). Default is 512 for
+; supporting ancient systems. Should be set to 2048 for CD-ROM, DVD and BluRay devices. Allowed
+; physical block sizes range from 256 to 32768 bytes (32 KiB). Default is 512 bytes
+PhysicalBlockSize=512
+
+; Logical block size of emulated device, rounded up to nearest power of two). Default is 4096 for
+; supporting modern systems. Should be set to 2048 for CD-ROM, DVD and BluRay devices. Allowed
+; logical block sizes range from 256 to 32768 bytes (32 KiB). Default is 4096 bytes (4 KiB)
+LogicalBlockSize=4096
+
+; Device is emulated as removable. Should be enabled for CD-ROM, DVD and BluRay and disabled for
+; hard drives. Default is true
+Removable=true
+
+...
+
+; SCSI device specific configuration for *.iso (case sensitive), i.e. all image files which
+; end with .iso extension. Block sizes are set to 2 KiB for CD-ROM, DVD and BluRay type devices
+; and the physical read only emulation flag is enabled
+[scsi-device-*.iso]
+; Physical block size of emulated device, rounded up to nearest power of two). Default is 512 for
+; supporting ancient systems. Should be set to 2048 for CD-ROM, DVD and BluRay devices. Allowed
+; physical block sizes range from 256 to 32768 bytes (32 KiB). Default is 512 bytes
+PhysicalBlockSize=2048
+
+; Logical block size of emulated device, rounded up to nearest power of two). Default is 4096 for
+; supporting modern systems. Should be set to 2048 for CD-ROM, DVD and BluRay devices. Allowed
+; logical block sizes range from 256 to 32768 bytes (32 KiB). Default is 4096 bytes (4 KiB)
+LogicalBlockSize=2048
+
+; Device is emulated as removable. Should be enabled for CD-ROM, DVD and BluRay and disabled for
+; hard drives. Default is true
+Removable=true
+
+; Device is emulated as physically read only. No possibility to enable writes in any case. Use
+; for CD-ROM, DVD and BluRay devices. Default is false
+PhysicalReadOnly=true
+
+; SCSI device specific configuration for *.ISO (case sensitive), i.e. all image files which
+; end with .ISO extension. Block sizes are set to 2 KiB for CD-ROM, DVD and BluRay type devices
+; and the physical read only emulation flag is enabled
+[scsi-device-*.ISO]
+; Physical block size of emulated device, rounded up to nearest power of two). Default is 512 for
+; supporting ancient systems. Should be set to 2048 for CD-ROM, DVD and BluRay devices. Allowed
+; physical block sizes range from 256 to 32768 bytes (32 KiB). Default is 512 bytes
+PhysicalBlockSize=2048
+
+; Logical block size of emulated device, rounded up to nearest power of two). Default is 4096 for
+; supporting modern systems. Should be set to 2048 for CD-ROM, DVD and BluRay devices. Allowed
+; logical block sizes range from 256 to 32768 bytes (32 KiB). Default is 4096 bytes (4 KiB)
+LogicalBlockSize=2048
+
+; Device is emulated as removable. Should be enabled for CD-ROM, DVD and BluRay and disabled for
+; hard drives. Default is true
+Removable=true
+
+; Device is emulated as physically read only. No possibility to enable writes in any case. Use
+; for CD-ROM, DVD and BluRay devices. Default is false
+PhysicalReadOnly=true
+
+```
+
+
+For a complete list of possible configuration options, look at the comments in the sample _iscsi.conf_ file, which describes the options in detail.
+
+
+### _World Wide Name (WWN)_ to DNBD3 image mapping for standard compliance.
+As the iSCSI target node name supports only a very restricted number of allowed characters, DNBD3 images also can be specified either using the _Network Address Authority (NAA) IEEE Extended_ name identifier, the _64-bit extended unique identifier (EUI-64)_ or _iSCSI Qualified Name (IQN)_ using the _wwn-0x_ prefix. The revision of the DNBD3 image is specified with a _:_ (colon) after the DNBD3 image name and also the _Logical Unit Number (LUN)_.
+
diff --git a/src/server/iscsi.c b/src/server/iscsi.c
index b44f695..e9b0fc1 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
@@ -3850,13 +3852,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;
@@ -5240,6 +5242,32 @@ static int iscsi_scsi_emu_queue_io_wait(iscsi_scsi_task *scsi_task, iscsi_scsi_e
}
/**
+ * @brief Called when data requested via an uplink server has arrived.
+ *
+ * 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 Uplink handle.
+ * @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 UNUSED, uint64_t start UNUSED, uint32_t length, const char *buffer)
+{
+ iscsi_scsi_task *scsi_task = (iscsi_scsi_task *) data;
+
+ memcpy( scsi_task->buf, buffer, length );
+
+ pthread_mutex_lock( &scsi_task->uplink_mutex );
+ pthread_cond_signal( &scsi_task->uplink_cond );
+ pthread_mutex_unlock( &scsi_task->uplink_mutex );
+}
+
+/**
* @brief Converts offset and length specified by a block size to offset and length in bytes.
*
* This function uses bit shifting if
@@ -5279,9 +5307,6 @@ static uint64_t iscsi_scsi_emu_blocks_to_bytes(uint64_t *offset_bytes, const uin
* @param[in] scsi_task Pointer to iSCSI SCSI task which
* executes the I/O read operation, may
* NOT be NULL, so be careful.
- * @param[in] buf Pointer to buffer where to store
- * the read data. NULL is NOT allowed
- * here, take caution.
* @param[in] image Pointer to DNBD3 image to read
* data from and may NOT be NULL, so
* be careful.
@@ -5297,16 +5322,62 @@ static uint64_t iscsi_scsi_emu_blocks_to_bytes(uint64_t *offset_bytes, const uin
* @return 0 on successful operation, a negative
* error code otherwise.
*/
-int iscsi_scsi_emu_io_block_read(iscsi_scsi_task *scsi_task, uint8_t *buf, dnbd3_image_t *image, const uint64_t offset_blocks, const uint64_t num_blocks, const uint32_t block_size, iscsi_scsi_emu_io_complete_callback callback, uint8_t *user_data)
+int iscsi_scsi_emu_io_block_read(iscsi_scsi_task *scsi_task, dnbd3_image_t *image, const uint64_t offset_blocks, const uint64_t num_blocks, const uint32_t block_size, iscsi_scsi_emu_io_complete_callback callback, uint8_t *user_data)
{
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);
+ const uint64_t num_bytes = iscsi_scsi_emu_blocks_to_bytes( &offset_bytes, offset_blocks, num_blocks, block_size );
+ dnbd3_cache_map_t *cache = ref_get_cachemap( image );
+ bool readFromFile;
+ bool success;
+
+ 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
+
+ if ( pthread_mutex_init( &scsi_task->uplink_mutex, NULL ) != 0 ) {
+ logadd( LOG_ERROR, "iscsi_scsi_emu_io_block_read: Error while initializing DNBD3 uplink mutex for iSCSI SCSI task" );
+
+ return -ENOMEM;
+ }
+
+ if ( pthread_cond_init( &scsi_task->uplink_cond, NULL ) != 0 ) {
+ logadd( LOG_ERROR, "iscsi_scsi_emu_io_block_read: Error while initializing DNBD3 uplink condition for iSCSI SCSI task" );
+
+ pthread_mutex_destroy( &scsi_task->uplink_mutex );
+
+ return -ENOMEM;
+ }
+
+ 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 )
+ pthread_cond_wait( &scsi_task->uplink_cond, &scsi_task->uplink_mutex );
+
+ pthread_mutex_unlock( &scsi_task->uplink_mutex );
+ pthread_cond_destroy( &scsi_task->uplink_cond );
+ pthread_mutex_destroy( &scsi_task->uplink_mutex );
+ }
+ }
+
+ if ( readFromFile ) {
+ const int64_t len = pread( image->readFd, scsi_task->buf, (size_t) num_bytes, offset_bytes );
+ 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 ) {
- 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;
}
@@ -5367,9 +5438,6 @@ uint8_t *iscsi_scsi_emu_block_read_complete_callback(dnbd3_image_t *image, uint8
* executes the I/O compare and write
* operation, may NOT be NULL, so be
* careful.
- * @param[in] buf Pointer to buffer which contains
- * the data to be written. NULL is NOT
- * allowed here, take caution.
* @param[in] cmp_buf Pointer to buffer which contains
* the data to be compared and may NOT
* be NULL, so be careful.
@@ -5388,7 +5456,7 @@ uint8_t *iscsi_scsi_emu_block_read_complete_callback(dnbd3_image_t *image, uint8
* @return 0 on successful operation, a negative
* error code otherwise.
*/
-int iscsi_scsi_emu_io_block_cmp_write(iscsi_scsi_task *scsi_task, uint8_t *buf, uint8_t *cmp_buf, dnbd3_image_t *image, const uint64_t offset_blocks, const uint64_t num_blocks, const uint32_t block_size, iscsi_scsi_emu_io_complete_callback callback, uint8_t *user_data)
+int iscsi_scsi_emu_io_block_cmp_write(iscsi_scsi_task *scsi_task, uint8_t *cmp_buf, dnbd3_image_t *image, const uint64_t offset_blocks, const uint64_t num_blocks, const uint32_t block_size, iscsi_scsi_emu_io_complete_callback callback, uint8_t *user_data)
{
// TODO: Implement compare and write I/O.
@@ -5440,9 +5508,6 @@ uint8_t *iscsi_scsi_emu_block_write_complete_callback(dnbd3_image_t *image, uint
* @param[in] scsi_task Pointer to iSCSI SCSI task which
* executes the I/O write operation, may
* NOT be NULL, so be careful.
- * @param[in] buf Pointer to buffer which contains
- * the data to be written. NULL is NOT
- * allowed here, take caution.
* @param[in] image Pointer to DNBD3 image to write
* data to and may NOT be NULL, so
* be careful.
@@ -5458,16 +5523,16 @@ uint8_t *iscsi_scsi_emu_block_write_complete_callback(dnbd3_image_t *image, uint
* @return 0 on successful operation, a negative
* error code otherwise.
*/
-int iscsi_scsi_emu_io_block_write(iscsi_scsi_task *scsi_task, uint8_t *buf, dnbd3_image_t *image, const uint64_t offset_blocks, const uint64_t num_blocks, const uint32_t block_size, iscsi_scsi_emu_io_complete_callback callback, uint8_t *user_data)
+int iscsi_scsi_emu_io_block_write(iscsi_scsi_task *scsi_task, dnbd3_image_t *image, const uint64_t offset_blocks, const uint64_t num_blocks, const uint32_t block_size, iscsi_scsi_emu_io_complete_callback callback, uint8_t *user_data)
{
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 = pwrite( image->readFd, buf, (size_t) num_bytes, offset_bytes );
+ const int64_t len = pwrite( image->readFd, scsi_task->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 ) {
- 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;
}
@@ -5575,7 +5640,7 @@ static int iscsi_scsi_emu_block_read_write(dnbd3_image_t *image, iscsi_scsi_task
return ISCSI_SCSI_TASK_RUN_PENDING;
}
- rc = iscsi_scsi_emu_io_block_read( scsi_task, scsi_task->buf, image, offset_blocks, num_blocks, block_size, iscsi_scsi_emu_block_read_complete_callback, (uint8_t *) scsi_task );
+ rc = iscsi_scsi_emu_io_block_read( scsi_task, image, offset_blocks, num_blocks, block_size, iscsi_scsi_emu_block_read_complete_callback, (uint8_t *) scsi_task );
} else if ( iscsi_scsi_emu_io_type_is_supported( image, ISCSI_SCSI_EMU_IO_TYPE_PHYSICAL_READ_ONLY ) || iscsi_scsi_emu_io_type_is_supported( image, ISCSI_SCSI_EMU_IO_TYPE_WRITE_PROTECT ) ) {
iscsi_scsi_task_status_set( scsi_task, ISCSI_SCSI_STATUS_CHECK_COND, ISCSI_SCSI_SENSE_KEY_DATA_PROTECT, ISCSI_SCSI_ASC_WRITE_PROTECTED, ISCSI_SCSI_ASCQ_CAUSE_NOT_REPORTABLE );
@@ -5589,9 +5654,9 @@ static int iscsi_scsi_emu_block_read_write(dnbd3_image_t *image, iscsi_scsi_task
uint8_t *cmp_buf = (scsi_task->buf + block_size);
- rc = iscsi_scsi_emu_io_block_cmp_write( scsi_task, scsi_task->buf, cmp_buf, image, offset_blocks, 1ULL, block_size, iscsi_scsi_emu_block_write_complete_callback, (uint8_t *) scsi_task );
+ rc = iscsi_scsi_emu_io_block_cmp_write( scsi_task, cmp_buf, image, offset_blocks, 1ULL, block_size, iscsi_scsi_emu_block_write_complete_callback, (uint8_t *) scsi_task );
} else {
- rc = iscsi_scsi_emu_io_block_write( scsi_task, scsi_task->buf, image, offset_blocks, num_blocks, block_size, iscsi_scsi_emu_block_write_complete_callback, (uint8_t *) scsi_task );
+ rc = iscsi_scsi_emu_io_block_write( scsi_task, image, offset_blocks, num_blocks, block_size, iscsi_scsi_emu_block_write_complete_callback, (uint8_t *) scsi_task );
}
if ( rc < 0 ) {
@@ -5726,7 +5791,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 193b292..ded2d1d 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 synchronization.
+ pthread_mutex_t uplink_mutex;
+
+ /// Conditional to signal uplink read complete.
+ pthread_cond_t uplink_cond;
+
/// Output buffer.
uint8_t *buf;
@@ -10935,11 +10941,11 @@ int iscsi_scsi_pr_in(iscsi_scsi_task *scsi_task, iscsi_scsi_pr_reserve_in_parame
int iscsi_scsi_pr_reserve_scsi2(iscsi_scsi_task *scsi_task, const iscsi_scsi_cdb_pr_reserve_6 *cdb_pr_reserve_6); // Reserves an iSCSI SCSI Persistent Reservation (PR) of an iSCSI SCSI task
int iscsi_scsi_pr_release_scsi2(iscsi_scsi_task *scsi_task); // Releases an iSCSI SCSI Persistent Reservation (PR) of an iSCSI SCSI task
-int iscsi_scsi_emu_io_block_read(iscsi_scsi_task *scsi_task, uint8_t *buf, dnbd3_image_t *image, const uint64_t offset_blocks, const uint64_t num_blocks, const uint32_t block_size, iscsi_scsi_emu_io_complete_callback callback, uint8_t *user_data); // Reads a number of blocks from a block offset of a DNBD3 image to a specified buffer
+int iscsi_scsi_emu_io_block_read(iscsi_scsi_task *scsi_task, dnbd3_image_t *image, const uint64_t offset_blocks, const uint64_t num_blocks, const uint32_t block_size, iscsi_scsi_emu_io_complete_callback callback, uint8_t *user_data); // Reads a number of blocks from a block offset of a DNBD3 image to a specified buffer
uint8_t *iscsi_scsi_emu_block_read_complete_callback(dnbd3_image_t *image, uint8_t *user_data, const bool success); // Completes an iSCSI SCSI task after a finished I/O read operation
-int iscsi_scsi_emu_io_block_cmp_write(iscsi_scsi_task *scsi_task, uint8_t *buf, uint8_t *cmp_buf, dnbd3_image_t *image, const uint64_t offset_blocks, const uint64_t num_blocks, const uint32_t block_size, iscsi_scsi_emu_io_complete_callback callback, uint8_t *user_data); // Compares and writes a number of blocks starting from a block offset in a DNBD3 image with specified buffers
+int iscsi_scsi_emu_io_block_cmp_write(iscsi_scsi_task *scsi_task, uint8_t *cmp_buf, dnbd3_image_t *image, const uint64_t offset_blocks, const uint64_t num_blocks, const uint32_t block_size, iscsi_scsi_emu_io_complete_callback callback, uint8_t *user_data); // Compares and writes a number of blocks starting from a block offset in a DNBD3 image with specified buffers
uint8_t *iscsi_scsi_emu_block_write_complete_callback(dnbd3_image_t *image, uint8_t *user_data, const bool success); // Completes an iSCSI SCSI task after a finished I/O write operation
-int iscsi_scsi_emu_io_block_write(iscsi_scsi_task *scsi_task, uint8_t *buf, dnbd3_image_t *image, const uint64_t offset_blocks, const uint64_t num_blocks, const uint32_t block_size, iscsi_scsi_emu_io_complete_callback callback, uint8_t *user_data); // Writes a number of blocks from a block offset to a DNBD3 image of a specified buffer
+int iscsi_scsi_emu_io_block_write(iscsi_scsi_task *scsi_task, dnbd3_image_t *image, const uint64_t offset_blocks, const uint64_t num_blocks, const uint32_t block_size, iscsi_scsi_emu_io_complete_callback callback, uint8_t *user_data); // Writes a number of blocks from a block offset to a DNBD3 image of a specified buffer
int iscsi_scsi_emu_io_queue(iscsi_scsi_emu_io_wait *io_wait); // Enqueues an I/O wait in the thread pool to execute
uint8_t *iscsi_scsi_emu_block_resubmit_process_callback(uint8_t *user_data); // Resubmits an iSCSI SCSI task for execution