block/iscsi: use 16 byte CDBs only when necessary
this patch changes the driver to uses 16 Byte CDBs for READ/WRITE only if the target requires 64bit lba addressing. On one hand this saves 6 bytes in each PDU on the other hand it seems that 10 Byte CDBs seems to be much better supported and tested as a recent issue I had with a major storage supplier lined out. For WRITESAME the logic is a bit more tricky as WRITESAME10 with UNMAP was added really late. Thus a fallback to WRITESAME16 is possible if it supports UNMAP and WRITESAME10 not. Signed-off-by: Peter Lieven <pl@kamp.de> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
		
							parent
							
								
									fcd470d857
								
							
						
					
					
						commit
						9281fe9eea
					
				| 
						 | 
					@ -65,6 +65,7 @@ typedef struct IscsiLun {
 | 
				
			||||||
    unsigned char *zeroblock;
 | 
					    unsigned char *zeroblock;
 | 
				
			||||||
    unsigned long *allocationmap;
 | 
					    unsigned long *allocationmap;
 | 
				
			||||||
    int cluster_sectors;
 | 
					    int cluster_sectors;
 | 
				
			||||||
 | 
					    bool use_16_for_rw;
 | 
				
			||||||
} IscsiLun;
 | 
					} IscsiLun;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef struct IscsiTask {
 | 
					typedef struct IscsiTask {
 | 
				
			||||||
| 
						 | 
					@ -381,10 +382,17 @@ static int coroutine_fn iscsi_co_writev(BlockDriverState *bs,
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
    iscsi_co_init_iscsitask(iscsilun, &iTask);
 | 
					    iscsi_co_init_iscsitask(iscsilun, &iTask);
 | 
				
			||||||
retry:
 | 
					retry:
 | 
				
			||||||
    iTask.task = iscsi_write16_task(iscsilun->iscsi, iscsilun->lun, lba,
 | 
					    if (iscsilun->use_16_for_rw) {
 | 
				
			||||||
                                    data, num_sectors * iscsilun->block_size,
 | 
					        iTask.task = iscsi_write16_task(iscsilun->iscsi, iscsilun->lun, lba,
 | 
				
			||||||
                                    iscsilun->block_size, 0, 0, 0, 0, 0,
 | 
					                                        data, num_sectors * iscsilun->block_size,
 | 
				
			||||||
                                    iscsi_co_generic_cb, &iTask);
 | 
					                                        iscsilun->block_size, 0, 0, 0, 0, 0,
 | 
				
			||||||
 | 
					                                        iscsi_co_generic_cb, &iTask);
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        iTask.task = iscsi_write10_task(iscsilun->iscsi, iscsilun->lun, lba,
 | 
				
			||||||
 | 
					                                        data, num_sectors * iscsilun->block_size,
 | 
				
			||||||
 | 
					                                        iscsilun->block_size, 0, 0, 0, 0, 0,
 | 
				
			||||||
 | 
					                                        iscsi_co_generic_cb, &iTask);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
    if (iTask.task == NULL) {
 | 
					    if (iTask.task == NULL) {
 | 
				
			||||||
        g_free(buf);
 | 
					        g_free(buf);
 | 
				
			||||||
        return -ENOMEM;
 | 
					        return -ENOMEM;
 | 
				
			||||||
| 
						 | 
					@ -570,14 +578,12 @@ static int coroutine_fn iscsi_co_readv(BlockDriverState *bs,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    iscsi_co_init_iscsitask(iscsilun, &iTask);
 | 
					    iscsi_co_init_iscsitask(iscsilun, &iTask);
 | 
				
			||||||
retry:
 | 
					retry:
 | 
				
			||||||
    switch (iscsilun->type) {
 | 
					    if (iscsilun->use_16_for_rw) {
 | 
				
			||||||
    case TYPE_DISK:
 | 
					 | 
				
			||||||
        iTask.task = iscsi_read16_task(iscsilun->iscsi, iscsilun->lun, lba,
 | 
					        iTask.task = iscsi_read16_task(iscsilun->iscsi, iscsilun->lun, lba,
 | 
				
			||||||
                                       num_sectors * iscsilun->block_size,
 | 
					                                       num_sectors * iscsilun->block_size,
 | 
				
			||||||
                                       iscsilun->block_size, 0, 0, 0, 0, 0,
 | 
					                                       iscsilun->block_size, 0, 0, 0, 0, 0,
 | 
				
			||||||
                                       iscsi_co_generic_cb, &iTask);
 | 
					                                       iscsi_co_generic_cb, &iTask);
 | 
				
			||||||
        break;
 | 
					    } else {
 | 
				
			||||||
    default:
 | 
					 | 
				
			||||||
        iTask.task = iscsi_read10_task(iscsilun->iscsi, iscsilun->lun, lba,
 | 
					        iTask.task = iscsi_read10_task(iscsilun->iscsi, iscsilun->lun, lba,
 | 
				
			||||||
                                       num_sectors * iscsilun->block_size,
 | 
					                                       num_sectors * iscsilun->block_size,
 | 
				
			||||||
                                       iscsilun->block_size,
 | 
					                                       iscsilun->block_size,
 | 
				
			||||||
| 
						 | 
					@ -585,7 +591,6 @@ retry:
 | 
				
			||||||
                                       0, 0, 0, 0, 0,
 | 
					                                       0, 0, 0, 0, 0,
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
                                       iscsi_co_generic_cb, &iTask);
 | 
					                                       iscsi_co_generic_cb, &iTask);
 | 
				
			||||||
        break;
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    if (iTask.task == NULL) {
 | 
					    if (iTask.task == NULL) {
 | 
				
			||||||
        return -ENOMEM;
 | 
					        return -ENOMEM;
 | 
				
			||||||
| 
						 | 
					@ -921,19 +926,27 @@ coroutine_fn iscsi_co_write_zeroes(BlockDriverState *bs, int64_t sector_num,
 | 
				
			||||||
    struct IscsiTask iTask;
 | 
					    struct IscsiTask iTask;
 | 
				
			||||||
    uint64_t lba;
 | 
					    uint64_t lba;
 | 
				
			||||||
    uint32_t nb_blocks;
 | 
					    uint32_t nb_blocks;
 | 
				
			||||||
 | 
					    bool use_16_for_ws = iscsilun->use_16_for_rw;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (!is_request_lun_aligned(sector_num, nb_sectors, iscsilun)) {
 | 
					    if (!is_request_lun_aligned(sector_num, nb_sectors, iscsilun)) {
 | 
				
			||||||
        return -EINVAL;
 | 
					        return -EINVAL;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if ((flags & BDRV_REQ_MAY_UNMAP) && !iscsilun->lbp.lbpws) {
 | 
					    if (flags & BDRV_REQ_MAY_UNMAP) {
 | 
				
			||||||
        /* WRITE SAME with UNMAP is not supported by the target,
 | 
					        if (!use_16_for_ws && !iscsilun->lbp.lbpws10) {
 | 
				
			||||||
         * fall back and try WRITE SAME without UNMAP */
 | 
					            /* WRITESAME10 with UNMAP is unsupported try WRITESAME16 */
 | 
				
			||||||
        flags &= ~BDRV_REQ_MAY_UNMAP;
 | 
					            use_16_for_ws = true;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        if (use_16_for_ws && !iscsilun->lbp.lbpws) {
 | 
				
			||||||
 | 
					            /* WRITESAME16 with UNMAP is not supported by the target,
 | 
				
			||||||
 | 
					             * fall back and try WRITESAME10/16 without UNMAP */
 | 
				
			||||||
 | 
					            flags &= ~BDRV_REQ_MAY_UNMAP;
 | 
				
			||||||
 | 
					            use_16_for_ws = iscsilun->use_16_for_rw;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (!(flags & BDRV_REQ_MAY_UNMAP) && !iscsilun->has_write_same) {
 | 
					    if (!(flags & BDRV_REQ_MAY_UNMAP) && !iscsilun->has_write_same) {
 | 
				
			||||||
        /* WRITE SAME without UNMAP is not supported by the target */
 | 
					        /* WRITESAME without UNMAP is not supported by the target */
 | 
				
			||||||
        return -ENOTSUP;
 | 
					        return -ENOTSUP;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -946,10 +959,18 @@ coroutine_fn iscsi_co_write_zeroes(BlockDriverState *bs, int64_t sector_num,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    iscsi_co_init_iscsitask(iscsilun, &iTask);
 | 
					    iscsi_co_init_iscsitask(iscsilun, &iTask);
 | 
				
			||||||
retry:
 | 
					retry:
 | 
				
			||||||
    if (iscsi_writesame16_task(iscsilun->iscsi, iscsilun->lun, lba,
 | 
					    if (use_16_for_ws) {
 | 
				
			||||||
                               iscsilun->zeroblock, iscsilun->block_size,
 | 
					        iTask.task = iscsi_writesame16_task(iscsilun->iscsi, iscsilun->lun, lba,
 | 
				
			||||||
                               nb_blocks, 0, !!(flags & BDRV_REQ_MAY_UNMAP),
 | 
					                                            iscsilun->zeroblock, iscsilun->block_size,
 | 
				
			||||||
                               0, 0, iscsi_co_generic_cb, &iTask) == NULL) {
 | 
					                                            nb_blocks, 0, !!(flags & BDRV_REQ_MAY_UNMAP),
 | 
				
			||||||
 | 
					                                            0, 0, iscsi_co_generic_cb, &iTask);
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        iTask.task = iscsi_writesame10_task(iscsilun->iscsi, iscsilun->lun, lba,
 | 
				
			||||||
 | 
					                                            iscsilun->zeroblock, iscsilun->block_size,
 | 
				
			||||||
 | 
					                                            nb_blocks, 0, !!(flags & BDRV_REQ_MAY_UNMAP),
 | 
				
			||||||
 | 
					                                            0, 0, iscsi_co_generic_cb, &iTask);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (iTask.task == NULL) {
 | 
				
			||||||
        return -ENOMEM;
 | 
					        return -ENOMEM;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1147,6 +1168,7 @@ static void iscsi_readcapacity_sync(IscsiLun *iscsilun, Error **errp)
 | 
				
			||||||
                    iscsilun->num_blocks = rc16->returned_lba + 1;
 | 
					                    iscsilun->num_blocks = rc16->returned_lba + 1;
 | 
				
			||||||
                    iscsilun->lbpme = rc16->lbpme;
 | 
					                    iscsilun->lbpme = rc16->lbpme;
 | 
				
			||||||
                    iscsilun->lbprz = rc16->lbprz;
 | 
					                    iscsilun->lbprz = rc16->lbprz;
 | 
				
			||||||
 | 
					                    iscsilun->use_16_for_rw = (rc16->returned_lba > 0xffffffff);
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue