target: Fix WRITE_SAME_[16,32] number of blocks=0 case
[firefly-linux-kernel-4.4.55.git] / drivers / target / target_core_cdb.c
index 7f19c8b7b84c704c0ab74ffdef7a19dca63737e2..8d5a0fc3a22053a8632ec9e7af856c4339b87611 100644 (file)
@@ -64,9 +64,9 @@ target_fill_alua_data(struct se_port *port, unsigned char *buf)
 static int
 target_emulate_inquiry_std(struct se_cmd *cmd)
 {
-       struct se_lun *lun = SE_LUN(cmd);
-       struct se_device *dev = SE_DEV(cmd);
-       unsigned char *buf = cmd->t_task->t_task_buf;
+       struct se_lun *lun = cmd->se_lun;
+       struct se_device *dev = cmd->se_dev;
+       unsigned char *buf = cmd->t_task.t_task_buf;
 
        /*
         * Make sure we at least have 6 bytes of INQUIRY response
@@ -75,7 +75,7 @@ target_emulate_inquiry_std(struct se_cmd *cmd)
        if (cmd->data_length < 6) {
                printk(KERN_ERR "SCSI Inquiry payload length: %u"
                        " too small for EVPD=0\n", cmd->data_length);
-               return -1;
+               return -EINVAL;
        }
 
        buf[0] = dev->transport->get_device_type(dev);
@@ -86,7 +86,7 @@ target_emulate_inquiry_std(struct se_cmd *cmd)
        /*
         * Enable SCCS and TPGS fields for Emulated ALUA
         */
-       if (T10_ALUA(dev->se_sub_dev)->alua_type == SPC3_ALUA_EMULATED)
+       if (dev->se_sub_dev->t10_alua.alua_type == SPC3_ALUA_EMULATED)
                target_fill_alua_data(lun->lun_sep, buf);
 
        if (cmd->data_length < 8) {
@@ -107,9 +107,9 @@ target_emulate_inquiry_std(struct se_cmd *cmd)
 
        snprintf((unsigned char *)&buf[8], 8, "LIO-ORG");
        snprintf((unsigned char *)&buf[16], 16, "%s",
-                &DEV_T10_WWN(dev)->model[0]);
+                &dev->se_sub_dev->t10_wwn.model[0]);
        snprintf((unsigned char *)&buf[32], 4, "%s",
-                &DEV_T10_WWN(dev)->revision[0]);
+                &dev->se_sub_dev->t10_wwn.revision[0]);
        buf[4] = 31; /* Set additional length to 31 */
        return 0;
 }
@@ -128,7 +128,7 @@ target_emulate_evpd_00(struct se_cmd *cmd, unsigned char *buf)
         * Registered Extended LUN WWN has been set via ConfigFS
         * during device creation/restart.
         */
