]> Pileus Git - ~andy/linux/blobdiff - drivers/target/target_core_spc.c
nfsd: fix lost nfserrno() call in nfsd_setattr()
[~andy/linux] / drivers / target / target_core_spc.c
index 021c3f4a4f004a8e308825612d0923c48ebe755f..43c5ca9878bc5b6f3f1d675c04779b245ccc1a22 100644 (file)
@@ -100,6 +100,11 @@ spc_emulate_inquiry_std(struct se_cmd *cmd, unsigned char *buf)
         */
        if (dev->dev_attrib.emulate_3pc)
                buf[5] |= 0x8;
+       /*
+        * Set Protection (PROTECT) bit when DIF has been enabled.
+        */
+       if (dev->dev_attrib.pi_prot_type)
+               buf[5] |= 0x1;
 
        buf[7] = 0x2; /* CmdQue=1 */
 
@@ -267,7 +272,7 @@ check_t10_vend_desc:
        port = lun->lun_sep;
        if (port) {
                struct t10_alua_lu_gp *lu_gp;
-               u32 padding, scsi_name_len;
+               u32 padding, scsi_name_len, scsi_target_len;
                u16 lu_gp_id = 0;
                u16 tg_pt_gp_id = 0;
                u16 tpgt;
@@ -365,16 +370,6 @@ check_lu_gp:
                 * section 7.5.1 Table 362
                 */
 check_scsi_name:
-               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 */
-               padding = ((-scsi_name_len) & 3);
-               if (padding != 0)
-                       scsi_name_len += padding;
-               /* Header size + Designation descriptor */
-               scsi_name_len += 4;
-
                buf[off] =
                        (tpg->se_tpg_tfo->get_fabric_proto_ident(tpg) << 4);
                buf[off++] |= 0x3; /* CODE SET == UTF-8 */
@@ -402,13 +397,57 @@ check_scsi_name:
                 * shall be no larger than 256 and shall be a multiple
                 * of four.
                 */
+               padding = ((-scsi_name_len) & 3);
                if (padding)
                        scsi_name_len += padding;
+               if (scsi_name_len > 256)
+                       scsi_name_len = 256;
 
                buf[off-1] = scsi_name_len;
                off += scsi_name_len;
                /* Header size + Designation descriptor */
                len += (scsi_name_len + 4);
+
+               /*
+                * Target device designator
+                */
+               buf[off] =
+                       (tpg->se_tpg_tfo->get_fabric_proto_ident(tpg) << 4);
+               buf[off++] |= 0x3; /* CODE SET == UTF-8 */
+               buf[off] = 0x80; /* Set PIV=1 */
+               /* Set ASSOCIATION == target device: 10b */
+               buf[off] |= 0x20;
+               /* DESIGNATOR TYPE == SCSI name string */
+               buf[off++] |= 0x8;
+               off += 2; /* Skip over Reserved and length */
+               /*
+                * SCSI name string identifer containing, $FABRIC_MOD
+                * dependent information.  For LIO-Target and iSCSI
+                * Target Port, this means "<iSCSI name>" in
+                * UTF-8 encoding.
+                */
+               scsi_target_len = sprintf(&buf[off], "%s",
+                                         tpg->se_tpg_tfo->tpg_get_wwn(tpg));
+               scsi_target_len += 1 /* Include  NULL terminator */;
+               /*
+                * The null-terminated, null-padded (see 4.4.2) SCSI
+                * NAME STRING field contains a UTF-8 format string.
+                * The number of bytes in the SCSI NAME STRING field
+                * (i.e., the value in the DESIGNATOR LENGTH field)
+                * shall be no larger than 256 and shall be a multiple
+                * of four.
+                */
+               padding = ((-scsi_target_len) & 3);
+               if (padding)
+                       scsi_target_len += padding;
+               if (scsi_name_len > 256)
+                       scsi_name_len = 256;
+
+               buf[off-1] = scsi_target_len;
+               off += scsi_target_len;
+
+               /* Header size + Designation descriptor */
+               len += (scsi_target_len + 4);
        }
        buf[2] = ((len >> 8) & 0xff);
        buf[3] = (len & 0xff); /* Page Length for VPD 0x83 */
@@ -436,12 +475,26 @@ spc_emulate_evpd_86(struct se_cmd *cmd, unsigned char *buf)
        struct se_device *dev = cmd->se_dev;
 
        buf[3] = 0x3c;
