scsi: target: Add tmr_notify backend function
authorBodo Stroesser <bstroesser@ts.fujitsu.com>
Sun, 26 Jul 2020 15:35:04 +0000 (17:35 +0200)
committerMartin K. Petersen <martin.petersen@oracle.com>
Wed, 29 Jul 2020 02:25:26 +0000 (22:25 -0400)
Target core is modified to call an optional backend callback function if a
TMR is received or commands are aborted implicitly after a PR command was
received.  The backend function takes as parameters the se_dev, the type of
the TMR, and the list of aborted commands.  If no commands were aborted, an
empty list is supplied.

Link: https://lore.kernel.org/r/20200726153510.13077-3-bstroesser@ts.fujitsu.com
Reviewed-by: Mike Christie <michael.christie@oracle.com>
Signed-off-by: Bodo Stroesser <bstroesser@ts.fujitsu.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
drivers/target/target_core_tmr.c
drivers/target/target_core_transport.c
include/target/target_core_backend.h
include/target/target_core_base.h

index 73c4155f3c1ed46576b937481c86ef0ebf54d5c3..e4513ef091593f8560c9815ac55be306a0f84118 100644 (file)
@@ -116,6 +116,7 @@ void core_tmr_abort_task(
        struct se_tmr_req *tmr,
        struct se_session *se_sess)
 {
+       LIST_HEAD(aborted_list);
        struct se_cmd *se_cmd, *next;
        unsigned long flags;
        bool rc;
@@ -144,7 +145,7 @@ void core_tmr_abort_task(
                if (!rc)
                        continue;
 
-               list_del_init(&se_cmd->state_list);
+               list_move_tail(&se_cmd->state_list, &aborted_list);
                se_cmd->state_active = false;
 
                spin_unlock_irqrestore(&dev->execute_task_lock, flags);
@@ -157,6 +158,11 @@ void core_tmr_abort_task(
                        WARN_ON_ONCE(transport_lookup_tmr_lun(tmr->task_cmd) <
                                        0);
 
+               if (dev->transport->tmr_notify)
+                       dev->transport->tmr_notify(dev, TMR_ABORT_TASK,
+                                                  &aborted_list);
+
+               list_del_init(&se_cmd->state_list);
                target_put_cmd_and_wait(se_cmd);
 
                printk("ABORT_TASK: Sending TMR_FUNCTION_COMPLETE for"
@@ -167,6 +173,9 @@ void core_tmr_abort_task(
        }
        spin_unlock_irqrestore(&dev->execute_task_lock, flags);
 
+       if (dev->transport->tmr_notify)
+               dev->transport->tmr_notify(dev, TMR_ABORT_TASK, &aborted_list);
+
        printk("ABORT_TASK: Sending TMR_TASK_DOES_NOT_EXIST for ref_tag: %lld\n",
                        tmr->ref_task_tag);
        tmr->response = TMR_TASK_DOES_NOT_EXIST;
@@ -318,6 +327,11 @@ static void core_tmr_drain_state_list(
        }
        spin_unlock_irqrestore(&dev->execute_task_lock, flags);
 
+       if (dev->transport->tmr_notify)
+               dev->transport->tmr_notify(dev, preempt_and_abort_list ?
+                                          TMR_LUN_RESET_PRO : TMR_LUN_RESET,
+                                          &drain_task_list);
+
        while (!list_empty(&drain_task_list)) {
                cmd = list_entry(drain_task_list.next, struct se_cmd, state_list);
                list_del_init(&cmd->state_list);
index e6e1fa68de542be848fee92f097c2d16899e9cde..9fb0be0aa620438babaaf1e1664cc4ad7aa05b1d 100644 (file)
@@ -2946,6 +2946,7 @@ static const char *target_tmf_name(enum tcm_tmreq_table tmf)
        case TMR_LUN_RESET:             return "LUN_RESET";
        case TMR_TARGET_WARM_RESET:     return "TARGET_WARM_RESET";
        case TMR_TARGET_COLD_RESET:     return "TARGET_COLD_RESET";
+       case TMR_LUN_RESET_PRO:         return "LUN_RESET_PRO";
        case TMR_UNKNOWN:               break;
        }
        return "(?)";
index f51452e3b984f8ce24aa58ccbb3374426ffe552f..6336780d83a7525085e3fdc86d209e179af37abc 100644 (file)
@@ -40,6 +40,8 @@ struct target_backend_ops {
        ssize_t (*show_configfs_dev_params)(struct se_device *, char *);
 
        sense_reason_t (*parse_cdb)(struct se_cmd *cmd);
+       void (*tmr_notify)(struct se_device *se_dev, enum tcm_tmreq_table,
+                          struct list_head *aborted_cmds);
        u32 (*get_device_type)(struct se_device *);
        sector_t (*get_blocks)(struct se_device *);
        sector_t (*get_alignment_offset_lbas)(struct se_device *);
index 18c3f277b7708f4c895775d9e83a6e750ccc0a78..549947d407cfd2f55455748ebde55d3d4860b531 100644 (file)
@@ -207,6 +207,7 @@ enum tcm_tmreq_table {
        TMR_LUN_RESET           = 5,
        TMR_TARGET_WARM_RESET   = 6,
        TMR_TARGET_COLD_RESET   = 7,
+       TMR_LUN_RESET_PRO       = 0x80,
        TMR_UNKNOWN             = 0xff,
 };