target: Add sbc_execute_unmap() helper
iblock_execute_unmap() and fd_execute_unmap share a lot of code. Add sbc_execute_unmap() helper to remove duplicated code for iblock_execute_unmap() and fd_execute_unmap(). Cc: Christoph Hellwig <hch@lst.de> Cc: Martin K. Petersen <martin.petersen@oracle.com> Cc: Nicholas Bellinger <nab@linux-iscsi.org> Signed-off-by: Asias He <asias@redhat.com> Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
This commit is contained in:
parent
dbc21c5abb
commit
86d7182985
4 changed files with 97 additions and 155 deletions
|
@ -480,8 +480,9 @@ fd_execute_write_same(struct se_cmd *cmd)
|
||||||
}
|
}
|
||||||
|
|
||||||
static sense_reason_t
|
static sense_reason_t
|
||||||
fd_do_unmap(struct se_cmd *cmd, struct file *file, sector_t lba, sector_t nolb)
|
fd_do_unmap(struct se_cmd *cmd, void *priv, sector_t lba, sector_t nolb)
|
||||||
{
|
{
|
||||||
|
struct file *file = priv;
|
||||||
struct inode *inode = file->f_mapping->host;
|
struct inode *inode = file->f_mapping->host;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
@ -542,84 +543,9 @@ fd_execute_write_same_unmap(struct se_cmd *cmd)
|
||||||
static sense_reason_t
|
static sense_reason_t
|
||||||
fd_execute_unmap(struct se_cmd *cmd)
|
fd_execute_unmap(struct se_cmd *cmd)
|
||||||
{
|
{
|
||||||
struct se_device *dev = cmd->se_dev;
|
struct file *file = FD_DEV(cmd->se_dev)->fd_file;
|
||||||
struct fd_dev *fd_dev = FD_DEV(dev);
|
|
||||||
struct file *file = fd_dev->fd_file;
|
|
||||||
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 */
|
return sbc_execute_unmap(cmd, fd_do_unmap, file);
|
||||||
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 = fd_do_unmap(cmd, file, lba, range);
|
|
||||||
if (ret)
|
|
||||||
goto err;
|
|
||||||
|
|
||||||
ptr += 16;
|
|
||||||
size -= 16;
|
|
||||||
}
|
|
||||||
|
|
||||||
err:
|
|
||||||
transport_kunmap_data_sg(cmd);
|
|
||||||
if (!ret)
|
|
||||||
target_complete_cmd(cmd, GOOD);
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static sense_reason_t
|
static sense_reason_t
|
||||||
|
|
|
@ -380,9 +380,10 @@ iblock_execute_sync_cache(struct se_cmd *cmd)
|
||||||
}
|
}
|
||||||
|
|
||||||
static sense_reason_t
|
static sense_reason_t
|
||||||
iblock_do_unmap(struct se_cmd *cmd, struct block_device *bdev,
|
iblock_do_unmap(struct se_cmd *cmd, void *priv,
|
||||||
sector_t lba, sector_t nolb)
|
sector_t lba, sector_t nolb)
|
||||||
{
|
{
|
||||||
|
struct block_device *bdev = priv;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = blkdev_issue_discard(bdev, lba, nolb, GFP_KERNEL, 0);
|
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
|
static sense_reason_t
|
||||||
iblock_execute_unmap(struct se_cmd *cmd)
|
iblock_execute_unmap(struct se_cmd *cmd)
|
||||||
{
|
{
|
||||||
struct se_device *dev = cmd->se_dev;
|
struct block_device *bdev = IBLOCK_DEV(cmd->se_dev)->ibd_bd;
|
||||||
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 */
|
return sbc_execute_unmap(cmd, iblock_do_unmap, bdev);
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
err:
|
|
||||||
transport_kunmap_data_sg(cmd);
|
|
||||||
if (!ret)
|
|
||||||
target_complete_cmd(cmd, GOOD);
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static sense_reason_t
|
static sense_reason_t
|
||||||
|
|
|
@ -596,3 +596,88 @@ u32 sbc_get_device_type(struct se_device *dev)
|
||||||
return TYPE_DISK;
|
return TYPE_DISK;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(sbc_get_device_type);
|
EXPORT_SYMBOL(sbc_get_device_type);
|
||||||
|
|
||||||
|
sense_reason_t
|
||||||
|
sbc_execute_unmap(struct se_cmd *cmd,
|
||||||
|
sense_reason_t (*do_unmap_fn)(struct se_cmd *, void *,
|
||||||
|
sector_t, sector_t),
|
||||||
|
void *priv)
|
||||||
|
{
|
||||||
|
struct se_device *dev = cmd->se_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 = do_unmap_fn(cmd, priv, lba, range);
|
||||||
|
if (ret)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
ptr += 16;
|
||||||
|
size -= 16;
|
||||||
|
}
|
||||||
|
|
||||||
|
err:
|
||||||
|
transport_kunmap_data_sg(cmd);
|
||||||
|
if (!ret)
|
||||||
|
target_complete_cmd(cmd, GOOD);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(sbc_execute_unmap);
|
||||||
|
|
|
@ -60,6 +60,10 @@ sense_reason_t sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops);
|
||||||
u32 sbc_get_device_rev(struct se_device *dev);
|
u32 sbc_get_device_rev(struct se_device *dev);
|
||||||
u32 sbc_get_device_type(struct se_device *dev);
|
u32 sbc_get_device_type(struct se_device *dev);
|
||||||
sector_t sbc_get_write_same_sectors(struct se_cmd *cmd);
|
sector_t sbc_get_write_same_sectors(struct se_cmd *cmd);
|
||||||
|
sense_reason_t sbc_execute_unmap(struct se_cmd *cmd,
|
||||||
|
sense_reason_t (*do_unmap_fn)(struct se_cmd *cmd, void *priv,
|
||||||
|
sector_t lba, sector_t nolb),
|
||||||
|
void *priv);
|
||||||
|
|
||||||
void transport_set_vpd_proto_id(struct t10_vpd *, unsigned char *);
|
void transport_set_vpd_proto_id(struct t10_vpd *, unsigned char *);
|
||||||
int transport_set_vpd_assoc(struct t10_vpd *, unsigned char *);
|
int transport_set_vpd_assoc(struct t10_vpd *, unsigned char *);
|
||||||
|
|
Loading…
Add table
Reference in a new issue