diff --git a/iscsi-scst/kernel/iscsi.c b/iscsi-scst/kernel/iscsi.c index 285e2d1a2..66247e69e 100644 --- a/iscsi-scst/kernel/iscsi.c +++ b/iscsi-scst/kernel/iscsi.c @@ -4047,10 +4047,10 @@ static int __init iscsi_init(void) iscsi_cmnd_abort_mempool = mempool_create_kmalloc_pool(2500, sizeof(struct iscsi_cmnd_abort_params)); - if (iscsi_cmnd_abort_mempool == NULL) { - err = -ENOMEM; - goto out_free_dummy; - } + if (iscsi_cmnd_abort_mempool == NULL) { + err = -ENOMEM; + goto out_free_dummy; + } #if defined(CONFIG_TCP_ZERO_COPY_TRANSFER_COMPLETION_NOTIFICATION) err = net_set_get_put_page_callbacks(iscsi_get_page_callback, diff --git a/scst/include/scst.h b/scst/include/scst.h index a7a4cdc8f..f66f006a3 100644 --- a/scst/include/scst.h +++ b/scst/include/scst.h @@ -1888,6 +1888,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; @@ -3789,6 +3795,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 37eb14711..f5c37c5f4 100644 --- a/scst/src/scst_targ.c +++ b/scst/src/scst_targ.c @@ -1949,7 +1949,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; @@ -2010,7 +2010,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; @@ -2343,8 +2343,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. */ @@ -2373,14 +2376,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 @@ -2946,7 +2951,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; }