-       if (SE_DEV(cmd)->se_sub_dev->su_dev_flags &
+       if (cmd->se_dev->se_sub_dev->su_dev_flags &
                        SDF_EMULATED_VPD_UNIT_SERIAL) {
                buf[3] = 3;
                buf[5] = 0x80;
@@ -143,7 +143,7 @@ target_emulate_evpd_00(struct se_cmd *cmd, unsigned char *buf)
 static int
 target_emulate_evpd_80(struct se_cmd *cmd, unsigned char *buf)
 {
-       struct se_device *dev = SE_DEV(cmd);
+       struct se_device *dev = cmd->se_dev;
        u16 len = 0;
 
        buf[1] = 0x80;
@@ -152,7 +152,7 @@ target_emulate_evpd_80(struct se_cmd *cmd, unsigned char *buf)
                u32 unit_serial_len;
 
                unit_serial_len =
-                       strlen(&DEV_T10_WWN(dev)->unit_serial[0]);
+                       strlen(&dev->se_sub_dev->t10_wwn.unit_serial[0]);
                unit_serial_len++; /* For NULL Terminator */
 
                if (((len + 4) + unit_serial_len) > cmd->data_length) {
@@ -162,7 +162,7 @@ target_emulate_evpd_80(struct se_cmd *cmd, unsigned char *buf)
                        return 0;
                }
                len += sprintf((unsigned char *)&buf[4], "%s",
-                       &DEV_T10_WWN(dev)->unit_serial[0]);
+                       &dev->se_sub_dev->t10_wwn.unit_serial[0]);
                len++; /* Extra Byte for NULL Terminator */
                buf[3] = len;
        }
@@ -176,15 +176,15 @@ target_emulate_evpd_80(struct se_cmd *cmd, unsigned char *buf)
 static int
 target_emulate_evpd_83(struct se_cmd *cmd, unsigned char *buf)
 {
-       struct se_device *dev = SE_DEV(cmd);
-       struct se_lun *lun = SE_LUN(cmd);
+       struct se_device *dev = cmd->se_dev;
+       struct se_lun *lun = cmd->se_lun;
        struct se_port *port = NULL;
        struct se_portal_group *tpg = NULL;
        struct t10_alua_lu_gp_member *lu_gp_mem;
        struct t10_alua_tg_pt_gp *tg_pt_gp;
        struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem;
        unsigned char binary, binary_new;
-       unsigned char *prod = &DEV_T10_WWN(dev)->model[0];
+       unsigned char *prod = &dev->se_sub_dev->t10_wwn.model[0];
        u32 prod_len;
        u32 unit_serial_len, off = 0;
        int i;
@@ -238,11 +238,11 @@ target_emulate_evpd_83(struct se_cmd *cmd, unsigned char *buf)
         * VENDOR_SPECIFIC_IDENTIFIER_EXTENTION
         */
        binary = transport_asciihex_to_binaryhex(
-                               &DEV_T10_WWN(dev)->unit_serial[0]);
+                               &dev->se_sub_dev->t10_wwn.unit_serial[0]);
        buf[off++] |= (binary & 0xf0) >> 4;
        for (i = 0; i < 24; i += 2) {
                binary_new = transport_asciihex_to_binaryhex(
-                       &DEV_T10_WWN(dev)->unit_serial[i+2]);
+                       &dev->se_sub_dev->t10_wwn.unit_serial[i+2]);
                buf[off] = (binary & 0x0f) << 4;
                buf[off++] |= (binary_new & 0xf0) >> 4;
                binary = binary_new;
@@ -263,7 +263,7 @@ check_t10_vend_desc:
        if (dev->se_sub_dev->su_dev_flags &
                        SDF_EMULATED_VPD_UNIT_SERIAL) {
                unit_serial_len =
-                       strlen(&DEV_T10_WWN(dev)->unit_serial[0]);
+                       strlen(&dev->se_sub_dev->t10_wwn.unit_serial[0]);
                unit_serial_len++; /* For NULL Terminator */
 
                if ((len + (id_len + 4) +
@@ -274,7 +274,7 @@ check_t10_vend_desc:
                }
                id_len += sprintf((unsigned char *)&buf[off+12],
                                "%s:%s", prod,
-                               &DEV_T10_WWN(dev)->unit_serial[0]);
+                               &dev->se_sub_dev->t10_wwn.unit_serial[0]);
        }
        buf[off] = 0x2; /* ASCII */
        buf[off+1] = 0x1; /* T10 Vendor ID */
@@ -312,7 +312,7 @@ check_port:
                        goto check_tpgi;
                }
                buf[off] =
-                       (TPG_TFO(tpg)->get_fabric_proto_ident(tpg) << 4);
+                       (tpg->se_tpg_tfo->get_fabric_proto_ident(tpg) << 4);
                buf[off++] |= 0x1; /* CODE SET == Binary */
                buf[off] = 0x80; /* Set PIV=1 */
                /* Set ASSOICATION == target port: 01b */
@@ -335,7 +335,7 @@ check_port:
                 * section 7.5.1 Table 362
                 */
 check_tpgi:
