mirror of https://gitee.com/openkylin/linux.git
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: Nicholas Bellinger <nab@linux-iscsi.org>
This commit is contained in:
parent
cd063bef41
commit
773cbaf746
|
@ -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,
|
||||
};
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -71,6 +71,8 @@
|
|||
#define DA_UNMAP_GRANULARITY_DEFAULT 0
|
||||
/* Default unmap_granularity_alignment */
|
||||
#define DA_UNMAP_GRANULARITY_ALIGNMENT_DEFAULT 0
|
||||
/* Default max_write_same_len, disabled by default */
|
||||
#define DA_MAX_WRITE_SAME_LEN 0
|
||||
/* Default max transfer length */
|
||||
#define DA_FABRIC_MAX_SECTORS 8192
|
||||
/* Emulation for Direct Page Out */
|
||||
|
@ -609,6 +611,7 @@ struct se_dev_attrib {
|
|||
u32 max_unmap_block_desc_count;
|
||||
u32 unmap_granularity;
|
||||
u32 unmap_granularity_alignment;
|
||||
u32 max_write_same_len;
|
||||
struct se_device *da_dev;
|
||||
struct config_group da_group;
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue