Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 773cbaf7 authored by Nicholas Bellinger's avatar Nicholas Bellinger
Browse files

target: Add/check max_write_same_len device attribute + update block limits VPD



This patch adds a new max_write_same_len device attribute for use with
WRITE_SAME w/ UNMAP=0 backend emulation.  This can be useful for
lowering the default backend value (IBLOCK uses 0xFFFF).

Also, update block limits VPD emulation code in spc_emulate_evpd_b0() to
report MAXIMUM WRITE SAME LENGTH, and enforce max_write_same_len during
sbc_parse() -> sbc_setup_write_same() CDB sanity checking for all emulated
WRITE_SAME w/ UNMAP=0 cases.

(Robert: Move max_write_same_len check in sbc_setup_write_same() to
         check both WRITE_SAME w/ UNMAP=1 and w/ UNMAP=0 cases)

Cc: Christoph Hellwig <hch@lst.de>
Cc: Martin K. Petersen <martin.petersen@oracle.com>
Cc: Robert Elliott <Elliott@hp.com>
Signed-off-by: default avatarNicholas Bellinger <nab@linux-iscsi.org>
parent cd063bef
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -676,6 +676,9 @@ SE_DEV_ATTR(unmap_granularity, S_IRUGO | S_IWUSR);
DEF_DEV_ATTRIB(unmap_granularity_alignment);
SE_DEV_ATTR(unmap_granularity_alignment, S_IRUGO | S_IWUSR);

DEF_DEV_ATTRIB(max_write_same_len);
SE_DEV_ATTR(max_write_same_len, S_IRUGO | S_IWUSR);

CONFIGFS_EATTR_OPS(target_core_dev_attrib, se_dev_attrib, da_group);

static struct configfs_attribute *target_core_dev_attrib_attrs[] = {
@@ -701,6 +704,7 @@ static struct configfs_attribute *target_core_dev_attrib_attrs[] = {
	&target_core_dev_attrib_max_unmap_block_desc_count.attr,
	&target_core_dev_attrib_unmap_granularity.attr,
	&target_core_dev_attrib_unmap_granularity_alignment.attr,
	&target_core_dev_attrib_max_write_same_len.attr,
	NULL,
};

+11 −0
Original line number Diff line number Diff line
@@ -706,6 +706,16 @@ int se_dev_set_unmap_granularity_alignment(
	return 0;
}

int se_dev_set_max_write_same_len(
	struct se_device *dev,
	u32 max_write_same_len)
{
	dev->dev_attrib.max_write_same_len = max_write_same_len;
	pr_debug("dev[%p]: Set max_write_same_len: %u\n",
			dev, dev->dev_attrib.max_write_same_len);
	return 0;
}

int se_dev_set_emulate_dpo(struct se_device *dev, int flag)
{
	if (flag != 0 && flag != 1) {
@@ -1393,6 +1403,7 @@ struct se_device *target_alloc_device(struct se_hba *hba, const char *name)
	dev->dev_attrib.unmap_granularity = DA_UNMAP_GRANULARITY_DEFAULT;
	dev->dev_attrib.unmap_granularity_alignment =
				DA_UNMAP_GRANULARITY_ALIGNMENT_DEFAULT;
	dev->dev_attrib.max_write_same_len = DA_MAX_WRITE_SAME_LEN;
	dev->dev_attrib.fabric_max_sectors = DA_FABRIC_MAX_SECTORS;
	dev->dev_attrib.optimal_sectors = DA_FABRIC_MAX_SECTORS;

+1 −0
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@ int se_dev_set_max_unmap_lba_count(struct se_device *, u32);
int	se_dev_set_max_unmap_block_desc_count(struct se_device *, u32);
int	se_dev_set_unmap_granularity(struct se_device *, u32);
int	se_dev_set_unmap_granularity_alignment(struct se_device *, u32);
int	se_dev_set_max_write_same_len(struct se_device *, u32);
int	se_dev_set_emulate_dpo(struct se_device *, int);
int	se_dev_set_emulate_fua_write(struct se_device *, int);
int	se_dev_set_emulate_fua_read(struct se_device *, int);
+7 −0
Original line number Diff line number Diff line
@@ -238,12 +238,19 @@ static inline unsigned long long transport_lba_64_ext(unsigned char *cdb)
static sense_reason_t
sbc_setup_write_same(struct se_cmd *cmd, unsigned char *flags, struct sbc_ops *ops)
{
	unsigned int sectors = spc_get_write_same_sectors(cmd);

	if ((flags[0] & 0x04) || (flags[0] & 0x02)) {
		pr_err("WRITE_SAME PBDATA and LBDATA"
			" bits not supported for Block Discard"
			" Emulation\n");
		return TCM_UNSUPPORTED_SCSI_OPCODE;
	}
	if (sectors > cmd->se_dev->dev_attrib.max_write_same_len) {
		pr_warn("WRITE_SAME sectors: %u exceeds max_write_same_len: %u\n",
			sectors, cmd->se_dev->dev_attrib.max_write_same_len);
		return TCM_INVALID_CDB_FIELD;
	}
	/*
	 * Special case for WRITE_SAME w/ UNMAP=1 that ends up getting
	 * translated into block discard requests within backend code.
+7 −1
Original line number Diff line number Diff line
@@ -465,7 +465,7 @@ spc_emulate_evpd_b0(struct se_cmd *cmd, unsigned char *buf)
	 * Exit now if we don't support TP.
	 */
	if (!have_tp)
		return 0;
		goto max_write_same;

	/*
	 * Set MAXIMUM UNMAP LBA COUNT
@@ -491,6 +491,12 @@ spc_emulate_evpd_b0(struct se_cmd *cmd, unsigned char *buf)
	if (dev->dev_attrib.unmap_granularity_alignment != 0)
		buf[32] |= 0x80; /* Set the UGAVALID bit */

	/*
	 * MAXIMUM WRITE SAME LENGTH
	 */
max_write_same:
	put_unaligned_be64(dev->dev_attrib.max_write_same_len, &buf[36]);

	return 0;
}

Loading