1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  23  * Use is subject to license terms.
  24  */
  25 
  26 #ifndef _SD_BCACHE_H
  27 #define _SD_BCACHE_H
  28 
  29 #ifdef __cplusplus
  30 extern "C" {
  31 #endif
  32 
  33 #ifdef DS_DDICT
  34 #include <sys/nsctl/contract.h>
  35 #endif
  36 #include <sys/nsctl/nsctl.h>
  37 #include <sys/nsctl/sdbc_ioctl.h>
  38 #include <sys/nsctl/sd_hash.h>
  39 #include <sys/nsctl/sd_cache.h>
  40 #include <sys/nsctl/sd_conf.h>
  41 #include <sys/nsctl/safestore.h>
  42 
  43 /*
  44  * Definitions for kstats
  45  */
  46 #define SDBC_KSTAT_CLASS        "storedge"
  47 #define SDBC_KSTAT_MODULE       "sdbc"
  48 
  49 #ifdef DEBUG
  50 #define SDBC_KSTAT_DYNMEM       "dynmem"
  51 #endif
  52 
  53 #define SDBC_KSTAT_CDNAME       "cdname"
  54 #define SDBC_KSTAT_CDSTATS      "cd"
  55 #define SDBC_KSTAT_GSTATS       "global"
  56 #define SDBC_KSTAT_STATS        "sdbcstats"
  57 #define SDBC_IOKSTAT_GSTATS     "gsdbc"
  58 #define SDBC_IOKSTAT_CDSTATS    "sdbc"
  59 
  60 /* Global kstat field names */
  61 #define SDBC_GKSTAT_COUNT       "sdbc_count"
  62 #define SDBC_GKSTAT_LOC_COUNT   "sdbc_loc_count"
  63 #define SDBC_GKSTAT_RDHITS      "sdbc_rdhits"
  64 #define SDBC_GKSTAT_RDMISS      "sdbc_rdmiss"
  65 #define SDBC_GKSTAT_WRHITS      "sdbc_wrhits"
  66 #define SDBC_GKSTAT_WRMISS      "sdbc_wrmiss"
  67 #define SDBC_GKSTAT_BLKSIZE     "sdbc_blksize"
  68 #define SDBC_GKSTAT_LRU_BLOCKS  "sdbc_lru_blocks"
  69 
  70 #ifdef DEBUG
  71 #define SDBC_GKSTAT_LRU_NOREQ   "sdbc_lru_noreq"
  72 #define SDBC_GKSTAT_LRU_REQ     "sdbc_lru_req"
  73 #endif
  74 
  75 #define SDBC_GKSTAT_WLRU_INQ    "sdbc_wlru_inq"
  76 #define SDBC_GKSTAT_CACHESIZE   "sdbc_cachesize"
  77 #define SDBC_GKSTAT_NUMBLOCKS   "sdbc_numblocks"
  78 #define SDBC_GKSTAT_NUM_SHARED  "sdbc_num_shared"
  79 #define SDBC_GKSTAT_WRCANCELNS  "sdbc_wrcancelns"
  80 #define SDBC_GKSTAT_DESTAGED    "sdbc_destaged"
  81 #define SDBC_GKSTAT_NODEHINTS   "sdbc_nodehints"
  82 
  83 /* per-cache descriptor kstats field names */
  84 #define SDBC_CDKSTAT_VOL_NAME   "sdbc_vol_name"
  85 #define SDBC_CDKSTAT_FAILED     "sdbc_failed"
  86 #define SDBC_CDKSTAT_CD         "sdbc_cd"
  87 #define SDBC_CDKSTAT_CACHE_READ "sdbc_cache_read"
  88 #define SDBC_CDKSTAT_CACHE_WRITE        "sdbc_cache_write"
  89 #define SDBC_CDKSTAT_DISK_READ  "sdbc_disk_read"
  90 #define SDBC_CDKSTAT_DISK_WRITE "sdbc_disk_write"
  91 #define SDBC_CDKSTAT_FILESIZE   "sdbc_filesize"
  92 #define SDBC_CDKSTAT_NUMDIRTY   "sdbc_numdirty"
  93 #define SDBC_CDKSTAT_NUMIO      "sdbc_numio"
  94 #define SDBC_CDKSTAT_NUMFAIL    "sdbc_numfail"
  95 #define SDBC_CDKSTAT_DESTAGED   "sdbc_destaged"
  96 #define SDBC_CDKSTAT_WRCANCELNS "sdbc_wrcancelns"
  97 #define SDBC_CDKSTAT_CDHINTS    "sdbc_cdhints"
  98 
  99 #ifdef DEBUG
 100 /* dynmem kstats field names */
 101 #define SDBC_DMKSTAT_MONITOR_DYNMEM     "sdbc_monitor_dynmem"
 102 #define SDBC_DMKSTAT_MAX_DYN_LIST       "sdbc_max_dyn_list"
 103 #define SDBC_DMKSTAT_CACHE_AGING_CT1    "sdbc_cache_aging_ct1"
 104 #define SDBC_DMKSTAT_CACHE_AGING_CT2    "sdbc_cache_aging_ct2"
 105 #define SDBC_DMKSTAT_CACHE_AGING_CT3    "sdbc_cache_aging_ct3"
 106 #define SDBC_DMKSTAT_CACHE_AGING_SEC1   "sdbc_cache_aging_sec1"
 107 #define SDBC_DMKSTAT_CACHE_AGING_SEC2   "sdbc_cache_aging_sec2"
 108 #define SDBC_DMKSTAT_CACHE_AGING_SEC3   "sdbc_cache_aging_sec3"
 109 #define SDBC_DMKSTAT_CACHE_AGING_PCNT1  "sdbc_cache_aging_pcnt1"
 110 #define SDBC_DMKSTAT_CACHE_AGING_PCNT2  "sdbc_cache_aging_pcnt2"
 111 #define SDBC_DMKSTAT_MAX_HOLDS_PCNT     "sdbc_max_holds_pcnt"
 112 #define SDBC_DMKSTAT_ALLOC_CNT          "sdbc_alloc_cnt"
 113 #define SDBC_DMKSTAT_DEALLOC_CNT        "sdbc_dealloc_cnt"
 114 #define SDBC_DMKSTAT_HISTORY            "sdbc_history"
 115 #define SDBC_DMKSTAT_NODATAS            "sdbc_nodatas"
 116 #define SDBC_DMKSTAT_CANDIDATES         "sdbc_candidates"
 117 #define SDBC_DMKSTAT_DEALLOCS           "sdbc_deallocs"
 118 #define SDBC_DMKSTAT_HOSTS              "sdbc_hosts"
 119 #define SDBC_DMKSTAT_PESTS              "sdbc_pests"
 120 #define SDBC_DMKSTAT_METAS              "sdbc_metas"
 121 #define SDBC_DMKSTAT_HOLDS              "sdbc_holds"
 122 #define SDBC_DMKSTAT_OTHERS             "sdbc_others"
 123 #define SDBC_DMKSTAT_NOTAVAIL           "sdbc_notavail"
 124 #define SDBC_DMKSTAT_PROCESS_DIRECTIVE  "sdbc_process_directive"
 125 #define SDBC_DMKSTAT_SIMPLECT           "sdbc_simplect"
 126 
 127 #endif
 128 
 129 /* ... values are in range [0-BLK_FBAS] */
 130 typedef uint32_t sdbc_cblk_fba_t; /* FBA len or offset in cache block */
 131 
 132 typedef unsigned char *ucaddr_t; /* unsigned char pointer */
 133 
 134 /*
 135  * Atomic exchange function
 136  */
 137 
 138 #ifdef _KERNEL
 139 
 140 /*
 141  * Note: ldstub sets all bits in the memory byte.
 142  * so far this is compatible with the usage of xmem_bu() whereby
 143  * the values of ptr are either 0 or 1, and the xmem_bu() is used
 144  * to set the byte to 1.
 145  */
 146 #define xmem_bu(val, ptr)       nsc_ldstub((uint8_t *)ptr)
 147 #define atomic_swap             xmem_bu
 148 #define sd_serialize            nsc_membar_stld
 149 
 150 #endif /* _KERNEL */
 151 
 152 #if defined(_KERNEL) || defined(_KMEMUSER)
 153 
 154 #if defined(_SD_8K_BLKSIZE)
 155 typedef unsigned short  _sd_bitmap_t;
 156 #else
 157 typedef unsigned char   _sd_bitmap_t;
 158 #endif
 159 
 160 /*
 161  * CCTL flag types
 162  */
 163 
 164 /*
 165  * Note: CC_INUSE and CC_PAGEIO are dummy flags that are used in
 166  * individual flags bytes (cc_inuse and cc_pageio) NOT cc_flag.
 167  * Thus they can take any convenient value, however, they must be
 168  * distinct and non-zero.
 169  */
 170 #define CC_INUSE        0x01    /* Cache entry is in use */
 171 #define CC_PAGEIO       0x02    /* Pagelist IO is active for cache entry */
 172 
 173 /*
 174  * Real cc_flag values.
 175  */
 176 #define CC_PEND_DIRTY   0x02    /* The entry needs to be reprocessed for io */
 177 #define CC_PINNED       0x04    /* The entry has data that is "pinned" */
 178 #define CC_PINNABLE     0x08    /* Issue pin if write fails */
 179 #define CC_QHEAD        0x10    /* NSC_NOCACHE: requeue at head */
 180 
 181 /* specify the size of _sd_cctl[] array */
 182 #define _SD_CCTL_GROUPS 32
 183 
 184 /*
 185  * Individual SDBC cache block entry
 186  *      "cc_lock" must be held when changing dirty/valid bits.
 187  *      "cc_inuse" (optimistic) atomic exchange replaces check/set of
 188  *        CC_INUSE bit in cc_flag; special handling of rare collisions.
 189  *      "cc_pageio" flusher / client locking of pagelist io operations,
 190  *        atomic exchange - needs machine ld/st protection.
 191  *      "cc_iostatus" is set by flusher without holding cc_lock,
 192  *        writer will set CC_PEND_DIRTY if cc_iostatus is set.
 193  * Thus "cc_inuse", "cc_iostatus" and "cc_pageio" are volatile.
 194  *
 195  * The cc_await_* values are in the main _sd_cctl to avoid over
 196  * signalling _cc_blkcv.
 197  *
 198  * The _sd_cctl structure is aligned to group related members and
 199  * to ensure good packing.
 200  */
 201 
 202 typedef struct _sd_cctl_sync {
 203         kcondvar_t      _cc_blkcv;      /* Synchronisation var to block on */
 204         kmutex_t        _cc_lock;       /* Cache entry spinlock         */
 205 } _sd_cctl_sync_t;
 206 
 207 typedef struct sd_addr_s {              /* Generic address structure */
 208         unsigned char   *sa_virt;       /* Virtual address of data */
 209 } sd_addr_t;
 210 
 211 /*
 212  * See notes above.
 213  */
 214 
 215 typedef struct _sd_cctl {
 216         _sd_hash_hd_t cc_head;          /* hash information - must be first */
 217         struct _sd_cctl *cc_next, *cc_prev; /* next and prev in a chain */
 218         struct _sd_cctl *cc_chain;      /* chaining request centries */
 219         struct _sd_cctl *cc_dirty_next; /* for chaining sequential writes */
 220         struct _sd_cctl *cc_dirty_link; /* for chaining the dirty lists   */
 221         struct _sd_cctl *cc_dirty_net_next; /* for chaining net writes */
 222         struct _sd_cctl *cc_dirty_net_link; /* for chaining net lists   */
 223         uint_t          cc_seq;         /* sequence number: for lru optim */
 224         volatile int    net_iostatus;   /* net status of io     */
 225         volatile _sd_bitmap_t net_dirty; /* net cache block dirty mask */
 226         _sd_bitmap_t    cc_valid;       /* Cache block valid mask          */
 227         _sd_bitmap_t    cc_toflush;     /* Cache block deferred dirty mask */
 228         volatile _sd_bitmap_t cc_dirty; /* Cache block dirty mask          */
 229         volatile ushort_t cc_await_use; /* # waiting for this entry (inuse) */
 230         volatile ushort_t cc_await_page; /* # waiting for this entry (pageio) */
 231         volatile uchar_t cc_inuse;      /* atomic_swap(CC_INUSE, cc_inuse) */
 232         volatile uchar_t cc_pageio;     /* atomic_swap(CC_PAGEIO, cc_pageio) */
 233         uchar_t         cc_flag;        /* flag */
 234         char            cc_iocount;     /* number of ios in progress */
 235         volatile uchar_t cc_iostatus;   /* status of io            */
 236         uchar_t         cc_prot;        /* Segmented LRU protection flag   */
 237         sd_addr_t       cc_addr;        /* Data address information        */
 238         ss_centry_info_t  *cc_write;    /* mirrored writes control block */
 239         struct _sd_cctl_sync *cc_sync;  /* Cache block synchronisation blk */
 240 
 241         /* support for backend i/o memory coalescing */
 242         sd_addr_t       cc_anon_addr;   /* address for backend mem coalescing */
 243         int             cc_anon_len;    /* length of anon mem */
 244 
 245         clock_t         cc_creat;
 246         int             cc_hits;
 247 
 248         /* dynamic memory support fields */
 249         uint_t                  cc_aging_dm;            /* For bit settings */
 250                                                         /* see defines */
 251         int                     cc_alloc_size_dm;       /* mem allocation */
 252                                                         /* size bytes */
 253         struct _sd_cctl *cc_head_dm;                    /* ptr to host centry */
 254                                                         /* for a host/pest */
 255                                                         /* chain */
 256         struct _sd_cctl *cc_next_dm;                    /* ptr to next centry */
 257                                                         /* in host/pest chain */
 258         struct _sd_cctl *cc_link_list_dm;               /* simple link list */
 259                                                         /* ptr of all centrys */
 260         /* dynmem chains */
 261         /* _sd_queue_t  *cc_dmchain_q;  dmqueue */
 262         int             cc_cblocks;     /* number of centrys for size_dm */
 263 
 264         /* debugging stats */
 265         int                     cc_alloc_ct_dm;
 266         int                     cc_dealloc_ct_dm;
 267 
 268 } _sd_cctl_t;
 269 
 270 /* cache entry allocation tokens */
 271 typedef struct sdbc_allocbuf_s {
 272         intptr_t opaque[2]; /* must be initialized to 0 */
 273 } sdbc_allocbuf_t;
 274 
 275 typedef struct sdbc_allocbuf_impl_s {
 276         _sd_cctl_t *sab_dmchain;
 277         int sab_q; /* dmqueue of last chain allocated */
 278         int reserved;  /* stats ? */
 279 } sdbc_allocbuf_impl_t;
 280 
 281 /*
 282  * bits for flag argument to sdbc_centry_alloc() and callees.
 283  */
 284 #define ALLOC_LOCKED            0x1     /* locked status of sdbc_queue_lock */
 285 #define ALLOC_NOWAIT            0x2     /* do not block, return NULL */
 286 
 287 /*
 288  * definitions supporting the dynmem dealloc thread
 289  */
 290 #define LOW_RESOURCES_DM                -1
 291 
 292 #define NO_THREAD_DM                    -1
 293 #define PROCESS_CACHE_DM                0
 294 #define CACHE_SHUTDOWN_DM               1
 295 #define CACHE_THREAD_TERMINATED_DM      2
 296 #define TIME_DELAY_LVL0                 3
 297 #define TIME_DELAY_LVL1                 4
 298 #define TIME_DELAY_LVL2                 5
 299 #define HISTORY_LVL0                    (ushort_t)0
 300 #define HISTORY_LVL1                    (ushort_t)0x00ff
 301 #define HISTORY_LVL2                    (ushort_t)0xff00
 302 /*
 303  * definitions supporing the ddditional fields in the cache
 304  * entry structure for dyn mem
 305  */
 306 #define FIRST_AGING_DM          0x00000001
 307 #define FINAL_AGING_DM          0x000000ff
 308 #define FOUND_IN_HASH_DM        0x00000100      /* used to bring cent info */
 309                                                 /* out of sd_centry_alloc() */
 310 #define FOUND_HOLD_OVER_DM      0x00000200      /* used to bring cent info */
 311                                                 /* out of sd_centry_alloc() */
 312 #define HOST_ENTRY_DM           0x00000400
 313 #define PARASITIC_ENTRY_DM      0x00000800
 314 #define STICKY_METADATA_DM      0x00001000
 315 #define CATAGORY_ENTRY_DM       (HOST_ENTRY_DM|PARASITIC_ENTRY_DM| \
 316                                     STICKY_METADATA_DM)
 317 #define ELIGIBLE_ENTRY_DM       0x00002000
 318 #define HASH_ENTRY_DM           0x00008000
 319 #define HOLD_ENTRY_DM           0x00010000
 320 #define ENTRY_FIELD_DM          (ELIGIBLE_ENTRY_DM|HASH_ENTRY_DM|HOLD_ENTRY_DM)
 321 #define AVAIL_ENTRY_DM          0x00020000
 322 
 323 /* info only */
 324 #define PREFETCH_BUF_I          0x00040000      /* implicit read-ahead */
 325 #define PREFETCH_BUF_E          0x00080000      /* explicit read-ahead */
 326 #define PREFETCH_BUF_IR         0x00100000      /* release when read complete */
 327 
 328 /* error processing */
 329 #define BAD_ENTRY_DM            0x20000000 /* inconsistent ccent */
 330 #define BAD_CHAIN_DM            0x40000000 /* chain containing bad ccent */
 331 
 332 /*
 333  * definitions supporting the dynmem monitoring
 334  */
 335 #define RPT_SHUTDOWN_PROCESS_DM 0x00000001
 336 #define RPT_DEALLOC_STATS1_DM   0x00000002      /* nodat,cand,host,pest,meta, */
 337                                                 /* other,dealloc */
 338 #define RPT_DEALLOC_STATS2_DM   0x00000004 /* hysterisis,grossct */
 339 /*
 340  * definitions supporting the processing directive bit flags
 341  */
 342 #define WAKE_DEALLOC_THREAD_DM          0x00000001      /* one shot - acted */
 343                                                         /* on then cleared */
 344 #define MAX_OUT_ACCEL_HIST_FLAG_DM      0x00000002      /* one shot - acted */
 345                                                         /* on then cleared */
 346 /*
 347  * Default - Max - Min definitions
 348  */
 349 #define MAX_DYN_LIST_DEFAULT            8
 350 #define MONITOR_DYNMEM_PROCESS_DEFAULT  0
 351 #define CACHE_AGING_CT_DEFAULT          3
 352 #define CACHE_AGING_SEC1_DEFAULT        10
 353 #define CACHE_AGING_SEC2_DEFAULT        5
 354 #define CACHE_AGING_SEC3_DEFAULT        1
 355 #define CACHE_AGING_PCNT1_DEFAULT       50
 356 #define CACHE_AGING_PCNT2_DEFAULT       25
 357 #define MAX_HOLDS_PCNT_DEFAULT          0
 358 #define PROCESS_DIRECTIVE_DEFAULT       0
 359 
 360 #define CACHE_AGING_CT_MAX      FINAL_AGING_DM  /* 255 */
 361 #define CACHE_AGING_SEC1_MAX    255     /* arbitrary but easy to remember */
 362 #define CACHE_AGING_SEC2_MAX    255     /* arbitrary but easy to remember */
 363 #define CACHE_AGING_SEC3_MAX    255     /* arbitrary but easy to remember */
 364 #define CACHE_AGING_PCNT1_MAX   100
 365 #define CACHE_AGING_PCNT2_MAX   100
 366 #define MAX_HOLDS_PCNT_MAX      100
 367 /*
 368  * dynmem global structure defn
 369  */
 370 typedef struct _dm_process_vars {
 371         kcondvar_t      thread_dm_cv;
 372         kmutex_t        thread_dm_lock;
 373         int     sd_dealloc_flagx;       /* gen'l purpose bit flag */
 374         int     monitor_dynmem_process; /* bit flag indicating what to report */
 375         int     max_dyn_list;           /* max num of pages to allow list to */
 376                                         /* grow */
 377         /* cache aging parameter set */
 378         int     cache_aging_ct1;        /* hosts/pests - aging hits which */
 379                                         /* trigger dealloc */
 380         int     cache_aging_ct2;        /* metas - aging hits which */
 381                                         /* trigger dealloc not yet imple */
 382         int     cache_aging_ct3;        /* holds - aging hits which */
 383                                         /* trigger dealloc */
 384         int     cache_aging_sec1;       /* sleep time between cache list */
 385                                         /* exam - 100% to pcnt1 free */
 386         int     cache_aging_sec2;       /* sleep time between cache list */
 387                                         /* exam - pcnt1 to pcnt2 free */
 388         int     cache_aging_sec3;       /* sleep time between cache list */
 389                                         /* exam - pcnt2 to 0% free */
 390         int     cache_aging_pcnt1;      /* % free when to kick in accel */
 391                                         /* aging - sec2 */
 392         int     cache_aging_pcnt2;      /* % free when to kick in accel */
 393                                         /* aging - sec3 */
 394         int     max_holds_pcnt;         /* max % of cents to act as holdovers */
 395         /* stats - debug */
 396         int     alloc_ct;               /* gross count */
 397         int     dealloc_ct;             /* gross count */
 398         /* thread stats - debug and on the fly tuning of dealloc vars */
 399         int     history;                /* history flag */
 400         int     nodatas;                /* # cctls w/o data assigned */
 401         int     notavail;               /* # cctls w/data but in use */
 402         int     candidates;             /* # cand. for dealloc checking */
 403         int     deallocs;               /* # deallocs */
 404         int     hosts;                  /* # hosts */
 405         int     pests;                  /* # pests */
 406         int     metas;                  /* # metas - sticky meata data */
 407         int     holds;                  /* # holdovers - single page, fully */
 408                                         /* aged but not dealloc'd or hash */
 409                                         /* del'd */
 410         int     others;                 /* # everybody else */
 411         int     process_directive;      /* processing directive bitmap flag */
 412         /* standard stats (no prefetch tallies here) */
 413         int     read_hits;              /* found in cache memory */
 414         int     read_misses;            /* not found in cache memory */
 415         int     write_hits;             /* found in cache memory */
 416         int     write_misses;           /* not found in cache memory */
 417         int     write_thru;             /* not bothering to put in cache mem */
 418         /*
 419          * prefetch tracked by _sd_prefetch_valid_cnt and _sd_prefetch_busy_cnt
 420          * might want different usage ?
 421          */
 422         int     prefetch_hits;
 423         int     prefetch_misses;
 424 } _dm_process_vars_t;
 425 
 426 /*
 427  * dynmem interface
 428  */
 429 int sdbc_edit_xfer_process_vars_dm(_dm_process_vars_t *process_vars);
 430 
 431 /*
 432  * Defines to hide the sd_addr_t structure
 433  */
 434 
 435 #define cc_data         cc_addr.sa_virt
 436 
 437 
 438 /*
 439  * Defines to hide the synchronisation block
 440  */
 441 
 442 #define cc_blkcv        cc_sync->_cc_blkcv
 443 #define cc_lock         cc_sync->_cc_lock
 444 
 445 /*
 446  * This struct exists solely so that sd_info is able to
 447  * extract this kind of data from sdbc without passing out
 448  * the entire _sd_cctl_t which has lots of pointers which
 449  * makes it impossible to deal with in 32bit program and an
 450  * LP64 kernel.
 451  */
 452 
 453 typedef struct {
 454         int             ci_write;       /* 0 == no wrt data */
 455         _sd_bitmap_t    ci_dirty;       /* dirty bits */
 456         _sd_bitmap_t    ci_valid;       /* valid bits */
 457         int             ci_cd;          /* the cd */
 458         nsc_off_t       ci_dblk;        /* the disk block number */
 459 } sdbc_info_t;
 460 
 461 typedef struct _sd_wr_cctl {
 462         ss_resource_t wc_res;
 463         ss_centry_info_t wc_centry_info;
 464 } _sd_wr_cctl_t;
 465 
 466 typedef struct _sd_queue {
 467         struct _sd_cctl sq_qhead;       /* LRU queue head */
 468         kmutex_t   sq_qlock;            /* LRU spinlock   */
 469         char       sq_await;            /* number blocked on lru sema */
 470         int        sq_inq;              /* Number of LRU entries in q */
 471         unsigned int sq_seq;            /* sequence number for lru optim */
 472         unsigned int sq_req_stat;
 473         unsigned int sq_noreq_stat;
 474 
 475         /* dmchain support */
 476         int     sq_dmchain_cblocks;     /* dmchain len in ccents */
 477 } _sd_queue_t;
 478 
 479 
 480 
 481 /*
 482  * The net structure contains which memory net has been configured for
 483  * cache, the amount of space allocated, the write control and fault
 484  * tolerant blocks etc
 485  */
 486 
 487 typedef struct _sd_net {
 488         unsigned short  sn_psize;       /* Page size of memory in this net */
 489         unsigned char   sn_configured;  /* is this network configured */
 490         size_t  sn_csize;               /* Cache size in bytes */
 491         uint_t  sn_wsize;               /* Write size in bytes */
 492         int     sn_cpages;              /* number of pages for Cache      */
 493 }_sd_net_t;
 494 
 495 #endif /* _KERNEL || _KMEMUSER */
 496 
 497 
 498 /*
 499  * Shared structure shared between cds and statistics
 500  *
 501  * NOTE - this structure is visible as an ioctl result.
 502  * If anything changes here _sd_get_stats() and convert_stats()
 503  * will need to be changed.
 504  */
 505 typedef struct _sd_shared {
 506         nsc_size_t sh_filesize;         /* Filesize  (in FBAs) */
 507         volatile uchar_t sh_alloc;      /* Is this allocated? */
 508         volatile uchar_t sh_failed;     /* Disk failure status (0 == ok, */
 509                                         /* 1 == i/o error, 2 == open failed ) */
 510         unsigned short sh_cd;           /* the cache descriptor. (for stats) */
 511         int sh_cache_read;              /* Number of FBAs read from cache */
 512         int sh_cache_write;             /* Number of FBAs written  to cache */
 513         int sh_disk_read;               /* Number of FBAs read from disk */
 514         int sh_disk_write;              /* Number of FBAs written  to disk */
 515         volatile int sh_numdirty;       /* Number of dirty blocks */
 516         volatile int sh_numio;          /* Number of blocks on way to disk */
 517         volatile int sh_numfail;        /* Number of blocks failed */
 518         int sh_flushloop;               /* Loops delayed so far */
 519         int sh_flag;                    /* Flags visible to user programs    */
 520         int sh_destaged;                /* number of bytes destaged to disk */
 521         int sh_wrcancelns;              /* number of writes to dirty blocks */
 522         char sh_filename[NSC_MAXPATH];
 523 } _sd_shared_t;
 524 
 525 
 526 #if defined(_KERNEL) || defined(_KMEMUSER)
 527 
 528 /*
 529  * Cache descriptor information.
 530  */
 531 typedef struct _sd_cd_info {
 532         int cd_desc;                    /* The cache descriptor         */
 533         int cd_flag;                    /* Flag                         */
 534         nsc_fd_t *cd_rawfd;             /* File descriptor for raw device */
 535         strategy_fn_t cd_strategy;      /* Cached copy of strategy func */
 536         dev_t cd_crdev;                 /* The device this represents   */
 537         nsc_iodev_t *cd_iodev;          /* I/O device for callbacks     */
 538         kmutex_t cd_lock;               /* spinlock guarding this cd    */
 539         volatile uchar_t  cd_writer;    /* Disk writer status           */
 540         unsigned int  cd_hint;          /* Hints for this descriptor    */
 541         ss_voldata_t *cd_global;  /* RM information for this cd   */
 542         struct _sd_cctl *cd_dirty_head, *cd_dirty_tail; /* dirty chain  */
 543         struct _sd_cctl *cd_last_ent;   /* last entry in dirty chain, for */
 544         int cd_lastchain;               /* sequential optimization      */
 545         struct _sd_cctl *cd_lastchain_ptr; /* last sequential chain     */
 546         struct _sd_cctl *cd_io_head, *cd_io_tail; /* io in progress q   */
 547         struct _sd_cctl *cd_fail_head;
 548         struct _sd_shared *cd_info;     /* shared info (filename, size)  */
 549         char cd_failover;               /* done nsc_reserve during failover */
 550         volatile char cd_recovering;    /* cd is being recovered failover or */
 551                                         /* disk_online */
 552         char cd_write_inprogress;
 553         struct sd_net_hnd *net_hnd;
 554 } _sd_cd_info_t;
 555 
 556 typedef struct _sd_buf_hlist {
 557         _sd_buf_handle_t hl_top;
 558         kmutex_t hl_lock;
 559         short   hl_count;
 560 } _sd_buf_hlist_t;
 561 
 562 #endif /* _KERNEL || _KMEMUSER */
 563 
 564 /*
 565  * Index into the following st_mem_sizes[] array
 566  */
 567 #define _SD_LOCAL_MEM   0x00    /* type of memory to allocate */
 568 #define _SD_CACHE_MEM   0x01
 569 #define _SD_IOBUF_MEM   0x02
 570 #define _SD_HASH_MEM    0x03
 571 #define _SD_GLOBAL_MEM  0x04
 572 #define _SD_STATS_MEM   0x05
 573 #define _SD_MAX_MEM     _SD_STATS_MEM + 1
 574 
 575 /* maintain stat struct layout */
 576 #define NUM_WQ_PAD 4
 577 /*
 578  * cache statistics structure
 579  *
 580  * NOTE - if anything changes here _sd_get_stats() and convert_stats()
 581  * must be changed and _sd_stats32_t must also be synchronized.
 582  *
 583  */
 584 typedef struct _sd_stats {
 585         int net_dirty;
 586         int net_pending;
 587         int net_free;
 588         int st_count;                   /* number of opens for device   */
 589         int st_loc_count;               /* number of open devices       */
 590         int st_rdhits;                  /* number of read hits          */
 591         int st_rdmiss;                  /* number of read misses        */
 592         int st_wrhits;                  /* number of write hits         */
 593         int st_wrmiss;                  /* number of write misses       */
 594         int st_blksize;                 /* cache block size (in bytes)  */
 595         uint_t st_lru_blocks;
 596         uint_t st_lru_noreq;
 597         uint_t st_lru_req;
 598         int st_wlru_inq;                /* number of write blocks       */
 599         int st_cachesize;               /* cache size (in bytes)        */
 600         int st_numblocks;               /* # of cache blocks            */
 601         int st_wrcancelns;              /* # of write cancellations     */
 602         int st_destaged;                /* # of bytes destaged to disk  */
 603         _sd_shared_t st_shared[1];      /* shared structures            */
 604 } _sd_stats_t;
 605 
 606 typedef struct _sd_stats_32 {
 607         int net_dirty;
 608         int net_pending;
 609         int net_free;
 610         int st_count;                   /* number of opens for device   */
 611         int st_loc_count;               /* number of open devices       */
 612         int st_rdhits;                  /* number of read hits          */
 613         int st_rdmiss;                  /* number of read misses        */
 614         int st_wrhits;                  /* number of write hits         */
 615         int st_wrmiss;                  /* number of write misses       */
 616         int st_blksize;                 /* cache block size (in bytes)  */
 617         uint_t st_lru_blocks;
 618         uint_t st_lru_noreq;
 619         uint_t st_lru_req;
 620         int st_wlru_inq;                /* number of write blocks       */
 621         int st_cachesize;               /* cache size (in bytes)        */
 622         int st_numblocks;               /* # of cache blocks            */
 623         int st_wrcancelns;              /* # of write cancellations     */
 624         int st_destaged;                /* # of bytes destaged to disk  */
 625         _sd_shared_t st_shared[1];      /* shared structures            */
 626 } _sd_stats32_t;
 627 
 628 
 629 #if defined(_KERNEL) || defined(_KMEMUSER)
 630 
 631 /*
 632  * The map structure contains mapping between a mask and relevent information
 633  * that would take some computation at runtime.
 634  * Given a mask, what is the first LSB set (stpos)
 635  * Given a mask, what are the consecutive number of LSB bits set (len)
 636  * Given a mask, what would be a new mask if the consecutive LSB bits are reset
 637  * Given a mask, how many ios would be needed to flush this block.
 638  * Given a mask, how many buffer descriptor lists (bdls) would be needed
 639  *      on a read.
 640  */
 641 
 642 typedef struct _sd_map_info {
 643         unsigned char mi_stpos;         /* position of first LSB set    */
 644         unsigned char mi_len;           /* Length of consecutive LSB set */
 645         unsigned char mi_dirty_count;   /* number of fragmented bits    */
 646         unsigned char mi_io_count;      /* number of bdls for a given mask */
 647         _sd_bitmap_t  mi_mask;          /* new mask with cons. LSB's reset */
 648 } _sd_map_info_t;
 649 
 650 
 651 /*
 652  * cc_inuse is set with atomic exchange instruction
 653  * when clearing, must check for waiters.
 654  * sd_serialize prohibits speculative reads
 655  */
 656 #define CENTRY_INUSE(centry)    ((centry)->cc_inuse)
 657 #define SET_CENTRY_INUSE(centry) \
 658         ((centry)->cc_inuse || atomic_swap(CC_INUSE, &(centry)->cc_inuse))
 659 #define CLEAR_CENTRY_INUSE(centry) { \
 660         (centry)->cc_inuse = 0; \
 661         sd_serialize(); \
 662         if ((centry)->cc_await_use) { \
 663                 mutex_enter(&(centry)->cc_lock); \
 664                 cv_broadcast(&(centry)->cc_blkcv); \
 665                 mutex_exit(&(centry)->cc_lock); \
 666         } \
 667 }
 668 
 669 
 670 /*
 671  * cc_pageio is set with atomic exchange instruction
 672  * when clearing, must check for waiters.
 673  * sd_serialize prohibits speculative reads
 674  */
 675 #define CENTRY_PAGEIO(centry)   ((centry)->cc_pageio)
 676 #define SET_CENTRY_PAGEIO(centry) \
 677         ((centry)->cc_pageio || atomic_swap(CC_PAGEIO, &(centry)->cc_pageio))
 678 #define WAIT_CENTRY_PAGEIO(centry, stat) { \
 679         while (SET_CENTRY_PAGEIO(centry)) { \
 680                 (stat)++; \
 681                 _sd_cc_wait(CENTRY_CD(centry), CENTRY_BLK(centry), \
 682                         centry, CC_PAGEIO); \
 683         } \
 684 }
 685 #define CLEAR_CENTRY_PAGEIO(centry) { \
 686         (centry)->cc_pageio = 0; \
 687         sd_serialize(); \
 688         if ((centry)->cc_await_page) { \
 689                 mutex_enter(&(centry)->cc_lock); \
 690                 cv_broadcast(&(centry)->cc_blkcv); \
 691                 mutex_exit(&(centry)->cc_lock); \
 692         } \
 693 }
 694 
 695 
 696 #define CENTRY_DIRTY_PENDING(centry)    ((centry)->cc_flag & CC_PEND_DIRTY)
 697 #define CENTRY_PINNED(centry)   ((centry)->cc_flag & CC_PINNED)
 698 #define CENTRY_PINNABLE(centry) ((centry)->cc_flag & CC_PINNABLE)
 699 #define CENTRY_QHEAD(centry)    ((centry)->cc_flag & CC_QHEAD)
 700 
 701 #define CENTRY_DIRTY(centry)    ((centry)->cc_dirty)
 702 #define CENTRY_CD(centry)       ((centry)->cc_head.hh_cd)
 703 #define CENTRY_BLK(centry)      ((centry)->cc_head.hh_blk_num)
 704 #define CENTRY_IO_INPROGRESS(centry)    ((centry)->cc_iostatus)
 705 
 706 #define HANDLE_CD(handle)               ((handle)->bh_cd)
 707 
 708 #endif /* _KERNEL || _KMEMUSER */
 709 
 710 #if defined(_KERNEL)
 711 
 712 #define CENTRY_SET_FTPOS(centry) \
 713         (centry)->cc_write->sc_cd = CENTRY_CD(centry), \
 714         (centry)->cc_write->sc_fpos = CENTRY_BLK(centry)
 715 
 716 #define CC_CD_BLK_MATCH(cd, blk, centry)  \
 717         (((centry)->cc_head.hh_cd == cd) && \
 718         ((centry)->cc_head.hh_blk_num == blk))
 719 
 720 
 721 #define _SD_ZEROADDR    ((ucaddr_t)(_sd_net_config.sn_zeroaddr))
 722 
 723 
 724 #define ASSERT_LEN(len) \
 725         if (len > _SD_MAX_FBAS) {\
 726                 cmn_err(CE_WARN, \
 727                     "!sdbc(ASSERT_LEN) fba exceeds limits. fba_len %" \
 728                     NSC_SZFMT ". Max %d", len, _SD_MAX_FBAS); \
 729                 return (EIO);    }
 730 
 731 #define ASSERT_IO_SIZE(fba_num, fba_len, cd) \
 732         if ((fba_num + fba_len) > \
 733             (_sd_cache_files[(cd)].cd_info->sh_filesize)) { \
 734                 cmn_err(CE_WARN, \
 735                     "!sdbc(ASSERT_IO_SIZE) io beyond end of file." \
 736                     " fpos %" NSC_SZFMT " len %" NSC_SZFMT " file size 0 - %" \
 737                     NSC_SZFMT "\n", fba_num, fba_len, \
 738                     (_sd_cache_files[(cd)].cd_info->sh_filesize)); \
 739                 return (EIO); \
 740         }
 741 
 742 
 743 #define ASSERT_HANDLE_LIMITS(m_h1, m_fpos, m_flen) \
 744         if (((m_fpos) < (m_h1)->bh_fba_pos) || \
 745             (((m_fpos) + (m_flen)) > \
 746             ((m_h1)->bh_fba_pos + (m_h1)->bh_fba_len))) { \
 747                 cmn_err(CE_WARN, \
 748                     "!sdbc(ASSERT_HANDLE_LIMITS) operation out of bounds" \
 749                     " cd %x want %" NSC_SZFMT " to %" NSC_SZFMT ". Handle %" \
 750                     NSC_SZFMT " to %" NSC_SZFMT, HANDLE_CD(m_h1), m_fpos,\
 751                     m_flen, (m_h1)->bh_fba_pos, (m_h1)->bh_fba_len); \
 752                 return (EINVAL); \
 753         }
 754 
 755 
 756 #define _SD_HANDLE_ACTIVE(handle)       ((handle)->bh_flag & NSC_HACTIVE)
 757 
 758 #define _SD_CD_HINTS(cd)        (_sd_cache_files[(cd)].cd_hint)
 759 #define _SD_NODE_HINTS          (_sd_node_hint)
 760 
 761 #define _SD_SETUP_HANDLE(hndl, cd, fpos, flen, flag) { \
 762                 hndl->bh_cd = cd; \
 763                 hndl->bh_vec = hndl->bh_bufvec; \
 764                 hndl->bh_fba_pos = fpos; \
 765                 hndl->bh_fba_len = flen; \
 766                 hndl->bh_busy_thread = nsc_threadp(); \
 767                 if (cd == _CD_NOHASH) \
 768                         hndl->bh_flag |= \
 769                             (flag | _SD_NODE_HINTS | NSC_HACTIVE); \
 770                 else \
 771                         hndl->bh_flag |= \
 772                             (flag | _SD_CD_HINTS(cd) | \
 773                             _SD_NODE_HINTS | NSC_HACTIVE); \
 774         }
 775 
 776 #define _SD_NOT_WRTHRU(handle)  (((handle)->bh_flag & _SD_WRTHRU_MASK) == 0)
 777 #define _SD_IS_WRTHRU(handle)   ((handle)->bh_flag & _SD_WRTHRU_MASK)
 778 
 779 #define FILE_OPENED(cd) (((cd) >= 0) && ((cd) < (sdbc_max_devs)) && \
 780                         (_sd_cache_files[(cd)].cd_info != NULL) && \
 781                         (_sd_cache_files[(cd)].cd_info->sh_alloc \
 782                         & CD_ALLOCATED))
 783 
 784 /*
 785  * bitmap stuff
 786  */
 787 
 788 #define SDBC_LOOKUP_STPOS(mask) (_sd_lookup_map[(mask)].mi_stpos)
 789 #define SDBC_LOOKUP_LEN(mask)   (_sd_lookup_map[(mask)].mi_len)
 790 #define SDBC_LOOKUP_MASK(mask)  (_sd_lookup_map[(mask)].mi_mask)
 791 #define SDBC_LOOKUP_DTCOUNT(mask) (_sd_lookup_map[(mask)].mi_dirty_count)
 792 #define SDBC_LOOKUP_IOCOUNT(mask) (_sd_lookup_map[(mask)].mi_io_count)
 793 #define SDBC_LOOKUP_MODIFY(mask) (mask &= ~(_sd_lookup_map[(mask)].mi_mask))
 794 
 795 #define SDBC_IS_FRAGMENTED(bmap)        (!_sd_contig_bmap[(bmap)])
 796 #define SDBC_IS_CONTIGUOUS(bmap)        (_sd_contig_bmap[(bmap)])
 797 
 798 #endif /* _KERNEL */
 799 
 800 #if defined(_KERNEL) || defined(_KMEMUSER)
 801 
 802 #define SDBC_GET_BITS(fba_off, fba_len) \
 803         (_fba_bits[(fba_len)] << (fba_off))
 804 
 805 #define SDBC_SET_VALID_BITS(fba_off, fba_len, cc_entry) \
 806         (cc_entry)->cc_valid |= SDBC_GET_BITS(fba_off, fba_len)
 807 
 808 #define SDBC_SET_DIRTY(fba_off, fba_len, cc_entry) { \
 809         _sd_bitmap_t dirty, newdb = SDBC_GET_BITS(fba_off, fba_len); \
 810         ss_centry_info_t *gl = (cc_entry)->cc_write; \
 811         (cc_entry)->cc_valid |= newdb; \
 812         dirty = ((cc_entry)->cc_dirty |= newdb);  \
 813         gl->sc_dirty = dirty; \
 814         gl->sc_flag = (int)(cc_entry)->cc_flag;   \
 815         SSOP_SETCENTRY(sdbc_safestore, gl); }
 816 
 817 #define SDBC_SET_TOFLUSH(fba_off, fba_len, cc_entry) { \
 818         _sd_bitmap_t dirty, newdb = SDBC_GET_BITS(fba_off, fba_len); \
 819         ss_centry_info_t *gl = (cc_entry)->cc_write; \
 820         (cc_entry)->cc_toflush |= newdb; \
 821         (cc_entry)->cc_valid |= newdb;  \
 822         dirty = (cc_entry)->cc_toflush | (cc_entry)->cc_dirty; \
 823         gl->sc_dirty = dirty;        \
 824         SSOP_SETCENTRY(sdbc_safestore, gl); }
 825 
 826 #define SDBC_VALID_BITS(fba_off, fba_len, cc_entry) \
 827         ((((cc_entry)->cc_valid) & (SDBC_GET_BITS(fba_off, fba_len))) \
 828         == (SDBC_GET_BITS(fba_off, fba_len)))
 829 
 830 
 831 #define SDBC_DIRTY_NEIGHBORS(last, next) \
 832         ((SDBC_IS_CONTIGUOUS((last)->cc_dirty)) && \
 833         (SDBC_IS_CONTIGUOUS((next)->cc_dirty)) && \
 834 (((last)->cc_dirty & (1 << (BLK_FBAS - 1))) && ((next)->cc_dirty & 0x01)))
 835 
 836 
 837 #define FULLY_VALID(cc_entry)   ((cc_entry)->cc_valid == BLK_FBA_BITS)
 838 #define SET_FULLY_VALID(cc_entry) \
 839         ((cc_entry)->cc_valid = BLK_FBA_BITS)
 840 
 841 #define FULLY_DIRTY(cc_entry)   ((cc_entry)->cc_dirty == BLK_FBA_BITS)
 842 
 843 #define _SD_BIT_ISSET(bmap, bit)        ((bmap & (1 << bit)) ? 1 : 0)
 844 #define _SD_BMAP_ISFULL(bmap)           (bmap == BLK_FBA_BITS)
 845 
 846 #endif /* _KERNEL || _KMEMUSER */
 847 
 848 #if defined(_KERNEL)
 849 
 850 #if !defined(_SD_NOSTATS)
 851 #define CACHE_FBA_READ(cd, blks) \
 852         if (((cd) >= 0) && ((cd) < sdbc_max_devs))\
 853                 _sd_cache_stats->st_shared[(cd)].sh_cache_read += (blks)
 854 #define DISK_FBA_READ(cd, blks) \
 855         if (((cd) >= 0) && ((cd) < sdbc_max_devs))\
 856                 _sd_cache_stats->st_shared[(cd)].sh_disk_read += (blks)
 857 #define CACHE_FBA_WRITE(cd, blks) \
 858         if (((cd) >= 0) && ((cd) < sdbc_max_devs))\
 859                 _sd_cache_stats->st_shared[(cd)].sh_cache_write += (blks)
 860 #define DISK_FBA_WRITE(cd, blks) \
 861         if (((cd) >= 0) && ((cd) < sdbc_max_devs))\
 862                 _sd_cache_stats->st_shared[(cd)].sh_disk_write += (blks)
 863 #define CACHE_READ_HIT          _sd_cache_stats->st_rdhits++
 864 #define CACHE_READ_MISS         _sd_cache_stats->st_rdmiss++
 865 #define CACHE_WRITE_HIT         _sd_cache_stats->st_wrhits++
 866 #define CACHE_WRITE_MISS        _sd_cache_stats->st_wrmiss++
 867 
 868 #define CACHE_WRITE_CANCELLATION(cd) {\
 869         if ((cd) < sdbc_max_devs)\
 870                 _sd_cache_stats->st_shared[(cd)].sh_wrcancelns++;\
 871         _sd_cache_stats->st_wrcancelns++;\
 872 }
 873 
 874 #define WRITE_DESTAGED(cd, bytes) {\
 875         if (((cd) >= 0) && ((cd) < sdbc_max_devs))\
 876                 _sd_cache_stats->st_shared[(cd)].sh_destaged += (bytes);\
 877         _sd_cache_stats->st_destaged += (bytes);\
 878 }
 879 
 880 #define FBA_READ_IO_KSTATS(cd, bytes) {\
 881         if (((cd) >= 0) && ((cd) < sdbc_max_devs) && sdbc_cd_io_kstats[(cd)]) {\
 882                 KSTAT_IO_PTR(sdbc_cd_io_kstats[(cd)])->reads++;\
 883                 KSTAT_IO_PTR(sdbc_cd_io_kstats[(cd)])->nread += (bytes);\
 884         }\
 885         if (sdbc_global_io_kstat) {\
 886                 KSTAT_IO_PTR(sdbc_global_io_kstat)->reads++;\
 887                 KSTAT_IO_PTR(sdbc_global_io_kstat)->nread += (bytes);\
 888         }\
 889 }
 890 
 891 #define FBA_WRITE_IO_KSTATS(cd, bytes) {\
 892         if (((cd) >= 0) && ((cd) < sdbc_max_devs) && sdbc_cd_io_kstats[(cd)]) {\
 893                 KSTAT_IO_PTR(sdbc_cd_io_kstats[(cd)])->writes++;\
 894                 KSTAT_IO_PTR(sdbc_cd_io_kstats[(cd)])->nwritten += (bytes);\
 895         }\
 896         if (sdbc_global_io_kstat) {\
 897                 KSTAT_IO_PTR(sdbc_global_io_kstat)->writes++;\
 898                 KSTAT_IO_PTR(sdbc_global_io_kstat)->nwritten += (bytes);\
 899         }\
 900 }
 901 
 902 /* start timer measuring amount of time spent in the cache */
 903 #define KSTAT_RUNQ_ENTER(cd) {\
 904         if (((cd) >= 0) && ((cd) < sdbc_max_devs) && \
 905             sdbc_cd_io_kstats[(cd)] && sdbc_cd_io_kstats_mutexes) {\
 906                 mutex_enter(sdbc_cd_io_kstats[(cd)]->ks_lock);\
 907                 kstat_runq_enter(KSTAT_IO_PTR(sdbc_cd_io_kstats[(cd)]));\
 908                 mutex_exit(sdbc_cd_io_kstats[(cd)]->ks_lock);\
 909         }\
 910         if (sdbc_global_io_kstat) {\
 911                 mutex_enter(sdbc_global_io_kstat->ks_lock);\
 912                 kstat_runq_enter(KSTAT_IO_PTR(sdbc_global_io_kstat));\
 913                 mutex_exit(sdbc_global_io_kstat->ks_lock);\
 914         }\
 915 }
 916 
 917 /* stop timer measuring amount of time spent in the cache */
 918 #define KSTAT_RUNQ_EXIT(cd) {\
 919         if (((cd) >= 0) && ((cd) < sdbc_max_devs) && \
 920             sdbc_cd_io_kstats[(cd)] && sdbc_cd_io_kstats_mutexes) {\
 921                 mutex_enter(sdbc_cd_io_kstats[(cd)]->ks_lock);\
 922                 kstat_runq_exit(KSTAT_IO_PTR(sdbc_cd_io_kstats[(cd)]));\
 923                 mutex_exit(sdbc_cd_io_kstats[(cd)]->ks_lock);\
 924         }\
 925         if (sdbc_global_io_kstat) {\
 926                 mutex_enter(sdbc_global_io_kstat->ks_lock);\
 927                 kstat_runq_exit(KSTAT_IO_PTR(sdbc_global_io_kstat));\
 928                 mutex_exit(sdbc_global_io_kstat->ks_lock);\
 929         }\
 930 }
 931 
 932 #else
 933 #define CACHE_FBA_READ(cd, blks)
 934 #define DISK_FBA_READ(cd, blks)
 935 #define CACHE_FBA_WRITE(cd, blks)
 936 #define DISK_FBA_WRITE(cd, blks)
 937 #define CACHE_READ_HIT
 938 #define CACHE_READ_MISS
 939 #define CACHE_WRITE_HIT
 940 #define CACHE_WRITE_MISS
 941 #define CACHE_WRITE_CANCELLATION(cd)
 942 #define WRITE_DESTAGED(cd, bytes)
 943 #endif
 944 
 945 #endif /* _KERNEL */
 946 
 947 /* defines for sh_alloc */
 948 
 949 #define CD_ALLOC_IN_PROGRESS    0x0001
 950 #define CD_ALLOCATED            0x0002
 951 #define CD_CLOSE_IN_PROGRESS    0x0010
 952 
 953 /* defines for sh_flag */
 954 
 955 #define CD_ATTACHED             0x0001
 956 
 957 #ifdef _KERNEL
 958 
 959 typedef void (*sdbc_ea_fn_t) (blind_t, nsc_off_t, nsc_size_t, int);
 960 
 961 #define _SD_DISCONNECT_CALLBACK(hndl)   \
 962         if ((hndl)->bh_disconnect_cb) { \
 963                 SDTRACE(SDF_DISCONNECT, (hndl)->bh_cd, (hndl)->bh_fba_len, \
 964                         (hndl)->bh_fba_pos, (hndl)->bh_flag, 0); \
 965                 ((*((hndl)->bh_disconnect_cb))(hndl)); \
 966         }
 967 #define _SD_READ_CALLBACK(hndl) \
 968         if ((hndl)->bh_read_cb) \
 969             ((*((hndl)->bh_read_cb))(hndl)); \
 970         else cmn_err(CE_WARN, \
 971             "!sdbc(_SD_READ_CALLBACK) not registered. io lost");
 972 #define _SD_WRITE_CALLBACK(hndl)        \
 973         if ((hndl)->bh_write_cb) \
 974                 ((*((hndl)->bh_write_cb))(hndl)); \
 975         else cmn_err(CE_WARN, \
 976             "!sdbc(_SD_WRITE_CALLBACK) not registered. io lost");
 977 
 978 #endif /* _KERNEL */
 979 
 980 
 981 #if defined(_SD_LRU_OPTIMIZE)
 982 /*
 983  * Do not requeue if we fall into the tail 25% of the lru
 984  */
 985 #define LRU_REQ_LIMIT(q)        (q->sq_inq >> 2)
 986 
 987 #define _sd_lru_reinsert(q, ent) \
 988         (((q->sq_seq - ent->cc_seq) > LRU_REQ_LIMIT(q)) ?\
 989         1 : ((q->sq_noreq_stat)++, 0))
 990 #else
 991 #define _sd_lru_reinsert(ent) 1
 992 #endif
 993 
 994 #if defined(_KERNEL)
 995 #define SD_WR_NUMIO     100
 996 #define SD_DCON_THRESH  0x10000 /* Disconnect if io len greater than 64 */
 997 
 998 /*
 999  * These defines are the hardwired values after sd_config_param was
1000  * zapped. Ought to remove the use of these entirely ....
1001  */
1002 
1003 #define _SD_CD_WRITER(cd)       ((_sd_cache_files[(cd)].cd_info->sh_numdirty>\
1004                                 SD_WR_NUMIO) ? \
1005                                 cd_writer(cd) : 0)
1006 #define _SD_FORCE_DISCONNECT(len)       (SD_DCON_THRESH < FBA_SIZE(len))
1007 
1008 /* -------------------------------- END sd_config_param defines ---------- */
1009 
1010 #define _SD_CD_WBLK_USED(cd)    (_sd_cache_stats->st_shared[(cd)].sh_numio +\
1011                                 _sd_cache_stats->st_shared[(cd)].sh_numdirty)
1012 
1013 #define _SD_CD_ALL_WRITES(cd)   (_sd_cache_stats->st_shared[(cd)].sh_numio +\
1014                                 _sd_cache_stats->st_shared[(cd)].sh_numdirty+\
1015                                 _sd_cache_stats->st_shared[(cd)].sh_numfail)
1016 
1017 
1018 
1019 /*
1020  * ncall usage
1021  */
1022 #define SD_ENABLE               (NCALL_SDBC +  0)
1023 #define SD_DISABLE              (NCALL_SDBC +  1)
1024 #define SD_DUAL_WRITE           (NCALL_SDBC +  2)
1025 #define SD_DUAL_READ            (NCALL_SDBC +  3)
1026 #define SD_SET_CD               (NCALL_SDBC +  4)
1027 #define SD_GETSIZE              (NCALL_SDBC +  5)
1028 #define SD_DUAL_OPEN            (NCALL_SDBC +  6)
1029 #define SD_REMOTE_FLUSH         (NCALL_SDBC +  7)
1030 #define SD_SGREMOTE_FLUSH       (NCALL_SDBC +  8)
1031 #define SD_DISK_IO              (NCALL_SDBC +  9)
1032 #define SD_GET_BMAP             (NCALL_SDBC + 10)
1033 #define SD_CD_DISCARD           (NCALL_SDBC + 11)
1034 #define SD_PING                 (NCALL_SDBC + 12)
1035 #define SD_DC_MAIN_LOOP         (NCALL_SDBC + 13)
1036 #define SD_DATA                 (NCALL_SDBC + 14)
1037 #define SD_BDATA                (NCALL_SDBC + 15)
1038 #define SD_UPDATE               (NCALL_SDBC + 16)
1039 #define SD_GET_SYSID            (NCALL_SDBC + 17)
1040 
1041 #ifdef lint
1042 #include <sys/nsctl/nsctl.h>
1043 #define LINTUSED(x)     (void)(x)++
1044 #else
1045 #define LINTUSED(x)
1046 #endif
1047 
1048 
1049 extern int BLK_FBAS;
1050 extern _sd_bitmap_t BLK_FBA_BITS;
1051 extern _sd_bitmap_t _fba_bits[];
1052 extern _sd_cctl_t       *_sd_cctl[];
1053 extern _sd_cd_info_t    *_sd_cache_files;
1054 extern _sd_hash_table_t *_sd_htable;
1055 extern _sd_map_info_t _sd_lookup_map[];
1056 extern _sd_net_t         _sd_net_config;
1057 extern _sd_queue_t _sd_lru_q;
1058 extern _sd_stats_t *_sd_cache_stats;
1059 extern char _sd_contig_bmap[];
1060 extern int CACHE_BLOCK_SIZE;
1061 extern int CBLOCKS;
1062 extern int _sd_cctl_groupsz;
1063 extern int sdbc_static_cache;
1064 extern kmutex_t _sd_cache_lock;
1065 extern nsc_def_t _sd_sdbc_def[];
1066 extern nsc_io_t *sdbc_io;
1067 extern nsc_mem_t *sdbc_iobuf_mem, *sdbc_hash_mem;
1068 extern uint_t _sd_node_hint;
1069 extern int _sd_minidsp;
1070 extern krwlock_t sdbc_queue_lock;
1071 extern safestore_ops_t *sdbc_safestore;
1072 extern ss_common_config_t safestore_config;
1073 extern ss_voldata_t *_sdbc_gl_file_info;
1074 
1075 extern int _sdbc_cache_configure(int cblocks, spcs_s_info_t kstatus);
1076 extern void _sdbc_cache_deconfigure(void);
1077 extern void _sd_requeue(_sd_cctl_t *centry);
1078 extern void _sd_requeue_head(_sd_cctl_t *centry);
1079 extern int _sd_open(char *filename, int flag);
1080 extern int _sd_open_cd(char *filename, const int cd, const int flag);
1081 extern int _sd_close(int cd);
1082 extern int _sdbc_remote_store_pinned(int cd);
1083 extern int _sdbc_io_attach_cd(blind_t xcd);
1084 extern int _sdbc_io_detach_cd(blind_t xcd);
1085 extern int _sd_get_pinned(blind_t cd);
1086 extern void _sd_cc_copy(_sd_cctl_t *cc_real, _sd_cctl_t *cc_shadow);
1087 extern _sd_buf_handle_t *_sd_allocate_buf(int cd, nsc_off_t fba_pos,
1088     nsc_size_t fba_len, int flag, int *sts);
1089 extern void _sd_cc_wait(int cd, nsc_off_t cblk, _sd_cctl_t *centry, int flag);
1090 extern int _sd_alloc_buf(blind_t xcd, nsc_off_t fba_pos, nsc_size_t fba_len,
1091     int flag, _sd_buf_handle_t **handle_p);
1092 extern int _sd_free_buf(_sd_buf_handle_t *handle);
1093 extern _sd_cctl_t *_sd_centry_alloc(int, int, int *, int, int);
1094 extern int _sd_centry_setup_dm(_sd_cctl_t *, int, int);
1095 extern void _sdbc_dealloc_deconfigure_dm(void);
1096 extern int _sdbc_dealloc_configure_dm(void);
1097 extern _sd_cctl_t *_sd_shadow_centry(_sd_cctl_t *, _sd_cctl_t *, int, int, int);
1098 extern void _sd_centry_release(_sd_cctl_t *centry);
1099 extern int _sd_alloc_write(_sd_cctl_t *centry, int *stall);
1100 extern int _sd_read(_sd_buf_handle_t *handle, nsc_off_t fba_pos,
1101     nsc_size_t fba_len, int flag);
1102 extern void _sd_read_complete(_sd_buf_handle_t *handle, nsc_off_t fba_pos,
1103     nsc_size_t fba_len, int error);
1104 extern int _sd_write(_sd_buf_handle_t *handle, nsc_off_t fba_pos,
1105     nsc_size_t fba_len, int flag);
1106 extern int _sd_zero(_sd_buf_handle_t *handle, nsc_off_t fba_pos,
1107     nsc_size_t fba_len, int flag);
1108 extern int _sd_copy(_sd_buf_handle_t *handle1, _sd_buf_handle_t *handle2,
1109     nsc_off_t fba_pos1, nsc_off_t fba_pos2, nsc_size_t fba_len);
1110 extern void _sd_enqueue_dirty(int cd, _sd_cctl_t *chain, _sd_cctl_t *cc_last,
1111     int numq);
1112 extern void _sd_enqueue_dirty_chain(int cd, _sd_cctl_t *chain_first,
1113     _sd_cctl_t *chain_last, int numq);
1114 extern int _sd_get_stats(_sd_stats_t *uptr, int convert_32);
1115 extern int _sd_set_hint(int cd, uint_t hint);
1116 extern int _sd_clear_hint(int cd, uint_t hint);
1117 extern int _sd_get_cd_hint(int cd, uint_t *hint);
1118 extern int _sd_set_node_hint(uint_t hint);
1119 extern int _sd_clear_node_hint(uint_t hint);
1120 extern int _sd_get_node_hint(uint_t *hint);
1121 extern int _sd_get_partsize(blind_t cd, nsc_size_t *ptr);
1122 extern int _sd_get_maxfbas(blind_t cd, int flag, nsc_size_t *ptr);
1123 extern int _sd_discard_pinned(blind_t cd, nsc_off_t fba_pos,
1124     nsc_size_t fba_len);
1125 extern void _sdbc_handles_unload(void);
1126 extern int _sdbc_handles_load(void);
1127 extern int _sdbc_handles_configure();
1128 extern void _sdbc_handles_deconfigure(void);
1129 extern _sd_buf_handle_t *_sd_alloc_handle(sdbc_callback_fn_t d_cb,
1130     sdbc_callback_fn_t r_cb, sdbc_callback_fn_t w_cb);
1131 extern int _sd_free_handle(_sd_buf_handle_t *handle);
1132 extern void _sd_init_contig_bmap(void);
1133 extern void _sd_init_lookup_map(void);
1134 extern int sd_get_file_info_size(void *uaddrp);
1135 extern int sd_get_file_info_data(char *uaddrp);
1136 extern int sd_get_glmul_sizes(int *uaddrp);
1137 extern int sd_get_glmul_info(char *uaddrp);
1138 extern _sd_cctl_t *sdbc_centry_alloc(int, nsc_off_t, nsc_size_t, int *,
1139                                         sdbc_allocbuf_t *, int);
1140 extern _sd_cctl_t *sdbc_centry_alloc_blks(int, nsc_off_t, nsc_size_t, int);
1141 extern int _sdbc_ft_hold_io;
1142 extern kcondvar_t _sdbc_ft_hold_io_cv;
1143 extern kmutex_t _sdbc_ft_hold_io_lk;
1144 
1145 #ifdef DEBUG
1146 /* for testing only */
1147 extern int _sdbc_flush_flag; /* inhibit flush for testing */
1148 extern int _sdbc_clear_ioerr(int);
1149 extern int _sdbc_inject_ioerr(int, int, int);
1150 extern void _sdbc_ioj_set_dev(int, dev_t);
1151 extern void _sdbc_ioj_load();
1152 extern void _sdbc_ioj_unload();
1153 #endif
1154 
1155 #endif /* _KERNEL */
1156 
1157 #ifdef __cplusplus
1158 }
1159 #endif
1160 
1161 #endif /* _SD_BCACHE_H */