mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/xiang/erofs.git
synced 2026-10-28 04:45:43 +01:00
Merge tag 'scsi-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi
Pull SCSI fixes from James Bottomley: "All fixes in drivers (or the tape ULD) and one core fix to bsg (the block ioctl equivalent of sg_io). The biggest is the race in auth updates fix in iscsi configfs, but the next biggest one is in bsg but the generic pieces of that are mostly threading reply_len" * tag 'scsi-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi: scsi: bsg: Pass reply_len to bsg_setup_queue() to fit UFS ARPMB replies scsi: libsas: Fix SMP IO deadlock during HA resume scsi: libiscsi: Validate the task named by a management response scsi: libiscsi: Validate the ITT reflected in a Reject PDU scsi: libiscsi: Reject a negative task index from parse_pdu_itt scsi: target: iscsi: Fix race in discovery auth updates scsi: target: Disable interrupts while holding delayed_cmd_lock scsi: st: Fix use-after-free race between st_remove() and st_open() scsi: st: Save the visited block for the partition the drive is in scsi: xen/scsifront: Check for a NULL shadow entry on a backend response
This commit is contained in:
commit
f909e534f5
13 files changed
+79
-36
No files matched your search
+10
-3
@@ -23,11 +23,14 @@ struct bsg_set {
|
||||
struct bsg_device *bd;
|
||||
bsg_job_fn *job_fn;
|
||||
bsg_timeout_fn *timeout_fn;
|
||||
unsigned int reply_len;
|
||||
};
|
||||
|
||||
static int bsg_transport_sg_io_fn(struct request_queue *q, struct sg_io_v4 *hdr,
|
||||
bool open_for_write, unsigned int timeout)
|
||||
{
|
||||
struct bsg_set *bset =
|
||||
container_of(q->tag_set, struct bsg_set, tag_set);
|
||||
struct bsg_job *job;
|
||||
struct request *rq;
|
||||
struct bio *bio;
|
||||
@@ -50,7 +53,7 @@ static int bsg_transport_sg_io_fn(struct request_queue *q, struct sg_io_v4 *hdr,
|
||||
reply = job->reply;
|
||||
memset(job, 0, sizeof(*job));
|
||||
job->reply = reply;
|
||||
job->reply_len = SCSI_SENSE_BUFFERSIZE;
|
||||
job->reply_len = bset->reply_len;
|
||||
job->dd_data = job + 1;
|
||||
|
||||
job->request_len = hdr->request_len;
|
||||
@@ -301,9 +304,10 @@ out:
|
||||
static int bsg_init_rq(struct blk_mq_tag_set *set, struct request *req,
|
||||
unsigned int hctx_idx, int numa_node)
|
||||
{
|
||||
struct bsg_set *bset = container_of(set, struct bsg_set, tag_set);
|
||||
struct bsg_job *job = blk_mq_rq_to_pdu(req);
|
||||
|
||||
job->reply = kzalloc(SCSI_SENSE_BUFFERSIZE, GFP_KERNEL);
|
||||
job->reply = kzalloc(bset->reply_len, GFP_KERNEL);
|
||||
if (!job->reply)
|
||||
return -ENOMEM;
|
||||
return 0;
|
||||
@@ -358,10 +362,12 @@ static const struct blk_mq_ops bsg_mq_ops = {
|
||||
* @job_fn: bsg job handler
|
||||
* @timeout: timeout handler function pointer
|
||||
* @dd_job_size: size of LLD data needed for each job
|
||||
* @reply_len: size of the reply buffer needed for each job
|
||||
*/
|
||||
struct request_queue *bsg_setup_queue(struct device *dev, const char *name,
|
||||
struct queue_limits *lim, bsg_job_fn *job_fn,
|
||||
bsg_timeout_fn *timeout, int dd_job_size)
|
||||
bsg_timeout_fn *timeout, int dd_job_size,
|
||||
unsigned int reply_len)
|
||||
{
|
||||
struct bsg_set *bset;
|
||||
struct blk_mq_tag_set *set;
|
||||
@@ -374,6 +380,7 @@ struct request_queue *bsg_setup_queue(struct device *dev, const char *name,
|
||||
|
||||
bset->job_fn = job_fn;
|
||||
bset->timeout_fn = timeout;
|
||||
bset->reply_len = reply_len;
|
||||
|
||||
set = &bset->tag_set;
|
||||
set->ops = &bsg_mq_ops;
|
||||
|
||||
@@ -1142,13 +1142,15 @@ static int iscsi_handle_reject(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
|
||||
spin_unlock(&conn->session->frwd_lock);
|
||||
spin_lock(&conn->session->back_lock);
|
||||
} else {
|
||||
struct iscsi_task *task;
|
||||
struct iscsi_task *task = NULL;
|
||||
/*
|
||||
* Our nop as ping got dropped. We know the target
|
||||
* and transport are ok so just clean up
|
||||
*/
|
||||
task = iscsi_itt_to_task(conn, rejected_pdu.itt);
|
||||
if (!task) {
|
||||
if (!iscsi_verify_itt(conn, rejected_pdu.itt))
|
||||
task = iscsi_itt_to_task(conn, rejected_pdu.itt);
|
||||
if (!task || task->state == ISCSI_TASK_FREE ||
|
||||
task->sc) {
|
||||
iscsi_conn_printk(KERN_ERR, conn,
|
||||
"Invalid pdu reject. Could "
|
||||
"not lookup rejected task.\n");
|
||||
@@ -1191,7 +1193,7 @@ struct iscsi_task *iscsi_itt_to_task(struct iscsi_conn *conn, itt_t itt)
|
||||
session->tt->parse_pdu_itt(conn, itt, &i, NULL);
|
||||
else
|
||||
i = get_itt(itt);
|
||||
if (i >= session->cmds_max)
|
||||
if (i < 0 || i >= session->cmds_max)
|
||||
return NULL;
|
||||
|
||||
return session->cmds[i];
|
||||
@@ -1284,7 +1286,7 @@ int __iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
|
||||
case ISCSI_OP_SCSI_TMFUNC_RSP:
|
||||
case ISCSI_OP_NOOP_IN:
|
||||
task = iscsi_itt_to_task(conn, hdr->itt);
|
||||
if (!task)
|
||||
if (!task || task->state == ISCSI_TASK_FREE || task->sc)
|
||||
return ISCSI_ERR_BAD_ITT;
|
||||
break;
|
||||
default:
|
||||
@@ -1384,7 +1386,7 @@ int iscsi_verify_itt(struct iscsi_conn *conn, itt_t itt)
|
||||
return ISCSI_ERR_BAD_ITT;
|
||||
}
|
||||
|
||||
if (i >= session->cmds_max) {
|
||||
if (i < 0 || i >= session->cmds_max) {
|
||||
iscsi_conn_printk(KERN_ERR, conn,
|
||||
"received invalid itt index %u (max cmds "
|
||||
"%u.\n", i, session->cmds_max);
|
||||
|
||||
@@ -62,7 +62,11 @@ static int smp_execute_task_sg(struct domain_device *dev,
|
||||
to_sas_internal(dev->port->ha->shost->transportt);
|
||||
struct sas_ha_struct *ha = dev->port->ha;
|
||||
|
||||
pm_runtime_get_sync(ha->dev);
|
||||
/*
|
||||
* Non-blocking: a sync resume here would deadlock against
|
||||
* sas_drain_work() during HA resume.
|
||||
*/
|
||||
pm_runtime_get_noresume(ha->dev);
|
||||
mutex_lock(&dev->ex_dev.cmd_mutex);
|
||||
for (retry = 0; retry < 3; retry++) {
|
||||
if (test_bit(SAS_DEV_GONE, &dev->state)) {
|
||||
@@ -135,7 +139,7 @@ static int smp_execute_task_sg(struct domain_device *dev,
|
||||
}
|
||||
}
|
||||
mutex_unlock(&dev->ex_dev.cmd_mutex);
|
||||
pm_runtime_put_sync(ha->dev);
|
||||
pm_runtime_put(ha->dev);
|
||||
|
||||
BUG_ON(retry == 3 && task != NULL);
|
||||
sas_free_task(task);
|
||||
@@ -2222,6 +2226,11 @@ void sas_smp_handler(struct bsg_job *job, struct Scsi_Host *shost,
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* The host may have autosuspended, resume it here. */
|
||||
ret = pm_runtime_resume_and_get(dev->port->ha->dev);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
ret = smp_execute_task_sg(dev, job->request_payload.sg_list,
|
||||
job->reply_payload.sg_list);
|
||||
if (ret >= 0) {
|
||||
@@ -2229,6 +2238,7 @@ void sas_smp_handler(struct bsg_job *job, struct Scsi_Host *shost,
|
||||
rcvlen = job->reply_payload.payload_len - ret;
|
||||
ret = 0;
|
||||
}
|
||||
pm_runtime_put(dev->port->ha->dev);
|
||||
|
||||
out:
|
||||
bsg_job_done(job, ret, rcvlen);
|
||||
|
||||
@@ -3053,7 +3053,7 @@ void mpi3mr_bsg_init(struct mpi3mr_ioc *mrioc)
|
||||
}
|
||||
|
||||
q = bsg_setup_queue(bsg_dev, dev_name(bsg_dev), &lim,
|
||||
mpi3mr_bsg_request, NULL, 0);
|
||||
mpi3mr_bsg_request, NULL, 0, SCSI_SENSE_BUFFERSIZE);
|
||||
if (IS_ERR(q)) {
|
||||
ioc_err(mrioc, "%s: bsg registration failed\n",
|
||||
dev_name(bsg_dev));
|
||||
|
||||
@@ -4345,7 +4345,8 @@ fc_bsg_hostadd(struct Scsi_Host *shost, struct fc_host_attrs *fc_host)
|
||||
scsi_init_limits(shost, &lim);
|
||||
lim.max_segments = min_not_zero(lim.max_segments, i->f->max_bsg_segments);
|
||||
q = bsg_setup_queue(dev, bsg_name, &lim, fc_bsg_dispatch,
|
||||
fc_bsg_job_timeout, i->f->dd_bsg_size);
|
||||
fc_bsg_job_timeout, i->f->dd_bsg_size,
|
||||
SCSI_SENSE_BUFFERSIZE);
|
||||
if (IS_ERR(q)) {
|
||||
dev_err(dev,
|
||||
"fc_host%d: bsg interface failed to initialize - setup queue\n",
|
||||
@@ -4378,7 +4379,8 @@ fc_bsg_rportadd(struct Scsi_Host *shost, struct fc_rport *rport)
|
||||
scsi_init_limits(shost, &lim);
|
||||
lim.max_segments = min_not_zero(lim.max_segments, i->f->max_bsg_segments);
|
||||
q = bsg_setup_queue(dev, dev_name(dev), &lim, fc_bsg_dispatch_prep,
|
||||
fc_bsg_job_timeout, i->f->dd_bsg_size);
|
||||
fc_bsg_job_timeout, i->f->dd_bsg_size,
|
||||
SCSI_SENSE_BUFFERSIZE);
|
||||
if (IS_ERR(q)) {
|
||||
dev_err(dev, "failed to setup bsg queue\n");
|
||||
return PTR_ERR(q);
|
||||
|
||||
@@ -1545,7 +1545,7 @@ iscsi_bsg_host_add(struct Scsi_Host *shost, struct iscsi_cls_host *ihost)
|
||||
snprintf(bsg_name, sizeof(bsg_name), "iscsi_host%d", shost->host_no);
|
||||
scsi_init_limits(shost, &lim);
|
||||
q = bsg_setup_queue(dev, bsg_name, &lim, iscsi_bsg_host_dispatch, NULL,
|
||||
0);
|
||||
0, SCSI_SENSE_BUFFERSIZE);
|
||||
if (IS_ERR(q)) {
|
||||
shost_printk(KERN_ERR, shost, "bsg interface failed to "
|
||||
"initialize - no request queue\n");
|
||||
|
||||
@@ -199,7 +199,8 @@ static int sas_bsg_initialize(struct Scsi_Host *shost, struct sas_rphy *rphy)
|
||||
|
||||
if (rphy) {
|
||||
q = bsg_setup_queue(&rphy->dev, dev_name(&rphy->dev), NULL,
|
||||
sas_smp_dispatch, NULL, 0);
|
||||
sas_smp_dispatch, NULL, 0,
|
||||
SCSI_SENSE_BUFFERSIZE);
|
||||
if (IS_ERR(q))
|
||||
return PTR_ERR(q);
|
||||
rphy->q = q;
|
||||
@@ -208,7 +209,8 @@ static int sas_bsg_initialize(struct Scsi_Host *shost, struct sas_rphy *rphy)
|
||||
|
||||
snprintf(name, sizeof(name), "sas_host%d", shost->host_no);
|
||||
q = bsg_setup_queue(&shost->shost_gendev, name, NULL,
|
||||
sas_smp_dispatch, NULL, 0);
|
||||
sas_smp_dispatch, NULL, 0,
|
||||
SCSI_SENSE_BUFFERSIZE);
|
||||
if (IS_ERR(q))
|
||||
return PTR_ERR(q);
|
||||
to_sas_host_attrs(shost)->q = q;
|
||||
|
||||
+12
-6
@@ -3217,14 +3217,20 @@ static int set_location(struct scsi_tape *STp, unsigned int block, int partition
|
||||
partition >= ST_NBR_PARTITIONS)
|
||||
return (-EINVAL);
|
||||
if (partition != STp->partition) {
|
||||
if (get_location(STp, &blk, &p, 1))
|
||||
/*
|
||||
* Save the location for the partition the drive reports,
|
||||
* not for STp->partition: after a reset STp->partition may
|
||||
* not match the partition the drive is in.
|
||||
*/
|
||||
if (get_location(STp, &blk, &p, 1) ||
|
||||
p < 0 || p >= ST_NBR_PARTITIONS)
|
||||
STps->last_block_valid = 0;
|
||||
else {
|
||||
STps->last_block_valid = 1;
|
||||
STps->last_block_visited = blk;
|
||||
STp->ps[p].last_block_valid = 1;
|
||||
STp->ps[p].last_block_visited = blk;
|
||||
DEBC_printk(STp, "Visited block %d for "
|
||||
"partition %d saved.\n",
|
||||
blk, STp->partition);
|
||||
blk, p);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4509,11 +4515,11 @@ static void st_remove(struct scsi_device *SDp)
|
||||
remove_cdevs(tpnt);
|
||||
|
||||
mutex_lock(&st_ref_mutex);
|
||||
kref_put(&tpnt->kref, scsi_tape_release);
|
||||
mutex_unlock(&st_ref_mutex);
|
||||
spin_lock(&st_index_lock);
|
||||
idr_remove(&st_index_idr, index);
|
||||
spin_unlock(&st_index_lock);
|
||||
kref_put(&tpnt->kref, scsi_tape_release);
|
||||
mutex_unlock(&st_ref_mutex);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -367,6 +367,7 @@ static void scsifront_do_response(struct vscsifrnt_info *info,
|
||||
struct vscsifrnt_shadow *shadow;
|
||||
|
||||
if (ring_rsp->rqid >= VSCSIIF_MAX_REQS ||
|
||||
!info->shadow[ring_rsp->rqid] ||
|
||||
!info->shadow[ring_rsp->rqid]->inflight) {
|
||||
scsifront_set_error(info, "illegal rqid returned by backend!");
|
||||
return;
|
||||
|
||||
@@ -1306,17 +1306,24 @@ static ssize_t iscsi_disc_enforce_discovery_auth_store(struct config_item *item,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (iscsit_get_tpg(discovery_tpg) < 0)
|
||||
return -EINVAL;
|
||||
|
||||
param = iscsi_find_param_from_key(AUTHMETHOD,
|
||||
discovery_tpg->param_list);
|
||||
if (!param)
|
||||
return -EINVAL;
|
||||
if (!param) {
|
||||
err = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (op) {
|
||||
/*
|
||||
* Reset the AuthMethod key to CHAP.
|
||||
*/
|
||||
if (iscsi_update_param_value(param, CHAP) < 0)
|
||||
return -EINVAL;
|
||||
if (iscsi_update_param_value(param, CHAP) < 0) {
|
||||
err = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
discovery_tpg->tpg_attrib.authentication = 1;
|
||||
iscsit_global->discovery_acl.node_auth.enforce_discovery_auth = 1;
|
||||
@@ -1327,8 +1334,10 @@ static ssize_t iscsi_disc_enforce_discovery_auth_store(struct config_item *item,
|
||||
/*
|
||||
* Reset the AuthMethod key to CHAP,None
|
||||
*/
|
||||
if (iscsi_update_param_value(param, "CHAP,None") < 0)
|
||||
return -EINVAL;
|
||||
if (iscsi_update_param_value(param, "CHAP,None") < 0) {
|
||||
err = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
discovery_tpg->tpg_attrib.authentication = 0;
|
||||
iscsit_global->discovery_acl.node_auth.enforce_discovery_auth = 0;
|
||||
@@ -1337,7 +1346,10 @@ static ssize_t iscsi_disc_enforce_discovery_auth_store(struct config_item *item,
|
||||
" Discovery TPG\n");
|
||||
}
|
||||
|
||||
return count;
|
||||
err = count;
|
||||
out:
|
||||
iscsit_put_tpg(discovery_tpg);
|
||||
return err;
|
||||
}
|
||||
|
||||
CONFIGFS_ATTR(iscsi_disc_, enforce_discovery_auth);
|
||||
|
||||
@@ -2359,7 +2359,7 @@ void target_do_delayed_work(struct work_struct *work)
|
||||
struct se_device *dev = container_of(work, struct se_device,
|
||||
delayed_cmd_work);
|
||||
|
||||
spin_lock(&dev->delayed_cmd_lock);
|
||||
spin_lock_irq(&dev->delayed_cmd_lock);
|
||||
while (!dev->ordered_sync_in_progress) {
|
||||
struct se_cmd *cmd;
|
||||
|
||||
@@ -2380,12 +2380,12 @@ void target_do_delayed_work(struct work_struct *work)
|
||||
dev->ordered_sync_in_progress = true;
|
||||
|
||||
list_del(&cmd->se_delayed_node);
|
||||
spin_unlock(&dev->delayed_cmd_lock);
|
||||
spin_unlock_irq(&dev->delayed_cmd_lock);
|
||||
|
||||
__target_execute_cmd(cmd, true);
|
||||
spin_lock(&dev->delayed_cmd_lock);
|
||||
spin_lock_irq(&dev->delayed_cmd_lock);
|
||||
}
|
||||
spin_unlock(&dev->delayed_cmd_lock);
|
||||
spin_unlock_irq(&dev->delayed_cmd_lock);
|
||||
}
|
||||
|
||||
static void transport_complete_ordered_sync(struct se_cmd *cmd)
|
||||
|
||||
@@ -258,7 +258,7 @@ int ufs_bsg_probe(struct ufs_hba *hba)
|
||||
goto out;
|
||||
|
||||
q = bsg_setup_queue(bsg_dev, dev_name(bsg_dev), NULL, ufs_bsg_request,
|
||||
NULL, 0);
|
||||
NULL, 0, sizeof(struct ufs_rpmb_reply));
|
||||
if (IS_ERR(q)) {
|
||||
ret = PTR_ERR(q);
|
||||
device_del(bsg_dev);
|
||||
|
||||
@@ -66,7 +66,8 @@ void bsg_job_done(struct bsg_job *job, int result,
|
||||
unsigned int reply_payload_rcv_len);
|
||||
struct request_queue *bsg_setup_queue(struct device *dev, const char *name,
|
||||
struct queue_limits *lim, bsg_job_fn *job_fn,
|
||||
bsg_timeout_fn *timeout, int dd_job_size);
|
||||
bsg_timeout_fn *timeout, int dd_job_size,
|
||||
unsigned int reply_len);
|
||||
void bsg_remove_queue(struct request_queue *q);
|
||||
void bsg_job_put(struct bsg_job *job);
|
||||
int __must_check bsg_job_get(struct bsg_job *job);
|
||||
|
||||
Reference in new issue
Block a user