Skip to content

Commit

Permalink
target: Make TCM_WRITE_PROTECT failure honor D_SENSE bit
Browse files Browse the repository at this point in the history
This patch changes transport_lookup_cmd_lun() to obtain
se_lun->lun_ref + se_cmd->se_device rcu_dereference during
TCM_WRITE_PROTECT -> CHECK_CONDITION failure status.

Do this to ensure the active control D_SENSE mode page bit
is being honored.

Reported-by: Sagi Grimberg <sagig@mellanox.com>
Reviewed-by: Sagi Grimberg <sagig@mellanox.com>
Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
  • Loading branch information
Nicholas Bellinger committed Sep 25, 2015
1 parent f3bb467 commit 8fa3a86
Showing 1 changed file with 23 additions and 17 deletions.
40 changes: 23 additions & 17 deletions drivers/target/target_core_device.c
Original file line number Diff line number Diff line change
Expand Up @@ -62,22 +62,13 @@ transport_lookup_cmd_lun(struct se_cmd *se_cmd, u64 unpacked_lun)
struct se_session *se_sess = se_cmd->se_sess;
struct se_node_acl *nacl = se_sess->se_node_acl;
struct se_dev_entry *deve;
sense_reason_t ret = TCM_NO_SENSE;

rcu_read_lock();
deve = target_nacl_find_deve(nacl, unpacked_lun);
if (deve) {
atomic_long_inc(&deve->total_cmds);

if ((se_cmd->data_direction == DMA_TO_DEVICE) &&
(deve->lun_flags & TRANSPORT_LUNFLAGS_READ_ONLY)) {
pr_err("TARGET_CORE[%s]: Detected WRITE_PROTECTED LUN"
" Access for 0x%08llx\n",
se_cmd->se_tfo->get_fabric_name(),
unpacked_lun);
rcu_read_unlock();
return TCM_WRITE_PROTECTED;
}

if (se_cmd->data_direction == DMA_TO_DEVICE)
atomic_long_add(se_cmd->data_length,
&deve->write_bytes);
Expand All @@ -93,6 +84,17 @@ transport_lookup_cmd_lun(struct se_cmd *se_cmd, u64 unpacked_lun)

percpu_ref_get(&se_lun->lun_ref);
se_cmd->lun_ref_active = true;

if ((se_cmd->data_direction == DMA_TO_DEVICE) &&
(deve->lun_flags & TRANSPORT_LUNFLAGS_READ_ONLY)) {
pr_err("TARGET_CORE[%s]: Detected WRITE_PROTECTED LUN"
" Access for 0x%08llx\n",
se_cmd->se_tfo->get_fabric_name(),
unpacked_lun);
rcu_read_unlock();
ret = TCM_WRITE_PROTECTED;
goto ref_dev;
}
}
rcu_read_unlock();

Expand All @@ -109,12 +111,6 @@ transport_lookup_cmd_lun(struct se_cmd *se_cmd, u64 unpacked_lun)
unpacked_lun);
return TCM_NON_EXISTENT_LUN;
}
/*
* Force WRITE PROTECT for virtual LUN 0
*/
if ((se_cmd->data_direction != DMA_FROM_DEVICE) &&
(se_cmd->data_direction != DMA_NONE))
return TCM_WRITE_PROTECTED;

se_lun = se_sess->se_tpg->tpg_virt_lun0;
se_cmd->se_lun = se_sess->se_tpg->tpg_virt_lun0;
Expand All @@ -123,13 +119,23 @@ transport_lookup_cmd_lun(struct se_cmd *se_cmd, u64 unpacked_lun)

percpu_ref_get(&se_lun->lun_ref);
se_cmd->lun_ref_active = true;

/*
* Force WRITE PROTECT for virtual LUN 0
*/
if ((se_cmd->data_direction != DMA_FROM_DEVICE) &&
(se_cmd->data_direction != DMA_NONE)) {
ret = TCM_WRITE_PROTECTED;
goto ref_dev;
}
}
/*
* RCU reference protected by percpu se_lun->lun_ref taken above that
* must drop to zero (including initial reference) before this se_lun
* pointer can be kfree_rcu() by the final se_lun->lun_group put via
* target_core_fabric_configfs.c:target_fabric_port_release
*/
ref_dev:
se_cmd->se_dev = rcu_dereference_raw(se_lun->lun_se_dev);
atomic_long_inc(&se_cmd->se_dev->num_cmds);

Expand All @@ -140,7 +146,7 @@ transport_lookup_cmd_lun(struct se_cmd *se_cmd, u64 unpacked_lun)
atomic_long_add(se_cmd->data_length,
&se_cmd->se_dev->read_bytes);

return 0;
return ret;
}
EXPORT_SYMBOL(transport_lookup_cmd_lun);

Expand Down

0 comments on commit 8fa3a86

Please sign in to comment.