Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/dev/iscsi Several improvements to the ISCSI driver.



details:   https://anonhg.NetBSD.org/src/rev/1ff5bf318410
branches:  trunk
changeset: 345452:1ff5bf318410
user:      mlelstv <mlelstv%NetBSD.org@localhost>
date:      Sun May 29 13:51:16 2016 +0000

description:
Several improvements to the ISCSI driver.

- Enable debug messages but set log level to be quiet. Provide a
  system (hw.iscsi.debug) to set the log level at run time.
- Replace old tsleep/wakeup synchronization with mutexes and condvars.
- Defer actions from callouts (basically timeouts) to the cleanup thread.
- Protect lists and unique ids with mutexes. protect connection usecount
  by using atomic operations.
- Assert kernel lock when calling into scsipi and network code.
- Use this to make send/receive/cleanup threads MPSAFE.

- Fix handling of out-of-CCB/out-of-PDU conditions against the scsipi layer.
- Bump number of PDUs to 128 to avoid virtually all out-of-PDU conditions

- Make use of softc structure for attach/detach operations.
- Track open file handles to prevent detach when busy.

- Move some global variables to make them static.

- Fix 'Overlapping Commands Attempted' error by marking commands as
  simply ordered (ATTR_SIMPLE) like FreeBSD.

diffstat:

 sys/dev/iscsi/iscsi_globals.h |   61 +++--
 sys/dev/iscsi/iscsi_ioctl.c   |  423 +++++++++++++++++++++++++++++------------
 sys/dev/iscsi/iscsi_main.c    |  165 +++++++++++----
 sys/dev/iscsi/iscsi_rcv.c     |   34 ++-
 sys/dev/iscsi/iscsi_send.c    |  149 +++++++-------
 sys/dev/iscsi/iscsi_text.c    |   42 ++-
 sys/dev/iscsi/iscsi_utils.c   |   85 ++++---
 7 files changed, 629 insertions(+), 330 deletions(-)

diffs (truncated from 2589 to 300 lines):

diff -r 9a89814a5be3 -r 1ff5bf318410 sys/dev/iscsi/iscsi_globals.h
--- a/sys/dev/iscsi/iscsi_globals.h     Sun May 29 13:35:45 2016 +0000
+++ b/sys/dev/iscsi/iscsi_globals.h     Sun May 29 13:51:16 2016 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: iscsi_globals.h,v 1.13 2015/05/30 20:09:47 joerg Exp $ */
+/*     $NetBSD: iscsi_globals.h,v 1.14 2016/05/29 13:51:16 mlelstv Exp $       */
 
 /*-
  * Copyright (c) 2004,2005,2006,2011 The NetBSD Foundation, Inc.
@@ -58,7 +58,7 @@
 
 /* ------------------------ Code selection constants ------------------------ */
 
-/* #define ISCSI_DEBUG      1 */
+#define ISCSI_DEBUG      0
 
 /* -------------------------  Global Constants  ----------------------------- */
 
@@ -96,7 +96,7 @@
    high values of First/MaxBurstLength and small values of
    MaxRecvDataSegmentLength of the target.
 */
-#define PDUS_PER_CONNECTION   64       /* ToDo: Reasonable number?? */
+#define PDUS_PER_CONNECTION   128      /* ToDo: Reasonable number?? */
 
 /* max outstanding serial nums before we give up on the connection */
 #define SERNUM_BUFFER_LENGTH  (CCBS_PER_SESSION / 2)   /* ToDo: Reasonable?? */
@@ -181,7 +181,6 @@
 
 typedef enum {
        PDUDISP_UNUSED,         /* 0 = In free pool */
-       PDUDISP_SIGNAL,         /* Free this PDU when done and wakeup(pdu) */
        PDUDISP_FREE,           /* Free this PDU when done */
        PDUDISP_WAIT            /* Waiting for acknowledge */
 } pdu_disp_t;
@@ -253,6 +252,7 @@
        ccb_disp_t              disp;   /* what to do with this ccb */
 
        struct callout          timeout; /* To make sure it isn't lost */
+       TAILQ_ENTRY(ccb_s)      tchain;
        int                     num_timeouts;
        /* How often we've sent out SNACK without answer */
        int                     total_tries;
