diff --git a/scst/include/scst.h b/scst/include/scst.h index 5bc76a108..67f4d763b 100644 --- a/scst/include/scst.h +++ b/scst/include/scst.h @@ -174,32 +174,26 @@ static inline unsigned int queue_max_hw_sectors(struct request_queue *q) /* Cmd is going to be sent for execution */ #define SCST_CMD_STATE_SEND_FOR_EXEC 5 -/* Cmd is being checked if it should be executed locally */ -#define SCST_CMD_STATE_LOCAL_EXEC 6 - -/* Cmd is ready for execution */ -#define SCST_CMD_STATE_REAL_EXEC 7 - /* Internal post-exec checks */ -#define SCST_CMD_STATE_PRE_DEV_DONE 8 +#define SCST_CMD_STATE_PRE_DEV_DONE 6 /* Internal MODE SELECT pages related checks */ -#define SCST_CMD_STATE_MODE_SELECT_CHECKS 9 +#define SCST_CMD_STATE_MODE_SELECT_CHECKS 7 /* Dev handler's dev_done() is going to be called */ -#define SCST_CMD_STATE_DEV_DONE 10 +#define SCST_CMD_STATE_DEV_DONE 8 /* Checks before target driver's xmit_response() is called */ -#define SCST_CMD_STATE_PRE_XMIT_RESP 11 +#define SCST_CMD_STATE_PRE_XMIT_RESP 9 /* Target driver's xmit_response() is going to be called */ -#define SCST_CMD_STATE_XMIT_RESP 12 +#define SCST_CMD_STATE_XMIT_RESP 10 /* Cmd finished */ -#define SCST_CMD_STATE_FINISHED 13 +#define SCST_CMD_STATE_FINISHED 11 /* Internal cmd finished */ -#define SCST_CMD_STATE_FINISHED_INTERNAL 14 +#define SCST_CMD_STATE_FINISHED_INTERNAL 12 #define SCST_CMD_STATE_LAST_ACTIVE (SCST_CMD_STATE_FINISHED_INTERNAL+100) @@ -215,11 +209,17 @@ static inline unsigned int queue_max_hw_sectors(struct request_queue *q) /* Waiting for data from the initiator (until scst_rx_data() called) */ #define SCST_CMD_STATE_DATA_WAIT (SCST_CMD_STATE_LAST_ACTIVE+4) +/* Cmd is being checked if it should be executed locally */ +#define SCST_CMD_STATE_LOCAL_EXEC (SCST_CMD_STATE_LAST_ACTIVE+5) + +/* Cmd is ready for execution */ +#define SCST_CMD_STATE_REAL_EXEC (SCST_CMD_STATE_LAST_ACTIVE+6) + /* Waiting for CDB's execution finish */ -#define SCST_CMD_STATE_REAL_EXECUTING (SCST_CMD_STATE_LAST_ACTIVE+5) +#define SCST_CMD_STATE_REAL_EXECUTING (SCST_CMD_STATE_LAST_ACTIVE+7) /* Waiting for response's transmission finish */ -#define SCST_CMD_STATE_XMIT_WAIT (SCST_CMD_STATE_LAST_ACTIVE+6) +#define SCST_CMD_STATE_XMIT_WAIT (SCST_CMD_STATE_LAST_ACTIVE+8) /************************************************************* * Can be returned instead of cmd's state by dev handlers' @@ -1884,6 +1884,12 @@ struct scst_cmd { */ unsigned int finished:1; + /* + * Set if scst_check_local_events() can be called more than once. Set by + * scst_pre_check_local_events(). + */ + unsigned int check_local_events_once_done:1; + #ifdef CONFIG_SCST_DEBUG_TM /* Set if the cmd was delayed by task management debugging code */ unsigned int tm_dbg_delayed:1; @@ -3863,6 +3869,13 @@ void scst_post_alloc_data_buf(struct scst_cmd *cmd); int scst_check_local_events(struct scst_cmd *cmd); +static inline int scst_pre_check_local_events(struct scst_cmd *cmd) +{ + int res = scst_check_local_events(cmd); + cmd->check_local_events_once_done = 1; + return res; +} + int scst_set_cmd_abnormal_done_state(struct scst_cmd *cmd); struct scst_trace_log { diff --git a/scst/src/scst_pres.h b/scst/src/scst_pres.h index 248b61357..f7b5cca2b 100644 --- a/scst/src/scst_pres.h +++ b/scst/src/scst_pres.h @@ -72,11 +72,14 @@ static inline void scst_dec_pr_readers_count(struct scst_cmd *cmd, { struct scst_device *dev = cmd->dev; - /* - * scst_check_local_events() should not be called twice for the - * same cmd - */ - WARN_ON(!cmd->dec_pr_readers_count_needed); + if (unlikely(!cmd->dec_pr_readers_count_needed)) { + PRINT_ERROR("scst_check_local_events() should not be called " + "twice (cmd %p, op %x)! Use " + "scst_pre_check_local_events() instead.", cmd, + cmd->cdb[0]); + WARN_ON(1); + goto out; + } if (!locked) spin_lock_bh(&dev->dev_lock); @@ -91,10 +94,19 @@ static inline void scst_dec_pr_readers_count(struct scst_cmd *cmd, if (!locked) spin_unlock_bh(&dev->dev_lock); +out: EXTRACHECKS_BUG_ON(dev->pr_readers_count < 0); return; } +static inline void scst_reset_requeued_cmd(struct scst_cmd *cmd) +{ + TRACE_DBG("Reset requeued cmd %p (op %x)", cmd, cmd->cdb[0]); + scst_inc_pr_readers_count(cmd, false); + cmd->check_local_events_once_done = 0; + return; +} + static inline bool scst_pr_type_valid(uint8_t type) { switch (type) { diff --git a/scst/src/scst_targ.c b/scst/src/scst_targ.c index 67c8080dd..dd8fdafbb 100644 --- a/scst/src/scst_targ.c +++ b/scst/src/scst_targ.c @@ -1950,7 +1950,7 @@ static int scst_reserve_local(struct scst_cmd *cmd) * it, also there's no point to do any extra protection actions. */ - rc = scst_check_local_events(cmd); + rc = scst_pre_check_local_events(cmd); if (unlikely(rc != 0)) goto out_done; @@ -2011,7 +2011,7 @@ static int scst_release_local(struct scst_cmd *cmd) * other protection is needed here. */ - rc = scst_check_local_events(cmd); + rc = scst_pre_check_local_events(cmd); if (unlikely(rc != 0)) goto out_done; @@ -2344,8 +2344,11 @@ out_done: * aborted, > 0 if there is an event and command should be immediately * completed, or 0 otherwise. * - * !! Dev handlers implementing exec() callback must call this function there - * !! just before the actual command's execution! + * !! 1.Dev handlers implementing exec() callback must call this function there + * !! just before the actual command's execution! + * !! + * !! 2. If this function can be called more than once on the processing path + * !! scst_pre_check_local_events() should be used for the first call! * * On call no locks, no IRQ or IRQ-disabled context allowed. */ @@ -2374,14 +2377,16 @@ int scst_check_local_events(struct scst_cmd *cmd) } } - if (dev->pr_is_set) { - if (unlikely(!scst_pr_is_cmd_allowed(cmd))) { - scst_set_cmd_error_status(cmd, - SAM_STAT_RESERVATION_CONFLICT); - goto out_complete; - } - } else - scst_dec_pr_readers_count(cmd, false); + if (likely(!cmd->check_local_events_once_done)) { + if (dev->pr_is_set) { + if (unlikely(!scst_pr_is_cmd_allowed(cmd))) { + scst_set_cmd_error_status(cmd, + SAM_STAT_RESERVATION_CONFLICT); + goto out_complete; + } + } else + scst_dec_pr_readers_count(cmd, false); + } /* * Let's check for ABORTED after scst_pr_is_cmd_allowed(), because @@ -2939,7 +2944,7 @@ static int scst_check_sense(struct scst_cmd *cmd) cmd->state = SCST_CMD_STATE_REAL_EXEC; cmd->retry = 1; - scst_inc_pr_readers_count(cmd, false); + scst_reset_requeued_cmd(cmd); res = 1; goto out; }