From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1756182Ab0IWXhk (ORCPT ); Thu, 23 Sep 2010 19:37:40 -0400 Received: from nm16-vm0.bullet.mail.ne1.yahoo.com ([98.138.91.49]:37393 "HELO nm16-vm0.bullet.mail.ne1.yahoo.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with SMTP id S1756076Ab0IWXhi (ORCPT ); Thu, 23 Sep 2010 19:37:38 -0400 X-Yahoo-Newman-Id: 183296.93889.bm@omp1029.mail.ne1.yahoo.com X-Yahoo-SMTP: fzDSGlOswBCWnIOrNw7KwwK1j9PqyNbe5PtLKiS4dDU.UNl_t6bdEZu9tTLW X-YMail-OSG: .HKu6S0VM1kK5uJVTx7HgtFFaxlpZyeaIgVqM.idhIDwNzR TGkQ0HoxNSr0odktyEpkZJPqkhOIbo117Qz0anFPRyDd25POSUBKoAdQ0W29 xdRVn4yYxFX5eKnEzZj1TwW83utSljl8cmXnhBpYmf70UOwTkTkzS.HUSgV6 Es2ainQzBbf8MBYIKDnSU4zhvrWNV_.57gHewKr5c8VJ0RqYKCYNdosdShAu OstvAmhy3LZ.78lxxz2L4x2sxKpdqo0piV1ce.QxC051X_VN4oV20E6n.XqG oOITTYcIUhp92wr0ncKLkkyZrAPhFUH.4mEfVTxPdr6Vru2q.c15uFzKP4O9 zDY99W1N07eQqJpk53PM- X-Yahoo-Newman-Property: ymail-3 From: "Nicholas A. Bellinger" To: linux-scsi , linux-kernel , Vasu Dev , Tim Chen , Andi Kleen , Matthew Wilcox , James Bottomley , Mike Christie Cc: James Smart , Andrew Vasquez , FUJITA Tomonori , Hannes Reinecke , Joe Eykholt , Christoph Hellwig , MPTFusionLinux , "eata.c maintainer" , Nicholas Bellinger Subject: [RFC v3 01/15] scsi: Drop struct Scsi_Host->host_lock usage in scsi_dispatch_cmd() Date: Thu, 23 Sep 2010 16:37:32 -0700 Message-Id: <1285285052-16351-1-git-send-email-nab@linux-iscsi.org> X-Mailer: git-send-email 1.5.6.5 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Nicholas Bellinger This patch converts scsi_dispatch_cmd() drop the struct Scsi_Host->host_lock legacy usage so that SHT->queuecommand() can be called without this lock held softirq interrupts disabled via spin_lock_irq() This patch drops the usage of scsi_cmd_get_serial() in scsi_dispatch_cmd() and assumes the legacy SCSI LLDs that depend upon struct scsi_cmnd->serial_number will call the now EXPORT_SYMBOL()'ed scsi_cmd_get_serial() call. This patch also updates scsi_error.c:scsi_try_to_abort_cmd() to use: if (test_bit(REQ_ATOM_COMPLETE, &scmd->request->atomic_flags)) return SUCCESS; instead of checking for (scmd->serial_number == 0) following a recommendation by Mike Christie. This patch also converts the remaining struct Scsi_Host->cmd_serial_number to atomic_t following a recommedation by Joe Eykholt to start struct Scsi_Host-> cmd_serial_number at 1, and increment each serial_number by 2 so that the serial is odd, and wraps to 1 instead of 0. Many thanks to Vasu Dev, Tim Chen, Mike and Joe for their help with particular series! Signed-off-by: Nicholas A. Bellinger --- drivers/scsi/scsi.c | 29 ++++++++++++++--------------- drivers/scsi/scsi_error.c | 10 +++++++--- include/scsi/scsi_cmnd.h | 1 + include/scsi/scsi_host.h | 5 ++--- 4 files changed, 24 insertions(+), 21 deletions(-) diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c index ad0ed21..84dbe76 100644 --- a/drivers/scsi/scsi.c +++ b/drivers/scsi/scsi.c @@ -628,18 +628,22 @@ void scsi_log_completion(struct scsi_cmnd *cmd, int disposition) /** * scsi_cmd_get_serial - Assign a serial number to a command - * @host: the scsi host * @cmd: command to assign serial number to * * Description: a serial number identifies a request for error recovery - * and debugging purposes. Protected by the Host_Lock of host. + * and debugging purposes. Called directly by SCSI LLDs that have a + * legacy requirement for struct scsi_cmnd->serial_number. */ -static inline void scsi_cmd_get_serial(struct Scsi_Host *host, struct scsi_cmnd *cmd) +void scsi_cmd_get_serial(struct scsi_cmnd *cmd) { - cmd->serial_number = host->cmd_serial_number++; - if (cmd->serial_number == 0) - cmd->serial_number = host->cmd_serial_number++; + struct Scsi_Host *host = cmd->device->host; + /* + * Increment the host->cmd_serial_number by 2 so cmd->serial_number + * is always odd and wraps to 1 instead of 0. + */ + cmd->serial_number = atomic_add_return(2, &host->cmd_serial_number); } +EXPORT_SYMBOL(scsi_cmd_get_serial); /** * scsi_dispatch_command - Dispatch a command to the low-level driver. @@ -651,7 +655,6 @@ static inline void scsi_cmd_get_serial(struct Scsi_Host *host, struct scsi_cmnd int scsi_dispatch_cmd(struct scsi_cmnd *cmd) { struct Scsi_Host *host = cmd->device->host; - unsigned long flags = 0; unsigned long timeout; int rtn = 0; @@ -736,15 +739,11 @@ int scsi_dispatch_cmd(struct scsi_cmnd *cmd) scsi_done(cmd); goto out; } - - spin_lock_irqsave(host->host_lock, flags); /* - * AK: unlikely race here: for some reason the timer could - * expire before the serial number is set up below. - * - * TODO: kill serial or move to blk layer + * Note that scsi_cmd_get_serial() used to be called here, but + * now we expect the legacy SCSI LLDs that actually need this + * to call it directly within their SHT->queuecommand() caller. */ - scsi_cmd_get_serial(host, cmd); if (unlikely(host->shost_state == SHOST_DEL)) { cmd->result = (DID_NO_CONNECT << 16); @@ -753,7 +752,7 @@ int scsi_dispatch_cmd(struct scsi_cmnd *cmd) trace_scsi_dispatch_cmd_start(cmd); rtn = host->hostt->queuecommand(cmd, scsi_done); } - spin_unlock_irqrestore(host->host_lock, flags); + if (rtn) { trace_scsi_dispatch_cmd_error(cmd, rtn); if (rtn != SCSI_MLQUEUE_DEVICE_BUSY && diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index 1de30eb..34a4fce 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c @@ -39,6 +39,8 @@ #include "scsi_logging.h" #include "scsi_transport_api.h" +#include <../block/blk.h> /* For REQ_ATOM_COMPLETE */ + #include #define SENSE_TIMEOUT (10*HZ) @@ -645,11 +647,13 @@ static int __scsi_try_to_abort_cmd(struct scsi_cmnd *scmd) static int scsi_try_to_abort_cmd(struct scsi_cmnd *scmd) { /* - * scsi_done was called just after the command timed out and before - * we had a chance to process it. (db) + * Use the struct request atomic_flags here to check if + * block/blk.h:blk_mark_rq_complete() has already been called + * from the block softirq */ - if (scmd->serial_number == 0) + if (test_bit(REQ_ATOM_COMPLETE, &scmd->request->atomic_flags)) return SUCCESS; + return __scsi_try_to_abort_cmd(scmd); } diff --git a/include/scsi/scsi_cmnd.h b/include/scsi/scsi_cmnd.h index a5e885a..bbba4fa 100644 --- a/include/scsi/scsi_cmnd.h +++ b/include/scsi/scsi_cmnd.h @@ -136,6 +136,7 @@ extern struct scsi_cmnd *__scsi_get_command(struct Scsi_Host *, gfp_t); extern void scsi_put_command(struct scsi_cmnd *); extern void __scsi_put_command(struct Scsi_Host *, struct scsi_cmnd *, struct device *); +extern void scsi_cmd_get_serial(struct scsi_cmnd *); extern void scsi_finish_command(struct scsi_cmnd *cmd); extern void *scsi_kmap_atomic_sg(struct scatterlist *sg, int sg_count, diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h index b7bdecb..1b69511 100644 --- a/include/scsi/scsi_host.h +++ b/include/scsi/scsi_host.h @@ -602,10 +602,9 @@ struct Scsi_Host { short unsigned int max_sectors; unsigned long dma_boundary; /* - * Used to assign serial numbers to the cmds. - * Protected by the host lock. + * Used to assign serial numbers to the cmds in scsi_cmd_get_serial() */ - unsigned long cmd_serial_number; + atomic_t cmd_serial_number; unsigned active_mode:2; unsigned unchecked_isa_dma:1; -- 1.7.3