Commit 9bc6548f authored by Christophe Vu-Brugier's avatar Christophe Vu-Brugier Committed by Nicholas Bellinger

target: do not reject FUA CDBs when write cache is enabled but emulate_write_cache is 0

A check that rejects a CDB with FUA bit set if no write cache is
emulated was added by the following commit:

  fde9f50f target: Add sanity checks for DPO/FUA bit usage

The condition is as follows:

  if (!dev->dev_attrib.emulate_fua_write ||
      !dev->dev_attrib.emulate_write_cache)

However, this check is wrong if the backend device supports WCE but
"emulate_write_cache" is disabled.

This patch uses se_dev_check_wce() (previously named
spc_check_dev_wce) to invoke transport->get_write_cache() if the
device has a write cache or check the "emulate_write_cache" attribute
otherwise.
Reported-by: default avatarChristoph Hellwig <hch@lst.de>
Signed-off-by: default avatarChristophe Vu-Brugier <cvubrugier@fastmail.fm>
Signed-off-by: default avatarNicholas Bellinger <nab@linux-iscsi.org>
parent 5f7da044
...@@ -650,6 +650,18 @@ static u32 se_dev_align_max_sectors(u32 max_sectors, u32 block_size) ...@@ -650,6 +650,18 @@ static u32 se_dev_align_max_sectors(u32 max_sectors, u32 block_size)
return aligned_max_sectors; return aligned_max_sectors;
} }
bool se_dev_check_wce(struct se_device *dev)
{
bool wce = false;
if (dev->transport->get_write_cache)
wce = dev->transport->get_write_cache(dev);
else if (dev->dev_attrib.emulate_write_cache > 0)
wce = true;
return wce;
}
int se_dev_set_max_unmap_lba_count( int se_dev_set_max_unmap_lba_count(
struct se_device *dev, struct se_device *dev,
u32 max_unmap_lba_count) u32 max_unmap_lba_count)
......
...@@ -708,8 +708,7 @@ sbc_check_dpofua(struct se_device *dev, struct se_cmd *cmd, unsigned char *cdb) ...@@ -708,8 +708,7 @@ sbc_check_dpofua(struct se_device *dev, struct se_cmd *cmd, unsigned char *cdb)
} }
} }
if (cdb[1] & 0x8) { if (cdb[1] & 0x8) {
if (!dev->dev_attrib.emulate_fua_write || if (!dev->dev_attrib.emulate_fua_write || !se_dev_check_wce(dev)) {
!dev->dev_attrib.emulate_write_cache) {
pr_err("Got CDB: 0x%02x with FUA bit set, but device" pr_err("Got CDB: 0x%02x with FUA bit set, but device"
" does not advertise support for FUA write\n", " does not advertise support for FUA write\n",
cdb[0]); cdb[0]);
......
...@@ -454,19 +454,6 @@ spc_emulate_evpd_83(struct se_cmd *cmd, unsigned char *buf) ...@@ -454,19 +454,6 @@ spc_emulate_evpd_83(struct se_cmd *cmd, unsigned char *buf)
} }
EXPORT_SYMBOL(spc_emulate_evpd_83); EXPORT_SYMBOL(spc_emulate_evpd_83);
static bool
spc_check_dev_wce(struct se_device *dev)
{
bool wce = false;
if (dev->transport->get_write_cache)
wce = dev->transport->get_write_cache(dev);
else if (dev->dev_attrib.emulate_write_cache > 0)
wce = true;
return wce;
}
/* Extended INQUIRY Data VPD Page */ /* Extended INQUIRY Data VPD Page */
static sense_reason_t static sense_reason_t
spc_emulate_evpd_86(struct se_cmd *cmd, unsigned char *buf) spc_emulate_evpd_86(struct se_cmd *cmd, unsigned char *buf)
...@@ -490,7 +477,7 @@ spc_emulate_evpd_86(struct se_cmd *cmd, unsigned char *buf) ...@@ -490,7 +477,7 @@ spc_emulate_evpd_86(struct se_cmd *cmd, unsigned char *buf)
buf[5] = 0x07; buf[5] = 0x07;
/* If WriteCache emulation is enabled, set V_SUP */ /* If WriteCache emulation is enabled, set V_SUP */
if (spc_check_dev_wce(dev)) if (se_dev_check_wce(dev))
buf[6] = 0x01; buf[6] = 0x01;
/* If an LBA map is present set R_SUP */ /* If an LBA map is present set R_SUP */
spin_lock(&cmd->se_dev->t10_alua.lba_map_lock); spin_lock(&cmd->se_dev->t10_alua.lba_map_lock);
...@@ -897,7 +884,7 @@ static int spc_modesense_caching(struct se_cmd *cmd, u8 pc, u8 *p) ...@@ -897,7 +884,7 @@ static int spc_modesense_caching(struct se_cmd *cmd, u8 pc, u8 *p)
if (pc == 1) if (pc == 1)
goto out; goto out;
if (spc_check_dev_wce(dev)) if (se_dev_check_wce(dev))
p[2] = 0x04; /* Write Cache Enable */ p[2] = 0x04; /* Write Cache Enable */
p[12] = 0x20; /* Disabled Read Ahead */ p[12] = 0x20; /* Disabled Read Ahead */
...@@ -1009,7 +996,7 @@ static sense_reason_t spc_emulate_modesense(struct se_cmd *cmd) ...@@ -1009,7 +996,7 @@ static sense_reason_t spc_emulate_modesense(struct se_cmd *cmd)
(cmd->se_deve->lun_flags & TRANSPORT_LUNFLAGS_READ_ONLY))) (cmd->se_deve->lun_flags & TRANSPORT_LUNFLAGS_READ_ONLY)))
spc_modesense_write_protect(&buf[length], type); spc_modesense_write_protect(&buf[length], type);
if ((spc_check_dev_wce(dev)) && if ((se_dev_check_wce(dev)) &&
(dev->dev_attrib.emulate_fua_write > 0)) (dev->dev_attrib.emulate_fua_write > 0))
spc_modesense_dpofua(&buf[length], type); spc_modesense_dpofua(&buf[length], type);
......
...@@ -111,6 +111,7 @@ void array_free(void *array, int n); ...@@ -111,6 +111,7 @@ void array_free(void *array, int n);
void target_core_setup_sub_cits(struct se_subsystem_api *); void target_core_setup_sub_cits(struct se_subsystem_api *);
/* attribute helpers from target_core_device.c for backend drivers */ /* attribute helpers from target_core_device.c for backend drivers */
bool se_dev_check_wce(struct se_device *);
int se_dev_set_max_unmap_lba_count(struct se_device *, u32); 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_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(struct se_device *, u32);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment