Print this page
NEX-6018 Return of the walking dead idm_refcnt_wait_ref comstar threads
Reviewed by:  Rick McNeal <rick.mcneal@nexenta.com>
Reviewed by:  Evan Layton <evan.layton@nexenta.com>
NEX-5428 Backout the 5.0 changes
NEX-2937 Continuous write_same starves all other commands
Reviewed by: Rick McNeal <rick.mcneal@nexenta.com>
Reviewed by: Steve Peng <steve.peng@nexenta.com>
NEX-3622 COMSTAR should have per remote port kstats for I/O and latency
Reviewed by: Rob Gittins <rob.gittins@nexenta.com>
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
NEX-3169 STMF has duplicate code in 6 places which is error prone.
Reviewed by: Rob Gittins <rob.gittins@nexenta.com>
Reviewby by: Steve Ping <steve.ping@nexenta.com>
Re #6790 backspace should perform delete on console
VAAI (XXX ATS support for COMSTAR, YYY Block-copy support for COMSTAR)

@@ -18,10 +18,12 @@
  *
  * CDDL HEADER END
  */
 /*
  * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
+ *
+ * Copyright 2016 Nexenta Systems, Inc.  All rights reserved.
  * Copyright (c) 2013 by Delphix. All rights reserved.
  */
 #ifndef _STMF_IMPL_H
 #define _STMF_IMPL_H
 

@@ -87,11 +89,11 @@
         uint32_t        ilu_task_cntr2;
         uint32_t        *ilu_cur_task_cntr;
         uint32_t        ilu_ntasks;      /* # of tasks in the ilu_task list */
         uint32_t        ilu_ntasks_free;        /* # of tasks that are free */
         uint32_t        ilu_ntasks_min_free; /* # minimal free tasks */
-        uint32_t        rsvd1;
+        uint32_t        ilu_additional_ref;
         uint32_t        ilu_proxy_registered;
         uint64_t        ilu_reg_msgid;
         struct stmf_i_scsi_task *ilu_tasks;
         struct stmf_i_scsi_task *ilu_free_tasks;
         struct stmf_itl_data    *ilu_itl_list;

@@ -162,10 +164,22 @@
         struct scsi_devid_desc  *irport_id;
         kmutex_t                irport_mutex;
         int                     irport_refcnt;
         id_t                    irport_instance;
         avl_node_t              irport_ln;
+        /* number of active read tasks */
+        uint32_t                irport_nread_tasks;
+        /* number of active write tasks */
+        uint32_t                irport_nwrite_tasks;
+        hrtime_t                irport_rdstart_timestamp;
+        hrtime_t                irport_rddone_timestamp;
+        hrtime_t                irport_wrstart_timestamp;
+        hrtime_t                irport_wrdone_timestamp;
+        kstat_t                 *irport_kstat_info;
+        kstat_t                 *irport_kstat_io;
+        kstat_t                 *irport_kstat_estat;    /* extended stats */
+        boolean_t               irport_info_dirty;
 } stmf_i_remote_port_t;
 
 /*
  * ilport flags
  */

@@ -235,19 +249,19 @@
 struct stmf_worker;
 typedef struct stmf_i_scsi_task {
         scsi_task_t             *itask_task;
         uint32_t                itask_alloc_size;
         uint32_t                itask_flags;
+        kmutex_t                itask_mutex; /* protects flags and lists */
         uint64_t                itask_proxy_msg_id;
         stmf_data_buf_t         *itask_proxy_dbuf;
         struct stmf_worker      *itask_worker;
         uint32_t                *itask_ilu_task_cntr;
         struct stmf_i_scsi_task *itask_worker_next;
         struct stmf_i_scsi_task *itask_lu_next;
         struct stmf_i_scsi_task *itask_lu_prev;
         struct stmf_i_scsi_task *itask_lu_free_next;
-        struct stmf_i_scsi_task *itask_abort_next;
         struct stmf_itl_data    *itask_itl_datap;
         clock_t                 itask_start_time;       /* abort and normal */
         /* For now we only support 4 parallel buffers. Should be enough. */
         stmf_data_buf_t         *itask_dbufs[4];
         clock_t                 itask_poll_timeout;

@@ -257,10 +271,11 @@
         uint16_t                itask_cdb_buf_size;
 
         /* Task profile data */
         hrtime_t                itask_start_timestamp;
         hrtime_t                itask_done_timestamp;
+        hrtime_t                itask_xfer_done_timestamp;
         hrtime_t                itask_waitq_enter_timestamp;
         hrtime_t                itask_waitq_time;
         hrtime_t                itask_lu_read_time;
         hrtime_t                itask_lu_write_time;
         hrtime_t                itask_lport_read_time;

@@ -273,10 +288,45 @@
 } stmf_i_scsi_task_t;
 
 #define ITASK_DEFAULT_ABORT_TIMEOUT     5
 
 /*
+ * Common code to encode an itask onto the worker_task queue is placed
+ * in this macro to simplify future maintenace activity.
+ */
+#define STMF_ENQUEUE_ITASK(w, i) \
+        ASSERT((itask->itask_flags & ITASK_IN_FREE_LIST) == 0); \
+        ASSERT(mutex_owned(&itask->itask_mutex)); \
+        ASSERT(mutex_owned(&w->worker_lock)); \
+        i->itask_worker_next = NULL; \
+        if (w->worker_task_tail) { \
+                w->worker_task_tail->itask_worker_next = i; \
+        } else { \
+                w->worker_task_head = i; \
+        } \
+        w->worker_task_tail = i; \
+        if (++(w->worker_queue_depth) > w->worker_max_qdepth_pu) { \
+                w->worker_max_qdepth_pu = w->worker_queue_depth; \
+        } \
+        atomic_inc_32(&w->worker_ref_count); \
+        atomic_or_32(&itask->itask_flags, ITASK_IN_WORKER_QUEUE); \
+        i->itask_waitq_enter_timestamp = gethrtime(); \
+        if ((w->worker_flags & STMF_WORKER_ACTIVE) == 0) \
+                cv_signal(&w->worker_cv);
+
+#define STMF_DEQUEUE_ITASK(w, itask) \
+        ASSERT(mutex_owned(&w->worker_lock)); \
+        if ((itask = w->worker_task_head) != NULL) { \
+                w->worker_task_head = itask->itask_worker_next; \
+                if (w->worker_task_head == NULL) { \
+                        w->worker_task_tail = NULL; \
+                } \
+        } else { \
+                w->worker_task_tail = NULL; \
+        }
+
+/*
  * itask_flags
  */
 #define ITASK_IN_FREE_LIST              0x0001
 #define ITASK_IN_TRANSITION             0x0002
 #define ITASK_IN_WORKER_QUEUE           0x0004