Merge tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi
Pull SCSI updates from James Bottomley: :This series consists of the usual driver updates (qla2xxx, ufs, zfcp, target, scsi_debug, lpfc, qedi, qedf, hisi_sas, mpt3sas) plus a host of other minor updates. There are no major core changes in this series apart from a refactoring in scsi_lib.c" * tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi: (207 commits) scsi: ufs: ti-j721e-ufs: Fix unwinding of pm_runtime changes scsi: cxgb3i: Fix some leaks in init_act_open() scsi: ibmvscsi: Make some functions static scsi: iscsi: Fix deadlock on recovery path during GFP_IO reclaim scsi: ufs: Fix WriteBooster flush during runtime suspend scsi: ufs: Fix index of attributes query for WriteBooster feature scsi: ufs: Allow WriteBooster on UFS 2.2 devices scsi: ufs: Remove unnecessary memset for dev_info scsi: ufs-qcom: Fix scheduling while atomic issue scsi: mpt3sas: Fix reply queue count in non RDPQ mode scsi: lpfc: Fix lpfc_nodelist leak when processing unsolicited event scsi: target: tcmu: Fix a use after free in tcmu_check_expired_queue_cmd() scsi: vhost: Notify TCM about the maximum sg entries supported per command scsi: qla2xxx: Remove return value from qla_nvme_ls() scsi: qla2xxx: Remove an unused function scsi: iscsi: Register sysfs for iscsi workqueue scsi: scsi_debug: Parser tables and code interaction scsi: core: Refactor scsi_mq_setup_tags function scsi: core: Fix incorrect usage of shost_for_each_device scsi: qla2xxx: Fix endianness annotations in source files ...
This commit is contained in:
@@ -1228,18 +1228,20 @@ void iscsit_print_session_params(struct iscsi_session *sess)
|
||||
iscsi_dump_sess_ops(sess->sess_ops);
|
||||
}
|
||||
|
||||
static int iscsit_do_rx_data(
|
||||
int rx_data(
|
||||
struct iscsi_conn *conn,
|
||||
struct iscsi_data_count *count)
|
||||
struct kvec *iov,
|
||||
int iov_count,
|
||||
int data)
|
||||
{
|
||||
int data = count->data_length, rx_loop = 0, total_rx = 0;
|
||||
int rx_loop = 0, total_rx = 0;
|
||||
struct msghdr msg;
|
||||
|
||||
if (!conn || !conn->sock || !conn->conn_ops)
|
||||
return -1;
|
||||
|
||||
memset(&msg, 0, sizeof(struct msghdr));
|
||||
iov_iter_kvec(&msg.msg_iter, READ, count->iov, count->iov_count, data);
|
||||
iov_iter_kvec(&msg.msg_iter, READ, iov, iov_count, data);
|
||||
|
||||
while (msg_data_left(&msg)) {
|
||||
rx_loop = sock_recvmsg(conn->sock, &msg, MSG_WAITALL);
|
||||
@@ -1256,26 +1258,6 @@ static int iscsit_do_rx_data(
|
||||
return total_rx;
|
||||
}
|
||||
|
||||
int rx_data(
|
||||
struct iscsi_conn *conn,
|
||||
struct kvec *iov,
|
||||
int iov_count,
|
||||
int data)
|
||||
{
|
||||
struct iscsi_data_count c;
|
||||
|
||||
if (!conn || !conn->sock || !conn->conn_ops)
|
||||
return -1;
|
||||
|
||||
memset(&c, 0, sizeof(struct iscsi_data_count));
|
||||
c.iov = iov;
|
||||
c.iov_count = iov_count;
|
||||
c.data_length = data;
|
||||
c.type = ISCSI_RX_DATA;
|
||||
|
||||
return iscsit_do_rx_data(conn, &c);
|
||||
}
|
||||
|
||||
int tx_data(
|
||||
struct iscsi_conn *conn,
|
||||
struct kvec *iov,
|
||||
|
@@ -545,32 +545,15 @@ static int tcm_loop_write_pending(struct se_cmd *se_cmd)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tcm_loop_queue_data_in(struct se_cmd *se_cmd)
|
||||
static int tcm_loop_queue_data_or_status(const char *func,
|
||||
struct se_cmd *se_cmd, u8 scsi_status)
|
||||
{
|
||||
struct tcm_loop_cmd *tl_cmd = container_of(se_cmd,
|
||||
struct tcm_loop_cmd, tl_se_cmd);
|
||||
struct scsi_cmnd *sc = tl_cmd->sc;
|
||||
|
||||
pr_debug("%s() called for scsi_cmnd: %p cdb: 0x%02x\n",
|
||||
__func__, sc, sc->cmnd[0]);
|
||||
|
||||
sc->result = SAM_STAT_GOOD;
|
||||
set_host_byte(sc, DID_OK);
|
||||
if ((se_cmd->se_cmd_flags & SCF_OVERFLOW_BIT) ||
|
||||
(se_cmd->se_cmd_flags & SCF_UNDERFLOW_BIT))
|
||||
scsi_set_resid(sc, se_cmd->residual_count);
|
||||
sc->scsi_done(sc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tcm_loop_queue_status(struct se_cmd *se_cmd)
|
||||
{
|
||||
struct tcm_loop_cmd *tl_cmd = container_of(se_cmd,
|
||||
struct tcm_loop_cmd, tl_se_cmd);
|
||||
struct scsi_cmnd *sc = tl_cmd->sc;
|
||||
|
||||
pr_debug("%s() called for scsi_cmnd: %p cdb: 0x%02x\n",
|
||||
__func__, sc, sc->cmnd[0]);
|
||||
func, sc, sc->cmnd[0]);
|
||||
|
||||
if (se_cmd->sense_buffer &&
|
||||
((se_cmd->se_cmd_flags & SCF_TRANSPORT_TASK_SENSE) ||
|
||||
@@ -581,7 +564,7 @@ static int tcm_loop_queue_status(struct se_cmd *se_cmd)
|
||||
sc->result = SAM_STAT_CHECK_CONDITION;
|
||||
set_driver_byte(sc, DRIVER_SENSE);
|
||||
} else
|
||||
sc->result = se_cmd->scsi_status;
|
||||
sc->result = scsi_status;
|
||||
|
||||
set_host_byte(sc, DID_OK);
|
||||
if ((se_cmd->se_cmd_flags & SCF_OVERFLOW_BIT) ||
|
||||
@@ -591,6 +574,17 @@ static int tcm_loop_queue_status(struct se_cmd *se_cmd)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tcm_loop_queue_data_in(struct se_cmd *se_cmd)
|
||||
{
|
||||
return tcm_loop_queue_data_or_status(__func__, se_cmd, SAM_STAT_GOOD);
|
||||
}
|
||||
|
||||
static int tcm_loop_queue_status(struct se_cmd *se_cmd)
|
||||
{
|
||||
return tcm_loop_queue_data_or_status(__func__,
|
||||
se_cmd, se_cmd->scsi_status);
|
||||
}
|
||||
|
||||
static void tcm_loop_queue_tm_rsp(struct se_cmd *se_cmd)
|
||||
{
|
||||
struct tcm_loop_cmd *tl_cmd = container_of(se_cmd,
|
||||
|
@@ -677,7 +677,7 @@ target_alua_state_check(struct se_cmd *cmd)
|
||||
|
||||
if (dev->se_hba->hba_flags & HBA_FLAGS_INTERNAL_USE)
|
||||
return 0;
|
||||
if (dev->transport->transport_flags & TRANSPORT_FLAG_PASSTHROUGH_ALUA)
|
||||
if (dev->transport_flags & TRANSPORT_FLAG_PASSTHROUGH_ALUA)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
@@ -1090,7 +1090,7 @@ int core_alua_do_port_transition(
|
||||
struct t10_alua_tg_pt_gp *tg_pt_gp;
|
||||
int primary, valid_states, rc = 0;
|
||||
|
||||
if (l_dev->transport->transport_flags & TRANSPORT_FLAG_PASSTHROUGH_ALUA)
|
||||
if (l_dev->transport_flags & TRANSPORT_FLAG_PASSTHROUGH_ALUA)
|
||||
return -ENODEV;
|
||||
|
||||
valid_states = l_tg_pt_gp->tg_pt_gp_alua_supported_states;
|
||||
@@ -1920,7 +1920,7 @@ ssize_t core_alua_store_tg_pt_gp_info(
|
||||
unsigned char buf[TG_PT_GROUP_NAME_BUF];
|
||||
int move = 0;
|
||||
|
||||
if (dev->transport->transport_flags & TRANSPORT_FLAG_PASSTHROUGH_ALUA ||
|
||||
if (dev->transport_flags & TRANSPORT_FLAG_PASSTHROUGH_ALUA ||
|
||||
(dev->se_hba->hba_flags & HBA_FLAGS_INTERNAL_USE))
|
||||
return -ENODEV;
|
||||
|
||||
@@ -2177,7 +2177,7 @@ ssize_t core_alua_store_offline_bit(
|
||||
unsigned long tmp;
|
||||
int ret;
|
||||
|
||||
if (dev->transport->transport_flags & TRANSPORT_FLAG_PASSTHROUGH_ALUA ||
|
||||
if (dev->transport_flags & TRANSPORT_FLAG_PASSTHROUGH_ALUA ||
|
||||
(dev->se_hba->hba_flags & HBA_FLAGS_INTERNAL_USE))
|
||||
return -ENODEV;
|
||||
|
||||
@@ -2263,7 +2263,7 @@ ssize_t core_alua_store_secondary_write_metadata(
|
||||
|
||||
int core_setup_alua(struct se_device *dev)
|
||||
{
|
||||
if (!(dev->transport->transport_flags &
|
||||
if (!(dev->transport_flags &
|
||||
TRANSPORT_FLAG_PASSTHROUGH_ALUA) &&
|
||||
!(dev->se_hba->hba_flags & HBA_FLAGS_INTERNAL_USE)) {
|
||||
struct t10_alua_lu_gp_member *lu_gp_mem;
|
||||
|
@@ -1099,21 +1099,73 @@ static ssize_t block_size_store(struct config_item *item,
|
||||
static ssize_t alua_support_show(struct config_item *item, char *page)
|
||||
{
|
||||
struct se_dev_attrib *da = to_attrib(item);
|
||||
u8 flags = da->da_dev->transport->transport_flags;
|
||||
u8 flags = da->da_dev->transport_flags;
|
||||
|
||||
return snprintf(page, PAGE_SIZE, "%d\n",
|
||||
flags & TRANSPORT_FLAG_PASSTHROUGH_ALUA ? 0 : 1);
|
||||
}
|
||||
|
||||
static ssize_t alua_support_store(struct config_item *item,
|
||||
const char *page, size_t count)
|
||||
{
|
||||
struct se_dev_attrib *da = to_attrib(item);
|
||||
struct se_device *dev = da->da_dev;
|
||||
bool flag;
|
||||
int ret;
|
||||
|
||||
if (!(dev->transport->transport_flags_changeable &
|
||||
TRANSPORT_FLAG_PASSTHROUGH_ALUA)) {
|
||||
pr_err("dev[%p]: Unable to change SE Device alua_support:"
|
||||
" alua_support has fixed value\n", dev);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = strtobool(page, &flag);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (flag)
|
||||
dev->transport_flags &= ~TRANSPORT_FLAG_PASSTHROUGH_ALUA;
|
||||
else
|
||||
dev->transport_flags |= TRANSPORT_FLAG_PASSTHROUGH_ALUA;
|
||||
return count;
|
||||
}
|
||||
|
||||
static ssize_t pgr_support_show(struct config_item *item, char *page)
|
||||
{
|
||||
struct se_dev_attrib *da = to_attrib(item);
|
||||
u8 flags = da->da_dev->transport->transport_flags;
|
||||
u8 flags = da->da_dev->transport_flags;
|
||||
|
||||
return snprintf(page, PAGE_SIZE, "%d\n",
|
||||
flags & TRANSPORT_FLAG_PASSTHROUGH_PGR ? 0 : 1);
|
||||
}
|
||||
|
||||
static ssize_t pgr_support_store(struct config_item *item,
|
||||
const char *page, size_t count)
|
||||
{
|
||||
struct se_dev_attrib *da = to_attrib(item);
|
||||
struct se_device *dev = da->da_dev;
|
||||
bool flag;
|
||||
int ret;
|
||||
|
||||
if (!(dev->transport->transport_flags_changeable &
|
||||
TRANSPORT_FLAG_PASSTHROUGH_PGR)) {
|
||||
pr_err("dev[%p]: Unable to change SE Device pgr_support:"
|
||||
" pgr_support has fixed value\n", dev);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = strtobool(page, &flag);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (flag)
|
||||
dev->transport_flags &= ~TRANSPORT_FLAG_PASSTHROUGH_PGR;
|
||||
else
|
||||
dev->transport_flags |= TRANSPORT_FLAG_PASSTHROUGH_PGR;
|
||||
return count;
|
||||
}
|
||||
|
||||
CONFIGFS_ATTR(, emulate_model_alias);
|
||||
CONFIGFS_ATTR(, emulate_dpo);
|
||||
CONFIGFS_ATTR(, emulate_fua_write);
|
||||
@@ -1146,8 +1198,8 @@ CONFIGFS_ATTR(, unmap_granularity);
|
||||
CONFIGFS_ATTR(, unmap_granularity_alignment);
|
||||
CONFIGFS_ATTR(, unmap_zeroes_data);
|
||||
CONFIGFS_ATTR(, max_write_same_len);
|
||||
CONFIGFS_ATTR_RO(, alua_support);
|
||||
CONFIGFS_ATTR_RO(, pgr_support);
|
||||
CONFIGFS_ATTR(, alua_support);
|
||||
CONFIGFS_ATTR(, pgr_support);
|
||||
|
||||
/*
|
||||
* dev_attrib attributes for devices using the target core SBC/SPC
|
||||
@@ -1203,12 +1255,24 @@ struct configfs_attribute *passthrough_attrib_attrs[] = {
|
||||
&attr_hw_block_size,
|
||||
&attr_hw_max_sectors,
|
||||
&attr_hw_queue_depth,
|
||||
&attr_emulate_pr,
|
||||
&attr_alua_support,
|
||||
&attr_pgr_support,
|
||||
NULL,
|
||||
};
|
||||
EXPORT_SYMBOL(passthrough_attrib_attrs);
|
||||
|
||||
/*
|
||||
* pr related dev_attrib attributes for devices passing through CDBs,
|
||||
* but allowing in core pr emulation.
|
||||
*/
|
||||
struct configfs_attribute *passthrough_pr_attrib_attrs[] = {
|
||||
&attr_enforce_pr_isids,
|
||||
&attr_force_pr_aptpl,
|
||||
NULL,
|
||||
};
|
||||
EXPORT_SYMBOL(passthrough_pr_attrib_attrs);
|
||||
|
||||
TB_CIT_SETUP_DRV(dev_attrib, NULL, NULL);
|
||||
TB_CIT_SETUP_DRV(dev_action, NULL, NULL);
|
||||
|
||||
@@ -1642,7 +1706,7 @@ static ssize_t target_pr_res_holder_show(struct config_item *item, char *page)
|
||||
if (!dev->dev_attrib.emulate_pr)
|
||||
return sprintf(page, "SPC_RESERVATIONS_DISABLED\n");
|
||||
|
||||
if (dev->transport->transport_flags & TRANSPORT_FLAG_PASSTHROUGH_PGR)
|
||||
if (dev->transport_flags & TRANSPORT_FLAG_PASSTHROUGH_PGR)
|
||||
return sprintf(page, "Passthrough\n");
|
||||
|
||||
spin_lock(&dev->dev_reservation_lock);
|
||||
@@ -1784,7 +1848,7 @@ static ssize_t target_pr_res_type_show(struct config_item *item, char *page)
|
||||
|
||||
if (!dev->dev_attrib.emulate_pr)
|
||||
return sprintf(page, "SPC_RESERVATIONS_DISABLED\n");
|
||||
if (dev->transport->transport_flags & TRANSPORT_FLAG_PASSTHROUGH_PGR)
|
||||
if (dev->transport_flags & TRANSPORT_FLAG_PASSTHROUGH_PGR)
|
||||
return sprintf(page, "SPC_PASSTHROUGH\n");
|
||||
if (dev->dev_reservation_flags & DRF_SPC2_RESERVATIONS)
|
||||
return sprintf(page, "SPC2_RESERVATIONS\n");
|
||||
@@ -1798,7 +1862,7 @@ static ssize_t target_pr_res_aptpl_active_show(struct config_item *item,
|
||||
struct se_device *dev = pr_to_dev(item);
|
||||
|
||||
if (!dev->dev_attrib.emulate_pr ||
|
||||
(dev->transport->transport_flags & TRANSPORT_FLAG_PASSTHROUGH_PGR))
|
||||
(dev->transport_flags & TRANSPORT_FLAG_PASSTHROUGH_PGR))
|
||||
return 0;
|
||||
|
||||
return sprintf(page, "APTPL Bit Status: %s\n",
|
||||
@@ -1811,7 +1875,7 @@ static ssize_t target_pr_res_aptpl_metadata_show(struct config_item *item,
|
||||
struct se_device *dev = pr_to_dev(item);
|
||||
|
||||
if (!dev->dev_attrib.emulate_pr ||
|
||||
(dev->transport->transport_flags & TRANSPORT_FLAG_PASSTHROUGH_PGR))
|
||||
(dev->transport_flags & TRANSPORT_FLAG_PASSTHROUGH_PGR))
|
||||
return 0;
|
||||
|
||||
return sprintf(page, "Ready to process PR APTPL metadata..\n");
|
||||
@@ -1858,7 +1922,7 @@ static ssize_t target_pr_res_aptpl_metadata_store(struct config_item *item,
|
||||
u8 type = 0;
|
||||
|
||||
if (!dev->dev_attrib.emulate_pr ||
|
||||
(dev->transport->transport_flags & TRANSPORT_FLAG_PASSTHROUGH_PGR))
|
||||
(dev->transport_flags & TRANSPORT_FLAG_PASSTHROUGH_PGR))
|
||||
return count;
|
||||
if (dev->dev_reservation_flags & DRF_SPC2_RESERVATIONS)
|
||||
return count;
|
||||
|
@@ -100,9 +100,10 @@ out_unlock:
|
||||
*/
|
||||
if (unpacked_lun != 0) {
|
||||
pr_err("TARGET_CORE[%s]: Detected NON_EXISTENT_LUN"
|
||||
" Access for 0x%08llx\n",
|
||||
" Access for 0x%08llx from %s\n",
|
||||
se_cmd->se_tfo->fabric_name,
|
||||
unpacked_lun);
|
||||
unpacked_lun,
|
||||
nacl->initiatorname);
|
||||
return TCM_NON_EXISTENT_LUN;
|
||||
}
|
||||
|
||||
@@ -174,9 +175,10 @@ out_unlock:
|
||||
|
||||
if (!se_lun) {
|
||||
pr_debug("TARGET_CORE[%s]: Detected NON_EXISTENT_LUN"
|
||||
" Access for 0x%08llx\n",
|
||||
" Access for 0x%08llx for %s\n",
|
||||
se_cmd->se_tfo->fabric_name,
|
||||
unpacked_lun);
|
||||
unpacked_lun,
|
||||
nacl->initiatorname);
|
||||
return -ENODEV;
|
||||
}
|
||||
se_cmd->se_dev = rcu_dereference_raw(se_lun->lun_se_dev);
|
||||
@@ -732,6 +734,7 @@ struct se_device *target_alloc_device(struct se_hba *hba, const char *name)
|
||||
|
||||
dev->se_hba = hba;
|
||||
dev->transport = hba->backend->ops;
|
||||
dev->transport_flags = dev->transport->transport_flags_default;
|
||||
dev->prot_length = sizeof(struct t10_pi_tuple);
|
||||
dev->hba_index = hba->hba_index;
|
||||
|
||||
@@ -1100,7 +1103,7 @@ passthrough_parse_cdb(struct se_cmd *cmd,
|
||||
* emulate the response, since tcmu does not have the information
|
||||
* required to process these commands.
|
||||
*/
|
||||
if (!(dev->transport->transport_flags &
|
||||
if (!(dev->transport_flags &
|
||||
TRANSPORT_FLAG_PASSTHROUGH_PGR)) {
|
||||
if (cdb[0] == PERSISTENT_RESERVE_IN) {
|
||||
cmd->execute_cmd = target_scsi3_emulate_pr_in;
|
||||
|
@@ -4086,7 +4086,7 @@ target_check_reservation(struct se_cmd *cmd)
|
||||
return 0;
|
||||
if (!dev->dev_attrib.emulate_pr)
|
||||
return 0;
|
||||
if (dev->transport->transport_flags & TRANSPORT_FLAG_PASSTHROUGH_PGR)
|
||||
if (dev->transport_flags & TRANSPORT_FLAG_PASSTHROUGH_PGR)
|
||||
return 0;
|
||||
|
||||
spin_lock(&dev->dev_reservation_lock);
|
||||
|
@@ -1070,9 +1070,9 @@ static void pscsi_req_done(struct request *req, blk_status_t status)
|
||||
static const struct target_backend_ops pscsi_ops = {
|
||||
.name = "pscsi",
|
||||
.owner = THIS_MODULE,
|
||||
.transport_flags = TRANSPORT_FLAG_PASSTHROUGH |
|
||||
TRANSPORT_FLAG_PASSTHROUGH_ALUA |
|
||||
TRANSPORT_FLAG_PASSTHROUGH_PGR,
|
||||
.transport_flags_default = TRANSPORT_FLAG_PASSTHROUGH |
|
||||
TRANSPORT_FLAG_PASSTHROUGH_ALUA |
|
||||
TRANSPORT_FLAG_PASSTHROUGH_PGR,
|
||||
.attach_hba = pscsi_attach_hba,
|
||||
.detach_hba = pscsi_detach_hba,
|
||||
.pmode_enable_hba = pscsi_pmode_enable_hba,
|
||||
|
@@ -582,8 +582,7 @@ int core_tpg_add_lun(
|
||||
if (ret)
|
||||
goto out_kill_ref;
|
||||
|
||||
if (!(dev->transport->transport_flags &
|
||||
TRANSPORT_FLAG_PASSTHROUGH_ALUA) &&
|
||||
if (!(dev->transport_flags & TRANSPORT_FLAG_PASSTHROUGH_ALUA) &&
|
||||
!(dev->se_hba->hba_flags & HBA_FLAGS_INTERNAL_USE))
|
||||
target_attach_tg_pt_gp(lun, dev->t10_alua.default_tg_pt_gp);
|
||||
|
||||
|
@@ -1397,7 +1397,7 @@ transport_check_alloc_task_attr(struct se_cmd *cmd)
|
||||
* Check if SAM Task Attribute emulation is enabled for this
|
||||
* struct se_device storage object
|
||||
*/
|
||||
if (dev->transport->transport_flags & TRANSPORT_FLAG_PASSTHROUGH)
|
||||
if (dev->transport_flags & TRANSPORT_FLAG_PASSTHROUGH)
|
||||
return 0;
|
||||
|
||||
if (cmd->sam_task_attr == TCM_ACA_TAG) {
|
||||
@@ -2012,7 +2012,7 @@ static bool target_handle_task_attr(struct se_cmd *cmd)
|
||||
{
|
||||
struct se_device *dev = cmd->se_dev;
|
||||
|
||||
if (dev->transport->transport_flags & TRANSPORT_FLAG_PASSTHROUGH)
|
||||
if (dev->transport_flags & TRANSPORT_FLAG_PASSTHROUGH)
|
||||
return false;
|
||||
|
||||
cmd->se_cmd_flags |= SCF_TASK_ATTR_SET;
|
||||
@@ -2126,7 +2126,7 @@ static void transport_complete_task_attr(struct se_cmd *cmd)
|
||||
{
|
||||
struct se_device *dev = cmd->se_dev;
|
||||
|
||||
if (dev->transport->transport_flags & TRANSPORT_FLAG_PASSTHROUGH)
|
||||
if (dev->transport_flags & TRANSPORT_FLAG_PASSTHROUGH)
|
||||
return;
|
||||
|
||||
if (!(cmd->se_cmd_flags & SCF_TASK_ATTR_SET))
|
||||
|
@@ -882,41 +882,24 @@ static inline size_t tcmu_cmd_get_cmd_size(struct tcmu_cmd *tcmu_cmd,
|
||||
return command_size;
|
||||
}
|
||||
|
||||
static int tcmu_setup_cmd_timer(struct tcmu_cmd *tcmu_cmd, unsigned int tmo,
|
||||
struct timer_list *timer)
|
||||
static void tcmu_setup_cmd_timer(struct tcmu_cmd *tcmu_cmd, unsigned int tmo,
|
||||
struct timer_list *timer)
|
||||
{
|
||||
struct tcmu_dev *udev = tcmu_cmd->tcmu_dev;
|
||||
int cmd_id;
|
||||
|
||||
if (tcmu_cmd->cmd_id)
|
||||
goto setup_timer;
|
||||
|
||||
cmd_id = idr_alloc(&udev->commands, tcmu_cmd, 1, USHRT_MAX, GFP_NOWAIT);
|
||||
if (cmd_id < 0) {
|
||||
pr_err("tcmu: Could not allocate cmd id.\n");
|
||||
return cmd_id;
|
||||
}
|
||||
tcmu_cmd->cmd_id = cmd_id;
|
||||
|
||||
pr_debug("allocated cmd %u for dev %s tmo %lu\n", tcmu_cmd->cmd_id,
|
||||
udev->name, tmo / MSEC_PER_SEC);
|
||||
|
||||
setup_timer:
|
||||
if (!tmo)
|
||||
return 0;
|
||||
return;
|
||||
|
||||
tcmu_cmd->deadline = round_jiffies_up(jiffies + msecs_to_jiffies(tmo));
|
||||
if (!timer_pending(timer))
|
||||
mod_timer(timer, tcmu_cmd->deadline);
|
||||
|
||||
return 0;
|
||||
pr_debug("Timeout set up for cmd %p, dev = %s, tmo = %lu\n", tcmu_cmd,
|
||||
tcmu_cmd->tcmu_dev->name, tmo / MSEC_PER_SEC);
|
||||
}
|
||||
|
||||
static int add_to_qfull_queue(struct tcmu_cmd *tcmu_cmd)
|
||||
{
|
||||
struct tcmu_dev *udev = tcmu_cmd->tcmu_dev;
|
||||
unsigned int tmo;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* For backwards compat if qfull_time_out is not set use
|
||||
@@ -931,13 +914,11 @@ static int add_to_qfull_queue(struct tcmu_cmd *tcmu_cmd)
|
||||
else
|
||||
tmo = TCMU_TIME_OUT;
|
||||
|
||||
ret = tcmu_setup_cmd_timer(tcmu_cmd, tmo, &udev->qfull_timer);
|
||||
if (ret)
|
||||
return ret;
|
||||
tcmu_setup_cmd_timer(tcmu_cmd, tmo, &udev->qfull_timer);
|
||||
|
||||
list_add_tail(&tcmu_cmd->queue_entry, &udev->qfull_queue);
|
||||
pr_debug("adding cmd %u on dev %s to ring space wait queue\n",
|
||||
tcmu_cmd->cmd_id, udev->name);
|
||||
pr_debug("adding cmd %p on dev %s to ring space wait queue\n",
|
||||
tcmu_cmd, udev->name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -959,7 +940,7 @@ static int queue_cmd_ring(struct tcmu_cmd *tcmu_cmd, sense_reason_t *scsi_err)
|
||||
struct tcmu_mailbox *mb;
|
||||
struct tcmu_cmd_entry *entry;
|
||||
struct iovec *iov;
|
||||
int iov_cnt, ret;
|
||||
int iov_cnt, cmd_id;
|
||||
uint32_t cmd_head;
|
||||
uint64_t cdb_off;
|
||||
bool copy_to_data_area;
|
||||
@@ -1060,14 +1041,21 @@ static int queue_cmd_ring(struct tcmu_cmd *tcmu_cmd, sense_reason_t *scsi_err)
|
||||
}
|
||||
entry->req.iov_bidi_cnt = iov_cnt;
|
||||
|
||||
ret = tcmu_setup_cmd_timer(tcmu_cmd, udev->cmd_time_out,
|
||||
&udev->cmd_timer);
|
||||
if (ret) {
|
||||
tcmu_cmd_free_data(tcmu_cmd, tcmu_cmd->dbi_cnt);
|
||||
cmd_id = idr_alloc(&udev->commands, tcmu_cmd, 1, USHRT_MAX, GFP_NOWAIT);
|
||||
if (cmd_id < 0) {
|
||||
pr_err("tcmu: Could not allocate cmd id.\n");
|
||||
|
||||
tcmu_cmd_free_data(tcmu_cmd, tcmu_cmd->dbi_cnt);
|
||||
*scsi_err = TCM_OUT_OF_RESOURCES;
|
||||
return -1;
|
||||
}
|
||||
tcmu_cmd->cmd_id = cmd_id;
|
||||
|
||||
pr_debug("allocated cmd id %u for cmd %p dev %s\n", tcmu_cmd->cmd_id,
|
||||
tcmu_cmd, udev->name);
|
||||
|
||||
tcmu_setup_cmd_timer(tcmu_cmd, udev->cmd_time_out, &udev->cmd_timer);
|
||||
|
||||
entry->hdr.cmd_id = tcmu_cmd->cmd_id;
|
||||
|
||||
/*
|
||||
@@ -1279,50 +1267,39 @@ static unsigned int tcmu_handle_completions(struct tcmu_dev *udev)
|
||||
return handled;
|
||||
}
|
||||
|
||||
static int tcmu_check_expired_cmd(int id, void *p, void *data)
|
||||
static void tcmu_check_expired_ring_cmd(struct tcmu_cmd *cmd)
|
||||
{
|
||||
struct tcmu_cmd *cmd = p;
|
||||
struct tcmu_dev *udev = cmd->tcmu_dev;
|
||||
u8 scsi_status;
|
||||
struct se_cmd *se_cmd;
|
||||
bool is_running;
|
||||
|
||||
if (test_bit(TCMU_CMD_BIT_EXPIRED, &cmd->flags))
|
||||
return 0;
|
||||
|
||||
if (!time_after(jiffies, cmd->deadline))
|
||||
return 0;
|
||||
return;
|
||||
|
||||
is_running = test_bit(TCMU_CMD_BIT_INFLIGHT, &cmd->flags);
|
||||
set_bit(TCMU_CMD_BIT_EXPIRED, &cmd->flags);
|
||||
list_del_init(&cmd->queue_entry);
|
||||
se_cmd = cmd->se_cmd;
|
||||
cmd->se_cmd = NULL;
|
||||
|
||||
if (is_running) {
|
||||
/*
|
||||
* If cmd_time_out is disabled but qfull is set deadline
|
||||
* will only reflect the qfull timeout. Ignore it.
|
||||
*/
|
||||
if (!udev->cmd_time_out)
|
||||
return 0;
|
||||
pr_debug("Timing out inflight cmd %u on dev %s.\n",
|
||||
cmd->cmd_id, cmd->tcmu_dev->name);
|
||||
|
||||
set_bit(TCMU_CMD_BIT_EXPIRED, &cmd->flags);
|
||||
/*
|
||||
* target_complete_cmd will translate this to LUN COMM FAILURE
|
||||
*/
|
||||
scsi_status = SAM_STAT_CHECK_CONDITION;
|
||||
list_del_init(&cmd->queue_entry);
|
||||
cmd->se_cmd = NULL;
|
||||
} else {
|
||||
list_del_init(&cmd->queue_entry);
|
||||
idr_remove(&udev->commands, id);
|
||||
tcmu_free_cmd(cmd);
|
||||
scsi_status = SAM_STAT_TASK_SET_FULL;
|
||||
}
|
||||
target_complete_cmd(se_cmd, SAM_STAT_CHECK_CONDITION);
|
||||
}
|
||||
|
||||
pr_debug("Timing out cmd %u on dev %s that is %s.\n",
|
||||
id, udev->name, is_running ? "inflight" : "queued");
|
||||
static void tcmu_check_expired_queue_cmd(struct tcmu_cmd *cmd)
|
||||
{
|
||||
struct se_cmd *se_cmd;
|
||||
|
||||
target_complete_cmd(se_cmd, scsi_status);
|
||||
return 0;
|
||||
if (!time_after(jiffies, cmd->deadline))
|
||||
return;
|
||||
|
||||
pr_debug("Timing out queued cmd %p on dev %s.\n",
|
||||
cmd, cmd->tcmu_dev->name);
|
||||
|
||||
list_del_init(&cmd->queue_entry);
|
||||
se_cmd = cmd->se_cmd;
|
||||
tcmu_free_cmd(cmd);
|
||||
|
||||
target_complete_cmd(se_cmd, SAM_STAT_TASK_SET_FULL);
|
||||
}
|
||||
|
||||
static void tcmu_device_timedout(struct tcmu_dev *udev)
|
||||
@@ -1407,16 +1384,15 @@ static struct se_device *tcmu_alloc_device(struct se_hba *hba, const char *name)
|
||||
return &udev->se_dev;
|
||||
}
|
||||
|
||||
static bool run_qfull_queue(struct tcmu_dev *udev, bool fail)
|
||||
static void run_qfull_queue(struct tcmu_dev *udev, bool fail)
|
||||
{
|
||||
struct tcmu_cmd *tcmu_cmd, *tmp_cmd;
|
||||
LIST_HEAD(cmds);
|
||||
bool drained = true;
|
||||
sense_reason_t scsi_ret;
|
||||
int ret;
|
||||
|
||||
if (list_empty(&udev->qfull_queue))
|
||||
return true;
|
||||
return;
|
||||
|
||||
pr_debug("running %s's cmdr queue forcefail %d\n", udev->name, fail);
|
||||
|
||||
@@ -1425,11 +1401,10 @@ static bool run_qfull_queue(struct tcmu_dev *udev, bool fail)
|
||||
list_for_each_entry_safe(tcmu_cmd, tmp_cmd, &cmds, queue_entry) {
|
||||
list_del_init(&tcmu_cmd->queue_entry);
|
||||
|
||||
pr_debug("removing cmd %u on dev %s from queue\n",
|
||||
tcmu_cmd->cmd_id, udev->name);
|
||||
pr_debug("removing cmd %p on dev %s from queue\n",
|
||||
tcmu_cmd, udev->name);
|
||||
|
||||
if (fail) {
|
||||
idr_remove(&udev->commands, tcmu_cmd->cmd_id);
|
||||
/*
|
||||
* We were not able to even start the command, so
|
||||
* fail with busy to allow a retry in case runner
|
||||
@@ -1444,10 +1419,8 @@ static bool run_qfull_queue(struct tcmu_dev *udev, bool fail)
|
||||
|
||||
ret = queue_cmd_ring(tcmu_cmd, &scsi_ret);
|
||||
if (ret < 0) {
|
||||
pr_debug("cmd %u on dev %s failed with %u\n",
|
||||
tcmu_cmd->cmd_id, udev->name, scsi_ret);
|
||||
|
||||
idr_remove(&udev->commands, tcmu_cmd->cmd_id);
|
||||
pr_debug("cmd %p on dev %s failed with %u\n",
|
||||
tcmu_cmd, udev->name, scsi_ret);
|
||||
/*
|
||||
* Ignore scsi_ret for now. target_complete_cmd
|
||||
* drops it.
|
||||
@@ -1462,13 +1435,11 @@ static bool run_qfull_queue(struct tcmu_dev *udev, bool fail)
|
||||
* the queue
|
||||
*/
|
||||
list_splice_tail(&cmds, &udev->qfull_queue);
|
||||
drained = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
tcmu_set_next_deadline(&udev->qfull_queue, &udev->qfull_timer);
|
||||
return drained;
|
||||
}
|
||||
|
||||
static int tcmu_irqcontrol(struct uio_info *info, s32 irq_on)
|
||||
@@ -1652,6 +1623,8 @@ static void tcmu_dev_kref_release(struct kref *kref)
|
||||
if (tcmu_check_and_free_pending_cmd(cmd) != 0)
|
||||
all_expired = false;
|
||||
}
|
||||
if (!list_empty(&udev->qfull_queue))
|
||||
all_expired = false;
|
||||
idr_destroy(&udev->commands);
|
||||
WARN_ON(!all_expired);
|
||||
|
||||
@@ -2037,9 +2010,6 @@ static void tcmu_reset_ring(struct tcmu_dev *udev, u8 err_level)
|
||||
mutex_lock(&udev->cmdr_lock);
|
||||
|
||||
idr_for_each_entry(&udev->commands, cmd, i) {
|
||||
if (!test_bit(TCMU_CMD_BIT_INFLIGHT, &cmd->flags))
|
||||
continue;
|
||||
|
||||
pr_debug("removing cmd %u on dev %s from ring (is expired %d)\n",
|
||||
cmd->cmd_id, udev->name,
|
||||
test_bit(TCMU_CMD_BIT_EXPIRED, &cmd->flags));
|
||||
@@ -2077,6 +2047,8 @@ static void tcmu_reset_ring(struct tcmu_dev *udev, u8 err_level)
|
||||
|
||||
del_timer(&udev->cmd_timer);
|
||||
|
||||
run_qfull_queue(udev, false);
|
||||
|
||||
mutex_unlock(&udev->cmdr_lock);
|
||||
}
|
||||
|
||||
@@ -2617,7 +2589,9 @@ static struct configfs_attribute *tcmu_action_attrs[] = {
|
||||
static struct target_backend_ops tcmu_ops = {
|
||||
.name = "user",
|
||||
.owner = THIS_MODULE,
|
||||
.transport_flags = TRANSPORT_FLAG_PASSTHROUGH,
|
||||
.transport_flags_default = TRANSPORT_FLAG_PASSTHROUGH,
|
||||
.transport_flags_changeable = TRANSPORT_FLAG_PASSTHROUGH_PGR |
|
||||
TRANSPORT_FLAG_PASSTHROUGH_ALUA,
|
||||
.attach_hba = tcmu_attach_hba,
|
||||
.detach_hba = tcmu_detach_hba,
|
||||
.alloc_device = tcmu_alloc_device,
|
||||
@@ -2698,6 +2672,7 @@ static void find_free_blocks(void)
|
||||
static void check_timedout_devices(void)
|
||||
{
|
||||
struct tcmu_dev *udev, *tmp_dev;
|
||||
struct tcmu_cmd *cmd, *tmp_cmd;
|
||||
LIST_HEAD(devs);
|
||||
|
||||
spin_lock_bh(&timed_out_udevs_lock);
|
||||
@@ -2708,9 +2683,24 @@ static void check_timedout_devices(void)
|
||||
spin_unlock_bh(&timed_out_udevs_lock);
|
||||
|
||||
mutex_lock(&udev->cmdr_lock);
|
||||
idr_for_each(&udev->commands, tcmu_check_expired_cmd, NULL);
|
||||
|
||||
tcmu_set_next_deadline(&udev->inflight_queue, &udev->cmd_timer);
|
||||
/*
|
||||
* If cmd_time_out is disabled but qfull is set deadline
|
||||
* will only reflect the qfull timeout. Ignore it.
|
||||
*/
|
||||
if (udev->cmd_time_out) {
|
||||
list_for_each_entry_safe(cmd, tmp_cmd,
|
||||
&udev->inflight_queue,
|
||||
queue_entry) {
|
||||
tcmu_check_expired_ring_cmd(cmd);
|
||||
}
|
||||
tcmu_set_next_deadline(&udev->inflight_queue,
|
||||
&udev->cmd_timer);
|
||||
}
|
||||
list_for_each_entry_safe(cmd, tmp_cmd, &udev->qfull_queue,
|
||||
queue_entry) {
|
||||
tcmu_check_expired_queue_cmd(cmd);
|
||||
}
|
||||
tcmu_set_next_deadline(&udev->qfull_queue, &udev->qfull_timer);
|
||||
|
||||
mutex_unlock(&udev->cmdr_lock);
|
||||
@@ -2753,12 +2743,12 @@ static int __init tcmu_module_init(void)
|
||||
goto out_unreg_device;
|
||||
}
|
||||
|
||||
for (i = 0; passthrough_attrib_attrs[i] != NULL; i++) {
|
||||
for (i = 0; passthrough_attrib_attrs[i] != NULL; i++)
|
||||
len += sizeof(struct configfs_attribute *);
|
||||
}
|
||||
for (i = 0; tcmu_attrib_attrs[i] != NULL; i++) {
|
||||
for (i = 0; passthrough_pr_attrib_attrs[i] != NULL; i++)
|
||||
len += sizeof(struct configfs_attribute *);
|
||||
for (i = 0; tcmu_attrib_attrs[i] != NULL; i++)
|
||||
len += sizeof(struct configfs_attribute *);
|
||||
}
|
||||
len += sizeof(struct configfs_attribute *);
|
||||
|
||||
tcmu_attrs = kzalloc(len, GFP_KERNEL);
|
||||
@@ -2767,13 +2757,12 @@ static int __init tcmu_module_init(void)
|
||||
goto out_unreg_genl;
|
||||
}
|
||||
|
||||
for (i = 0; passthrough_attrib_attrs[i] != NULL; i++) {
|
||||
for (i = 0; passthrough_attrib_attrs[i] != NULL; i++)
|
||||
tcmu_attrs[i] = passthrough_attrib_attrs[i];
|
||||
}
|
||||
for (k = 0; tcmu_attrib_attrs[k] != NULL; k++) {
|
||||
tcmu_attrs[i] = tcmu_attrib_attrs[k];
|
||||
i++;
|
||||
}
|
||||
for (k = 0; passthrough_pr_attrib_attrs[k] != NULL; k++)
|
||||
tcmu_attrs[i++] = passthrough_pr_attrib_attrs[k];
|
||||
for (k = 0; tcmu_attrib_attrs[k] != NULL; k++)
|
||||
tcmu_attrs[i++] = tcmu_attrib_attrs[k];
|
||||
tcmu_ops.tb_dev_attrib_attrs = tcmu_attrs;
|
||||
|
||||
ret = transport_backend_register(&tcmu_ops);
|
||||
|
Reference in New Issue
Block a user