@ -380,9 +380,10 @@ iblock_execute_sync_cache(struct se_cmd *cmd)
}
static sense_reason_t
iblock_do_unmap ( struct se_cmd * cmd , struct block_device * bde v,
iblock_do_unmap ( struct se_cmd * cmd , void * pri v,
sector_t lba , sector_t nolb )
{
struct block_device * bdev = priv ;
int ret ;
ret = blkdev_issue_discard ( bdev , lba , nolb , GFP_KERNEL , 0 ) ;
@ -397,83 +398,9 @@ iblock_do_unmap(struct se_cmd *cmd, struct block_device *bdev,
static sense_reason_t
iblock_execute_unmap ( struct se_cmd * cmd )
{
struct se_device * dev = cmd - > se_dev ;
struct iblock_dev * ib_dev = IBLOCK_DEV ( dev ) ;
unsigned char * buf , * ptr = NULL ;
sector_t lba ;
int size ;
u32 range ;
sense_reason_t ret = 0 ;
int dl , bd_dl ;
/* We never set ANC_SUP */
if ( cmd - > t_task_cdb [ 1 ] )
return TCM_INVALID_CDB_FIELD ;
if ( cmd - > data_length = = 0 ) {
target_complete_cmd ( cmd , SAM_STAT_GOOD ) ;
return 0 ;
}
if ( cmd - > data_length < 8 ) {
pr_warn ( " UNMAP parameter list length %u too small \n " ,
cmd - > data_length ) ;
return TCM_PARAMETER_LIST_LENGTH_ERROR ;
}
buf = transport_kmap_data_sg ( cmd ) ;
if ( ! buf )
return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE ;
dl = get_unaligned_be16 ( & buf [ 0 ] ) ;
bd_dl = get_unaligned_be16 ( & buf [ 2 ] ) ;
size = cmd - > data_length - 8 ;
if ( bd_dl > size )
pr_warn ( " UNMAP parameter list length %u too small, ignoring bd_dl %u \n " ,
cmd - > data_length , bd_dl ) ;
else
size = bd_dl ;
if ( size / 16 > dev - > dev_attrib . max_unmap_block_desc_count ) {
ret = TCM_INVALID_PARAMETER_LIST ;
goto err ;
}
/* First UNMAP block descriptor starts at 8 byte offset */
ptr = & buf [ 8 ] ;
pr_debug ( " UNMAP: Sub: %s Using dl: %u bd_dl: %u size: %u "
" ptr: %p \n " , dev - > transport - > name , dl , bd_dl , size , ptr ) ;
while ( size > = 16 ) {
lba = get_unaligned_be64 ( & ptr [ 0 ] ) ;
range = get_unaligned_be32 ( & ptr [ 8 ] ) ;
pr_debug ( " UNMAP: Using lba: %llu and range: %u \n " ,
( unsigned long long ) lba , range ) ;
if ( range > dev - > dev_attrib . max_unmap_lba_count ) {
ret = TCM_INVALID_PARAMETER_LIST ;
goto err ;
}
if ( lba + range > dev - > transport - > get_blocks ( dev ) + 1 ) {
ret = TCM_ADDRESS_OUT_OF_RANGE ;
goto err ;
}
ret = iblock_do_unmap ( cmd , ib_dev - > ibd_bd , lba , range ) ;
if ( ret )
goto err ;
ptr + = 16 ;
size - = 16 ;
}
struct block_device * bdev = IBLOCK_DEV ( cmd - > se_dev ) - > ibd_bd ;
err :
transport_kunmap_data_sg ( cmd ) ;
if ( ! ret )
target_complete_cmd ( cmd , GOOD ) ;
return ret ;
return sbc_execute_unmap ( cmd , iblock_do_unmap , bdev ) ;
}
static sense_reason_t