@@ -309,6 +309,11 @@
 struct connection_s {
        TAILQ_ENTRY(connection_s)       connections;
 
+       kmutex_t                        lock;
+       kcondvar_t                      conn_cv;
+       kcondvar_t                      ccb_cv;
+       kcondvar_t                      idle_cv;
+
        pdu_list_t                      pdu_pool; /* the free PDU pool */
 
        ccb_list_t                      ccbs_waiting;
@@ -358,7 +363,7 @@
                                        /* if closing down: status */
        int                             recover; /* recovery count */
                /* (reset on first successful data transfer) */
-       int                             usecount; /* number of active CCBs */
+       unsigned                        usecount; /* number of active CCBs */
 
        bool                            destroy; /* conn will be destroyed */
        bool                            in_session;
@@ -367,6 +372,7 @@
                /* status of logout (for recovery) */
        struct callout                  timeout;
                /* Timeout for checking if connection is dead */
+       TAILQ_ENTRY(connection_s)       tchain;
        int                             num_timeouts;
                /* How often we've sent out a NOP without answer */
        uint32_t                        idle_timeout_val;
@@ -402,6 +408,10 @@
        /* local stuff */
        TAILQ_ENTRY(session_s)  sessions;       /* the list of sessions */
 
+       kmutex_t                lock;
+       kcondvar_t              sess_cv;
+       kcondvar_t              ccb_cv;
+
        ccb_list_t              ccb_pool;       /* The free CCB pool */
        ccb_list_t              ccbs_throttled;
                                /* CCBs waiting for MaxCmdSN to increase */
@@ -457,18 +467,6 @@
 
 
 /*
-   The softc structure. This driver doesn't really need one, because there's
-   always just one instance, and for the time being it's only loaded as
-   an LKM (which doesn't create a softc), but we need one to put into the
-   scsipi interface structures, so here it is.
-*/
-
-typedef struct iscsi_softc {
-       device_t                sc_dev;
-} iscsi_softc_t;
-
-
-/*
    Event notification structures
 */
 
@@ -502,7 +500,9 @@
 
 /* /dev/iscsi0 state */
 struct iscsifd {
-       char dummy;
+       TAILQ_ENTRY(iscsifd)            link;
+       device_t        dev;
+       int             unit;
 };
 
 /* -------------------------  Global Variables  ----------------------------- */
@@ -512,12 +512,7 @@
 extern struct cfattach iscsi_ca;               /* the device attach structure */
 
 extern session_list_t iscsi_sessions;          /* the list of sessions */
-
-extern connection_list_t iscsi_cleanupc_list;  /* connections to clean up */
-extern session_list_t iscsi_cleanups_list;     /* sessions to clean up */
 extern bool iscsi_detaching;                   /* signal to cleanup thread it should exit */
-extern struct lwp *iscsi_cleanproc;            /* pointer to cleanup proc */
-
 extern uint32_t iscsi_num_send_threads;                /* the number of active send threads */
 
 extern uint8_t iscsi_InitiatorName[ISCSI_STRING_LENGTH];
@@ -539,7 +534,7 @@
 #define DEBC(conn,lev,x) { if (iscsi_debug_level >= lev) { printf("S%dC%d: ", \
                                conn ? conn->session->id : -1, \
                                conn ? conn->id : -1); printf x ;}}
-void dump(void *buf, int len);
+void iscsi_hexdump(void *buf, int len);
 
 #define STATIC static
 
@@ -548,7 +543,7 @@
 #define DEBOUT(x)
 #define DEB(lev,x)
 #define DEBC(conn,lev,x)
-#define dump(a,b)
+#define iscsi_hexdump(a,b)
 
 #define STATIC static
 
@@ -634,6 +629,11 @@
 
 /* in iscsi_ioctl.c */
 
+void iscsi_init_cleanup(void);
+void iscsi_destroy_cleanup(void);
+void iscsi_notify_cleanup(void);
+
+
 /* Parameter for logout is reason code in logout PDU, -1 for don't send logout */
 #define NO_LOGOUT          -1
 #define LOGOUT_SESSION     0
@@ -646,7 +646,7 @@
 void kill_session(session_t *, uint32_t, int, bool);
 void kill_all_sessions(void);
 void handle_connection_error(connection_t *, uint32_t, int);
-void iscsi_cleanup_thread(void *);
+void add_connection_cleanup(connection_t *);
 
 #ifndef ISCSI_MINIMAL
 uint32_t map_databuf(struct proc *, void **, uint32_t);
@@ -664,7 +664,7 @@
 int iscsidetach(device_t, int);
 
 void iscsi_done(ccb_t *);
-int map_session(session_t *);
+int map_session(session_t *, device_t);
 int unmap_session(session_t *);
 
 /* in iscsi_send.c */
@@ -694,8 +694,11 @@
 int send_io_command(session_t *, uint64_t, scsireq_t *, bool, uint32_t);
 #endif
 