+       /*
+        * Set GRD_CHK + REF_CHK for TYPE1 protection, or GRD_CHK
+        * only for TYPE3 protection.
+        */
+       if (dev->dev_attrib.pi_prot_type == TARGET_DIF_TYPE1_PROT)
+               buf[4] = 0x5;
+       else if (dev->dev_attrib.pi_prot_type == TARGET_DIF_TYPE3_PROT)
+               buf[4] = 0x4;
+
        /* Set HEADSUP, ORDSUP, SIMPSUP */
        buf[5] = 0x07;
 
        /* If WriteCache emulation is enabled, set V_SUP */
        if (spc_check_dev_wce(dev))
                buf[6] = 0x01;
+       /* If an LBA map is present set R_SUP */
+       spin_lock(&cmd->se_dev->t10_alua.lba_map_lock);
+       if (!list_empty(&dev->t10_alua.lba_map_list))
+               buf[8] = 0x10;
+       spin_unlock(&cmd->se_dev->t10_alua.lba_map_lock);
        return 0;
 }
 
@@ -600,6 +653,20 @@ spc_emulate_evpd_b2(struct se_cmd *cmd, unsigned char *buf)
        return 0;
 }
 
+/* Referrals VPD page */
+static sense_reason_t
+spc_emulate_evpd_b3(struct se_cmd *cmd, unsigned char *buf)
+{
+       struct se_device *dev = cmd->se_dev;
+
+       buf[0] = dev->transport->get_device_type(dev);
+       buf[3] = 0x0c;
+       put_unaligned_be32(dev->t10_alua.lba_map_segment_size, &buf[8]);
+       put_unaligned_be32(dev->t10_alua.lba_map_segment_size, &buf[12]);
+
+       return 0;
+}
+
 static sense_reason_t
 spc_emulate_evpd_00(struct se_cmd *cmd, unsigned char *buf);
 
@@ -614,6 +681,7 @@ static struct {
        { .page = 0xb0, .emulate = spc_emulate_evpd_b0 },
        { .page = 0xb1, .emulate = spc_emulate_evpd_b1 },
        { .page = 0xb2, .emulate = spc_emulate_evpd_b2 },
+       { .page = 0xb3, .emulate = spc_emulate_evpd_b3 },
 };
 
 /* supported vital product data pages */
@@ -643,11 +711,15 @@ spc_emulate_inquiry(struct se_cmd *cmd)
        struct se_portal_group *tpg = cmd->se_lun->lun_sep->sep_tpg;
        unsigned char *rbuf;
        unsigned char *cdb = cmd->t_task_cdb;
-       unsigned char buf[SE_INQUIRY_BUF];
+       unsigned char *buf;
        sense_reason_t ret;
        int p;
 
-       memset(buf, 0, SE_INQUIRY_BUF);
+       buf = kzalloc(SE_INQUIRY_BUF, GFP_KERNEL);
+       if (!buf) {
+               pr_err("Unable to allocate response buffer for INQUIRY\n");
+               return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
+       }
 
        if (dev == tpg->tpg_virt_lun0.lun_se_dev)
                buf[0] = 0x3f; /* Not connected */
@@ -680,9 +752,10 @@ spc_emulate_inquiry(struct se_cmd *cmd)
 out:
        rbuf = transport_kmap_data_sg(cmd);
        if (rbuf) {
-               memcpy(rbuf, buf, min_t(u32, sizeof(buf), cmd->data_length));
+               memcpy(rbuf, buf, min_t(u32, SE_INQUIRY_BUF, cmd->data_length));
                transport_kunmap_data_sg(cmd);
        }
+       kfree(buf);
 
        if (!ret)
                target_complete_cmd(cmd, GOOD);
@@ -785,6 +858,19 @@ static int spc_modesense_control(struct se_device *dev, u8 pc, u8 *p)
         * status (see SAM-4).
         */
        p[5] = (dev->dev_attrib.emulate_tas) ? 0x40 : 0x00;
+       /*
+        * From spc4r30, section 7.5.7 Control mode page
+        *
+        * Application Tag Owner (ATO) bit set to one.
+        *
+        * If the ATO bit is set to one the device server shall not modify the
+        * LOGICAL BLOCK APPLICATION TAG field and, depending on the protection
+        * type, shall not modify the contents of the LOGICAL BLOCK REFERENCE
+        * TAG field.
+        */
+       if (dev->dev_attrib.pi_prot_type)
+               p[5] |= 0x80;
+
        p[8] = 0xff;
        p[9] = 0xff;
        p[11] = 30;