summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSebastian Vater2025-09-29 16:58:27 +0200
committerSebastian Vater2025-09-29 16:58:27 +0200
commita5eec7a4b1ba615fb77e744fc614360ddc715f16 (patch)
tree2586b36789292d52ec250263408d50ecf9213504
parentFixed various memory leaks reported by valgrind. Also fixed some bugs in DNBD... (diff)
downloaddnbd3-a5eec7a4b1ba615fb77e744fc614360ddc715f16.tar.gz
dnbd3-a5eec7a4b1ba615fb77e744fc614360ddc715f16.tar.xz
dnbd3-a5eec7a4b1ba615fb77e744fc614360ddc715f16.zip
Images are now propagated as a read-only SCSI device in iSCSI implementation and WRITE operations return correct SCSI sense key, ASC and ASCQ in an attempt to write to a read-only device. Finally, another valgrind SCSI INQUIRY memleak fixed.
-rw-r--r--src/server/iscsi.c42
-rw-r--r--src/server/iscsi.h17
2 files changed, 48 insertions, 11 deletions
diff --git a/src/server/iscsi.c b/src/server/iscsi.c
index 05c8876..d833076 100644
--- a/src/server/iscsi.c
+++ b/src/server/iscsi.c
@@ -3737,7 +3737,7 @@ int iscsi_scsi_pr_release_scsi2(iscsi_scsi_task *scsi_task)
* @retval false The I/O feature is NOT supported for the
* DNBD3 image.
*/
-static inline bool iscsi_scsi_emu_io_type_is_supported(const dnbd3_image_t *image, int type)
+static inline bool iscsi_scsi_emu_io_type_is_supported(const dnbd3_image_t *image, const int type)
{
// TODO: Actually implement this function.
@@ -3757,6 +3757,16 @@ static inline bool iscsi_scsi_emu_io_type_is_supported(const dnbd3_image_t *imag
break;
}
+ case ISCSI_SCSI_EMU_IO_TYPE_PHYSICAL_READ_ONLY : {
+ return false;
+
+ break;
+ }
+ case ISCSI_SCSI_EMU_IO_TYPE_WRITE_PROTECT : {
+ return true;
+
+ break;
+ }
case ISCSI_SCSI_EMU_IO_TYPE_WRITE_CACHE : {
return false;
@@ -4152,7 +4162,7 @@ uint8_t *iscsi_scsi_emu_block_write_complete_callback(dnbd3_image_t *image, uint
if ( success )
scsi_task->status = ISCSI_SCSI_STATUS_GOOD;
else
- iscsi_scsi_task_status_set( scsi_task, ISCSI_SCSI_STATUS_CHECK_COND, ISCSI_SCSI_SENSE_KEY_MEDIUM_ERR, ISCSI_SCSI_ASC_UNRECOVERED_READ_ERR, ISCSI_SCSI_ASCQ_CAUSE_NOT_REPORTABLE );
+ iscsi_scsi_task_status_set( scsi_task, ISCSI_SCSI_STATUS_CHECK_COND, ISCSI_SCSI_SENSE_KEY_MEDIUM_ERR, ISCSI_SCSI_ASC_WRITE_ERR, ISCSI_SCSI_ASCQ_CAUSE_NOT_REPORTABLE );
iscsi_scsi_lun_task_complete( scsi_task->lun, scsi_task );
@@ -4192,11 +4202,23 @@ int iscsi_scsi_emu_io_blocks_write(iscsi_scsi_task *scsi_task, uint8_t *buf, dnb
{
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 ); // TODO: Make write I/O async
+ const int64_t len = pwrite( image->readFd, buf, (size_t) num_bytes, offset_bytes ); // TODO: Make read I/O async
const bool success = ((uint64_t) len == num_bytes);
- scsi_task->xfer_pos = scsi_task->len;
- callback( image, user_data, success );
+ // TODO: Begin remove after I/O async implementation
+ uint64_t *exec_data = malloc( 64 );
+
+ exec_data[2] = (uint64_t *) callback;
+ exec_data[3] = 3ULL;
+ exec_data[4] = (dnbd3_image_t *) image;
+ exec_data[5] = user_data;
+ exec_data[6] = success;
+
+ iscsi_list_enqueue( &iscsi_globvec->exec_queue, (iscsi_node *) exec_data );
+ // TODO: End remove after I/O async implementation
+
+ // scsi_task->xfer_pos = scsi_task->len;
+ // callback( image, user_data, success );
return (success ? 0 : -1);
}
@@ -4286,6 +4308,10 @@ static int iscsi_scsi_emu_block_read_write(dnbd3_image_t *image, iscsi_scsi_task
}
rc = iscsi_scsi_emu_io_blocks_read( scsi_task, scsi_task->buf, 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 );
+
+ return ISCSI_SCSI_TASK_RUN_COMPLETE;
} else if ( (flags & ISCSI_SCSI_EMU_BLOCK_FLAGS_VERIFY) != 0 ) {
if ( scsi_task->len != (block_size + block_size) ) {
iscsi_scsi_task_status_set( scsi_task, ISCSI_SCSI_STATUS_CHECK_COND, ISCSI_SCSI_SENSE_KEY_ILLEGAL_REQ, ISCSI_SCSI_ASC_INVALID_FIELD_IN_CDB, ISCSI_SCSI_ASCQ_CAUSE_NOT_REPORTABLE );
@@ -5215,6 +5241,8 @@ static int iscsi_scsi_emu_primary_inquiry(dnbd3_image_t *image, iscsi_scsi_task
alloc_len = sizeof(struct iscsi_scsi_vpd_page_block_limits_inquiry_data_packet);
+ vpd_page_block_limits_inquiry_data_pkt->flags = 0;
+
uint32_t blocks = (ISCSI_SCSI_EMU_MAX_XFER_LEN >> iscsi_scsi_emu_block_get_size_shift( image ));
if ( blocks > 255UL )
@@ -5846,14 +5874,14 @@ static int iscsi_scsi_emu_primary_mode_sense(dnbd3_image_t *image, iscsi_scsi_ta
if ( hdr_len == sizeof(struct iscsi_scsi_mode_sense_6_parameter_header_data_packet) ) {
mode_sense_6_parameter_hdr_data_pkt->mode_data_len = (uint8_t) (alloc_len - sizeof(uint8_t));
mode_sense_6_parameter_hdr_data_pkt->medium_type = 0U;
- mode_sense_6_parameter_hdr_data_pkt->flags = 0;
+ mode_sense_6_parameter_hdr_data_pkt->flags = (int8_t) ((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_MODE_SENSE_6_PARAM_HDR_DATA_FLAGS_WP : 0);
mode_sense_6_parameter_hdr_data_pkt->block_desc_len = (uint8_t) block_desc_len;
} else {
iscsi_scsi_mode_sense_10_parameter_header_data_packet *mode_sense_10_parameter_hdr_data_pkt = (iscsi_scsi_mode_sense_10_parameter_header_data_packet *) mode_sense_6_parameter_hdr_data_pkt;
iscsi_put_be16( (uint8_t *) &mode_sense_10_parameter_hdr_data_pkt->mode_data_len, (uint16_t) (alloc_len - sizeof(uint16_t)) );
mode_sense_10_parameter_hdr_data_pkt->medium_type = 0U;
- mode_sense_10_parameter_hdr_data_pkt->flags = 0;
+ mode_sense_10_parameter_hdr_data_pkt->flags = (int8_t) ((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_MODE_SENSE_10_PARAM_HDR_DATA_FLAGS_WP : 0);
mode_sense_10_parameter_hdr_data_pkt->long_lba = (uint8_t) long_lba;
mode_sense_10_parameter_hdr_data_pkt->reserved = 0U;
iscsi_put_be16( (uint8_t *) &mode_sense_10_parameter_hdr_data_pkt->block_desc_len, (uint16_t) block_desc_len );
diff --git a/src/server/iscsi.h b/src/server/iscsi.h
index 6f48e80..4ee5dac 100644
--- a/src/server/iscsi.h
+++ b/src/server/iscsi.h
@@ -10123,6 +10123,9 @@ void iscsi_portal_destroy(iscsi_portal *portal);
/// iSCSI SCSI Additional Sense Code (ASC): Warning.
#define ISCSI_SCSI_ASC_WARNING 0x0B
+/// iSCSI SCSI Additional Sense Code (ASC): Write error.
+#define ISCSI_SCSI_ASC_WRITE_ERR 0x0C
+
/// iSCSI SCSI Additional Sense Code (ASC): Block guard check failed.
#define ISCSI_SCSI_ASC_LOGICAL_BLOCK_GUARD_CHECK_FAIL 0x10
@@ -10487,16 +10490,22 @@ typedef struct iscsi_scsi_task {
/// iSCSI SCSI emulation I/O type: Removable.
-#define ISCSI_SCSI_EMU_IO_TYPE_REMOVABLE (1 << 0)
+#define ISCSI_SCSI_EMU_IO_TYPE_REMOVABLE (1 << 0)
/// iSCSI SCSI emulation I/O type: Unmap.
-#define ISCSI_SCSI_EMU_IO_TYPE_UNMAP (1 << 1)
+#define ISCSI_SCSI_EMU_IO_TYPE_UNMAP (1 << 1)
/// iSCSI SCSI emulation I/O type: Non-rotating medium (e.g., solid state).
-#define ISCSI_SCSI_EMU_IO_TYPE_NO_ROTATION (1 << 2)
+#define ISCSI_SCSI_EMU_IO_TYPE_NO_ROTATION (1 << 2)
+
+/// iSCSI SCSI emulation I/O type: Physical read only device.
+#define ISCSI_SCSI_EMU_IO_TYPE_PHYSICAL_READ_ONLY (1 << 3)
+
+/// iSCSI SCSI emulation I/O type: Device is (temporarily) write protected.
+#define ISCSI_SCSI_EMU_IO_TYPE_WRITE_PROTECT (1 << 4)
/// iSCSI SCSI emulation I/O type: Write cache available.
-#define ISCSI_SCSI_EMU_IO_TYPE_WRITE_CACHE (1 << 3)
+#define ISCSI_SCSI_EMU_IO_TYPE_WRITE_CACHE (1 << 5)
/// iSCSI SCSI emulation block flags: Write operation.