-void connection_timeout(void *);
-void ccb_timeout(void *);
+void connection_timeout_co(void *);
+void ccb_timeout_co(void *);
+
+void connection_timeout(connection_t *);
+void ccb_timeout(ccb_t *);
 
 /* in iscsi_rcv.c */
 
diff -r 9a89814a5be3 -r 1ff5bf318410 sys/dev/iscsi/iscsi_ioctl.c
--- a/sys/dev/iscsi/iscsi_ioctl.c       Sun May 29 13:35:45 2016 +0000
+++ b/sys/dev/iscsi/iscsi_ioctl.c       Sun May 29 13:51:16 2016 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: iscsi_ioctl.c,v 1.13 2015/09/19 18:32:42 dholland Exp $        */
+/*     $NetBSD: iscsi_ioctl.c,v 1.14 2016/05/29 13:51:16 mlelstv Exp $ */
 
 /*-
  * Copyright (c) 2004,2005,2006,2011 The NetBSD Foundation, Inc.
@@ -40,12 +40,29 @@
 #include <uvm/uvm_pmap.h>
 #endif
 
+static kmutex_t iscsi_cleanup_mtx;
+static kcondvar_t iscsi_cleanup_cv;
+static kcondvar_t iscsi_event_cv;
+static struct lwp *iscsi_cleanproc = NULL;
+
 static uint16_t current_id = 0;        /* Global session ID counter */
 
 /* list of event handlers */
 static event_handler_list_t event_handlers =
        TAILQ_HEAD_INITIALIZER(event_handlers);
 
+static connection_list_t iscsi_timeout_conn_list =
+       TAILQ_HEAD_INITIALIZER(iscsi_timeout_conn_list);
+
+static ccb_list_t iscsi_timeout_ccb_list =
+       TAILQ_HEAD_INITIALIZER(iscsi_timeout_ccb_list);
+
+static session_list_t iscsi_cleanups_list =
+       TAILQ_HEAD_INITIALIZER(iscsi_cleanups_list);
+
+static connection_list_t iscsi_cleanupc_list =
+       TAILQ_HEAD_INITIALIZER(iscsi_cleanupc_list);
+
 static uint32_t handler_id = 0;        /* Handler ID counter */
 
 /* -------------------------------------------------------------------------- */
@@ -64,11 +81,13 @@
  */
 
 
-STATIC event_handler_t *
+static event_handler_t *
 find_handler(uint32_t id)
 {
        event_handler_t *curr;
 
+       KASSERT(mutex_owned(&iscsi_cleanup_mtx));
+
        TAILQ_FOREACH(curr, &event_handlers, link)
                if (curr->id == id)
                        break;
@@ -85,12 +104,11 @@
  *          par   The parameter.
  */
 
-STATIC void
+static void
 register_event(iscsi_register_event_parameters_t *par)
 {
        event_handler_t *handler;
        int was_empty;
-       int s;
 
        handler = malloc(sizeof(event_handler_t), M_DEVBUF, M_WAITOK | M_ZERO);
        if (handler == NULL) {
@@ -101,21 +119,19 @@
 
        TAILQ_INIT(&handler->events);
 
+       mutex_enter(&iscsi_cleanup_mtx);
        /* create a unique ID */
-       s = splbio();
        do {
                ++handler_id;
        } while (!handler_id || find_handler(handler_id) != NULL);
        par->event_id = handler->id = handler_id;
 
        was_empty = TAILQ_FIRST(&event_handlers) == NULL;
-
        TAILQ_INSERT_TAIL(&event_handlers, handler, link);
+       mutex_exit(&iscsi_cleanup_mtx);
 
-       if (was_empty) {
-               wakeup(&iscsi_cleanupc_list);
-       }
-       splx(s);
+       if (was_empty)
+               iscsi_notify_cleanup();
 
        par->status = ISCSI_STATUS_SUCCESS;
        DEB(5, ("Register Event OK, ID %d\n", par->event_id));
@@ -130,27 +146,27 @@
  *          par   The parameter.
  */
 
-STATIC void
+static void
 deregister_event(iscsi_register_event_parameters_t *par)
 {
        event_handler_t *handler;
        event_t *evt;
-       int s;
 
+       mutex_enter(&iscsi_cleanup_mtx);
        handler = find_handler(par->event_id);
        if (handler == NULL) {
+               mutex_exit(&iscsi_cleanup_mtx);
                DEB(1, ("Deregister Event ID %d not found\n", par->event_id));
                par->status = ISCSI_STATUS_INVALID_EVENT_ID;



Home | Main Index | Thread Index | Old Index