Skip to content

Commit

Permalink
Merge tag 'scsi-fixes' of git://git.kernel.org/pub/scm/linux/kernel/g…
Browse files Browse the repository at this point in the history
…it/jejb/scsi

Pull SCSI fixes from James Bottomley:
 "This has two libfc fixes for bugs causing rare crashes, one iscsi fix
  for a potential hang on shutdown, and a fix for an I/O blocksize issue
  which caused a regression"

* tag 'scsi-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi:
  sd: Fix maximum I/O size for BLOCK_PC requests
  libfc: Fix fc_fcp_cleanup_each_cmd()
  libfc: Fix fc_exch_recv_req() error path
  libiscsi: Fix host busy blocking during connection teardown
  • Loading branch information
torvalds committed Aug 15, 2015
2 parents 45e38cf + 4f258a4 commit 1efdb5f
Show file tree
Hide file tree
Showing 5 changed files with 28 additions and 34 deletions.
4 changes: 2 additions & 2 deletions block/blk-settings.c
Original file line number Diff line number Diff line change
Expand Up @@ -241,8 +241,8 @@ EXPORT_SYMBOL(blk_queue_bounce_limit);
* Description:
* Enables a low level driver to set a hard upper limit,
* max_hw_sectors, on the size of requests. max_hw_sectors is set by
* the device driver based upon the combined capabilities of I/O
* controller and storage device.
* the device driver based upon the capabilities of the I/O
* controller.
*
* max_sectors is a soft limit imposed by the block layer for
* filesystem type requests. This value can be overridden on a
Expand Down
8 changes: 4 additions & 4 deletions drivers/scsi/libfc/fc_exch.c
Original file line number Diff line number Diff line change
Expand Up @@ -733,8 +733,6 @@ static bool fc_invoke_resp(struct fc_exch *ep, struct fc_seq *sp,
if (resp) {
resp(sp, fp, arg);
res = true;
} else if (!IS_ERR(fp)) {
fc_frame_free(fp);
}

spin_lock_bh(&ep->ex_lock);
Expand Down Expand Up @@ -1596,7 +1594,8 @@ static void fc_exch_recv_seq_resp(struct fc_exch_mgr *mp, struct fc_frame *fp)
* If new exch resp handler is valid then call that
* first.
*/
fc_invoke_resp(ep, sp, fp);
if (!fc_invoke_resp(ep, sp, fp))
fc_frame_free(fp);

fc_exch_release(ep);
return;
Expand Down Expand Up @@ -1695,7 +1694,8 @@ static void fc_exch_abts_resp(struct fc_exch *ep, struct fc_frame *fp)
fc_exch_hold(ep);
if (!rc)
fc_exch_delete(ep);
fc_invoke_resp(ep, sp, fp);
if (!fc_invoke_resp(ep, sp, fp))
fc_frame_free(fp);
if (has_rec)
fc_exch_timer_set(ep, ep->r_a_tov);
fc_exch_release(ep);
Expand Down
19 changes: 17 additions & 2 deletions drivers/scsi/libfc/fc_fcp.c
Original file line number Diff line number Diff line change
Expand Up @@ -1039,11 +1039,26 @@ static void fc_fcp_cleanup_each_cmd(struct fc_lport *lport, unsigned int id,
fc_fcp_pkt_hold(fsp);
spin_unlock_irqrestore(&si->scsi_queue_lock, flags);

if (!fc_fcp_lock_pkt(fsp)) {
spin_lock_bh(&fsp->scsi_pkt_lock);
if (!(fsp->state & FC_SRB_COMPL)) {
fsp->state |= FC_SRB_COMPL;
/*
* TODO: dropping scsi_pkt_lock and then reacquiring
* again around fc_fcp_cleanup_cmd() is required,
* since fc_fcp_cleanup_cmd() calls into
* fc_seq_set_resp() and that func preempts cpu using
* schedule. May be schedule and related code should be
* removed instead of unlocking here to avoid scheduling
* while atomic bug.
*/
spin_unlock_bh(&fsp->scsi_pkt_lock);

fc_fcp_cleanup_cmd(fsp, error);

spin_lock_bh(&fsp->scsi_pkt_lock);
fc_io_compl(fsp);
fc_fcp_unlock_pkt(fsp);
}
spin_unlock_bh(&fsp->scsi_pkt_lock);

fc_fcp_pkt_release(fsp);
spin_lock_irqsave(&si->scsi_queue_lock, flags);
Expand Down
25 changes: 2 additions & 23 deletions drivers/scsi/libiscsi.c
Original file line number Diff line number Diff line change
Expand Up @@ -2941,10 +2941,10 @@ void iscsi_conn_teardown(struct iscsi_cls_conn *cls_conn)
{
struct iscsi_conn *conn = cls_conn->dd_data;
struct iscsi_session *session = conn->session;
unsigned long flags;

del_timer_sync(&conn->transport_timer);

mutex_lock(&session->eh_mutex);
spin_lock_bh(&session->frwd_lock);
conn->c_stage = ISCSI_CONN_CLEANUP_WAIT;
if (session->leadconn == conn) {
Expand All @@ -2956,28 +2956,6 @@ void iscsi_conn_teardown(struct iscsi_cls_conn *cls_conn)
}
spin_unlock_bh(&session->frwd_lock);

/*
* Block until all in-progress commands for this connection
* time out or fail.
*/
for (;;) {
spin_lock_irqsave(session->host->host_lock, flags);
if (!atomic_read(&session->host->host_busy)) { /* OK for ERL == 0 */
spin_unlock_irqrestore(session->host->host_lock, flags);
break;
}
spin_unlock_irqrestore(session->host->host_lock, flags);
msleep_interruptible(500);
iscsi_conn_printk(KERN_INFO, conn, "iscsi conn_destroy(): "
"host_busy %d host_failed %d\n",
atomic_read(&session->host->host_busy),
session->host->host_failed);
/*
* force eh_abort() to unblock
*/
wake_up(&conn->ehwait);
}

/* flush queued up work because we free the connection below */
iscsi_suspend_tx(conn);

Expand All @@ -2994,6 +2972,7 @@ void iscsi_conn_teardown(struct iscsi_cls_conn *cls_conn)
if (session->leadconn == conn)
session->leadconn = NULL;
spin_unlock_bh(&session->frwd_lock);
mutex_unlock(&session->eh_mutex);

iscsi_destroy_conn(cls_conn);
}
Expand Down
6 changes: 3 additions & 3 deletions drivers/scsi/sd.c
Original file line number Diff line number Diff line change
Expand Up @@ -2770,9 +2770,9 @@ static int sd_revalidate_disk(struct gendisk *disk)
max_xfer = sdkp->max_xfer_blocks;
max_xfer <<= ilog2(sdp->sector_size) - 9;

max_xfer = min_not_zero(queue_max_hw_sectors(sdkp->disk->queue),
max_xfer);
blk_queue_max_hw_sectors(sdkp->disk->queue, max_xfer);
sdkp->disk->queue->limits.max_sectors =
min_not_zero(queue_max_hw_sectors(sdkp->disk->queue), max_xfer);

set_capacity(disk, sdkp->capacity);
sd_config_write_same(sdkp);
kfree(buffer);
Expand Down

0 comments on commit 1efdb5f

Please sign in to comment.