-               if (T10_ALUA(dev->se_sub_dev)->alua_type !=
+               if (dev->se_sub_dev->t10_alua.alua_type !=
                                SPC3_ALUA_EMULATED)
                        goto check_scsi_name;
 
@@ -357,7 +357,7 @@ check_tpgi:
                spin_unlock(&tg_pt_gp_mem->tg_pt_gp_mem_lock);
 
                buf[off] =
-                       (TPG_TFO(tpg)->get_fabric_proto_ident(tpg) << 4);
+                       (tpg->se_tpg_tfo->get_fabric_proto_ident(tpg) << 4);
                buf[off++] |= 0x1; /* CODE SET == Binary */
                buf[off] = 0x80; /* Set PIV=1 */
                /* Set ASSOICATION == target port: 01b */
@@ -409,7 +409,7 @@ check_lu_gp:
                 * section 7.5.1 Table 362
                 */
 check_scsi_name:
-               scsi_name_len = strlen(TPG_TFO(tpg)->tpg_get_wwn(tpg));
+               scsi_name_len = strlen(tpg->se_tpg_tfo->tpg_get_wwn(tpg));
                /* UTF-8 ",t,0x<16-bit TPGT>" + NULL Terminator */
                scsi_name_len += 10;
                /* Check for 4-byte padding */
@@ -424,7 +424,7 @@ check_scsi_name:
                        goto set_len;
                }
                buf[off] =
-                       (TPG_TFO(tpg)->get_fabric_proto_ident(tpg) << 4);
+                       (tpg->se_tpg_tfo->get_fabric_proto_ident(tpg) << 4);
                buf[off++] |= 0x3; /* CODE SET == UTF-8 */
                buf[off] = 0x80; /* Set PIV=1 */
                /* Set ASSOICATION == target port: 01b */
@@ -438,9 +438,9 @@ check_scsi_name:
                 * Target Port, this means "<iSCSI name>,t,0x<TPGT> in
                 * UTF-8 encoding.
                 */
-               tpgt = TPG_TFO(tpg)->tpg_get_tag(tpg);
+               tpgt = tpg->se_tpg_tfo->tpg_get_tag(tpg);
                scsi_name_len = sprintf(&buf[off], "%s,t,0x%04x",
-                                       TPG_TFO(tpg)->tpg_get_wwn(tpg), tpgt);
+                                       tpg->se_tpg_tfo->tpg_get_wwn(tpg), tpgt);
                scsi_name_len += 1 /* Include  NULL terminator */;
                /*
                 * The null-terminated, null-padded (see 4.4.2) SCSI
@@ -477,7 +477,7 @@ target_emulate_evpd_86(struct se_cmd *cmd, unsigned char *buf)
        buf[5] = 0x07;
 
        /* If WriteCache emulation is enabled, set V_SUP */
-       if (DEV_ATTRIB(SE_DEV(cmd))->emulate_write_cache > 0)
+       if (cmd->se_dev->se_sub_dev->se_dev_attrib.emulate_write_cache > 0)
                buf[6] = 0x01;
        return 0;
 }
