target: Add sbc_execute_unmap() helper
authorAsias He <asias@redhat.com>
Mon, 25 Feb 2013 06:03:46 +0000 (14:03 +0800)
committerNicholas Bellinger <nab@linux-iscsi.org>
Thu, 25 Apr 2013 08:05:24 +0000 (01:05 -0700)
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>
drivers/target/target_core_file.c
drivers/target/target_core_iblock.c
drivers/target/target_core_sbc.c
include/target/target_core_backend.h

index d5b84fa..9063c31 100644 (file)
@@ -480,8 +480,9 @@ fd_execute_write_same(struct se_cmd *cmd)
 }
 
 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;
        int ret;
 
@@ -542,84 +543,9 @@ fd_execute_write_same_unmap(struct se_cmd *cmd)
 static sense_reason_t
 fd_execute_unmap(struct se_cmd *cmd)
 {
-       struct se_device *dev = cmd->se_dev;
-       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 */
-       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]);
+       struct file *file = FD_DEV(cmd->se_dev)->fd_file;
 
-       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;
+       return sbc_execute_unmap(cmd, fd_do_unmap, file);
 }
 
 static sense_reason_t
index 96a9b62..07f5f94 100644 (file)
@@ -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 *bdev,
+iblock_do_unmap(struct se_cmd *cmd, void *priv,
                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
index 60d4b51..bbc5b0e 100644 (file)
@@ -596,3 +596,88 @@ u32 sbc_get_device_type(struct se_device *dev)
        return TYPE_DISK;
 }
 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);
index b128c20..ffa2696 100644 (file)
@@ -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_type(struct se_device *dev);
 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 *);
 int    transport_set_vpd_assoc(struct t10_vpd *, unsigned char *);