@@ -486,7 +486,7 @@ target_emulate_evpd_86(struct se_cmd *cmd, unsigned char *buf)
 static int
 target_emulate_evpd_b0(struct se_cmd *cmd, unsigned char *buf)
 {
-       struct se_device *dev = SE_DEV(cmd);
+       struct se_device *dev = cmd->se_dev;
        int have_tp = 0;
 
        /*
@@ -494,14 +494,14 @@ target_emulate_evpd_b0(struct se_cmd *cmd, unsigned char *buf)
         * emulate_tpu=1 or emulate_tpws=1 we will be expect a
         * different page length for Thin Provisioning.
         */
-       if (DEV_ATTRIB(dev)->emulate_tpu || DEV_ATTRIB(dev)->emulate_tpws)
+       if (dev->se_sub_dev->se_dev_attrib.emulate_tpu || dev->se_sub_dev->se_dev_attrib.emulate_tpws)
                have_tp = 1;
 
        if (cmd->data_length < (0x10 + 4)) {
                printk(KERN_INFO "Received data_length: %u"
                        " too small for EVPD 0xb0\n",
                        cmd->data_length);
-               return -1;
+               return -EINVAL;
        }
 
        if (have_tp && cmd->data_length < (0x3c + 4)) {
@@ -523,12 +523,12 @@ target_emulate_evpd_b0(struct se_cmd *cmd, unsigned char *buf)
        /*
         * Set MAXIMUM TRANSFER LENGTH
         */
-       put_unaligned_be32(DEV_ATTRIB(dev)->max_sectors, &buf[8]);
+       put_unaligned_be32(dev->se_sub_dev->se_dev_attrib.max_sectors, &buf[8]);
 
        /*
         * Set OPTIMAL TRANSFER LENGTH
         */
-       put_unaligned_be32(DEV_ATTRIB(dev)->optimal_sectors, &buf[12]);
+       put_unaligned_be32(dev->se_sub_dev->se_dev_attrib.optimal_sectors, &buf[12]);
 
        /*
         * Exit now if we don't support TP or the initiator sent a too
@@ -540,25 +540,25 @@ target_emulate_evpd_b0(struct se_cmd *cmd, unsigned char *buf)
        /*
         * Set MAXIMUM UNMAP LBA COUNT
         */
-       put_unaligned_be32(DEV_ATTRIB(dev)->max_unmap_lba_count, &buf[20]);
+       put_unaligned_be32(dev->se_sub_dev->se_dev_attrib.max_unmap_lba_count, &buf[20]);
 
        /*
         * Set MAXIMUM UNMAP BLOCK DESCRIPTOR COUNT
         */
-       put_unaligned_be32(DEV_ATTRIB(dev)->max_unmap_block_desc_count,
+       put_unaligned_be32(dev->se_sub_dev->se_dev_attrib.max_unmap_block_desc_count,
                           &buf[24]);
 
        /*
         * Set OPTIMAL UNMAP GRANULARITY
         */
-       put_unaligned_be32(DEV_ATTRIB(dev)->unmap_granularity, &buf[28]);
+       put_unaligned_be32(dev->se_sub_dev->se_dev_attrib.unmap_granularity, &buf[28]);
 
        /*
         * UNMAP GRANULARITY ALIGNMENT
         */
-       put_unaligned_be32(DEV_ATTRIB(dev)->unmap_granularity_alignment,
+       put_unaligned_be32(dev->se_sub_dev->se_dev_attrib.unmap_granularity_alignment,
                           &buf[32]);
-       if (DEV_ATTRIB(dev)->unmap_granularity_alignment != 0)
+       if (dev->se_sub_dev->se_dev_attrib.unmap_granularity_alignment != 0)
                buf[32] |= 0x80; /* Set the UGAVALID bit */
 
        return 0;
@@ -568,7 +568,7 @@ target_emulate_evpd_b0(struct se_cmd *cmd, unsigned char *buf)
 static int
 target_emulate_evpd_b2(struct se_cmd *cmd, unsigned char *buf)
 {
-       struct se_device *dev = SE_DEV(cmd);
+       struct se_device *dev = cmd->se_dev;
 
        /*
         * From sbc3r22 section 6.5.4 Thin Provisioning VPD page:
@@ -602,7 +602,7 @@ target_emulate_evpd_b2(struct se_cmd *cmd, unsigned char *buf)
         * the UNMAP command (see 5.25). A TPU bit set to zero indicates
         * that the device server does not support the UNMAP command.
         */
-       if (DEV_ATTRIB(dev)->emulate_tpu != 0)
+       if (dev->se_sub_dev->se_dev_attrib.emulate_tpu != 0)
                buf[5] = 0x80;
 
        /*
@@ -611,7 +611,7 @@ target_emulate_evpd_b2(struct se_cmd *cmd, unsigned char *buf)
         * A TPWS bit set to zero indicates that the device server does not
         * support the use of the WRITE SAME (16) command to unmap LBAs.
         */
-       if (DEV_ATTRIB(dev)->emulate_tpws != 0)
+       if (dev->se_sub_dev->se_dev_attrib.emulate_tpws != 0)
                buf[5] |= 0x40;
 
        return 0;
@@ -620,9 +620,9 @@ target_emulate_evpd_b2(struct se_cmd *cmd, unsigned char *buf)
 static int
 target_emulate_inquiry(struct se_cmd *cmd)
 {
-       struct se_device *dev = SE_DEV(cmd);
-       unsigned char *buf = cmd->t_task->t_task_buf;
-       unsigned char *cdb = cmd->t_task->t_task_cdb;
+       struct se_device *dev = cmd->se_dev;
+       unsigned char *buf = cmd->t_task.t_task_buf;
+       unsigned char *cdb = cmd->t_task.t_task_cdb;
 
        if (!(cdb[1] & 0x1))
                return target_emulate_inquiry_std(cmd);
@@ -637,7 +637,7 @@ target_emulate_inquiry(struct se_cmd *cmd)
        if (cmd->data_length < 4) {
                printk(KERN_ERR "SCSI Inquiry payload length: %u"
                        " too small for EVPD=1\n", cmd->data_length);
-               return -1;
+               return -EINVAL;
        }
        buf[0] = dev->transport->get_device_type(dev);
 
@@ -656,7 +656,7 @@ target_emulate_inquiry(struct se_cmd *cmd)
                return target_emulate_evpd_b2(cmd, buf);
        default:
                printk(KERN_ERR "Unknown VPD Code: 0x%02x\n", cdb[2]);
-               return -1;
+               return -EINVAL;
        }
 
        return 0;
@@ -665,8 +665,8 @@ target_emulate_inquiry(struct se_cmd *cmd)
 static int
 target_emulate_readcapacity(struct se_cmd *cmd)
 {
-       struct se_device *dev = SE_DEV(cmd);
-       unsigned char *buf = cmd->t_task->t_task_buf;
+       struct se_device *dev = cmd->se_dev;
+       unsigned char *buf = cmd->t_task.t_task_buf;
        unsigned long long blocks_long = dev->transport->get_blocks(dev);
        u32 blocks;
 
@@ -679,14 +679,14 @@ target_emulate_readcapacity(struct se_cmd *cmd)
        buf[1] = (blocks >> 16) & 0xff;
        buf[2] = (blocks >> 8) & 0xff;
        buf[3] = blocks & 0xff;
-       buf[4] = (DEV_ATTRIB(dev)->block_size >> 24) & 0xff;
-       buf[5] = (DEV_ATTRIB(dev)->block_size >> 16) & 0xff;
-       buf[6] = (DEV_ATTRIB(dev)->block_size >> 8) & 0xff;
-       buf[7] = DEV_ATTRIB(dev)->block_size & 0xff;
+       buf[4] = (dev->se_sub_dev->se_dev_attrib.block_size >> 24) & 0xff;
+       buf[5] = (dev->se_sub_dev->se_dev_attrib.block_size >> 16) & 0xff;
+       buf[6] = (dev->se_sub_dev->se_dev_attrib.block_size >> 8) & 0xff;
+       buf[7] = dev->se_sub_dev->se_dev_attrib.block_size & 0xff;
        /*
         * Set max 32-bit blocks to signal SERVICE ACTION READ_CAPACITY_16
        */
-       if (DEV_ATTRIB(dev)->emulate_tpu || DEV_ATTRIB(dev)->emulate_tpws)
+       if (dev->se_sub_dev->se_dev_attrib.emulate_tpu || dev->se_sub_dev->se_dev_attrib.emulate_tpws)
                put_unaligned_be32(0xFFFFFFFF, &buf[0]);
 
        return 0;
@@ -695,8 +695,8 @@ target_emulate_readcapacity(struct se_cmd *cmd)
 static int
 target_emulate_readcapacity_16(struct se_cmd *cmd)
 {
-       struct se_device *dev = SE_DEV(cmd);
-       unsigned char *buf = cmd->t_task->t_task_buf;
+       struct se_device *dev = cmd->se_dev;
+       unsigned char *buf = cmd->t_task.t_task_buf;
        unsigned long long blocks = dev->transport->get_blocks(dev);
 
        buf[0] = (blocks >> 56) & 0xff;
@@ -707,15 +707,15 @@ target_emulate_readcapacity_16(struct se_cmd *cmd)
        buf[5] = (blocks >> 16) & 0xff;
        buf[6] = (blocks >> 8) & 0xff;
        buf[7] = blocks & 0xff;
-       buf[8] = (DEV_ATTRIB(dev)->block_size >> 24) & 0xff;
-       buf[9] = (DEV_ATTRIB(dev)->block_size >> 16) & 0xff;
-       buf[10] = (DEV_ATTRIB(dev)->block_size >> 8) & 0xff;
-       buf[11] = DEV_ATTRIB(dev)->block_size & 0xff;
+       buf[8] = (dev->se_sub_dev->se_dev_attrib.block_size >> 24) & 0xff;
+       buf[9] = (dev->se_sub_dev->se_dev_attrib.block_size >> 16) & 0xff;
+       buf[10] = (dev->se_sub_dev->se_dev_attrib.block_size >> 8) & 0xff;
+       buf[11] = dev->se_sub_dev->se_dev_attrib.block_size & 0xff;
        /*
         * Set Thin Provisioning Enable bit following sbc3r22 in section
         * READ CAPACITY (16) byte 14 if emulate_tpu or emulate_tpws is enabled.
         */
-       if (DEV_ATTRIB(dev)->emulate_tpu || DEV_ATTRIB(dev)->emulate_tpws)
+       if (dev->se_sub_dev->se_dev_attrib.emulate_tpu || dev->se_sub_dev->se_dev_attrib.emulate_tpws)
                buf[14] = 0x80;
 
        return 0;
@@ -765,8 +765,8 @@ target_modesense_control(struct se_device *dev, unsigned char *p)
         * for a BUSY, TASK SET FULL, or RESERVATION CONFLICT status regardless
         * to the number of commands completed with one of those status codes.
         */
-       p[4] = (DEV_ATTRIB(dev)->emulate_ua_intlck_ctrl == 2) ? 0x30 :
-              (DEV_ATTRIB(dev)->emulate_ua_intlck_ctrl == 1) ? 0x20 : 0x00;
+       p[4] = (dev->se_sub_dev->se_dev_attrib.emulate_ua_intlck_ctrl == 2) ? 0x30 :
+              (dev->se_sub_dev->se_dev_attrib.emulate_ua_intlck_ctrl == 1) ? 0x20 : 0x00;
        /*
         * From spc4r17, section 7.4.6 Control mode Page
         *
@@ -779,7 +779,7 @@ target_modesense_control(struct se_device *dev, unsigned char *p)
         * which the command was received shall be completed with TASK ABORTED
         * status (see SAM-4).
         */
-       p[5] = (DEV_ATTRIB(dev)->emulate_tas) ? 0x40 : 0x00;
+       p[5] = (dev->se_sub_dev->se_dev_attrib.emulate_tas) ? 0x40 : 0x00;
        p[8] = 0xff;
        p[9] = 0xff;
        p[11] = 30;
@@ -792,7 +792,7 @@ target_modesense_caching(struct se_device *dev, unsigned char *p)
 {
        p[0] = 0x08;
        p[1] = 0x12;
-       if (DEV_ATTRIB(dev)->emulate_write_cache > 0)
+       if (dev->se_sub_dev->se_dev_attrib.emulate_write_cache > 0)
                p[2] = 0x04; /* Write Cache Enable */
        p[12] = 0x20; /* Disabled Read Ahead */
 
@@ -830,9 +830,9 @@ target_modesense_dpofua(unsigned char *buf, int type)
 static int
 target_emulate_modesense(struct se_cmd *cmd, int ten)
 {
-       struct se_device *dev = SE_DEV(cmd);
-       char *cdb = cmd->t_task->t_task_cdb;
-       unsigned char *rbuf = cmd->t_task->t_task_buf;
+       struct se_device *dev = cmd->se_dev;
+       char *cdb = cmd->t_task.t_task_cdb;
+       unsigned char *rbuf = cmd->t_task.t_task_buf;
        int type = dev->transport->get_device_type(dev);
        int offset = (ten) ? 8 : 4;
        int length = 0;
@@ -867,13 +867,13 @@ target_emulate_modesense(struct se_cmd *cmd, int ten)
                buf[0] = (offset >> 8) & 0xff;
                buf[1] = offset & 0xff;
 
-               if ((SE_LUN(cmd)->lun_access & TRANSPORT_LUNFLAGS_READ_ONLY) ||
+               if ((cmd->se_lun->lun_access & TRANSPORT_LUNFLAGS_READ_ONLY) ||
                    (cmd->se_deve &&
                    (cmd->se_deve->lun_flags & TRANSPORT_LUNFLAGS_READ_ONLY)))
                        target_modesense_write_protect(&buf[3], type);
 
-               if ((DEV_ATTRIB(dev)->emulate_write_cache > 0) &&
-                   (DEV_ATTRIB(dev)->emulate_fua_write > 0))
+               if ((dev->se_sub_dev->se_dev_attrib.emulate_write_cache > 0) &&
+                   (dev->se_sub_dev->se_dev_attrib.emulate_fua_write > 0))
                        target_modesense_dpofua(&buf[3], type);
 
                if ((offset + 2) > cmd->data_length)
@@ -883,13 +883,13 @@ target_emulate_modesense(struct se_cmd *cmd, int ten)
                offset -= 1;
                buf[0] = offset & 0xff;
 
-               if ((SE_LUN(cmd)->lun_access & TRANSPORT_LUNFLAGS_READ_ONLY) ||
+               if ((cmd->se_lun->lun_access & TRANSPORT_LUNFLAGS_READ_ONLY) ||
                    (cmd->se_deve &&
                    (cmd->se_deve->lun_flags & TRANSPORT_LUNFLAGS_READ_ONLY)))
                        target_modesense_write_protect(&buf[2], type);
 
-               if ((DEV_ATTRIB(dev)->emulate_write_cache > 0) &&
-                   (DEV_ATTRIB(dev)->emulate_fua_write > 0))
+               if ((dev->se_sub_dev->se_dev_attrib.emulate_write_cache > 0) &&
+                   (dev->se_sub_dev->se_dev_attrib.emulate_fua_write > 0))
                        target_modesense_dpofua(&buf[2], type);
 
                if ((offset + 1) > cmd->data_length)
@@ -903,8 +903,8 @@ target_emulate_modesense(struct se_cmd *cmd, int ten)
 static int
 target_emulate_request_sense(struct se_cmd *cmd)
 {
-       unsigned char *cdb = cmd->t_task->t_task_cdb;
-       unsigned char *buf = cmd->t_task->t_task_buf;
+       unsigned char *cdb = cmd->t_task.t_task_cdb;
+       unsigned char *buf = cmd->t_task.t_task_buf;
        u8 ua_asc = 0, ua_ascq = 0;
 
        if (cdb[1] & 0x01) {
@@ -963,10 +963,10 @@ target_emulate_request_sense(struct se_cmd *cmd)
 static int
 target_emulate_unmap(struct se_task *task)
 {
-       struct se_cmd *cmd = TASK_CMD(task);
-       struct se_device *dev = SE_DEV(cmd);
-       unsigned char *buf = cmd->t_task->t_task_buf, *ptr = NULL;
-       unsigned char *cdb = &cmd->t_task->t_task_cdb[0];
+       struct se_cmd *cmd = task->task_se_cmd;
+       struct se_device *dev = cmd->se_dev;
+       unsigned char *buf = cmd->t_task.t_task_buf, *ptr = NULL;
+       unsigned char *cdb = &cmd->t_task.t_task_cdb[0];
        sector_t lba;
        unsigned int size = cmd->data_length, range;
        int ret, offset;
@@ -991,7 +991,7 @@ target_emulate_unmap(struct se_task *task)
                if (ret < 0) {
                        printk(KERN_ERR "blkdev_issue_discard() failed: %d\n",
                                        ret);
-                       return -1;
+                       return ret;
                }
 
                ptr += 16;
@@ -1008,23 +1008,35 @@ target_emulate_unmap(struct se_task *task)
  * Note this is not used for TCM/pSCSI passthrough
  */
 static int
-target_emulate_write_same(struct se_task *task)
+target_emulate_write_same(struct se_task *task, int write_same32)
 {
-       struct se_cmd *cmd = TASK_CMD(task);
-       struct se_device *dev = SE_DEV(cmd);
-       sector_t lba = cmd->t_task->t_task_lba;
-       unsigned int range;
+       struct se_cmd *cmd = task->task_se_cmd;
+       struct se_device *dev = cmd->se_dev;
+       sector_t range, lba = cmd->t_task.t_task_lba;
+       unsigned int num_blocks;
        int ret;
+       /*
+        * Extract num_blocks from the WRITE_SAME_* CDB.  Then use the explict
+        * range when non zero is supplied, otherwise calculate the remaining
+        * range based on ->get_blocks() - starting LBA.
+        */
+       if (write_same32)
+               num_blocks = get_unaligned_be32(&cmd->t_task.t_task_cdb[28]);
+       else
+               num_blocks = get_unaligned_be32(&cmd->t_task.t_task_cdb[10]);
 
-       range = (cmd->data_length / DEV_ATTRIB(dev)->block_size);
+       if (num_blocks != 0)
+               range = num_blocks;
+       else
+               range = (dev->transport->get_blocks(dev) - lba);
 
-       printk(KERN_INFO "WRITE_SAME UNMAP: LBA: %llu Range: %u\n",
-                        (unsigned long long)lba, range);
+       printk(KERN_INFO "WRITE_SAME UNMAP: LBA: %llu Range: %llu\n",
+                (unsigned long long)lba, (unsigned long long)range);
 
        ret = dev->transport->do_discard(dev, lba, range);
        if (ret < 0) {
                printk(KERN_INFO "blkdev_issue_discard() failed for WRITE_SAME\n");
-               return -1;
+               return ret;
        }
 
        task->task_scsi_status = GOOD;
@@ -1035,12 +1047,12 @@ target_emulate_write_same(struct se_task *task)
 int
 transport_emulate_control_cdb(struct se_task *task)
 {
-       struct se_cmd *cmd = TASK_CMD(task);
-       struct se_device *dev = SE_DEV(cmd);
+       struct se_cmd *cmd = task->task_se_cmd;
+       struct se_device *dev = cmd->se_dev;
        unsigned short service_action;
        int ret = 0;
 
-       switch (cmd->t_task->t_task_cdb[0]) {
+       switch (cmd->t_task.t_task_cdb[0]) {
        case INQUIRY:
                ret = target_emulate_inquiry(cmd);
                break;
@@ -1054,13 +1066,13 @@ transport_emulate_control_cdb(struct se_task *task)
                ret = target_emulate_modesense(cmd, 1);
                break;
        case SERVICE_ACTION_IN:
-               switch (cmd->t_task->t_task_cdb[1] & 0x1f) {
+               switch (cmd->t_task.t_task_cdb[1] & 0x1f) {
                case SAI_READ_CAPACITY_16:
                        ret = target_emulate_readcapacity_16(cmd);
                        break;
                default:
                        printk(KERN_ERR "Unsupported SA: 0x%02x\n",
-                               cmd->t_task->t_task_cdb[1] & 0x1f);
+                               cmd->t_task.t_task_cdb[1] & 0x1f);
                        return PYX_TRANSPORT_UNKNOWN_SAM_OPCODE;
                }
                break;
@@ -1081,11 +1093,11 @@ transport_emulate_control_cdb(struct se_task *task)
                                        " for: %s\n", dev->transport->name);
                        return PYX_TRANSPORT_UNKNOWN_SAM_OPCODE;
                }
-               ret = target_emulate_write_same(task);
+               ret = target_emulate_write_same(task, 0);
                break;
        case VARIABLE_LENGTH_CMD:
                service_action =
-                       get_unaligned_be16(&cmd->t_task->t_task_cdb[8]);
+                       get_unaligned_be16(&cmd->t_task.t_task_cdb[8]);
                switch (service_action) {
                case WRITE_SAME_32:
                        if (!dev->transport->do_discard) {
@@ -1094,7 +1106,7 @@ transport_emulate_control_cdb(struct se_task *task)
                                        dev->transport->name);
                                return PYX_TRANSPORT_UNKNOWN_SAM_OPCODE;
                        }
-                       ret = target_emulate_write_same(task);
+                       ret = target_emulate_write_same(task, 1);
                        break;
                default:
                        printk(KERN_ERR "Unsupported VARIABLE_LENGTH_CMD SA:"
@@ -1124,7 +1136,7 @@ transport_emulate_control_cdb(struct se_task *task)
                break;
        default:
                printk(KERN_ERR "Unsupported SCSI Opcode: 0x%02x for %s\n",
-                       cmd->t_task->t_task_cdb[0], dev->transport->name);
+                       cmd->t_task.t_task_cdb[0], dev->transport->name);
                return PYX_TRANSPORT_UNKNOWN_SAM_OPCODE;
        }