17836SJohn.Forte@Sun.COM /*
27836SJohn.Forte@Sun.COM * CDDL HEADER START
37836SJohn.Forte@Sun.COM *
47836SJohn.Forte@Sun.COM * The contents of this file are subject to the terms of the
57836SJohn.Forte@Sun.COM * Common Development and Distribution License (the "License").
67836SJohn.Forte@Sun.COM * You may not use this file except in compliance with the License.
77836SJohn.Forte@Sun.COM *
87836SJohn.Forte@Sun.COM * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97836SJohn.Forte@Sun.COM * or http://www.opensolaris.org/os/licensing.
107836SJohn.Forte@Sun.COM * See the License for the specific language governing permissions
117836SJohn.Forte@Sun.COM * and limitations under the License.
127836SJohn.Forte@Sun.COM *
137836SJohn.Forte@Sun.COM * When distributing Covered Code, include this CDDL HEADER in each
147836SJohn.Forte@Sun.COM * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157836SJohn.Forte@Sun.COM * If applicable, add the following below this CDDL HEADER, with the
167836SJohn.Forte@Sun.COM * fields enclosed by brackets "[]" replaced with your own identifying
177836SJohn.Forte@Sun.COM * information: Portions Copyright [yyyy] [name of copyright owner]
187836SJohn.Forte@Sun.COM *
197836SJohn.Forte@Sun.COM * CDDL HEADER END
207836SJohn.Forte@Sun.COM */
217836SJohn.Forte@Sun.COM /*
229093SRamana.Srikanth@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
237836SJohn.Forte@Sun.COM * Use is subject to license terms.
247836SJohn.Forte@Sun.COM */
257836SJohn.Forte@Sun.COM
267836SJohn.Forte@Sun.COM #include <sys/types.h>
277836SJohn.Forte@Sun.COM #include <sys/ksynch.h>
287836SJohn.Forte@Sun.COM #include <sys/cmn_err.h>
297836SJohn.Forte@Sun.COM #include <sys/kmem.h>
307836SJohn.Forte@Sun.COM #include <sys/buf.h>
317836SJohn.Forte@Sun.COM #include <sys/cred.h>
327836SJohn.Forte@Sun.COM #include <sys/errno.h>
337836SJohn.Forte@Sun.COM #include <sys/ddi.h>
347836SJohn.Forte@Sun.COM
357836SJohn.Forte@Sun.COM #include <sys/nsc_thread.h>
367836SJohn.Forte@Sun.COM #include <sys/nsctl/nsctl.h>
377836SJohn.Forte@Sun.COM
387836SJohn.Forte@Sun.COM #include <sys/sdt.h> /* dtrace is S10 or later */
397836SJohn.Forte@Sun.COM
407836SJohn.Forte@Sun.COM #include "sd_bcache.h"
417836SJohn.Forte@Sun.COM #include "sd_trace.h"
427836SJohn.Forte@Sun.COM #include "sd_io.h"
437836SJohn.Forte@Sun.COM #include "sd_bio.h"
447836SJohn.Forte@Sun.COM #include "sd_misc.h"
457836SJohn.Forte@Sun.COM #include "sd_ft.h"
467836SJohn.Forte@Sun.COM #include "sd_pcu.h"
477836SJohn.Forte@Sun.COM
487836SJohn.Forte@Sun.COM /*
497836SJohn.Forte@Sun.COM * dynamic memory support
507836SJohn.Forte@Sun.COM */
517836SJohn.Forte@Sun.COM _dm_process_vars_t dynmem_processing_dm;
527836SJohn.Forte@Sun.COM static int sd_dealloc_flag_dm = NO_THREAD_DM;
537836SJohn.Forte@Sun.COM static void _sd_dealloc_dm(void);
547836SJohn.Forte@Sun.COM static int _sd_entry_availability_dm(_sd_cctl_t *cc_ent, int *nodata);
557836SJohn.Forte@Sun.COM
567836SJohn.Forte@Sun.COM extern void sdbc_requeue_dmchain(_sd_queue_t *, _sd_cctl_t *, int, int);
577836SJohn.Forte@Sun.COM extern void sdbc_ins_dmqueue_front(_sd_queue_t *q, _sd_cctl_t *cc_ent);
587836SJohn.Forte@Sun.COM extern void sdbc_remq_dmchain(_sd_queue_t *q, _sd_cctl_t *cc_ent);
597836SJohn.Forte@Sun.COM extern void sdbc_requeue_head_dm_try(_sd_cctl_t *);
607836SJohn.Forte@Sun.COM extern int sdbc_use_dmchain;
617836SJohn.Forte@Sun.COM extern _sd_queue_t *sdbc_dm_queues;
627836SJohn.Forte@Sun.COM
637836SJohn.Forte@Sun.COM kcondvar_t _sd_flush_cv;
647836SJohn.Forte@Sun.COM static volatile int _sd_flush_exit;
657836SJohn.Forte@Sun.COM
667836SJohn.Forte@Sun.COM /* secret flush toggle flag for testing */
677836SJohn.Forte@Sun.COM #ifdef DEBUG
687836SJohn.Forte@Sun.COM int _sdbc_flush_flag = 1; /* 0 ==> noflushing, 1 ==> flush */
697836SJohn.Forte@Sun.COM #endif
707836SJohn.Forte@Sun.COM
717836SJohn.Forte@Sun.COM static int sdbc_flush_pageio;
727836SJohn.Forte@Sun.COM
737836SJohn.Forte@Sun.COM
747836SJohn.Forte@Sun.COM
757836SJohn.Forte@Sun.COM /*
767836SJohn.Forte@Sun.COM * Forward declare all statics that are used before defined to enforce
777836SJohn.Forte@Sun.COM * parameter checking
787836SJohn.Forte@Sun.COM * Some (if not all) of these could be removed if the code were reordered
797836SJohn.Forte@Sun.COM */
807836SJohn.Forte@Sun.COM
817836SJohn.Forte@Sun.COM static void _sd_flcent_ea(blind_t xcc_ent, nsc_off_t fba_pos,
827836SJohn.Forte@Sun.COM nsc_size_t fba_len, int error);
837836SJohn.Forte@Sun.COM static void _sd_flclist_ea(blind_t xcc_ent, nsc_off_t fba_pos,
847836SJohn.Forte@Sun.COM nsc_size_t fba_len, int error);
857836SJohn.Forte@Sun.COM static void _sd_process_reflush(_sd_cctl_t *cc_ent);
867836SJohn.Forte@Sun.COM static void _sd_flush_thread(void);
877836SJohn.Forte@Sun.COM
887836SJohn.Forte@Sun.COM int
_sdbc_flush_configure(void)897836SJohn.Forte@Sun.COM _sdbc_flush_configure(void)
907836SJohn.Forte@Sun.COM {
917836SJohn.Forte@Sun.COM _sd_flush_exit = 1;
927836SJohn.Forte@Sun.COM sdbc_flush_pageio = 0;
937836SJohn.Forte@Sun.COM return (nsc_create_process(
949093SRamana.Srikanth@Sun.COM (void (*)(void *))_sd_flush_thread, 0, TRUE));
957836SJohn.Forte@Sun.COM }
967836SJohn.Forte@Sun.COM
977836SJohn.Forte@Sun.COM
987836SJohn.Forte@Sun.COM void
_sdbc_flush_deconfigure(void)997836SJohn.Forte@Sun.COM _sdbc_flush_deconfigure(void)
1007836SJohn.Forte@Sun.COM {
1017836SJohn.Forte@Sun.COM _sd_unblock(&_sd_flush_cv);
1027836SJohn.Forte@Sun.COM _sd_flush_exit = 0;
1037836SJohn.Forte@Sun.COM }
1047836SJohn.Forte@Sun.COM
1057836SJohn.Forte@Sun.COM static int
sdbc_alloc_static_cache(int reqblks)1067836SJohn.Forte@Sun.COM sdbc_alloc_static_cache(int reqblks)
1077836SJohn.Forte@Sun.COM {
1087836SJohn.Forte@Sun.COM _sd_cctl_t *centry;
1097836SJohn.Forte@Sun.COM _sd_cctl_t *next_centry;
1107836SJohn.Forte@Sun.COM
1117836SJohn.Forte@Sun.COM if (centry = sdbc_centry_alloc_blks(_CD_NOHASH, 0, reqblks,
1129093SRamana.Srikanth@Sun.COM ALLOC_NOWAIT)) {
1137836SJohn.Forte@Sun.COM /* release the blocks to the queue */
1147836SJohn.Forte@Sun.COM while (centry) {
1157836SJohn.Forte@Sun.COM next_centry = centry->cc_chain;
1167836SJohn.Forte@Sun.COM _sd_centry_release(centry);
1177836SJohn.Forte@Sun.COM centry = next_centry;
1187836SJohn.Forte@Sun.COM }
1197836SJohn.Forte@Sun.COM return (reqblks);
1207836SJohn.Forte@Sun.COM }
1217836SJohn.Forte@Sun.COM return (0);
1227836SJohn.Forte@Sun.COM }
1237836SJohn.Forte@Sun.COM
1247836SJohn.Forte@Sun.COM int
_sdbc_dealloc_configure_dm(void)1257836SJohn.Forte@Sun.COM _sdbc_dealloc_configure_dm(void)
1267836SJohn.Forte@Sun.COM {
1277836SJohn.Forte@Sun.COM int rc = 0;
1287836SJohn.Forte@Sun.COM int reqblks = MEGABYTE/BLK_SIZE(1); /* alloc in mb chunks */
1297836SJohn.Forte@Sun.COM int i;
1307836SJohn.Forte@Sun.COM int blk_groups; /* number of ~MB groups */
1317836SJohn.Forte@Sun.COM int blks_remaining;
1327836SJohn.Forte@Sun.COM int blks_allocd = 0;
1337836SJohn.Forte@Sun.COM
1347836SJohn.Forte@Sun.COM dynmem_processing_dm.alloc_ct = 0;
1357836SJohn.Forte@Sun.COM dynmem_processing_dm.dealloc_ct = 0;
1367836SJohn.Forte@Sun.COM
1377836SJohn.Forte@Sun.COM if (sdbc_static_cache) { /* alloc all static cache memory here */
1387836SJohn.Forte@Sun.COM dynmem_processing_dm.max_dyn_list = reqblks;
1397836SJohn.Forte@Sun.COM
1407836SJohn.Forte@Sun.COM blk_groups = CBLOCKS / reqblks;
1417836SJohn.Forte@Sun.COM blks_remaining = CBLOCKS % reqblks;
1427836SJohn.Forte@Sun.COM
1437836SJohn.Forte@Sun.COM for (i = 0; i < blk_groups; ++i) {
1447836SJohn.Forte@Sun.COM if (!sdbc_alloc_static_cache(reqblks))
1457836SJohn.Forte@Sun.COM break;
1467836SJohn.Forte@Sun.COM blks_allocd += reqblks;
1477836SJohn.Forte@Sun.COM }
1487836SJohn.Forte@Sun.COM DTRACE_PROBE2(_sdbc_dealloc_configure_dm1,
1499093SRamana.Srikanth@Sun.COM int, i, int, blks_allocd);
1507836SJohn.Forte@Sun.COM
1517836SJohn.Forte@Sun.COM /* if successful then allocate any remaining blocks */
1527836SJohn.Forte@Sun.COM if ((i == blk_groups) && blks_remaining)
1537836SJohn.Forte@Sun.COM if (sdbc_alloc_static_cache(blks_remaining))
1547836SJohn.Forte@Sun.COM blks_allocd += blks_remaining;
1557836SJohn.Forte@Sun.COM
1567836SJohn.Forte@Sun.COM DTRACE_PROBE2(_sdbc_dealloc_configure_dm2,
1579093SRamana.Srikanth@Sun.COM int, i, int, blks_allocd);
1587836SJohn.Forte@Sun.COM
1597836SJohn.Forte@Sun.COM sd_dealloc_flag_dm = NO_THREAD_DM;
1607836SJohn.Forte@Sun.COM
1617836SJohn.Forte@Sun.COM if (blks_allocd < CBLOCKS) {
1629093SRamana.Srikanth@Sun.COM cmn_err(CE_WARN, "!Failed to allocate sdbc cache "
1637836SJohn.Forte@Sun.COM "memory.\n requested mem: %d MB; actual mem: %d MB",
1647836SJohn.Forte@Sun.COM CBLOCKS/reqblks, blks_allocd/reqblks);
1657836SJohn.Forte@Sun.COM rc = ENOMEM;
1667836SJohn.Forte@Sun.COM }
1677836SJohn.Forte@Sun.COM
1687836SJohn.Forte@Sun.COM
1697836SJohn.Forte@Sun.COM #ifdef DEBUG
1709093SRamana.Srikanth@Sun.COM cmn_err(CE_NOTE, "!sdbc(_sdbc_dealloc_configure_dm) %d bytes "
1719093SRamana.Srikanth@Sun.COM "(%d cache blocks) allocated for static cache, "
1729093SRamana.Srikanth@Sun.COM "block size %d", blks_allocd * BLK_SIZE(1), blks_allocd,
1739093SRamana.Srikanth@Sun.COM BLK_SIZE(1));
1747836SJohn.Forte@Sun.COM #endif /* DEBUG */
1757836SJohn.Forte@Sun.COM } else {
1767836SJohn.Forte@Sun.COM sd_dealloc_flag_dm = PROCESS_CACHE_DM;
1777836SJohn.Forte@Sun.COM rc = nsc_create_process((void (*)(void *))_sd_dealloc_dm, 0,
1789093SRamana.Srikanth@Sun.COM TRUE);
1797836SJohn.Forte@Sun.COM if (rc != 0)
1807836SJohn.Forte@Sun.COM sd_dealloc_flag_dm = NO_THREAD_DM;
1817836SJohn.Forte@Sun.COM }
1827836SJohn.Forte@Sun.COM return (rc);
1837836SJohn.Forte@Sun.COM }
1847836SJohn.Forte@Sun.COM
1857836SJohn.Forte@Sun.COM /*
1867836SJohn.Forte@Sun.COM * sdbc_dealloc_dm_shutdown - deallocate cache memory.
1877836SJohn.Forte@Sun.COM *
1887836SJohn.Forte@Sun.COM * ARGUMENTS: none
1897836SJohn.Forte@Sun.COM *
1907836SJohn.Forte@Sun.COM * RETURNS: nothing
1917836SJohn.Forte@Sun.COM *
1927836SJohn.Forte@Sun.COM * USAGE:
1937836SJohn.Forte@Sun.COM * this function is intended for use after all i/o has stopped and all
1947836SJohn.Forte@Sun.COM * other cache threads have terminated. write cache resources, if any
1957836SJohn.Forte@Sun.COM * are released, except in the case of pinned data.
1967836SJohn.Forte@Sun.COM */
1977836SJohn.Forte@Sun.COM static void
sdbc_dealloc_dm_shutdown()1987836SJohn.Forte@Sun.COM sdbc_dealloc_dm_shutdown()
1997836SJohn.Forte@Sun.COM {
2007836SJohn.Forte@Sun.COM _sd_cctl_t *cc_ent;
2017836SJohn.Forte@Sun.COM ss_centry_info_t *wctl;
2027836SJohn.Forte@Sun.COM
2037836SJohn.Forte@Sun.COM cc_ent = _sd_cctl[0];
2047836SJohn.Forte@Sun.COM
2057836SJohn.Forte@Sun.COM if (!cc_ent)
2067836SJohn.Forte@Sun.COM return;
2077836SJohn.Forte@Sun.COM
2087836SJohn.Forte@Sun.COM do {
2097836SJohn.Forte@Sun.COM if (cc_ent->cc_alloc_size_dm) {
2107836SJohn.Forte@Sun.COM /* HOST or OTHER */
2117836SJohn.Forte@Sun.COM
2127836SJohn.Forte@Sun.COM if (cc_ent->cc_data)
2137836SJohn.Forte@Sun.COM kmem_free(cc_ent->cc_data,
2147836SJohn.Forte@Sun.COM cc_ent->cc_alloc_size_dm);
2157836SJohn.Forte@Sun.COM
2167836SJohn.Forte@Sun.COM cc_ent->cc_alloc_size_dm = 0;
2177836SJohn.Forte@Sun.COM
2187836SJohn.Forte@Sun.COM dynmem_processing_dm.dealloc_ct++;
2197836SJohn.Forte@Sun.COM
2209093SRamana.Srikanth@Sun.COM DTRACE_PROBE2(sdbc_dealloc_dm_shutdown, char *,
2219093SRamana.Srikanth@Sun.COM cc_ent->cc_data, int, cc_ent->cc_alloc_size_dm);
2227836SJohn.Forte@Sun.COM }
2237836SJohn.Forte@Sun.COM
2247836SJohn.Forte@Sun.COM /* release safestore resource, if any. preserve pinned data */
2257836SJohn.Forte@Sun.COM if (!(CENTRY_DIRTY(cc_ent)) && (wctl = cc_ent->cc_write)) {
2267836SJohn.Forte@Sun.COM wctl->sc_flag = 0;
2277836SJohn.Forte@Sun.COM wctl->sc_dirty = 0;
2287836SJohn.Forte@Sun.COM
2297836SJohn.Forte@Sun.COM SSOP_SETCENTRY(sdbc_safestore, wctl);
2307836SJohn.Forte@Sun.COM SSOP_DEALLOCRESOURCE(sdbc_safestore, wctl->sc_res);
2317836SJohn.Forte@Sun.COM }
2327836SJohn.Forte@Sun.COM cc_ent = cc_ent->cc_link_list_dm;
2337836SJohn.Forte@Sun.COM } while (cc_ent != _sd_cctl[0]);
2347836SJohn.Forte@Sun.COM }
2357836SJohn.Forte@Sun.COM
2367836SJohn.Forte@Sun.COM void
_sdbc_dealloc_deconfigure_dm(void)2377836SJohn.Forte@Sun.COM _sdbc_dealloc_deconfigure_dm(void)
2387836SJohn.Forte@Sun.COM {
2397836SJohn.Forte@Sun.COM int one_sec;
2407836SJohn.Forte@Sun.COM
2417836SJohn.Forte@Sun.COM if (sdbc_static_cache) {
2427836SJohn.Forte@Sun.COM sdbc_dealloc_dm_shutdown();
2437836SJohn.Forte@Sun.COM return;
2447836SJohn.Forte@Sun.COM }
2457836SJohn.Forte@Sun.COM
2467836SJohn.Forte@Sun.COM if (sd_dealloc_flag_dm == NO_THREAD_DM)
2477836SJohn.Forte@Sun.COM return; /* thread never started */
2487836SJohn.Forte@Sun.COM one_sec = HZ; /* drv_usectohz(1000000); */
2497836SJohn.Forte@Sun.COM
2507836SJohn.Forte@Sun.COM mutex_enter(&dynmem_processing_dm.thread_dm_lock);
2517836SJohn.Forte@Sun.COM sd_dealloc_flag_dm = CACHE_SHUTDOWN_DM;
2527836SJohn.Forte@Sun.COM cv_broadcast(&dynmem_processing_dm.thread_dm_cv);
2537836SJohn.Forte@Sun.COM mutex_exit(&dynmem_processing_dm.thread_dm_lock);
2547836SJohn.Forte@Sun.COM
2557836SJohn.Forte@Sun.COM while (sd_dealloc_flag_dm != CACHE_THREAD_TERMINATED_DM)
2567836SJohn.Forte@Sun.COM delay(one_sec);
2577836SJohn.Forte@Sun.COM
2587836SJohn.Forte@Sun.COM sd_dealloc_flag_dm = NO_THREAD_DM;
2597836SJohn.Forte@Sun.COM }
2607836SJohn.Forte@Sun.COM
2617836SJohn.Forte@Sun.COM /*
2627836SJohn.Forte@Sun.COM * This complicated - possibly overly complicated routine works as follows:
2637836SJohn.Forte@Sun.COM * In general the routine sleeps a specified amount of time then wakes and
2647836SJohn.Forte@Sun.COM * examines the entire centry list. If an entry is avail. it ages it by one
2657836SJohn.Forte@Sun.COM * tick else it clears the aging flag completely. It then determines if the
2667836SJohn.Forte@Sun.COM * centry has aged sufficiently to have its memory deallocated and for it to
2677836SJohn.Forte@Sun.COM * be placed at the top of the lru.
2687836SJohn.Forte@Sun.COM *
2697836SJohn.Forte@Sun.COM * There are two deallocation schemes in place depending on whether the
2707836SJohn.Forte@Sun.COM * centry is a standalone entry or it is a member of a host/parasite chain.
2717836SJohn.Forte@Sun.COM *
2727836SJohn.Forte@Sun.COM * The behavior for a standalone entry is as follows:
2737836SJohn.Forte@Sun.COM * If the given centry is selected it will age normally however at full
2747836SJohn.Forte@Sun.COM * aging it will only be placed at the head of the lru. It's memory will
2757836SJohn.Forte@Sun.COM * not be deallocated until a further aging level has been reached. The
2767836SJohn.Forte@Sun.COM * entries selected for this behavior are goverend by counting the number
2777836SJohn.Forte@Sun.COM * of these holdovers in existence on each wakeup and and comparing it
2787836SJohn.Forte@Sun.COM * to a specified percentage. This comparision is always one cycle out of
2797836SJohn.Forte@Sun.COM * date and will float in the relative vicinity of the specified number.
2807836SJohn.Forte@Sun.COM *
2817836SJohn.Forte@Sun.COM * The behavior for a host/parasite chain is as follows:
2827836SJohn.Forte@Sun.COM * The chain is examined. If all entries are fully aged the entire chain
2837836SJohn.Forte@Sun.COM * is removed - ie mem is dealloc. from the host entry and all memory ref.
2847836SJohn.Forte@Sun.COM * removed from the parasitic entries and each entry requeued on to the lru.
2857836SJohn.Forte@Sun.COM *
2867836SJohn.Forte@Sun.COM * There are three delay timeouts and two percentage levels specified. Timeout
2877836SJohn.Forte@Sun.COM * level 1 is honored between 100% free and pcnt level 1. Timeout level 2 is
2887836SJohn.Forte@Sun.COM * honored between pcnt level 1 and pcnt level 2, Timeout level 3 is
2897836SJohn.Forte@Sun.COM * honored between pcnt level 2 and 0% free. In addition there exist an
2907836SJohn.Forte@Sun.COM * accelerated
2917836SJohn.Forte@Sun.COM * aging flag which mimics hysterisis behavior. If the available centrys fall
2927836SJohn.Forte@Sun.COM * between pcnt1 and pcnt2 an 8 bit counter is switched on. The effect is to
2937836SJohn.Forte@Sun.COM * keep the timer value at timer level 2 for 8 cycles even if the number
2947836SJohn.Forte@Sun.COM * available cache entries drifts above pcnt1. If it falls below pcnt2 an
2957836SJohn.Forte@Sun.COM * additional 8 bit counter is switched on. This causes the sleep timer to
2967836SJohn.Forte@Sun.COM * remain at timer level 3 for at least 8 cycles even if it floats above
2977836SJohn.Forte@Sun.COM * pcnt2 or even pcnt1. The effect of all this is to accelerate the release
2987836SJohn.Forte@Sun.COM * of system resources under a heavy load.
2997836SJohn.Forte@Sun.COM *
3007836SJohn.Forte@Sun.COM * All of the footwork can be stubbed out by a judicious selection of values
3017836SJohn.Forte@Sun.COM * for the times, aging counts and pcnts.
3027836SJohn.Forte@Sun.COM *
3037836SJohn.Forte@Sun.COM * All of these behavior parameters are adjustable on the fly via the kstat
3047836SJohn.Forte@Sun.COM * mechanism. In addition there is a thread wakeup msg available through the
3057836SJohn.Forte@Sun.COM * same mechanism.
3067836SJohn.Forte@Sun.COM */
3077836SJohn.Forte@Sun.COM
3087836SJohn.Forte@Sun.COM static void
_sd_dealloc_dm(void)3097836SJohn.Forte@Sun.COM _sd_dealloc_dm(void)
3107836SJohn.Forte@Sun.COM {
3117836SJohn.Forte@Sun.COM int one_sec_tics, tic_delay;
3127836SJohn.Forte@Sun.COM int sleep_tics_lvl1, sleep_tics_lvl2, sleep_tics_lvl3;
3137836SJohn.Forte@Sun.COM int transition_lvl1, transition_lvl2;
3147836SJohn.Forte@Sun.COM int host_cache_aging_ct, meta_cache_aging_ct, hold_cache_aging_ct;
3157836SJohn.Forte@Sun.COM int max_holds_ct;
3167836SJohn.Forte@Sun.COM int cache_aging_ct, hold_candidate, last_holds_ct;
3177836SJohn.Forte@Sun.COM _sd_cctl_t *cc_ent, *next_ccentry, *cur_ent, *nxt_ent;
3187836SJohn.Forte@Sun.COM ss_centry_info_t *wctl;
3197836SJohn.Forte@Sun.COM int current_breakout_count, number_cache_entries;
3207836SJohn.Forte@Sun.COM int dealloc;
3217836SJohn.Forte@Sun.COM _dm_process_vars_t *ppvars;
3227836SJohn.Forte@Sun.COM
3237836SJohn.Forte@Sun.COM int write_dealloc; /* remove after debugging */
3247836SJohn.Forte@Sun.COM
3257836SJohn.Forte@Sun.COM ppvars = &dynmem_processing_dm;
3267836SJohn.Forte@Sun.COM
3277836SJohn.Forte@Sun.COM /* setup a one sec time var */
3287836SJohn.Forte@Sun.COM one_sec_tics = HZ; /* drv_usectohz(1000000); */
3297836SJohn.Forte@Sun.COM
3307836SJohn.Forte@Sun.COM ppvars->history = 0;
3317836SJohn.Forte@Sun.COM
3327836SJohn.Forte@Sun.COM cc_ent = _sd_cctl[0];
3337836SJohn.Forte@Sun.COM
3347836SJohn.Forte@Sun.COM number_cache_entries = _sd_net_config.sn_cpages;
3357836SJohn.Forte@Sun.COM
3367836SJohn.Forte@Sun.COM last_holds_ct = 0;
3377836SJohn.Forte@Sun.COM
3387836SJohn.Forte@Sun.COM /*CONSTANTCONDITION*/
3397836SJohn.Forte@Sun.COM while (1) {
3407836SJohn.Forte@Sun.COM if (sd_dealloc_flag_dm == CACHE_SHUTDOWN_DM) {
3417836SJohn.Forte@Sun.COM /* finished. shutdown - get out */
3427836SJohn.Forte@Sun.COM sdbc_dealloc_dm_shutdown(); /* free all memory */
3437836SJohn.Forte@Sun.COM sd_dealloc_flag_dm = CACHE_THREAD_TERMINATED_DM;
3447836SJohn.Forte@Sun.COM return;
3457836SJohn.Forte@Sun.COM }
3467836SJohn.Forte@Sun.COM
3477836SJohn.Forte@Sun.COM /* has the world changed */
3487836SJohn.Forte@Sun.COM
3497836SJohn.Forte@Sun.COM /*
3507836SJohn.Forte@Sun.COM * get num cctl entries (%) below which different sleep
3517836SJohn.Forte@Sun.COM * rates kick in
3527836SJohn.Forte@Sun.COM */
3537836SJohn.Forte@Sun.COM transition_lvl1 =
3547836SJohn.Forte@Sun.COM (ppvars->cache_aging_pcnt1*number_cache_entries) / 100;
3557836SJohn.Forte@Sun.COM transition_lvl2 =
3567836SJohn.Forte@Sun.COM (ppvars->cache_aging_pcnt2*number_cache_entries) / 100;
3577836SJohn.Forte@Sun.COM
3587836SJohn.Forte@Sun.COM /* get sleep rates for each level */
3597836SJohn.Forte@Sun.COM sleep_tics_lvl1 = ppvars->cache_aging_sec1 * one_sec_tics;
3607836SJohn.Forte@Sun.COM sleep_tics_lvl2 = ppvars->cache_aging_sec2 * one_sec_tics;
3617836SJohn.Forte@Sun.COM sleep_tics_lvl3 = ppvars->cache_aging_sec3 * one_sec_tics;
3627836SJohn.Forte@Sun.COM
3637836SJohn.Forte@Sun.COM /* get num of cycles for full normal aging */
3647836SJohn.Forte@Sun.COM host_cache_aging_ct = ppvars->cache_aging_ct1;
3657836SJohn.Forte@Sun.COM
3667836SJohn.Forte@Sun.COM /* get num of cycles for full meta aging */
3677836SJohn.Forte@Sun.COM meta_cache_aging_ct = ppvars->cache_aging_ct2;
3687836SJohn.Forte@Sun.COM
3697836SJohn.Forte@Sun.COM /* get num of cycles for full extended holdover aging */
3707836SJohn.Forte@Sun.COM hold_cache_aging_ct = ppvars->cache_aging_ct3;
3717836SJohn.Forte@Sun.COM
3727836SJohn.Forte@Sun.COM /* get maximum holds count in % */
3737836SJohn.Forte@Sun.COM max_holds_ct = (ppvars->max_holds_pcnt*number_cache_entries)
3747836SJohn.Forte@Sun.COM / 100;
3757836SJohn.Forte@Sun.COM
3767836SJohn.Forte@Sun.COM /* apply the delay */
3777836SJohn.Forte@Sun.COM tic_delay = sleep_tics_lvl1;
3787836SJohn.Forte@Sun.COM if (sd_dealloc_flag_dm == TIME_DELAY_LVL1)
3797836SJohn.Forte@Sun.COM tic_delay = sleep_tics_lvl2;
3807836SJohn.Forte@Sun.COM else
3817836SJohn.Forte@Sun.COM if (sd_dealloc_flag_dm == TIME_DELAY_LVL2)
3827836SJohn.Forte@Sun.COM tic_delay = sleep_tics_lvl3;
3837836SJohn.Forte@Sun.COM
3847836SJohn.Forte@Sun.COM mutex_enter(&ppvars->thread_dm_lock);
385*11066Srafael.vanoni@sun.com (void) cv_reltimedwait(&ppvars->thread_dm_cv,
386*11066Srafael.vanoni@sun.com &ppvars->thread_dm_lock, tic_delay, TR_CLOCK_TICK);
3877836SJohn.Forte@Sun.COM mutex_exit(&ppvars->thread_dm_lock);
3887836SJohn.Forte@Sun.COM
3897836SJohn.Forte@Sun.COM /* check for special directives on wakeup */
3907836SJohn.Forte@Sun.COM if (ppvars->process_directive &
3917836SJohn.Forte@Sun.COM MAX_OUT_ACCEL_HIST_FLAG_DM) {
3927836SJohn.Forte@Sun.COM ppvars->process_directive &=
3937836SJohn.Forte@Sun.COM ~MAX_OUT_ACCEL_HIST_FLAG_DM;
3947836SJohn.Forte@Sun.COM ppvars->history =
3957836SJohn.Forte@Sun.COM (HISTORY_LVL1|HISTORY_LVL2);
3967836SJohn.Forte@Sun.COM }
3977836SJohn.Forte@Sun.COM
3987836SJohn.Forte@Sun.COM /* Start of deallocation loop */
3997836SJohn.Forte@Sun.COM current_breakout_count = 0;
4007836SJohn.Forte@Sun.COM
4017836SJohn.Forte@Sun.COM ppvars->nodatas = 0;
4027836SJohn.Forte@Sun.COM write_dealloc = 0;
4037836SJohn.Forte@Sun.COM ppvars->deallocs = 0;
4047836SJohn.Forte@Sun.COM ppvars->candidates = 0;
4057836SJohn.Forte@Sun.COM ppvars->hosts = 0;
4067836SJohn.Forte@Sun.COM ppvars->pests = 0;
4077836SJohn.Forte@Sun.COM ppvars->metas = 0;
4087836SJohn.Forte@Sun.COM ppvars->holds = 0;
4097836SJohn.Forte@Sun.COM ppvars->others = 0;
4107836SJohn.Forte@Sun.COM ppvars->notavail = 0;
4117836SJohn.Forte@Sun.COM
4127836SJohn.Forte@Sun.COM while (sd_dealloc_flag_dm != CACHE_SHUTDOWN_DM &&
4137836SJohn.Forte@Sun.COM current_breakout_count < number_cache_entries) {
4147836SJohn.Forte@Sun.COM
4157836SJohn.Forte@Sun.COM next_ccentry = cc_ent->cc_link_list_dm;
4167836SJohn.Forte@Sun.COM
4177836SJohn.Forte@Sun.COM if (_sd_entry_availability_dm(cc_ent, &ppvars->nodatas)
4187836SJohn.Forte@Sun.COM == FALSE) {
4197836SJohn.Forte@Sun.COM ppvars->notavail++;
4207836SJohn.Forte@Sun.COM goto next_dealloc_entry;
4217836SJohn.Forte@Sun.COM }
4227836SJohn.Forte@Sun.COM
4237836SJohn.Forte@Sun.COM cache_aging_ct = host_cache_aging_ct;
4247836SJohn.Forte@Sun.COM hold_candidate = FALSE;
4257836SJohn.Forte@Sun.COM if (cc_ent->cc_aging_dm & HOST_ENTRY_DM)
4267836SJohn.Forte@Sun.COM ppvars->hosts++;
4277836SJohn.Forte@Sun.COM else
4287836SJohn.Forte@Sun.COM if (cc_ent->cc_aging_dm & PARASITIC_ENTRY_DM)
4297836SJohn.Forte@Sun.COM ppvars->pests++;
4307836SJohn.Forte@Sun.COM else
4317836SJohn.Forte@Sun.COM if (cc_ent->cc_aging_dm & STICKY_METADATA_DM) {
4327836SJohn.Forte@Sun.COM cache_aging_ct = meta_cache_aging_ct;
4337836SJohn.Forte@Sun.COM ppvars->metas++;
4347836SJohn.Forte@Sun.COM } else {
4357836SJohn.Forte@Sun.COM if (last_holds_ct < max_holds_ct)
4367836SJohn.Forte@Sun.COM hold_candidate = TRUE;
4377836SJohn.Forte@Sun.COM ppvars->others++;
4387836SJohn.Forte@Sun.COM }
4397836SJohn.Forte@Sun.COM
4407836SJohn.Forte@Sun.COM ppvars->candidates++;
4417836SJohn.Forte@Sun.COM
4427836SJohn.Forte@Sun.COM if ((cc_ent->cc_aging_dm & FINAL_AGING_DM) <
4437836SJohn.Forte@Sun.COM cache_aging_ct) {
4447836SJohn.Forte@Sun.COM cc_ent->cc_aging_dm += FIRST_AGING_DM;
4457836SJohn.Forte@Sun.COM CLEAR_CENTRY_PAGEIO(cc_ent);
4467836SJohn.Forte@Sun.COM CLEAR_CENTRY_INUSE(cc_ent);
4477836SJohn.Forte@Sun.COM goto next_dealloc_entry;
4487836SJohn.Forte@Sun.COM }
4497836SJohn.Forte@Sun.COM
4507836SJohn.Forte@Sun.COM /* bonafide aged entry - examine its chain */
4517836SJohn.Forte@Sun.COM dealloc = TRUE;
4527836SJohn.Forte@Sun.COM cur_ent = cc_ent->cc_head_dm;
4537836SJohn.Forte@Sun.COM while (cur_ent) {
4547836SJohn.Forte@Sun.COM if (cur_ent == cc_ent)
4557836SJohn.Forte@Sun.COM cur_ent->cc_aging_dm |= AVAIL_ENTRY_DM;
4567836SJohn.Forte@Sun.COM else {
4577836SJohn.Forte@Sun.COM if (_sd_entry_availability_dm(cur_ent,
4587836SJohn.Forte@Sun.COM 0) == TRUE) {
4597836SJohn.Forte@Sun.COM cur_ent->cc_aging_dm |=
4607836SJohn.Forte@Sun.COM AVAIL_ENTRY_DM;
4617836SJohn.Forte@Sun.COM if ((cur_ent->cc_aging_dm &
4627836SJohn.Forte@Sun.COM FINAL_AGING_DM) <
4637836SJohn.Forte@Sun.COM cache_aging_ct)
4647836SJohn.Forte@Sun.COM dealloc = FALSE;
4657836SJohn.Forte@Sun.COM } else
4667836SJohn.Forte@Sun.COM dealloc = FALSE;
4677836SJohn.Forte@Sun.COM }
4687836SJohn.Forte@Sun.COM
4697836SJohn.Forte@Sun.COM cur_ent = cur_ent->cc_next_dm;
4707836SJohn.Forte@Sun.COM }
4717836SJohn.Forte@Sun.COM cur_ent = cc_ent->cc_head_dm;
4727836SJohn.Forte@Sun.COM
4737836SJohn.Forte@Sun.COM /* chain not fully free - free inuse for all entries */
4747836SJohn.Forte@Sun.COM if (dealloc == FALSE) {
4757836SJohn.Forte@Sun.COM while (cur_ent) {
4767836SJohn.Forte@Sun.COM nxt_ent = cur_ent->cc_next_dm;
4777836SJohn.Forte@Sun.COM
4787836SJohn.Forte@Sun.COM if (cur_ent->cc_aging_dm &
4797836SJohn.Forte@Sun.COM AVAIL_ENTRY_DM) {
4807836SJohn.Forte@Sun.COM cur_ent->cc_aging_dm &=
4817836SJohn.Forte@Sun.COM ~AVAIL_ENTRY_DM;
4827836SJohn.Forte@Sun.COM CLEAR_CENTRY_PAGEIO(cur_ent);
4837836SJohn.Forte@Sun.COM CLEAR_CENTRY_INUSE(cur_ent);
4847836SJohn.Forte@Sun.COM }
4857836SJohn.Forte@Sun.COM cur_ent = nxt_ent;
4867836SJohn.Forte@Sun.COM }
4877836SJohn.Forte@Sun.COM } else { /* OK - free memory */
4887836SJohn.Forte@Sun.COM if (hold_candidate == TRUE &&
4897836SJohn.Forte@Sun.COM (cur_ent->cc_aging_dm & FINAL_AGING_DM) <
4907836SJohn.Forte@Sun.COM hold_cache_aging_ct) {
4917836SJohn.Forte@Sun.COM ppvars->holds++;
4927836SJohn.Forte@Sun.COM
4937836SJohn.Forte@Sun.COM ASSERT(cur_ent == cc_ent);
4947836SJohn.Forte@Sun.COM
4957836SJohn.Forte@Sun.COM cc_ent->cc_aging_dm += FIRST_AGING_DM;
4967836SJohn.Forte@Sun.COM
4977836SJohn.Forte@Sun.COM cur_ent->cc_aging_dm &= ~AVAIL_ENTRY_DM;
4987836SJohn.Forte@Sun.COM
4997836SJohn.Forte@Sun.COM wctl = cur_ent->cc_write;
5007836SJohn.Forte@Sun.COM
5017836SJohn.Forte@Sun.COM CLEAR_CENTRY_PAGEIO(cur_ent);
5027836SJohn.Forte@Sun.COM CLEAR_CENTRY_INUSE(cur_ent);
5037836SJohn.Forte@Sun.COM
5047836SJohn.Forte@Sun.COM if (wctl) {
5057836SJohn.Forte@Sun.COM write_dealloc++;
5067836SJohn.Forte@Sun.COM wctl->sc_flag = 0;
5077836SJohn.Forte@Sun.COM wctl->sc_dirty = 0;
5087836SJohn.Forte@Sun.COM SSOP_SETCENTRY(sdbc_safestore,
5099093SRamana.Srikanth@Sun.COM wctl);
5107836SJohn.Forte@Sun.COM SSOP_DEALLOCRESOURCE(
5119093SRamana.Srikanth@Sun.COM sdbc_safestore,
5129093SRamana.Srikanth@Sun.COM wctl->sc_res);
5137836SJohn.Forte@Sun.COM }
5147836SJohn.Forte@Sun.COM goto next_dealloc_entry;
5157836SJohn.Forte@Sun.COM } /* if (hold_candidate == TRUE */
5167836SJohn.Forte@Sun.COM
5177836SJohn.Forte@Sun.COM while (cur_ent) {
5187836SJohn.Forte@Sun.COM
5197836SJohn.Forte@Sun.COM DTRACE_PROBE4(_sd_dealloc_dm,
5207836SJohn.Forte@Sun.COM _sd_cctl_t *, cur_ent,
5217836SJohn.Forte@Sun.COM int, CENTRY_CD(cur_ent),
5227836SJohn.Forte@Sun.COM int, CENTRY_BLK(cur_ent),
5237836SJohn.Forte@Sun.COM uint_t, cur_ent->cc_aging_dm);
5247836SJohn.Forte@Sun.COM
5257836SJohn.Forte@Sun.COM if ((cur_ent->cc_aging_dm
5269093SRamana.Srikanth@Sun.COM & BAD_CHAIN_DM)) {
5277836SJohn.Forte@Sun.COM (void) _sd_hash_delete(
5287836SJohn.Forte@Sun.COM (_sd_hash_hd_t *)cur_ent,
5297836SJohn.Forte@Sun.COM _sd_htable);
5307836SJohn.Forte@Sun.COM
5317836SJohn.Forte@Sun.COM nxt_ent = cur_ent->cc_next_dm;
5327836SJohn.Forte@Sun.COM CLEAR_CENTRY_PAGEIO(cur_ent);
5337836SJohn.Forte@Sun.COM CLEAR_CENTRY_INUSE(cur_ent);
5347836SJohn.Forte@Sun.COM cur_ent = nxt_ent;
5357836SJohn.Forte@Sun.COM continue;
5367836SJohn.Forte@Sun.COM }
5377836SJohn.Forte@Sun.COM
5387836SJohn.Forte@Sun.COM ppvars->deallocs++;
5397836SJohn.Forte@Sun.COM
5407836SJohn.Forte@Sun.COM if (cur_ent->cc_alloc_size_dm) {
5417836SJohn.Forte@Sun.COM int qidx;
5427836SJohn.Forte@Sun.COM _sd_queue_t *q;
5437836SJohn.Forte@Sun.COM
5447836SJohn.Forte@Sun.COM /* HOST or OTHER */
5457836SJohn.Forte@Sun.COM
5467836SJohn.Forte@Sun.COM /* debugging */
5477836SJohn.Forte@Sun.COM ppvars->dealloc_ct++;
5487836SJohn.Forte@Sun.COM cur_ent->cc_dealloc_ct_dm++;
5497836SJohn.Forte@Sun.COM kmem_free(cur_ent->cc_data,
5507836SJohn.Forte@Sun.COM cur_ent->cc_alloc_size_dm);
5517836SJohn.Forte@Sun.COM
5527836SJohn.Forte@Sun.COM /*
5537836SJohn.Forte@Sun.COM * remove from queue
5547836SJohn.Forte@Sun.COM * in preparation for putting
5557836SJohn.Forte@Sun.COM * on the 0 queue after
5567836SJohn.Forte@Sun.COM * memory is freed
5577836SJohn.Forte@Sun.COM */
5587836SJohn.Forte@Sun.COM if (sdbc_use_dmchain) {
5597836SJohn.Forte@Sun.COM
5607836SJohn.Forte@Sun.COM qidx =
5617836SJohn.Forte@Sun.COM cur_ent->cc_cblocks;
5627836SJohn.Forte@Sun.COM q = &sdbc_dm_queues
5639093SRamana.Srikanth@Sun.COM [qidx];
5647836SJohn.Forte@Sun.COM
5657836SJohn.Forte@Sun.COM sdbc_remq_dmchain(q,
5669093SRamana.Srikanth@Sun.COM cur_ent);
5677836SJohn.Forte@Sun.COM }
5687836SJohn.Forte@Sun.COM }
5697836SJohn.Forte@Sun.COM
5707836SJohn.Forte@Sun.COM wctl = cur_ent->cc_write;
5717836SJohn.Forte@Sun.COM cur_ent->cc_write = 0;
5727836SJohn.Forte@Sun.COM cur_ent->cc_data = 0;
5737836SJohn.Forte@Sun.COM cur_ent->cc_alloc_size_dm = 0;
5747836SJohn.Forte@Sun.COM cur_ent->cc_head_dm = NULL;
5757836SJohn.Forte@Sun.COM cur_ent->cc_aging_dm &=
5767836SJohn.Forte@Sun.COM ~(FINAL_AGING_DM | ENTRY_FIELD_DM |
5777836SJohn.Forte@Sun.COM CATAGORY_ENTRY_DM | AVAIL_ENTRY_DM |
5787836SJohn.Forte@Sun.COM PREFETCH_BUF_I | PREFETCH_BUF_E);
5797836SJohn.Forte@Sun.COM
5807836SJohn.Forte@Sun.COM (void) _sd_hash_delete(
5817836SJohn.Forte@Sun.COM (_sd_hash_hd_t *)cur_ent,
5827836SJohn.Forte@Sun.COM _sd_htable);
5837836SJohn.Forte@Sun.COM cur_ent->cc_valid = 0;
5847836SJohn.Forte@Sun.COM
5857836SJohn.Forte@Sun.COM if (sdbc_use_dmchain) {
5867836SJohn.Forte@Sun.COM _sd_queue_t *q;
5877836SJohn.Forte@Sun.COM
5887836SJohn.Forte@Sun.COM nxt_ent = cur_ent->cc_next_dm;
5897836SJohn.Forte@Sun.COM
5907836SJohn.Forte@Sun.COM cur_ent->cc_next_dm = NULL;
5917836SJohn.Forte@Sun.COM
5927836SJohn.Forte@Sun.COM CLEAR_CENTRY_PAGEIO(cur_ent);
5937836SJohn.Forte@Sun.COM CLEAR_CENTRY_INUSE(cur_ent);
5947836SJohn.Forte@Sun.COM
5957836SJohn.Forte@Sun.COM q = &sdbc_dm_queues[0];
5967836SJohn.Forte@Sun.COM sdbc_ins_dmqueue_front(q,
5979093SRamana.Srikanth@Sun.COM cur_ent);
5987836SJohn.Forte@Sun.COM } else {
5997836SJohn.Forte@Sun.COM _sd_requeue_head(cur_ent);
6007836SJohn.Forte@Sun.COM
6017836SJohn.Forte@Sun.COM nxt_ent = cur_ent->cc_next_dm;
6027836SJohn.Forte@Sun.COM cur_ent->cc_next_dm = NULL;
6037836SJohn.Forte@Sun.COM
6047836SJohn.Forte@Sun.COM CLEAR_CENTRY_PAGEIO(cur_ent);
6057836SJohn.Forte@Sun.COM CLEAR_CENTRY_INUSE(cur_ent);
6067836SJohn.Forte@Sun.COM }
6077836SJohn.Forte@Sun.COM
6087836SJohn.Forte@Sun.COM cur_ent = nxt_ent;
6097836SJohn.Forte@Sun.COM
6107836SJohn.Forte@Sun.COM if (wctl) {
6117836SJohn.Forte@Sun.COM write_dealloc++;
6127836SJohn.Forte@Sun.COM wctl->sc_flag = 0;
6137836SJohn.Forte@Sun.COM wctl->sc_dirty = 0;
6147836SJohn.Forte@Sun.COM SSOP_SETCENTRY(sdbc_safestore,
6159093SRamana.Srikanth@Sun.COM wctl);
6167836SJohn.Forte@Sun.COM SSOP_DEALLOCRESOURCE(
6179093SRamana.Srikanth@Sun.COM sdbc_safestore,
6189093SRamana.Srikanth@Sun.COM wctl->sc_res);
6197836SJohn.Forte@Sun.COM }
6207836SJohn.Forte@Sun.COM } /* while (cur_ent) */
6217836SJohn.Forte@Sun.COM } /* else OK - free memory */
6227836SJohn.Forte@Sun.COM next_dealloc_entry:
6237836SJohn.Forte@Sun.COM current_breakout_count++;
6247836SJohn.Forte@Sun.COM
6257836SJohn.Forte@Sun.COM cc_ent = next_ccentry;
6267836SJohn.Forte@Sun.COM } /* while (entries) */
6277836SJohn.Forte@Sun.COM
6287836SJohn.Forte@Sun.COM if (ppvars->monitor_dynmem_process & RPT_DEALLOC_STATS1_DM) {
6297836SJohn.Forte@Sun.COM cmn_err(CE_NOTE,
6309093SRamana.Srikanth@Sun.COM "!notavl=%x, nodat=%x, cand=%x, hosts=%x,"
6317836SJohn.Forte@Sun.COM " pests=%x, metas=%x, holds=%x, others=%x,"
6327836SJohn.Forte@Sun.COM " deallo=%x",
6337836SJohn.Forte@Sun.COM ppvars->notavail, ppvars->nodatas,
6347836SJohn.Forte@Sun.COM ppvars->candidates, ppvars->hosts, ppvars->pests,
6357836SJohn.Forte@Sun.COM ppvars->metas, ppvars->holds, ppvars->others,
6367836SJohn.Forte@Sun.COM ppvars->deallocs);
6377836SJohn.Forte@Sun.COM }
6387836SJohn.Forte@Sun.COM
6397836SJohn.Forte@Sun.COM if (ppvars->monitor_dynmem_process & RPT_DEALLOC_STATS2_DM) {
6407836SJohn.Forte@Sun.COM cmn_err(CE_NOTE,
6419093SRamana.Srikanth@Sun.COM "!hist=%x, gross a/d=%x %x", ppvars->history,
6427836SJohn.Forte@Sun.COM ppvars->alloc_ct, ppvars->dealloc_ct);
6437836SJohn.Forte@Sun.COM }
6447836SJohn.Forte@Sun.COM
6457836SJohn.Forte@Sun.COM if (sd_dealloc_flag_dm == CACHE_SHUTDOWN_DM)
6467836SJohn.Forte@Sun.COM continue;
6477836SJohn.Forte@Sun.COM
6487836SJohn.Forte@Sun.COM last_holds_ct = ppvars->holds;
6497836SJohn.Forte@Sun.COM
6507836SJohn.Forte@Sun.COM /* set the history flag which will govern the sleep rate */
6517836SJohn.Forte@Sun.COM if (ppvars->nodatas > transition_lvl1) {
6527836SJohn.Forte@Sun.COM /* upper - lots of virgin cctls */
6537836SJohn.Forte@Sun.COM if (ppvars->history)
6547836SJohn.Forte@Sun.COM ppvars->history >>= 1;
6557836SJohn.Forte@Sun.COM } else {
6567836SJohn.Forte@Sun.COM if (ppvars->nodatas > transition_lvl2) {
6577836SJohn.Forte@Sun.COM /* middle - not so many virgin cctls */
6587836SJohn.Forte@Sun.COM if (ppvars->history & (HISTORY_LVL1-1))
6597836SJohn.Forte@Sun.COM ppvars->history >>= 1;
6607836SJohn.Forte@Sun.COM else
6617836SJohn.Forte@Sun.COM ppvars->history = HISTORY_LVL1;
6627836SJohn.Forte@Sun.COM
6637836SJohn.Forte@Sun.COM } else {
6647836SJohn.Forte@Sun.COM /*
6657836SJohn.Forte@Sun.COM * appear to be running low - accelerate the
6667836SJohn.Forte@Sun.COM * aging to free more
6677836SJohn.Forte@Sun.COM */
6687836SJohn.Forte@Sun.COM if (ppvars->history & HISTORY_LVL2)
6697836SJohn.Forte@Sun.COM ppvars->history >>= 1;
6707836SJohn.Forte@Sun.COM else
6717836SJohn.Forte@Sun.COM ppvars->history =
6727836SJohn.Forte@Sun.COM (HISTORY_LVL1|HISTORY_LVL2);
6737836SJohn.Forte@Sun.COM }
6747836SJohn.Forte@Sun.COM }
6757836SJohn.Forte@Sun.COM
6767836SJohn.Forte@Sun.COM sd_dealloc_flag_dm = TIME_DELAY_LVL0;
6777836SJohn.Forte@Sun.COM if (ppvars->history & HISTORY_LVL2)
6787836SJohn.Forte@Sun.COM sd_dealloc_flag_dm = TIME_DELAY_LVL2;
6797836SJohn.Forte@Sun.COM else
6807836SJohn.Forte@Sun.COM if (ppvars->history & HISTORY_LVL1)
6817836SJohn.Forte@Sun.COM sd_dealloc_flag_dm = TIME_DELAY_LVL1;
6827836SJohn.Forte@Sun.COM
6837836SJohn.Forte@Sun.COM } /* while (TRUE) */
6847836SJohn.Forte@Sun.COM }
6857836SJohn.Forte@Sun.COM
6867836SJohn.Forte@Sun.COM int
_sd_entry_availability_dm(_sd_cctl_t * cc_ent,int * nodata)6877836SJohn.Forte@Sun.COM _sd_entry_availability_dm(_sd_cctl_t *cc_ent, int *nodata)
6887836SJohn.Forte@Sun.COM {
6897836SJohn.Forte@Sun.COM /*
6907836SJohn.Forte@Sun.COM * if using dmchaining return immediately and do not attempt
6917836SJohn.Forte@Sun.COM * to acquire the cc_ent if there is no memory associated with
6927836SJohn.Forte@Sun.COM * this cc_ent.
6937836SJohn.Forte@Sun.COM * this avoids conflicts for centrys on the 0 queue.
6947836SJohn.Forte@Sun.COM * see sdbc_get_dmchain()
6957836SJohn.Forte@Sun.COM */
6967836SJohn.Forte@Sun.COM
6977836SJohn.Forte@Sun.COM if ((sdbc_use_dmchain) && (cc_ent->cc_data == 0)) {
6987836SJohn.Forte@Sun.COM
6997836SJohn.Forte@Sun.COM if (nodata)
7007836SJohn.Forte@Sun.COM (*nodata)++;
7017836SJohn.Forte@Sun.COM
7027836SJohn.Forte@Sun.COM DTRACE_PROBE(sdbc_availability_dm_end1);
7037836SJohn.Forte@Sun.COM return (FALSE);
7047836SJohn.Forte@Sun.COM }
7057836SJohn.Forte@Sun.COM
7067836SJohn.Forte@Sun.COM if ((SET_CENTRY_INUSE(cc_ent))) {
7077836SJohn.Forte@Sun.COM
7087836SJohn.Forte@Sun.COM DTRACE_PROBE(sdbc_availability_dm_end2);
7097836SJohn.Forte@Sun.COM
7107836SJohn.Forte@Sun.COM return (FALSE);
7117836SJohn.Forte@Sun.COM }
7127836SJohn.Forte@Sun.COM
7137836SJohn.Forte@Sun.COM
7147836SJohn.Forte@Sun.COM if ((SET_CENTRY_PAGEIO(cc_ent))) {
7157836SJohn.Forte@Sun.COM
7167836SJohn.Forte@Sun.COM CLEAR_CENTRY_INUSE(cc_ent);
7177836SJohn.Forte@Sun.COM
7187836SJohn.Forte@Sun.COM DTRACE_PROBE(sdbc_availability_dm_end3);
7197836SJohn.Forte@Sun.COM
7207836SJohn.Forte@Sun.COM return (FALSE);
7217836SJohn.Forte@Sun.COM }
7227836SJohn.Forte@Sun.COM
7237836SJohn.Forte@Sun.COM /*
7247836SJohn.Forte@Sun.COM * we allow the QHEAD flag as it does not affect the availabilty
7257836SJohn.Forte@Sun.COM * of memory for aging
7267836SJohn.Forte@Sun.COM */
7277836SJohn.Forte@Sun.COM if ((CENTRY_DIRTY(cc_ent)) || (CENTRY_IO_INPROGRESS(cc_ent)) ||
7289093SRamana.Srikanth@Sun.COM (cc_ent->cc_flag & ~(CC_QHEAD)) ||
7299093SRamana.Srikanth@Sun.COM cc_ent->cc_dirty_next || cc_ent->cc_dirty_link ||
7309093SRamana.Srikanth@Sun.COM cc_ent->cc_data == 0) {
7317836SJohn.Forte@Sun.COM
7327836SJohn.Forte@Sun.COM cc_ent->cc_aging_dm &= ~FINAL_AGING_DM;
7337836SJohn.Forte@Sun.COM if (nodata)
7347836SJohn.Forte@Sun.COM if (cc_ent->cc_data == 0) {
7357836SJohn.Forte@Sun.COM (*nodata)++;
7367836SJohn.Forte@Sun.COM }
7377836SJohn.Forte@Sun.COM
7387836SJohn.Forte@Sun.COM CLEAR_CENTRY_PAGEIO(cc_ent);
7397836SJohn.Forte@Sun.COM CLEAR_CENTRY_INUSE(cc_ent);
7407836SJohn.Forte@Sun.COM
7417836SJohn.Forte@Sun.COM DTRACE_PROBE(sdbc_availability_dm_end4);
7427836SJohn.Forte@Sun.COM
7437836SJohn.Forte@Sun.COM return (FALSE);
7447836SJohn.Forte@Sun.COM }
7457836SJohn.Forte@Sun.COM
7467836SJohn.Forte@Sun.COM return (TRUE);
7477836SJohn.Forte@Sun.COM }
7487836SJohn.Forte@Sun.COM
7497836SJohn.Forte@Sun.COM /*
7507836SJohn.Forte@Sun.COM * function below to prohibit code movement by compiler
7517836SJohn.Forte@Sun.COM * and avoid using spinlocks for syncronization
7527836SJohn.Forte@Sun.COM */
7537836SJohn.Forte@Sun.COM static void
_sd_cc_iostatus_initiate(_sd_cctl_t * cc_ent)7547836SJohn.Forte@Sun.COM _sd_cc_iostatus_initiate(_sd_cctl_t *cc_ent)
7557836SJohn.Forte@Sun.COM {
7567836SJohn.Forte@Sun.COM cc_ent->cc_iostatus = _SD_IO_INITIATE;
7577836SJohn.Forte@Sun.COM sd_serialize();
7587836SJohn.Forte@Sun.COM }
7597836SJohn.Forte@Sun.COM
7607836SJohn.Forte@Sun.COM /*
7617836SJohn.Forte@Sun.COM * Yet another switch!
7627836SJohn.Forte@Sun.COM * alloc mem and coalesce if at least this number of frags
7637836SJohn.Forte@Sun.COM */
7647836SJohn.Forte@Sun.COM static int sdbc_coalesce_backend = 1;
7657836SJohn.Forte@Sun.COM
7667836SJohn.Forte@Sun.COM /*
7677836SJohn.Forte@Sun.COM * optimization for _sd_async_flclist()
7687836SJohn.Forte@Sun.COM * called only if not doing pageio and sdbc_coalesce_backend > 0
7697836SJohn.Forte@Sun.COM *
7707836SJohn.Forte@Sun.COM * returns with pagio bit set in the centrys in list
7717836SJohn.Forte@Sun.COM */
7727836SJohn.Forte@Sun.COM static unsigned char *
sdbc_alloc_io_mem(_sd_cctl_t * cc_ent,int first_dirty,int last_dirty)7737836SJohn.Forte@Sun.COM sdbc_alloc_io_mem(_sd_cctl_t *cc_ent, int first_dirty, int last_dirty)
7747836SJohn.Forte@Sun.COM {
7757836SJohn.Forte@Sun.COM unsigned char *prev_addr = NULL;
7767836SJohn.Forte@Sun.COM _sd_cctl_t *cc_ent_orig = cc_ent;
7777836SJohn.Forte@Sun.COM int fba_len;
7787836SJohn.Forte@Sun.COM int total_len_bytes = 0;
7797836SJohn.Forte@Sun.COM unsigned char *start_addr = NULL; /* function return value */
7807836SJohn.Forte@Sun.COM unsigned char *next_addr;
7817836SJohn.Forte@Sun.COM int num_frags = 0;
7827836SJohn.Forte@Sun.COM
7837836SJohn.Forte@Sun.COM if (first_dirty && (!_SD_BMAP_ISFULL(first_dirty))) {
7847836SJohn.Forte@Sun.COM WAIT_CENTRY_PAGEIO(cc_ent, sdbc_flush_pageio);
7857836SJohn.Forte@Sun.COM
7867836SJohn.Forte@Sun.COM fba_len = SDBC_LOOKUP_LEN(first_dirty);
7877836SJohn.Forte@Sun.COM total_len_bytes += FBA_SIZE(fba_len);
7887836SJohn.Forte@Sun.COM
7897836SJohn.Forte@Sun.COM prev_addr = cc_ent->cc_data;
7907836SJohn.Forte@Sun.COM cc_ent = cc_ent->cc_dirty_next;
7917836SJohn.Forte@Sun.COM }
7927836SJohn.Forte@Sun.COM
7937836SJohn.Forte@Sun.COM while (cc_ent) {
7947836SJohn.Forte@Sun.COM
7957836SJohn.Forte@Sun.COM WAIT_CENTRY_PAGEIO(cc_ent, sdbc_flush_pageio);
7967836SJohn.Forte@Sun.COM /* check for contiguity */
7977836SJohn.Forte@Sun.COM if (prev_addr &&
7989093SRamana.Srikanth@Sun.COM !((prev_addr + CACHE_BLOCK_SIZE) == cc_ent->cc_data))
7997836SJohn.Forte@Sun.COM ++num_frags;
8007836SJohn.Forte@Sun.COM
8017836SJohn.Forte@Sun.COM /* compute length */
8027836SJohn.Forte@Sun.COM if (FULLY_DIRTY(cc_ent)) {
8037836SJohn.Forte@Sun.COM total_len_bytes += CACHE_BLOCK_SIZE;
8047836SJohn.Forte@Sun.COM } else {
8057836SJohn.Forte@Sun.COM fba_len = SDBC_LOOKUP_LEN(last_dirty);
8067836SJohn.Forte@Sun.COM total_len_bytes += FBA_SIZE(fba_len);
8077836SJohn.Forte@Sun.COM }
8087836SJohn.Forte@Sun.COM
8097836SJohn.Forte@Sun.COM prev_addr = cc_ent->cc_data;
8107836SJohn.Forte@Sun.COM cc_ent = cc_ent->cc_dirty_next;
8117836SJohn.Forte@Sun.COM }
8127836SJohn.Forte@Sun.COM
8137836SJohn.Forte@Sun.COM if (num_frags >= sdbc_coalesce_backend) {
8147836SJohn.Forte@Sun.COM /*
8157836SJohn.Forte@Sun.COM * TODO - determine metric for deciding
8167836SJohn.Forte@Sun.COM * whether to coalesce memory or do separate i/o's
8177836SJohn.Forte@Sun.COM */
8187836SJohn.Forte@Sun.COM
8197836SJohn.Forte@Sun.COM DTRACE_PROBE(sdbc_io_mem_kmem_start);
8207836SJohn.Forte@Sun.COM
8217836SJohn.Forte@Sun.COM if (start_addr = kmem_alloc(total_len_bytes, KM_NOSLEEP)) {
8227836SJohn.Forte@Sun.COM int sblk, offset;
8237836SJohn.Forte@Sun.COM
8247836SJohn.Forte@Sun.COM cc_ent = cc_ent_orig;
8257836SJohn.Forte@Sun.COM
8267836SJohn.Forte@Sun.COM cc_ent->cc_anon_addr.sa_virt = start_addr;
8277836SJohn.Forte@Sun.COM cc_ent->cc_anon_len = total_len_bytes;
8287836SJohn.Forte@Sun.COM
8297836SJohn.Forte@Sun.COM next_addr = start_addr;
8307836SJohn.Forte@Sun.COM
8317836SJohn.Forte@Sun.COM DTRACE_PROBE2(sdbc_io_mem_bcopy_start,
8329093SRamana.Srikanth@Sun.COM int, num_frags, int, total_len_bytes);
8337836SJohn.Forte@Sun.COM
8347836SJohn.Forte@Sun.COM /* copy the first dirty piece */
8357836SJohn.Forte@Sun.COM if (first_dirty && (!_SD_BMAP_ISFULL(first_dirty))) {
8367836SJohn.Forte@Sun.COM
8377836SJohn.Forte@Sun.COM fba_len = SDBC_LOOKUP_LEN(first_dirty);
8387836SJohn.Forte@Sun.COM sblk = SDBC_LOOKUP_STPOS(first_dirty);
8397836SJohn.Forte@Sun.COM offset = FBA_SIZE(sblk);
8407836SJohn.Forte@Sun.COM
8417836SJohn.Forte@Sun.COM bcopy(cc_ent->cc_data + offset, next_addr,
8429093SRamana.Srikanth@Sun.COM FBA_SIZE(fba_len));
8437836SJohn.Forte@Sun.COM cc_ent = cc_ent->cc_dirty_next;
8447836SJohn.Forte@Sun.COM next_addr += FBA_SIZE(fba_len);
8457836SJohn.Forte@Sun.COM }
8467836SJohn.Forte@Sun.COM
8477836SJohn.Forte@Sun.COM /* copy the rest of data */
8487836SJohn.Forte@Sun.COM while (cc_ent) {
8497836SJohn.Forte@Sun.COM if (FULLY_DIRTY(cc_ent)) {
8507836SJohn.Forte@Sun.COM bcopy(cc_ent->cc_data, next_addr,
8519093SRamana.Srikanth@Sun.COM CACHE_BLOCK_SIZE);
8527836SJohn.Forte@Sun.COM next_addr += CACHE_BLOCK_SIZE;
8537836SJohn.Forte@Sun.COM } else {
8547836SJohn.Forte@Sun.COM fba_len = SDBC_LOOKUP_LEN(last_dirty);
8557836SJohn.Forte@Sun.COM bcopy(cc_ent->cc_data, next_addr,
8569093SRamana.Srikanth@Sun.COM FBA_SIZE(fba_len));
8577836SJohn.Forte@Sun.COM next_addr += FBA_SIZE(fba_len);
8587836SJohn.Forte@Sun.COM }
8597836SJohn.Forte@Sun.COM
8607836SJohn.Forte@Sun.COM cc_ent = cc_ent->cc_dirty_next;
8617836SJohn.Forte@Sun.COM }
8627836SJohn.Forte@Sun.COM
8637836SJohn.Forte@Sun.COM DTRACE_PROBE(sdbc_io_mem_bcopy_end);
8647836SJohn.Forte@Sun.COM }
8657836SJohn.Forte@Sun.COM
8667836SJohn.Forte@Sun.COM DTRACE_PROBE(sdbc_io_mem_kmem_end);
8677836SJohn.Forte@Sun.COM }
8687836SJohn.Forte@Sun.COM
8697836SJohn.Forte@Sun.COM return (start_addr);
8707836SJohn.Forte@Sun.COM }
8717836SJohn.Forte@Sun.COM
8727836SJohn.Forte@Sun.COM void
_sd_async_flclist(_sd_cctl_t * cclist,dev_t rdev)8737836SJohn.Forte@Sun.COM _sd_async_flclist(_sd_cctl_t *cclist, dev_t rdev)
8747836SJohn.Forte@Sun.COM {
8757836SJohn.Forte@Sun.COM int flushed, i, cd;
8767836SJohn.Forte@Sun.COM uint_t first_dirty, last_dirty;
8777836SJohn.Forte@Sun.COM _sd_cctl_t *cc_ent, *cc_prev = NULL;
8787836SJohn.Forte@Sun.COM struct buf *bp;
8797836SJohn.Forte@Sun.COM int dblk, fba_len;
8807836SJohn.Forte@Sun.COM int len;
8817836SJohn.Forte@Sun.COM int toflush;
8827836SJohn.Forte@Sun.COM int coalesce; /* convenience boolean */
8837836SJohn.Forte@Sun.COM unsigned char *anon_mem = NULL;
8847836SJohn.Forte@Sun.COM extern int sdbc_do_page;
8857836SJohn.Forte@Sun.COM
8867836SJohn.Forte@Sun.COM
8877836SJohn.Forte@Sun.COM SDTRACE(ST_ENTER|SDF_FLCLIST, CENTRY_CD(cclist),
8889093SRamana.Srikanth@Sun.COM 0, BLK_TO_FBA_NUM(CENTRY_BLK(cclist)), 0, 0);
8897836SJohn.Forte@Sun.COM
8907836SJohn.Forte@Sun.COM coalesce = (!sdbc_do_page && sdbc_coalesce_backend);
8917836SJohn.Forte@Sun.COM
8927836SJohn.Forte@Sun.COM cc_ent = cclist;
8937836SJohn.Forte@Sun.COM _sd_cc_iostatus_initiate(cc_ent);
8947836SJohn.Forte@Sun.COM first_dirty = CENTRY_DIRTY(cc_ent);
8957836SJohn.Forte@Sun.COM if (SDBC_IS_FRAGMENTED(first_dirty)) {
8967836SJohn.Forte@Sun.COM cclist = cc_ent->cc_dirty_next;
8977836SJohn.Forte@Sun.COM cc_ent->cc_dirty_next = NULL;
8987836SJohn.Forte@Sun.COM _sd_async_flcent(cc_ent, rdev);
8997836SJohn.Forte@Sun.COM cc_ent = cclist;
9007836SJohn.Forte@Sun.COM first_dirty = 0;
9017836SJohn.Forte@Sun.COM }
9027836SJohn.Forte@Sun.COM
9037836SJohn.Forte@Sun.COM toflush = 0;
9047836SJohn.Forte@Sun.COM while (cc_ent->cc_dirty_next) {
9057836SJohn.Forte@Sun.COM if (cc_ent->cc_iocount)
9067836SJohn.Forte@Sun.COM SDALERT(SDF_FLCLIST, CENTRY_CD(cc_ent), 0,
9079093SRamana.Srikanth@Sun.COM BLK_TO_FBA_NUM(CENTRY_BLK(cc_ent)),
9089093SRamana.Srikanth@Sun.COM cc_ent->cc_iocount, 0);
9097836SJohn.Forte@Sun.COM cc_prev = cc_ent;
9107836SJohn.Forte@Sun.COM cc_ent = cc_ent->cc_dirty_next;
9117836SJohn.Forte@Sun.COM toflush++;
9127836SJohn.Forte@Sun.COM }
9137836SJohn.Forte@Sun.COM _sd_cc_iostatus_initiate(cc_ent);
9147836SJohn.Forte@Sun.COM last_dirty = CENTRY_DIRTY(cc_ent);
9157836SJohn.Forte@Sun.COM if (SDBC_IS_FRAGMENTED(last_dirty)) {
9167836SJohn.Forte@Sun.COM if (cc_prev)
9177836SJohn.Forte@Sun.COM cc_prev->cc_dirty_next = NULL;
9187836SJohn.Forte@Sun.COM _sd_async_flcent(cc_ent, rdev);
9197836SJohn.Forte@Sun.COM last_dirty = 0;
9207836SJohn.Forte@Sun.COM }
9217836SJohn.Forte@Sun.COM else
9227836SJohn.Forte@Sun.COM toflush++;
9237836SJohn.Forte@Sun.COM
9247836SJohn.Forte@Sun.COM if (toflush == 0)
9257836SJohn.Forte@Sun.COM return;
9267836SJohn.Forte@Sun.COM
9277836SJohn.Forte@Sun.COM
9287836SJohn.Forte@Sun.COM dblk = BLK_TO_FBA_NUM(CENTRY_BLK(cclist));
9297836SJohn.Forte@Sun.COM if (first_dirty && (!_SD_BMAP_ISFULL(first_dirty)))
9307836SJohn.Forte@Sun.COM dblk += SDBC_LOOKUP_STPOS(first_dirty);
9317836SJohn.Forte@Sun.COM
9327836SJohn.Forte@Sun.COM cd = CENTRY_CD(cclist);
9337836SJohn.Forte@Sun.COM bp = sd_alloc_iob(rdev, dblk, toflush, B_WRITE);
9347836SJohn.Forte@Sun.COM cc_ent = cclist;
9357836SJohn.Forte@Sun.COM
9369093SRamana.Srikanth@Sun.COM if (coalesce && (anon_mem = sdbc_alloc_io_mem(cc_ent, first_dirty,
9379093SRamana.Srikanth@Sun.COM last_dirty)))
9387836SJohn.Forte@Sun.COM sd_add_fba(bp, &cc_ent->cc_anon_addr, 0,
9399093SRamana.Srikanth@Sun.COM FBA_NUM(cc_ent->cc_anon_len));
9407836SJohn.Forte@Sun.COM
9417836SJohn.Forte@Sun.COM if (first_dirty && (!_SD_BMAP_ISFULL(first_dirty))) {
9427836SJohn.Forte@Sun.COM cc_ent->cc_iocount = flushed = 1;
9437836SJohn.Forte@Sun.COM
9447836SJohn.Forte@Sun.COM /* pageio bit already set in sdbc_alloc_io_mem() above */
9457836SJohn.Forte@Sun.COM if (!coalesce)
9467836SJohn.Forte@Sun.COM WAIT_CENTRY_PAGEIO(cc_ent, sdbc_flush_pageio);
9477836SJohn.Forte@Sun.COM
9487836SJohn.Forte@Sun.COM fba_len = SDBC_LOOKUP_LEN(first_dirty);
9497836SJohn.Forte@Sun.COM
9507836SJohn.Forte@Sun.COM /* build buffer only if it was not done above */
9517836SJohn.Forte@Sun.COM if (!anon_mem) {
9527836SJohn.Forte@Sun.COM i = SDBC_LOOKUP_STPOS(first_dirty);
9537836SJohn.Forte@Sun.COM sd_add_fba(bp, &cc_ent->cc_addr, i, fba_len);
9547836SJohn.Forte@Sun.COM DATA_LOG(SDF_FLSHLIST, cc_ent, i, fba_len);
9557836SJohn.Forte@Sun.COM
9569093SRamana.Srikanth@Sun.COM DTRACE_PROBE4(_sd_async_flclist_data1, int,
9579093SRamana.Srikanth@Sun.COM BLK_TO_FBA_NUM(CENTRY_BLK(cc_ent)) + i,
9589093SRamana.Srikanth@Sun.COM int, fba_len, char *,
9599093SRamana.Srikanth@Sun.COM *(int64_t *)(cc_ent->cc_data + FBA_SIZE(i)),
9609093SRamana.Srikanth@Sun.COM char *, *(int64_t *)(cc_ent->cc_data +
9619093SRamana.Srikanth@Sun.COM FBA_SIZE(i + fba_len) - 8));
9627836SJohn.Forte@Sun.COM }
9637836SJohn.Forte@Sun.COM
9647836SJohn.Forte@Sun.COM len = FBA_SIZE(fba_len);
9657836SJohn.Forte@Sun.COM cc_ent = cc_ent->cc_dirty_next;
9667836SJohn.Forte@Sun.COM } else {
9677836SJohn.Forte@Sun.COM len = 0;
9687836SJohn.Forte@Sun.COM flushed = 0;
9697836SJohn.Forte@Sun.COM }
9707836SJohn.Forte@Sun.COM while (cc_ent) {
9717836SJohn.Forte@Sun.COM _sd_cc_iostatus_initiate(cc_ent);
9727836SJohn.Forte@Sun.COM
9737836SJohn.Forte@Sun.COM /* pageio bit already set in sdbc_alloc_io_mem() above */
9747836SJohn.Forte@Sun.COM if (!coalesce)
9757836SJohn.Forte@Sun.COM WAIT_CENTRY_PAGEIO(cc_ent, sdbc_flush_pageio);
9767836SJohn.Forte@Sun.COM
9777836SJohn.Forte@Sun.COM if (FULLY_DIRTY(cc_ent)) {
9787836SJohn.Forte@Sun.COM flushed++;
9797836SJohn.Forte@Sun.COM cc_ent->cc_iocount = 1;
9807836SJohn.Forte@Sun.COM
9817836SJohn.Forte@Sun.COM /* build buffer only if it was not done above */
9827836SJohn.Forte@Sun.COM if (!anon_mem) {
9837836SJohn.Forte@Sun.COM sd_add_fba(bp, &cc_ent->cc_addr, 0, BLK_FBAS);
9847836SJohn.Forte@Sun.COM DATA_LOG(SDF_FLSHLIST, cc_ent, 0, BLK_FBAS);
9857836SJohn.Forte@Sun.COM
9867836SJohn.Forte@Sun.COM DTRACE_PROBE4(_sd_async_flclist_data2,
9879093SRamana.Srikanth@Sun.COM int, BLK_TO_FBA_NUM(CENTRY_BLK(cc_ent)),
9889093SRamana.Srikanth@Sun.COM int, BLK_FBAS, char *,
9899093SRamana.Srikanth@Sun.COM *(int64_t *)(cc_ent->cc_data),
9909093SRamana.Srikanth@Sun.COM char *, *(int64_t *)(cc_ent->cc_data +
9919093SRamana.Srikanth@Sun.COM FBA_SIZE(BLK_FBAS) - 8));
9927836SJohn.Forte@Sun.COM }
9937836SJohn.Forte@Sun.COM
9947836SJohn.Forte@Sun.COM len += CACHE_BLOCK_SIZE;
9957836SJohn.Forte@Sun.COM } else {
9967836SJohn.Forte@Sun.COM #if defined(_SD_DEBUG)
9977836SJohn.Forte@Sun.COM /*
9987836SJohn.Forte@Sun.COM * consistency check.
9997836SJohn.Forte@Sun.COM */
10007836SJohn.Forte@Sun.COM if (!last_dirty || cc_ent->cc_dirty_next ||
10017836SJohn.Forte@Sun.COM SDBC_IS_FRAGMENTED(last_dirty)) {
10027836SJohn.Forte@Sun.COM SDALERT(SDF_FLCLIST, cd, 0,
10037836SJohn.Forte@Sun.COM BLK_TO_FBA_NUM(CENTRY_BLK(cc_ent)),
10047836SJohn.Forte@Sun.COM cc_ent->cc_dirty_next, last_dirty);
10057836SJohn.Forte@Sun.COM cmn_err(CE_WARN,
10069093SRamana.Srikanth@Sun.COM "!_sd_err: flclist: last_dirty %x next %x",
10077836SJohn.Forte@Sun.COM last_dirty, cc_ent->cc_dirty_next);
10087836SJohn.Forte@Sun.COM }
10097836SJohn.Forte@Sun.COM #endif
10107836SJohn.Forte@Sun.COM flushed++;
10117836SJohn.Forte@Sun.COM cc_ent->cc_iocount = 1;
10127836SJohn.Forte@Sun.COM
10137836SJohn.Forte@Sun.COM fba_len = SDBC_LOOKUP_LEN(last_dirty);
10147836SJohn.Forte@Sun.COM
10157836SJohn.Forte@Sun.COM /* build buffer only if it was not done above */
10167836SJohn.Forte@Sun.COM if (!anon_mem) {
10177836SJohn.Forte@Sun.COM sd_add_fba(bp, &cc_ent->cc_addr, 0, fba_len);
10187836SJohn.Forte@Sun.COM DATA_LOG(SDF_FLSHLIST, cc_ent, 0, fba_len);
10197836SJohn.Forte@Sun.COM
10209093SRamana.Srikanth@Sun.COM DTRACE_PROBE4(_sd_async_flclist_data3, int,
10219093SRamana.Srikanth@Sun.COM BLK_TO_FBA_NUM(CENTRY_BLK(cc_ent)),
10229093SRamana.Srikanth@Sun.COM int, fba_len, char *,
10239093SRamana.Srikanth@Sun.COM *(int64_t *)(cc_ent->cc_data), char *,
10249093SRamana.Srikanth@Sun.COM *(int64_t *)(cc_ent->cc_data +
10259093SRamana.Srikanth@Sun.COM FBA_SIZE(fba_len) - 8));
10267836SJohn.Forte@Sun.COM }
10277836SJohn.Forte@Sun.COM
10287836SJohn.Forte@Sun.COM len += FBA_SIZE(fba_len);
10297836SJohn.Forte@Sun.COM }
10307836SJohn.Forte@Sun.COM cc_ent = cc_ent->cc_dirty_next;
10317836SJohn.Forte@Sun.COM }
10327836SJohn.Forte@Sun.COM
10337836SJohn.Forte@Sun.COM #ifdef DEBUG
10347836SJohn.Forte@Sun.COM if (anon_mem)
10357836SJohn.Forte@Sun.COM ASSERT(len == cclist->cc_anon_len);
10367836SJohn.Forte@Sun.COM #endif
10377836SJohn.Forte@Sun.COM
10387836SJohn.Forte@Sun.COM /* SDTRACE(ST_INFO|SDF_FLCLIST, cd, FBA_NUM(len), dblk, flushed, bp); */
10397836SJohn.Forte@Sun.COM (void) sd_start_io(bp, _sd_cache_files[cd].cd_strategy,
10407836SJohn.Forte@Sun.COM _sd_flclist_ea, cclist);
10417836SJohn.Forte@Sun.COM
10427836SJohn.Forte@Sun.COM DISK_FBA_WRITE(cd, FBA_NUM(len));
10437836SJohn.Forte@Sun.COM /* increment number of bytes destaged to disk */
10447836SJohn.Forte@Sun.COM WRITE_DESTAGED(cd, FBA_NUM(len));
10457836SJohn.Forte@Sun.COM
10467836SJohn.Forte@Sun.COM _sd_enqueue_io_pending(cd, cclist);
10477836SJohn.Forte@Sun.COM
10487836SJohn.Forte@Sun.COM SDTRACE(ST_EXIT|SDF_FLCLIST, cd, FBA_NUM(len), dblk, flushed, 0);
10497836SJohn.Forte@Sun.COM }
10507836SJohn.Forte@Sun.COM
10517836SJohn.Forte@Sun.COM
10527836SJohn.Forte@Sun.COM void
_sd_enqueue_io_pending(int cd,_sd_cctl_t * cclist)10537836SJohn.Forte@Sun.COM _sd_enqueue_io_pending(int cd, _sd_cctl_t *cclist)
10547836SJohn.Forte@Sun.COM {
10557836SJohn.Forte@Sun.COM _sd_cd_info_t *cdi;
10567836SJohn.Forte@Sun.COM
10577836SJohn.Forte@Sun.COM cdi = &(_sd_cache_files[cd]);
10587836SJohn.Forte@Sun.COM if (cdi->cd_io_head == NULL)
10597836SJohn.Forte@Sun.COM cdi->cd_io_head = cdi->cd_io_tail = cclist;
10607836SJohn.Forte@Sun.COM else {
10617836SJohn.Forte@Sun.COM cdi->cd_io_tail->cc_dirty_link = cclist;
10627836SJohn.Forte@Sun.COM cdi->cd_io_tail = cclist;
10637836SJohn.Forte@Sun.COM }
10647836SJohn.Forte@Sun.COM }
10657836SJohn.Forte@Sun.COM
10667836SJohn.Forte@Sun.COM
10677836SJohn.Forte@Sun.COM
10687836SJohn.Forte@Sun.COM void
_sd_async_flcent(_sd_cctl_t * cc_ent,dev_t rdev)10697836SJohn.Forte@Sun.COM _sd_async_flcent(_sd_cctl_t *cc_ent, dev_t rdev)
10707836SJohn.Forte@Sun.COM {
10717836SJohn.Forte@Sun.COM int dblk, len, sblk;
10727836SJohn.Forte@Sun.COM int dirty;
10737836SJohn.Forte@Sun.COM struct buf *bp;
10747836SJohn.Forte@Sun.COM int cd;
10757836SJohn.Forte@Sun.COM
10767836SJohn.Forte@Sun.COM cd = CENTRY_CD(cc_ent);
10777836SJohn.Forte@Sun.COM
10787836SJohn.Forte@Sun.COM SDTRACE(ST_ENTER|SDF_FLCENT, cd, 0,
10799093SRamana.Srikanth@Sun.COM BLK_TO_FBA_NUM(CENTRY_BLK(cc_ent)), 0, 0);
10807836SJohn.Forte@Sun.COM #if defined(_SD_DEBUG_PATTERN)
10817836SJohn.Forte@Sun.COM check_write_consistency(cc_ent);
10827836SJohn.Forte@Sun.COM #endif
10837836SJohn.Forte@Sun.COM if (cc_ent->cc_iocount)
10849093SRamana.Srikanth@Sun.COM SDALERT(SDF_FLCENT, cd, 0, BLK_TO_FBA_NUM(CENTRY_BLK(cc_ent)),
10859093SRamana.Srikanth@Sun.COM cc_ent->cc_iocount, 0);
10867836SJohn.Forte@Sun.COM _sd_cc_iostatus_initiate(cc_ent);
10877836SJohn.Forte@Sun.COM WAIT_CENTRY_PAGEIO(cc_ent, sdbc_flush_pageio);
10887836SJohn.Forte@Sun.COM
10897836SJohn.Forte@Sun.COM dirty = CENTRY_DIRTY(cc_ent);
10907836SJohn.Forte@Sun.COM
10917836SJohn.Forte@Sun.COM if (_SD_BMAP_ISFULL(dirty)) {
10927836SJohn.Forte@Sun.COM cc_ent->cc_iocount = 1;
10937836SJohn.Forte@Sun.COM dblk = BLK_TO_FBA_NUM(CENTRY_BLK(cc_ent));
10947836SJohn.Forte@Sun.COM bp = sd_alloc_iob(rdev, dblk, 1, B_WRITE);
10957836SJohn.Forte@Sun.COM sd_add_fba(bp, &cc_ent->cc_addr, 0, BLK_FBAS);
10967836SJohn.Forte@Sun.COM DATA_LOG(SDF_FLSHENT, cc_ent, 0, BLK_FBAS);
10977836SJohn.Forte@Sun.COM
10987836SJohn.Forte@Sun.COM DTRACE_PROBE4(_sd_async_flcent_data1,
10999093SRamana.Srikanth@Sun.COM int, BLK_TO_FBA_NUM(CENTRY_BLK(cc_ent)),
11009093SRamana.Srikanth@Sun.COM int, BLK_FBAS, char *, *(int64_t *)(cc_ent->cc_data),
11019093SRamana.Srikanth@Sun.COM char *, *(int64_t *)(cc_ent->cc_data +
11029093SRamana.Srikanth@Sun.COM FBA_SIZE(BLK_FBAS) - 8));
11037836SJohn.Forte@Sun.COM cc_ent->cc_iocount = 1;
11047836SJohn.Forte@Sun.COM (void) sd_start_io(bp, _sd_cache_files[cd].cd_strategy,
11057836SJohn.Forte@Sun.COM _sd_flcent_ea, cc_ent);
11067836SJohn.Forte@Sun.COM DISK_FBA_WRITE(cd, BLK_FBAS);
11077836SJohn.Forte@Sun.COM /* increment number of bytes destaged to disk */
11087836SJohn.Forte@Sun.COM WRITE_DESTAGED(cd, BLK_FBAS);
11097836SJohn.Forte@Sun.COM } else {
11107836SJohn.Forte@Sun.COM cc_ent->cc_iocount = SDBC_LOOKUP_DTCOUNT(dirty);
11117836SJohn.Forte@Sun.COM
11127836SJohn.Forte@Sun.COM while (dirty) {
11137836SJohn.Forte@Sun.COM sblk = SDBC_LOOKUP_STPOS(dirty);
11147836SJohn.Forte@Sun.COM len = SDBC_LOOKUP_LEN(dirty);
11157836SJohn.Forte@Sun.COM SDBC_LOOKUP_MODIFY(dirty);
11167836SJohn.Forte@Sun.COM
11177836SJohn.Forte@Sun.COM dblk = BLK_TO_FBA_NUM(CENTRY_BLK(cc_ent)) + sblk;
11187836SJohn.Forte@Sun.COM bp = sd_alloc_iob(rdev, dblk, 1, B_WRITE);
11197836SJohn.Forte@Sun.COM sd_add_fba(bp, &cc_ent->cc_addr, sblk, len);
11207836SJohn.Forte@Sun.COM DATA_LOG(SDF_FLSHENT, cc_ent, sblk, len);
11217836SJohn.Forte@Sun.COM
11229093SRamana.Srikanth@Sun.COM DTRACE_PROBE4(_sd_async_flcent_data2, int,
11239093SRamana.Srikanth@Sun.COM BLK_TO_FBA_NUM(CENTRY_BLK(cc_ent)) + sblk,
11249093SRamana.Srikanth@Sun.COM int, len, char *,
11259093SRamana.Srikanth@Sun.COM *(int64_t *)(cc_ent->cc_data + FBA_SIZE(sblk)),
11269093SRamana.Srikanth@Sun.COM char *, *(int64_t *)(cc_ent->cc_data +
11279093SRamana.Srikanth@Sun.COM FBA_SIZE(sblk + len) - 8));
11287836SJohn.Forte@Sun.COM
11297836SJohn.Forte@Sun.COM /* SDTRACE(ST_INFO|SDF_FLCENT, cd, len, dblk, 0, bp); */
11307836SJohn.Forte@Sun.COM
11317836SJohn.Forte@Sun.COM (void) sd_start_io(bp, _sd_cache_files[cd].cd_strategy,
11327836SJohn.Forte@Sun.COM _sd_flcent_ea, cc_ent);
11337836SJohn.Forte@Sun.COM DISK_FBA_WRITE(cd, len);
11347836SJohn.Forte@Sun.COM /* increment number of bytes destaged to disk */
11357836SJohn.Forte@Sun.COM WRITE_DESTAGED(cd, len);
11367836SJohn.Forte@Sun.COM }
11377836SJohn.Forte@Sun.COM }
11387836SJohn.Forte@Sun.COM _sd_enqueue_io_pending(cd, cc_ent);
11397836SJohn.Forte@Sun.COM
11407836SJohn.Forte@Sun.COM SDTRACE(ST_EXIT|SDF_FLCENT, cd, 0, dblk, 0, 0);
11417836SJohn.Forte@Sun.COM }
11427836SJohn.Forte@Sun.COM
11437836SJohn.Forte@Sun.COM static void
_sd_process_pending(int cd)11447836SJohn.Forte@Sun.COM _sd_process_pending(int cd)
11457836SJohn.Forte@Sun.COM {
11467836SJohn.Forte@Sun.COM _sd_cd_info_t *cdi;
11477836SJohn.Forte@Sun.COM _sd_cctl_t *cc_ent, *cc_next;
11487836SJohn.Forte@Sun.COM int dirty_enq;
11497836SJohn.Forte@Sun.COM ss_centry_info_t *wctl;
11507836SJohn.Forte@Sun.COM _sd_cctl_t *dirty_hd, **dirty_nxt;
11517836SJohn.Forte@Sun.COM int sts, processed = 0;
11527836SJohn.Forte@Sun.COM
11537836SJohn.Forte@Sun.COM cdi = &(_sd_cache_files[cd]);
11547836SJohn.Forte@Sun.COM
11557836SJohn.Forte@Sun.COM SDTRACE(ST_ENTER|SDF_FLDONE, cd, 0,
11569093SRamana.Srikanth@Sun.COM SDT_INV_BL, cdi->cd_info->sh_numio, 0);
11577836SJohn.Forte@Sun.COM process_loop:
11587836SJohn.Forte@Sun.COM if (cdi->cd_io_head == NULL) {
11597836SJohn.Forte@Sun.COM if (processed) {
11607836SJohn.Forte@Sun.COM mutex_enter(&cdi->cd_lock);
11617836SJohn.Forte@Sun.COM cdi->cd_info->sh_numio -= processed;
11627836SJohn.Forte@Sun.COM mutex_exit(&cdi->cd_lock);
11637836SJohn.Forte@Sun.COM }
11647836SJohn.Forte@Sun.COM SDTRACE(ST_EXIT|SDF_FLDONE, cd, 0,
11659093SRamana.Srikanth@Sun.COM SDT_INV_BL, cdi->cd_info->sh_numio, processed);
11667836SJohn.Forte@Sun.COM return;
11677836SJohn.Forte@Sun.COM }
11687836SJohn.Forte@Sun.COM cc_ent = cdi->cd_io_head;
11697836SJohn.Forte@Sun.COM if ((sts = cc_ent->cc_iostatus) == _SD_IO_INITIATE) {
11707836SJohn.Forte@Sun.COM if (processed) {
11717836SJohn.Forte@Sun.COM mutex_enter(&cdi->cd_lock);
11727836SJohn.Forte@Sun.COM cdi->cd_info->sh_numio -= processed;
11737836SJohn.Forte@Sun.COM mutex_exit(&cdi->cd_lock);
11747836SJohn.Forte@Sun.COM }
11757836SJohn.Forte@Sun.COM SDTRACE(ST_EXIT|SDF_FLDONE, cd, 0,
11769093SRamana.Srikanth@Sun.COM SDT_INV_BL, cdi->cd_info->sh_numio, processed);
11777836SJohn.Forte@Sun.COM return;
11787836SJohn.Forte@Sun.COM }
11797836SJohn.Forte@Sun.COM LINTUSED(sts);
11807836SJohn.Forte@Sun.COM #if defined(_SD_DEBUG)
11817836SJohn.Forte@Sun.COM if ((sts != _SD_IO_DONE) && (sts != _SD_IO_FAILED))
11827836SJohn.Forte@Sun.COM SDALERT(SDF_FLDONE, cd, 0,
11839093SRamana.Srikanth@Sun.COM BLK_TO_FBA_NUM(CENTRY_BLK(cc_ent)), 0, sts);
11847836SJohn.Forte@Sun.COM #endif
11857836SJohn.Forte@Sun.COM
11867836SJohn.Forte@Sun.COM if ((cdi->cd_io_head = cc_ent->cc_dirty_link) == NULL)
11877836SJohn.Forte@Sun.COM cdi->cd_io_tail = NULL;
11887836SJohn.Forte@Sun.COM
11897836SJohn.Forte@Sun.COM cc_ent->cc_dirty_link = NULL;
11907836SJohn.Forte@Sun.COM if (cc_ent->cc_iostatus == _SD_IO_FAILED &&
11917836SJohn.Forte@Sun.COM _sd_process_failure(cc_ent))
11927836SJohn.Forte@Sun.COM goto process_loop;
11937836SJohn.Forte@Sun.COM
11947836SJohn.Forte@Sun.COM dirty_enq = 0;
11957836SJohn.Forte@Sun.COM dirty_nxt = &(dirty_hd);
11967836SJohn.Forte@Sun.COM
11979093SRamana.Srikanth@Sun.COM DTRACE_PROBE1(_sd_process_pending_cd, int, cd);
11987836SJohn.Forte@Sun.COM
11997836SJohn.Forte@Sun.COM for (; cc_ent; cc_ent = cc_next) {
12007836SJohn.Forte@Sun.COM
12017836SJohn.Forte@Sun.COM DTRACE_PROBE1(_sd_process_pending_cc_ent,
12029093SRamana.Srikanth@Sun.COM _sd_cctl_t *, cc_ent);
12037836SJohn.Forte@Sun.COM processed++;
12047836SJohn.Forte@Sun.COM cc_next = cc_ent->cc_dirty_next;
12057836SJohn.Forte@Sun.COM cc_ent->cc_dirty_next = NULL;
12067836SJohn.Forte@Sun.COM
12077836SJohn.Forte@Sun.COM if (CENTRY_PINNED(cc_ent))
12087836SJohn.Forte@Sun.COM _sd_process_reflush(cc_ent);
12097836SJohn.Forte@Sun.COM
12107836SJohn.Forte@Sun.COM /*
12117836SJohn.Forte@Sun.COM * Optimize for common case where block not inuse
12127836SJohn.Forte@Sun.COM * Grabbing cc_inuse is faster than cc_lock.
12137836SJohn.Forte@Sun.COM */
12147836SJohn.Forte@Sun.COM if (SET_CENTRY_INUSE(cc_ent))
12157836SJohn.Forte@Sun.COM goto must_lock;
12167836SJohn.Forte@Sun.COM
12177836SJohn.Forte@Sun.COM cc_ent->cc_iostatus = _SD_IO_NONE;
12187836SJohn.Forte@Sun.COM if (CENTRY_DIRTY_PENDING(cc_ent)) {
12197836SJohn.Forte@Sun.COM cc_ent->cc_flag &= ~CC_PEND_DIRTY;
12207836SJohn.Forte@Sun.COM
12217836SJohn.Forte@Sun.COM CLEAR_CENTRY_INUSE(cc_ent);
12227836SJohn.Forte@Sun.COM if (dirty_enq)
12237836SJohn.Forte@Sun.COM dirty_nxt = &((*dirty_nxt)->cc_dirty_link);
12247836SJohn.Forte@Sun.COM (*dirty_nxt) = cc_ent;
12257836SJohn.Forte@Sun.COM dirty_enq++;
12267836SJohn.Forte@Sun.COM continue;
12277836SJohn.Forte@Sun.COM }
12287836SJohn.Forte@Sun.COM cc_ent->cc_dirty = 0;
12297836SJohn.Forte@Sun.COM wctl = cc_ent->cc_write;
12307836SJohn.Forte@Sun.COM cc_ent->cc_write = NULL;
12317836SJohn.Forte@Sun.COM cc_ent->cc_flag &= ~(CC_PINNABLE);
12327836SJohn.Forte@Sun.COM
12337836SJohn.Forte@Sun.COM
12347836SJohn.Forte@Sun.COM wctl->sc_dirty = 0;
12357836SJohn.Forte@Sun.COM SSOP_SETCENTRY(sdbc_safestore, wctl);
12367836SJohn.Forte@Sun.COM SSOP_DEALLOCRESOURCE(sdbc_safestore, wctl->sc_res);
12377836SJohn.Forte@Sun.COM
12387836SJohn.Forte@Sun.COM /*
12397836SJohn.Forte@Sun.COM * if this was a QHEAD cache block, then
12407836SJohn.Forte@Sun.COM * _sd_centry_release() did not requeue it as
12417836SJohn.Forte@Sun.COM * it was dirty. Requeue it now.
12427836SJohn.Forte@Sun.COM */
12437836SJohn.Forte@Sun.COM
12447836SJohn.Forte@Sun.COM if (CENTRY_QHEAD(cc_ent))
12457836SJohn.Forte@Sun.COM if (sdbc_use_dmchain) {
12467836SJohn.Forte@Sun.COM
12477836SJohn.Forte@Sun.COM /* attempt to que head */
12487836SJohn.Forte@Sun.COM if (cc_ent->cc_alloc_size_dm) {
12497836SJohn.Forte@Sun.COM
12507836SJohn.Forte@Sun.COM sdbc_requeue_head_dm_try(cc_ent);
12517836SJohn.Forte@Sun.COM }
12527836SJohn.Forte@Sun.COM } else
12537836SJohn.Forte@Sun.COM _sd_requeue_head(cc_ent);
12547836SJohn.Forte@Sun.COM
12557836SJohn.Forte@Sun.COM CLEAR_CENTRY_INUSE(cc_ent);
12567836SJohn.Forte@Sun.COM continue;
12577836SJohn.Forte@Sun.COM
12587836SJohn.Forte@Sun.COM /*
12597836SJohn.Forte@Sun.COM * Block is inuse, must take cc_lock
12607836SJohn.Forte@Sun.COM * if DIRTY_PENDING, must re-issue
12617836SJohn.Forte@Sun.COM */
12627836SJohn.Forte@Sun.COM must_lock:
12637836SJohn.Forte@Sun.COM /* was FAST */
12647836SJohn.Forte@Sun.COM mutex_enter(&cc_ent->cc_lock);
12657836SJohn.Forte@Sun.COM cc_ent->cc_iostatus = _SD_IO_NONE;
12667836SJohn.Forte@Sun.COM if (CENTRY_DIRTY_PENDING(cc_ent)) {
12677836SJohn.Forte@Sun.COM cc_ent->cc_flag &= ~CC_PEND_DIRTY;
12687836SJohn.Forte@Sun.COM /* was FAST */
12697836SJohn.Forte@Sun.COM mutex_exit(&cc_ent->cc_lock);
12707836SJohn.Forte@Sun.COM if (dirty_enq)
12717836SJohn.Forte@Sun.COM dirty_nxt = &((*dirty_nxt)->cc_dirty_link);
12727836SJohn.Forte@Sun.COM (*dirty_nxt) = cc_ent;
12737836SJohn.Forte@Sun.COM dirty_enq++;
12747836SJohn.Forte@Sun.COM continue;
12757836SJohn.Forte@Sun.COM }
12767836SJohn.Forte@Sun.COM /*
12777836SJohn.Forte@Sun.COM * clear dirty bits, if block no longer inuse release cc_write
12787836SJohn.Forte@Sun.COM */
12797836SJohn.Forte@Sun.COM cc_ent->cc_dirty = 0;
12807836SJohn.Forte@Sun.COM if (SET_CENTRY_INUSE(cc_ent) == 0) {
12817836SJohn.Forte@Sun.COM
12827836SJohn.Forte@Sun.COM wctl = cc_ent->cc_write;
12837836SJohn.Forte@Sun.COM cc_ent->cc_write = NULL;
12847836SJohn.Forte@Sun.COM cc_ent->cc_flag &= ~(CC_PINNABLE);
12857836SJohn.Forte@Sun.COM /* was FAST */
12867836SJohn.Forte@Sun.COM mutex_exit(&cc_ent->cc_lock);
12877836SJohn.Forte@Sun.COM
12887836SJohn.Forte@Sun.COM
12897836SJohn.Forte@Sun.COM wctl->sc_dirty = 0;
12907836SJohn.Forte@Sun.COM SSOP_SETCENTRY(sdbc_safestore, wctl);
12917836SJohn.Forte@Sun.COM SSOP_DEALLOCRESOURCE(sdbc_safestore, wctl->sc_res);
12927836SJohn.Forte@Sun.COM
12937836SJohn.Forte@Sun.COM /*
12947836SJohn.Forte@Sun.COM * if this was a QHEAD cache block, then
12957836SJohn.Forte@Sun.COM * _sd_centry_release() did not requeue it as
12967836SJohn.Forte@Sun.COM * it was dirty. Requeue it now.
12977836SJohn.Forte@Sun.COM */
12987836SJohn.Forte@Sun.COM
12997836SJohn.Forte@Sun.COM if (CENTRY_QHEAD(cc_ent))
13007836SJohn.Forte@Sun.COM if (sdbc_use_dmchain) {
13017836SJohn.Forte@Sun.COM
13027836SJohn.Forte@Sun.COM /* attempt to que head */
13037836SJohn.Forte@Sun.COM if (cc_ent->cc_alloc_size_dm) {
13049093SRamana.Srikanth@Sun.COM sdbc_requeue_head_dm_try
13059093SRamana.Srikanth@Sun.COM (cc_ent);
13067836SJohn.Forte@Sun.COM }
13077836SJohn.Forte@Sun.COM } else
13087836SJohn.Forte@Sun.COM _sd_requeue_head(cc_ent);
13097836SJohn.Forte@Sun.COM CLEAR_CENTRY_INUSE(cc_ent);
13107836SJohn.Forte@Sun.COM } else {
13117836SJohn.Forte@Sun.COM /* was FAST */
13127836SJohn.Forte@Sun.COM mutex_exit(&cc_ent->cc_lock);
13137836SJohn.Forte@Sun.COM }
13147836SJohn.Forte@Sun.COM }
13157836SJohn.Forte@Sun.COM
13167836SJohn.Forte@Sun.COM if (dirty_enq)
13177836SJohn.Forte@Sun.COM _sd_enqueue_dirty_chain(cd, dirty_hd, (*dirty_nxt), dirty_enq);
13187836SJohn.Forte@Sun.COM
13197836SJohn.Forte@Sun.COM goto process_loop;
13207836SJohn.Forte@Sun.COM }
13217836SJohn.Forte@Sun.COM
13227836SJohn.Forte@Sun.COM
13237836SJohn.Forte@Sun.COM static void
_sd_flcent_ea(blind_t xcc_ent,nsc_off_t fba_pos,nsc_size_t fba_len,int error)13247836SJohn.Forte@Sun.COM _sd_flcent_ea(blind_t xcc_ent, nsc_off_t fba_pos, nsc_size_t fba_len, int error)
13257836SJohn.Forte@Sun.COM {
13267836SJohn.Forte@Sun.COM _sd_cctl_t *cc_ent = (_sd_cctl_t *)xcc_ent;
13277836SJohn.Forte@Sun.COM int cd;
13287836SJohn.Forte@Sun.COM nsc_off_t dblk;
13297836SJohn.Forte@Sun.COM
13307836SJohn.Forte@Sun.COM _sd_cd_info_t *cdi;
13317836SJohn.Forte@Sun.COM
13327836SJohn.Forte@Sun.COM cd = CENTRY_CD(cc_ent);
13337836SJohn.Forte@Sun.COM dblk = BLK_TO_FBA_NUM(CENTRY_BLK(cc_ent));
13347836SJohn.Forte@Sun.COM cdi = &(_sd_cache_files[cd]);
13357836SJohn.Forte@Sun.COM
13367836SJohn.Forte@Sun.COM SDTRACE(ST_ENTER|SDF_FLCENT_EA, cd, 0, dblk, 2, (unsigned long)cc_ent);
13377836SJohn.Forte@Sun.COM
13387836SJohn.Forte@Sun.COM if (error) {
13397836SJohn.Forte@Sun.COM if (cdi->cd_info->sh_failed == 0) {
13407836SJohn.Forte@Sun.COM cdi->cd_info->sh_failed = 1;
13419093SRamana.Srikanth@Sun.COM cmn_err(CE_WARN, "!sdbc(_sd_flcent_ea) "
13427836SJohn.Forte@Sun.COM "Disk write failed cd %d (%s): err %d",
13437836SJohn.Forte@Sun.COM cd, cdi->cd_info->sh_filename, error);
13447836SJohn.Forte@Sun.COM }
13457836SJohn.Forte@Sun.COM }
13467836SJohn.Forte@Sun.COM
13477836SJohn.Forte@Sun.COM /* was FAST */
13487836SJohn.Forte@Sun.COM mutex_enter(&cc_ent->cc_lock);
13497836SJohn.Forte@Sun.COM if (--(cc_ent->cc_iocount) != 0) {
13507836SJohn.Forte@Sun.COM /* more io's to complete before the cc_ent is done. */
13517836SJohn.Forte@Sun.COM
13527836SJohn.Forte@Sun.COM if (cc_ent->cc_iocount < 0) {
13537836SJohn.Forte@Sun.COM /* was FAST */
13547836SJohn.Forte@Sun.COM mutex_exit(&cc_ent->cc_lock);
13557836SJohn.Forte@Sun.COM SDALERT(SDF_FLCENT_EA, cd, 0,
13569093SRamana.Srikanth@Sun.COM dblk, cc_ent->cc_iocount, 0);
13577836SJohn.Forte@Sun.COM } else {
13587836SJohn.Forte@Sun.COM /* was FAST */
13597836SJohn.Forte@Sun.COM mutex_exit(&cc_ent->cc_lock);
13607836SJohn.Forte@Sun.COM }
13617836SJohn.Forte@Sun.COM SDTRACE(ST_EXIT|SDF_FLCENT_EA, cd, 0, dblk, 2,
13627836SJohn.Forte@Sun.COM (unsigned long)cc_ent);
13637836SJohn.Forte@Sun.COM
13647836SJohn.Forte@Sun.COM DTRACE_PROBE(_sd_flcent_ea_end);
13657836SJohn.Forte@Sun.COM return;
13667836SJohn.Forte@Sun.COM }
13677836SJohn.Forte@Sun.COM /* was FAST */
13687836SJohn.Forte@Sun.COM mutex_exit(&cc_ent->cc_lock);
13697836SJohn.Forte@Sun.COM
13707836SJohn.Forte@Sun.COM DATA_LOG(SDF_FLEA, cc_ent, BLK_FBA_OFF(fba_pos), fba_len);
13717836SJohn.Forte@Sun.COM
13729093SRamana.Srikanth@Sun.COM DTRACE_PROBE4(_sd_flcent_ea_data, uint64_t, ((uint64_t)
13739093SRamana.Srikanth@Sun.COM BLK_TO_FBA_NUM(CENTRY_BLK(cc_ent) + BLK_FBA_OFF(fba_pos))),
13749093SRamana.Srikanth@Sun.COM uint64_t, (uint64_t)fba_len, char *,
13759093SRamana.Srikanth@Sun.COM *(int64_t *)(cc_ent->cc_data + FBA_SIZE(BLK_FBA_OFF(fba_pos))),
13767836SJohn.Forte@Sun.COM char *, *(int64_t *)(cc_ent->cc_data +
13779093SRamana.Srikanth@Sun.COM FBA_SIZE(BLK_FBA_OFF(fba_pos) + fba_len) - 8));
13787836SJohn.Forte@Sun.COM
13797836SJohn.Forte@Sun.COM /*
13807836SJohn.Forte@Sun.COM * All io's are done for this cc_ent.
13817836SJohn.Forte@Sun.COM * Clear the pagelist io flag.
13827836SJohn.Forte@Sun.COM */
13837836SJohn.Forte@Sun.COM CLEAR_CENTRY_PAGEIO(cc_ent);
13847836SJohn.Forte@Sun.COM
13857836SJohn.Forte@Sun.COM if (error)
13867836SJohn.Forte@Sun.COM cc_ent->cc_iostatus = _SD_IO_FAILED;
13877836SJohn.Forte@Sun.COM else
13887836SJohn.Forte@Sun.COM cc_ent->cc_iostatus = _SD_IO_DONE;
13897836SJohn.Forte@Sun.COM
13907836SJohn.Forte@Sun.COM SDTRACE(ST_EXIT|SDF_FLCENT_EA, cd, 0, dblk, 2, (unsigned long)cc_ent);
13917836SJohn.Forte@Sun.COM
13927836SJohn.Forte@Sun.COM }
13937836SJohn.Forte@Sun.COM
13947836SJohn.Forte@Sun.COM
13957836SJohn.Forte@Sun.COM
13967836SJohn.Forte@Sun.COM static void
_sd_flclist_ea(blind_t xcc_ent,nsc_off_t fba_pos,nsc_size_t fba_len,int error)13977836SJohn.Forte@Sun.COM _sd_flclist_ea(blind_t xcc_ent, nsc_off_t fba_pos, nsc_size_t fba_len,
13987836SJohn.Forte@Sun.COM int error)
13997836SJohn.Forte@Sun.COM {
14007836SJohn.Forte@Sun.COM _sd_cctl_t *cc_ent = (_sd_cctl_t *)xcc_ent;
14017836SJohn.Forte@Sun.COM _sd_cctl_t *first_cc = cc_ent;
14027836SJohn.Forte@Sun.COM _sd_cd_info_t *cdi;
14037836SJohn.Forte@Sun.COM int cd;
14047836SJohn.Forte@Sun.COM nsc_off_t dblk;
14057836SJohn.Forte@Sun.COM
14067836SJohn.Forte@Sun.COM cd = CENTRY_CD(cc_ent);
14077836SJohn.Forte@Sun.COM dblk = BLK_TO_FBA_NUM(CENTRY_BLK(cc_ent));
14087836SJohn.Forte@Sun.COM cdi = &(_sd_cache_files[cd]);
14097836SJohn.Forte@Sun.COM
14107836SJohn.Forte@Sun.COM SDTRACE(ST_ENTER|SDF_FLCLIST_EA, cd, 0, dblk, 1, (unsigned long)cc_ent);
14117836SJohn.Forte@Sun.COM
14127836SJohn.Forte@Sun.COM if (error) {
14137836SJohn.Forte@Sun.COM if (cdi->cd_info->sh_failed == 0) {
14147836SJohn.Forte@Sun.COM cdi->cd_info->sh_failed = 1;
14159093SRamana.Srikanth@Sun.COM cmn_err(CE_WARN, "!sdbc(_sd_flclist_ea) "
14167836SJohn.Forte@Sun.COM "Disk write failed cd %d (%s): err %d",
14177836SJohn.Forte@Sun.COM cd, cdi->cd_info->sh_filename, error);
14187836SJohn.Forte@Sun.COM }
14197836SJohn.Forte@Sun.COM }
14207836SJohn.Forte@Sun.COM /*
14217836SJohn.Forte@Sun.COM * Important: skip the first cc_ent in the list. Marking this will
14227836SJohn.Forte@Sun.COM * make the writer think the io is done, though the rest of the
14237836SJohn.Forte@Sun.COM * chain have not been processed here. so mark the first cc_ent
14247836SJohn.Forte@Sun.COM * last. Optimization, so as not to use locks
14257836SJohn.Forte@Sun.COM */
14267836SJohn.Forte@Sun.COM
14277836SJohn.Forte@Sun.COM cc_ent = cc_ent->cc_dirty_next;
14287836SJohn.Forte@Sun.COM while (cc_ent) {
14299093SRamana.Srikanth@Sun.COM DTRACE_PROBE2(_sd_flclist_ea, _sd_cctl_t *, cc_ent,
14309093SRamana.Srikanth@Sun.COM int, CENTRY_CD(cc_ent));
14317836SJohn.Forte@Sun.COM
14327836SJohn.Forte@Sun.COM if (cc_ent->cc_iocount != 1)
14337836SJohn.Forte@Sun.COM SDALERT(SDF_FLCLIST_EA, cd, 0,
14349093SRamana.Srikanth@Sun.COM BLK_TO_FBA_NUM(CENTRY_BLK(cc_ent)),
14359093SRamana.Srikanth@Sun.COM cc_ent->cc_iocount, 0);
14367836SJohn.Forte@Sun.COM cc_ent->cc_iocount = 0;
14377836SJohn.Forte@Sun.COM
14387836SJohn.Forte@Sun.COM /*
14397836SJohn.Forte@Sun.COM * Clear the pagelist io flag.
14407836SJohn.Forte@Sun.COM */
14417836SJohn.Forte@Sun.COM CLEAR_CENTRY_PAGEIO(cc_ent);
14427836SJohn.Forte@Sun.COM
14437836SJohn.Forte@Sun.COM if (error)
14447836SJohn.Forte@Sun.COM cc_ent->cc_iostatus = _SD_IO_FAILED;
14457836SJohn.Forte@Sun.COM else
14467836SJohn.Forte@Sun.COM cc_ent->cc_iostatus = _SD_IO_DONE;
14477836SJohn.Forte@Sun.COM if (cc_ent->cc_dirty_next) {
14487836SJohn.Forte@Sun.COM DATA_LOG(SDF_FLSTEA, cc_ent, 0, BLK_FBAS);
14497836SJohn.Forte@Sun.COM
14509093SRamana.Srikanth@Sun.COM DTRACE_PROBE4(_sd_flclist_ea_data1, uint64_t,
14519093SRamana.Srikanth@Sun.COM BLK_TO_FBA_NUM(CENTRY_BLK(cc_ent)),
14529093SRamana.Srikanth@Sun.COM int, BLK_FBAS, char *,
14539093SRamana.Srikanth@Sun.COM *(int64_t *)(cc_ent->cc_data),
14547836SJohn.Forte@Sun.COM char *, *(int64_t *)(cc_ent->cc_data +
14559093SRamana.Srikanth@Sun.COM FBA_SIZE(BLK_FBAS) - 8));
14567836SJohn.Forte@Sun.COM } else {
14577836SJohn.Forte@Sun.COM DATA_LOG(SDF_FLSTEA, cc_ent, 0,
14589093SRamana.Srikanth@Sun.COM BLK_FBA_OFF(fba_pos + fba_len));
14597836SJohn.Forte@Sun.COM
14609093SRamana.Srikanth@Sun.COM DTRACE_PROBE4(_sd_flclist_ea_data2, uint64_t,
14619093SRamana.Srikanth@Sun.COM (uint64_t)BLK_TO_FBA_NUM(CENTRY_BLK(cc_ent)),
14629093SRamana.Srikanth@Sun.COM uint64_t, (uint64_t)BLK_FBA_OFF(fba_pos + fba_len),
14637836SJohn.Forte@Sun.COM char *, *(int64_t *)(cc_ent->cc_data),
14647836SJohn.Forte@Sun.COM char *, *(int64_t *)(cc_ent->cc_data +
14659093SRamana.Srikanth@Sun.COM FBA_SIZE(BLK_FBA_OFF(fba_pos + fba_len)) - 8));
14667836SJohn.Forte@Sun.COM }
14677836SJohn.Forte@Sun.COM
14687836SJohn.Forte@Sun.COM cc_ent = cc_ent->cc_dirty_next;
14697836SJohn.Forte@Sun.COM }
14707836SJohn.Forte@Sun.COM
14717836SJohn.Forte@Sun.COM /*
14727836SJohn.Forte@Sun.COM * Now process the first cc_ent in the list.
14737836SJohn.Forte@Sun.COM */
14747836SJohn.Forte@Sun.COM cc_ent = first_cc;
14757836SJohn.Forte@Sun.COM DATA_LOG(SDF_FLSTEA, cc_ent, BLK_FBA_OFF(fba_pos),
14769093SRamana.Srikanth@Sun.COM BLK_FBAS - BLK_FBA_OFF(fba_pos));
14777836SJohn.Forte@Sun.COM
14789093SRamana.Srikanth@Sun.COM DTRACE_PROBE4(_sd_flclist_ea_data3, uint64_t,
14799093SRamana.Srikanth@Sun.COM (uint64_t)fba_pos, int, BLK_FBAS - BLK_FBA_OFF(fba_pos),
14809093SRamana.Srikanth@Sun.COM char *, *(int64_t *)(cc_ent->cc_data +
14819093SRamana.Srikanth@Sun.COM FBA_SIZE(BLK_FBA_OFF(fba_pos))), char *,
14829093SRamana.Srikanth@Sun.COM *(int64_t *)(cc_ent->cc_data + FBA_SIZE(BLK_FBA_OFF(fba_pos) +
14839093SRamana.Srikanth@Sun.COM BLK_FBAS - BLK_FBA_OFF(fba_pos)) - 8));
14847836SJohn.Forte@Sun.COM
14857836SJohn.Forte@Sun.COM cc_ent->cc_iocount = 0;
14867836SJohn.Forte@Sun.COM
14877836SJohn.Forte@Sun.COM if (cc_ent->cc_anon_addr.sa_virt) {
14887836SJohn.Forte@Sun.COM kmem_free(cc_ent->cc_anon_addr.sa_virt, cc_ent->cc_anon_len);
14897836SJohn.Forte@Sun.COM cc_ent->cc_anon_addr.sa_virt = NULL;
14907836SJohn.Forte@Sun.COM cc_ent->cc_anon_len = 0;
14917836SJohn.Forte@Sun.COM }
14927836SJohn.Forte@Sun.COM
14937836SJohn.Forte@Sun.COM /*
14947836SJohn.Forte@Sun.COM * Clear the pagelist io flag.
14957836SJohn.Forte@Sun.COM */
14967836SJohn.Forte@Sun.COM CLEAR_CENTRY_PAGEIO(cc_ent);
14977836SJohn.Forte@Sun.COM
14987836SJohn.Forte@Sun.COM if (error)
14997836SJohn.Forte@Sun.COM cc_ent->cc_iostatus = _SD_IO_FAILED;
15007836SJohn.Forte@Sun.COM else
15017836SJohn.Forte@Sun.COM cc_ent->cc_iostatus = _SD_IO_DONE;
15027836SJohn.Forte@Sun.COM
15037836SJohn.Forte@Sun.COM SDTRACE(ST_EXIT|SDF_FLCLIST_EA, cd, 0, dblk, 1, (unsigned long)cc_ent);
15047836SJohn.Forte@Sun.COM }
15057836SJohn.Forte@Sun.COM
15067836SJohn.Forte@Sun.COM
15077836SJohn.Forte@Sun.COM static void
_sd_mark_failed(_sd_cctl_t * cclist)15087836SJohn.Forte@Sun.COM _sd_mark_failed(_sd_cctl_t *cclist)
15097836SJohn.Forte@Sun.COM {
15107836SJohn.Forte@Sun.COM _sd_cctl_t *cc_ent;
15117836SJohn.Forte@Sun.COM int cd;
15127836SJohn.Forte@Sun.COM
15137836SJohn.Forte@Sun.COM cd = CENTRY_CD(cclist);
15147836SJohn.Forte@Sun.COM cc_ent = cclist;
15157836SJohn.Forte@Sun.COM while (cc_ent) {
15167836SJohn.Forte@Sun.COM cc_ent->cc_iostatus = _SD_IO_FAILED;
15177836SJohn.Forte@Sun.COM cc_ent = cc_ent->cc_dirty_next;
15187836SJohn.Forte@Sun.COM }
15197836SJohn.Forte@Sun.COM _sd_enqueue_io_pending(cd, cclist);
15207836SJohn.Forte@Sun.COM }
15217836SJohn.Forte@Sun.COM
15227836SJohn.Forte@Sun.COM
15237836SJohn.Forte@Sun.COM
15247836SJohn.Forte@Sun.COM /*
15257836SJohn.Forte@Sun.COM * Fail single chain of cache blocks, updating numfail/numio counts.
15267836SJohn.Forte@Sun.COM * For dual-copy, log & clear PINNED, fall thru to regular processing.
15277836SJohn.Forte@Sun.COM */
15287836SJohn.Forte@Sun.COM int
_sd_process_failure(_sd_cctl_t * cc_ent)15297836SJohn.Forte@Sun.COM _sd_process_failure(_sd_cctl_t *cc_ent)
15307836SJohn.Forte@Sun.COM {
15317836SJohn.Forte@Sun.COM int cd, num;
15327836SJohn.Forte@Sun.COM _sd_cctl_t *cc_chain;
15337836SJohn.Forte@Sun.COM _sd_cd_info_t *cdi;
15347836SJohn.Forte@Sun.COM
15357836SJohn.Forte@Sun.COM cd = CENTRY_CD(cc_ent);
15367836SJohn.Forte@Sun.COM cdi = &(_sd_cache_files[cd]);
15377836SJohn.Forte@Sun.COM
15387836SJohn.Forte@Sun.COM cc_chain = cc_ent;
15397836SJohn.Forte@Sun.COM
15407836SJohn.Forte@Sun.COM if (!cdi->cd_global->sv_pinned) {
15417836SJohn.Forte@Sun.COM cdi->cd_global->sv_pinned = _SD_SELF_HOST;
15427836SJohn.Forte@Sun.COM SSOP_SETVOL(sdbc_safestore, cdi->cd_global);
15437836SJohn.Forte@Sun.COM }
15447836SJohn.Forte@Sun.COM
15457836SJohn.Forte@Sun.COM for (num = 0; cc_ent; cc_ent = cc_ent->cc_dirty_next) {
15467836SJohn.Forte@Sun.COM num++;
15477836SJohn.Forte@Sun.COM /* was FAST */
15487836SJohn.Forte@Sun.COM mutex_enter(&cc_ent->cc_lock);
15497836SJohn.Forte@Sun.COM cc_ent->cc_flag |= (CC_PEND_DIRTY |
15507836SJohn.Forte@Sun.COM (CENTRY_PINNABLE(cc_ent) ? CC_PINNED : 0));
15517836SJohn.Forte@Sun.COM if (cc_ent->cc_write) {
15527836SJohn.Forte@Sun.COM cc_ent->cc_write->sc_flag = cc_ent->cc_flag;
15537836SJohn.Forte@Sun.COM SSOP_SETCENTRY(sdbc_safestore, cc_ent->cc_write);
15547836SJohn.Forte@Sun.COM }
15557836SJohn.Forte@Sun.COM mutex_exit(&cc_ent->cc_lock);
15567836SJohn.Forte@Sun.COM if (CENTRY_PINNED(cc_ent))
15577836SJohn.Forte@Sun.COM nsc_pinned_data(cdi->cd_iodev,
15587836SJohn.Forte@Sun.COM BLK_TO_FBA_NUM(CENTRY_BLK(cc_ent)), BLK_FBAS);
15597836SJohn.Forte@Sun.COM }
15607836SJohn.Forte@Sun.COM
15617836SJohn.Forte@Sun.COM /*
15627836SJohn.Forte@Sun.COM * In normal processing we wouldn't need a lock here as all i/o
15637836SJohn.Forte@Sun.COM * is single threaded by cd. However during failover blocks can
15647836SJohn.Forte@Sun.COM * be failing from real i/o and as soon as the disk is marked bad
15657836SJohn.Forte@Sun.COM * the failover code which is furiously cloning safe-store into
15667836SJohn.Forte@Sun.COM * more blocks will short circuit to here (see _sd_ft_clone)
15677836SJohn.Forte@Sun.COM * and two threads can be executing in here simultaneously.
15687836SJohn.Forte@Sun.COM */
15697836SJohn.Forte@Sun.COM mutex_enter(&cdi->cd_lock);
15707836SJohn.Forte@Sun.COM cc_chain->cc_dirty_link = cdi->cd_fail_head;
15717836SJohn.Forte@Sun.COM cdi->cd_fail_head = cc_chain;
15727836SJohn.Forte@Sun.COM cdi->cd_info->sh_numfail += num;
15737836SJohn.Forte@Sun.COM cdi->cd_info->sh_numio -= num;
15747836SJohn.Forte@Sun.COM mutex_exit(&cdi->cd_lock);
15757836SJohn.Forte@Sun.COM return (1); /* blocks are failed */
15767836SJohn.Forte@Sun.COM }
15777836SJohn.Forte@Sun.COM
15787836SJohn.Forte@Sun.COM
15797836SJohn.Forte@Sun.COM static void
_sd_process_reflush(_sd_cctl_t * cc_ent)15807836SJohn.Forte@Sun.COM _sd_process_reflush(_sd_cctl_t *cc_ent)
15817836SJohn.Forte@Sun.COM {
15827836SJohn.Forte@Sun.COM int cd;
15837836SJohn.Forte@Sun.COM
15847836SJohn.Forte@Sun.COM if (CENTRY_PINNABLE(cc_ent)) {
15857836SJohn.Forte@Sun.COM cd = CENTRY_CD(cc_ent);
15867836SJohn.Forte@Sun.COM nsc_unpinned_data(_sd_cache_files[cd].cd_iodev,
15879093SRamana.Srikanth@Sun.COM BLK_TO_FBA_NUM(CENTRY_BLK(cc_ent)), BLK_FBAS);
15887836SJohn.Forte@Sun.COM }
15897836SJohn.Forte@Sun.COM
15907836SJohn.Forte@Sun.COM /* was FAST */
15917836SJohn.Forte@Sun.COM mutex_enter(&cc_ent->cc_lock);
15927836SJohn.Forte@Sun.COM cc_ent->cc_flag &= ~CC_PINNED;
15937836SJohn.Forte@Sun.COM /* was FAST */
15947836SJohn.Forte@Sun.COM mutex_exit(&cc_ent->cc_lock);
15957836SJohn.Forte@Sun.COM }
15967836SJohn.Forte@Sun.COM
15977836SJohn.Forte@Sun.COM
15987836SJohn.Forte@Sun.COM
15997836SJohn.Forte@Sun.COM /*
16007836SJohn.Forte@Sun.COM * cd_write_thread -- flush dirty buffers.
16017836SJohn.Forte@Sun.COM *
16027836SJohn.Forte@Sun.COM * ARGUMENTS:
16037836SJohn.Forte@Sun.COM *
16047836SJohn.Forte@Sun.COM * cd - cache descriptor
16057836SJohn.Forte@Sun.COM *
16067836SJohn.Forte@Sun.COM * USAGE:
16077836SJohn.Forte@Sun.COM * called by cd's writer thread, returns when no more entries
16087836SJohn.Forte@Sun.COM *
16097836SJohn.Forte@Sun.COM * NOTE: if sdbc is being shutdown (for powerfail) then we will
16107836SJohn.Forte@Sun.COM * process pending i/o's but issue no more new ones.
16117836SJohn.Forte@Sun.COM */
16127836SJohn.Forte@Sun.COM static int SD_LOOP_DELAY = 32;
16137836SJohn.Forte@Sun.COM #if !defined(m88k) && !defined(sun)
16147836SJohn.Forte@Sun.COM static int SD_WRITE_HIGH = 255; /* cache blocks */
16157836SJohn.Forte@Sun.COM #endif
16167836SJohn.Forte@Sun.COM
16177836SJohn.Forte@Sun.COM static void
cd_write_thread(int cd)16187836SJohn.Forte@Sun.COM cd_write_thread(int cd)
16197836SJohn.Forte@Sun.COM {
16207836SJohn.Forte@Sun.COM _sd_cctl_t *cc_list, *dirty_head, *last_chain;
16217836SJohn.Forte@Sun.COM _sd_cd_info_t *cdi;
16227836SJohn.Forte@Sun.COM
16237836SJohn.Forte@Sun.COM cdi = &(_sd_cache_files[cd]);
16247836SJohn.Forte@Sun.COM if (!FILE_OPENED(cd)) {
16257836SJohn.Forte@Sun.COM cdi->cd_writer = _SD_WRITER_NONE;
16267836SJohn.Forte@Sun.COM return;
16277836SJohn.Forte@Sun.COM }
16287836SJohn.Forte@Sun.COM cdi->cd_writer = _SD_WRITER_RUNNING;
16297836SJohn.Forte@Sun.COM
16307836SJohn.Forte@Sun.COM _sd_process_pending(cd);
16317836SJohn.Forte@Sun.COM
16327836SJohn.Forte@Sun.COM if (_sdbc_shutdown_in_progress) {
16337836SJohn.Forte@Sun.COM cdi->cd_write_inprogress = 0;
16347836SJohn.Forte@Sun.COM cdi->cd_writer = _SD_WRITER_NONE;
16357836SJohn.Forte@Sun.COM return;
16367836SJohn.Forte@Sun.COM }
16377836SJohn.Forte@Sun.COM #if !defined(m88k) && !defined(sun)
16387836SJohn.Forte@Sun.COM if (cdi->cd_info->sh_numio > SD_WRITE_HIGH) {
16397836SJohn.Forte@Sun.COM /* let I/Os complete before issuing more */
16407836SJohn.Forte@Sun.COM cdi->cd_writer = _SD_WRITER_NONE;
16417836SJohn.Forte@Sun.COM return;
16427836SJohn.Forte@Sun.COM }
16437836SJohn.Forte@Sun.COM #endif
16447836SJohn.Forte@Sun.COM
16457836SJohn.Forte@Sun.COM #ifdef DEBUG
16467836SJohn.Forte@Sun.COM if (!_sdbc_flush_flag) { /* hang the flusher for testing */
16477836SJohn.Forte@Sun.COM cdi->cd_write_inprogress = 0;
16487836SJohn.Forte@Sun.COM cdi->cd_writer = _SD_WRITER_NONE;
16497836SJohn.Forte@Sun.COM return;
16507836SJohn.Forte@Sun.COM }
16517836SJohn.Forte@Sun.COM #endif
16527836SJohn.Forte@Sun.COM
16537836SJohn.Forte@Sun.COM dirty_head = cdi->cd_dirty_head;
16547836SJohn.Forte@Sun.COM if (dirty_head && (dirty_head != cdi->cd_lastchain_ptr ||
16559093SRamana.Srikanth@Sun.COM ++cdi->cd_info->sh_flushloop > SD_LOOP_DELAY)) {
16567836SJohn.Forte@Sun.COM cdi->cd_info->sh_flushloop = 0;
16577836SJohn.Forte@Sun.COM /* was FAST */
16587836SJohn.Forte@Sun.COM mutex_enter(&cdi->cd_lock);
16597836SJohn.Forte@Sun.COM if (SD_LOOP_DELAY == 0 ||
16607836SJohn.Forte@Sun.COM dirty_head == cdi->cd_lastchain_ptr) {
16617836SJohn.Forte@Sun.COM last_chain = NULL;
16627836SJohn.Forte@Sun.COM cdi->cd_dirty_head = NULL;
16637836SJohn.Forte@Sun.COM cdi->cd_dirty_tail = NULL;
16647836SJohn.Forte@Sun.COM cdi->cd_info->sh_numio += cdi->cd_info->sh_numdirty;
16657836SJohn.Forte@Sun.COM cdi->cd_info->sh_numdirty = 0;
16667836SJohn.Forte@Sun.COM } else
16677836SJohn.Forte@Sun.COM #if !defined(m88k) && !defined(sun)
16687836SJohn.Forte@Sun.COM if (cdi->cd_info->sh_numdirty > SD_WRITE_HIGH) {
16697836SJohn.Forte@Sun.COM int count = 0;
16707836SJohn.Forte@Sun.COM for (last_chain = dirty_head; last_chain;
16719093SRamana.Srikanth@Sun.COM last_chain = last_chain->cc_dirty_next)
16729093SRamana.Srikanth@Sun.COM count++;
16737836SJohn.Forte@Sun.COM last_chain = dirty_head->cc_dirty_link;
16747836SJohn.Forte@Sun.COM cdi->cd_dirty_head = last_chain;
16757836SJohn.Forte@Sun.COM /* cdi->cd_dirty_tail is unchanged */
16767836SJohn.Forte@Sun.COM cdi->cd_info->sh_numio += count;
16777836SJohn.Forte@Sun.COM cdi->cd_info->sh_numdirty -= count;
16787836SJohn.Forte@Sun.COM } else
16797836SJohn.Forte@Sun.COM #endif
16807836SJohn.Forte@Sun.COM {
16817836SJohn.Forte@Sun.COM last_chain = cdi->cd_lastchain_ptr;
16827836SJohn.Forte@Sun.COM cdi->cd_dirty_head = last_chain;
16837836SJohn.Forte@Sun.COM cdi->cd_dirty_tail = last_chain;
16847836SJohn.Forte@Sun.COM cdi->cd_info->sh_numio += cdi->cd_info->sh_numdirty -
16859093SRamana.Srikanth@Sun.COM cdi->cd_lastchain;
16867836SJohn.Forte@Sun.COM cdi->cd_info->sh_numdirty = cdi->cd_lastchain;
16877836SJohn.Forte@Sun.COM }
16887836SJohn.Forte@Sun.COM /* was FAST */
16897836SJohn.Forte@Sun.COM mutex_exit(&cdi->cd_lock);
16907836SJohn.Forte@Sun.COM
16917836SJohn.Forte@Sun.COM while (((cc_list = dirty_head) != NULL) &&
16927836SJohn.Forte@Sun.COM cc_list != last_chain) {
16937836SJohn.Forte@Sun.COM dirty_head = cc_list->cc_dirty_link;
16947836SJohn.Forte@Sun.COM cc_list->cc_dirty_link = NULL;
16957836SJohn.Forte@Sun.COM if (cdi->cd_info->sh_failed)
16967836SJohn.Forte@Sun.COM _sd_mark_failed(cc_list);
16977836SJohn.Forte@Sun.COM else if (cc_list->cc_dirty_next == NULL)
16987836SJohn.Forte@Sun.COM _sd_async_flcent(cc_list, cdi->cd_crdev);
16997836SJohn.Forte@Sun.COM else
17007836SJohn.Forte@Sun.COM _sd_async_flclist(cc_list, cdi->cd_crdev);
17017836SJohn.Forte@Sun.COM cdi->cd_write_inprogress++;
17027836SJohn.Forte@Sun.COM }
17037836SJohn.Forte@Sun.COM }
17047836SJohn.Forte@Sun.COM cdi->cd_write_inprogress = 0;
17057836SJohn.Forte@Sun.COM cdi->cd_writer = _SD_WRITER_NONE;
17067836SJohn.Forte@Sun.COM }
17077836SJohn.Forte@Sun.COM
17087836SJohn.Forte@Sun.COM /*
17097836SJohn.Forte@Sun.COM * cd_writer -- spawn new writer if not running already
17107836SJohn.Forte@Sun.COM * called after enqueing the dirty blocks
17117836SJohn.Forte@Sun.COM */
17127836SJohn.Forte@Sun.COM int
cd_writer(int cd)17137836SJohn.Forte@Sun.COM cd_writer(int cd)
17147836SJohn.Forte@Sun.COM {
17157836SJohn.Forte@Sun.COM _sd_cd_info_t *cdi;
17167836SJohn.Forte@Sun.COM nstset_t *tset = NULL;
17177836SJohn.Forte@Sun.COM nsthread_t *t;
17187836SJohn.Forte@Sun.COM
17197836SJohn.Forte@Sun.COM #if defined(_SD_USE_THREADS)
17207836SJohn.Forte@Sun.COM tset = _sd_ioset;
17217836SJohn.Forte@Sun.COM #endif /* _SD_USE_THREADS */
17227836SJohn.Forte@Sun.COM
17237836SJohn.Forte@Sun.COM cdi = &(_sd_cache_files[cd]);
17247836SJohn.Forte@Sun.COM
17257836SJohn.Forte@Sun.COM if (cdi->cd_writer)
17267836SJohn.Forte@Sun.COM return (0);
17277836SJohn.Forte@Sun.COM
17287836SJohn.Forte@Sun.COM if (tset == NULL) {
17297836SJohn.Forte@Sun.COM _sd_unblock(&_sd_flush_cv);
17307836SJohn.Forte@Sun.COM return (0);
17317836SJohn.Forte@Sun.COM }
17327836SJohn.Forte@Sun.COM
17337836SJohn.Forte@Sun.COM if (cdi->cd_writer || xmem_bu(_SD_WRITER_CREATE, &cdi->cd_writer))
17347836SJohn.Forte@Sun.COM return (0);
17357836SJohn.Forte@Sun.COM
17367836SJohn.Forte@Sun.COM t = nst_create(tset, cd_write_thread, (blind_t)(unsigned long)cd, 0);
17377836SJohn.Forte@Sun.COM if (t)
17387836SJohn.Forte@Sun.COM return (1);
17397836SJohn.Forte@Sun.COM
17409093SRamana.Srikanth@Sun.COM cmn_err(CE_WARN, "!sdbc(cd_writer) cd %d nst_create error", cd);
17417836SJohn.Forte@Sun.COM cdi->cd_writer = _SD_WRITER_NONE;
17427836SJohn.Forte@Sun.COM return (-1);
17437836SJohn.Forte@Sun.COM }
17447836SJohn.Forte@Sun.COM
17457836SJohn.Forte@Sun.COM /*
17467836SJohn.Forte@Sun.COM * _sd_ccent_rd - add appropriate parts of cc_ent to struct buf.
17477836SJohn.Forte@Sun.COM * optimized not to read dirty FBAs from disk.
17487836SJohn.Forte@Sun.COM *
17497836SJohn.Forte@Sun.COM * ARGUMENTS:
17507836SJohn.Forte@Sun.COM *
17517836SJohn.Forte@Sun.COM * cc_ent - single cache block
17527836SJohn.Forte@Sun.COM * wanted - bitlist of FBAs that need to be read
17537836SJohn.Forte@Sun.COM * bp - struct buf to extend
17547836SJohn.Forte@Sun.COM *
17557836SJohn.Forte@Sun.COM * USAGE:
17567836SJohn.Forte@Sun.COM * Called for each dirty in a read I/O.
17577836SJohn.Forte@Sun.COM * The bp must be sized to allow for one entry per FBA that needs
17587836SJohn.Forte@Sun.COM * to be read (see _sd_doread()).
17597836SJohn.Forte@Sun.COM */
17607836SJohn.Forte@Sun.COM
17617836SJohn.Forte@Sun.COM void
_sd_ccent_rd(_sd_cctl_t * cc_ent,uint_t wanted,struct buf * bp)17627836SJohn.Forte@Sun.COM _sd_ccent_rd(_sd_cctl_t *cc_ent, uint_t wanted, struct buf *bp)
17637836SJohn.Forte@Sun.COM {
17647836SJohn.Forte@Sun.COM int index, offset = 0, size = 0;
17657836SJohn.Forte@Sun.COM int state, state1 = -3; /* state1 is previous state */
17667836SJohn.Forte@Sun.COM sd_addr_t *addr = NULL;
17677836SJohn.Forte@Sun.COM uint_t dirty;
17687836SJohn.Forte@Sun.COM
17697836SJohn.Forte@Sun.COM dirty = CENTRY_DIRTY(cc_ent);
17707836SJohn.Forte@Sun.COM for (index = 0; index < BLK_FBAS; index++) {
17717836SJohn.Forte@Sun.COM if (!_SD_BIT_ISSET(wanted, index))
17727836SJohn.Forte@Sun.COM continue;
17737836SJohn.Forte@Sun.COM state = _SD_BIT_ISSET(dirty, index);
17747836SJohn.Forte@Sun.COM if (state == state1) /* same state, expand size */
17757836SJohn.Forte@Sun.COM size++;
17767836SJohn.Forte@Sun.COM else {
17777836SJohn.Forte@Sun.COM if (state1 != -3) /* not first FBA */
17787836SJohn.Forte@Sun.COM sd_add_fba(bp, addr, offset, size);
17797836SJohn.Forte@Sun.COM state1 = state; /* new previous state */
17807836SJohn.Forte@Sun.COM offset = index;
17817836SJohn.Forte@Sun.COM size = 1;
17827836SJohn.Forte@Sun.COM if (state) { /* dirty, don't overwrite */
17837836SJohn.Forte@Sun.COM addr = NULL;
17847836SJohn.Forte@Sun.COM } else {
17857836SJohn.Forte@Sun.COM addr = &cc_ent->cc_addr;
17867836SJohn.Forte@Sun.COM }
17877836SJohn.Forte@Sun.COM }
17887836SJohn.Forte@Sun.COM }
17897836SJohn.Forte@Sun.COM if (state1 != -3)
17907836SJohn.Forte@Sun.COM sd_add_fba(bp, addr, offset, size);
17917836SJohn.Forte@Sun.COM }
17927836SJohn.Forte@Sun.COM
17937836SJohn.Forte@Sun.COM
17947836SJohn.Forte@Sun.COM
17957836SJohn.Forte@Sun.COM int _SD_WR_THRESHOLD = 1000;
17967836SJohn.Forte@Sun.COM static void
_sd_flush_thread(void)17977836SJohn.Forte@Sun.COM _sd_flush_thread(void)
17987836SJohn.Forte@Sun.COM {
17997836SJohn.Forte@Sun.COM int cd;
18007836SJohn.Forte@Sun.COM _sd_cd_info_t *cdi;
18017836SJohn.Forte@Sun.COM _sd_shared_t *shi;
18027836SJohn.Forte@Sun.COM int cnt;
18037836SJohn.Forte@Sun.COM int short_sleep = 0;
18047836SJohn.Forte@Sun.COM long tics;
18057836SJohn.Forte@Sun.COM int waiting_for_idle = 0;
18067836SJohn.Forte@Sun.COM int check_count = 0;
18077836SJohn.Forte@Sun.COM int pending, last_pending;
18087836SJohn.Forte@Sun.COM int SD_LONG_SLEEP_TICS, SD_SHORT_SLEEP_TICS;
18097836SJohn.Forte@Sun.COM nstset_t *tset = NULL;
18107836SJohn.Forte@Sun.COM nsthread_t *t;
18117836SJohn.Forte@Sun.COM
18127836SJohn.Forte@Sun.COM #if defined(_SD_USE_THREADS)
18137836SJohn.Forte@Sun.COM tset = _sd_ioset;
18147836SJohn.Forte@Sun.COM #endif /* _SD_USE_THREADS */
18157836SJohn.Forte@Sun.COM
18167836SJohn.Forte@Sun.COM mutex_enter(&_sd_cache_lock);
18177836SJohn.Forte@Sun.COM _sd_cache_dem_cnt++;
18187836SJohn.Forte@Sun.COM mutex_exit(&_sd_cache_lock);
18197836SJohn.Forte@Sun.COM
18207836SJohn.Forte@Sun.COM /* .2 seconds */
18217836SJohn.Forte@Sun.COM SD_LONG_SLEEP_TICS = drv_usectohz(200000);
18227836SJohn.Forte@Sun.COM /* .02 seconds */
18237836SJohn.Forte@Sun.COM SD_SHORT_SLEEP_TICS = drv_usectohz(20000);
18247836SJohn.Forte@Sun.COM
18257836SJohn.Forte@Sun.COM /* CONSTCOND */
18267836SJohn.Forte@Sun.COM while (1) {
18277836SJohn.Forte@Sun.COM if (_sd_flush_exit == 0) {
18287836SJohn.Forte@Sun.COM /*
18297836SJohn.Forte@Sun.COM * wait until no i/o's pending (on two successive
18307836SJohn.Forte@Sun.COM * iterations) or we see no progress after
18317836SJohn.Forte@Sun.COM * GIVE_UP_WAITING total sleeps.
18327836SJohn.Forte@Sun.COM */
18337836SJohn.Forte@Sun.COM /* at most 5*128 ticks about 6 seconds of no progress */
18347836SJohn.Forte@Sun.COM #define GIVE_UP_WAITING 128
18357836SJohn.Forte@Sun.COM if (waiting_for_idle) {
18367836SJohn.Forte@Sun.COM pending = _sd_pending_iobuf();
18377836SJohn.Forte@Sun.COM /*LINTED*/
18387836SJohn.Forte@Sun.COM if (pending == last_pending) {
18397836SJohn.Forte@Sun.COM if (pending != 0)
18407836SJohn.Forte@Sun.COM check_count++;
18417836SJohn.Forte@Sun.COM } else
18427836SJohn.Forte@Sun.COM check_count = 0;
18437836SJohn.Forte@Sun.COM if ((last_pending == 0 && (pending == 0)) ||
18447836SJohn.Forte@Sun.COM (check_count == GIVE_UP_WAITING)) {
18457836SJohn.Forte@Sun.COM mutex_enter(&_sd_cache_lock);
18467836SJohn.Forte@Sun.COM _sd_cache_dem_cnt--;
18477836SJohn.Forte@Sun.COM mutex_exit(&_sd_cache_lock);
18487836SJohn.Forte@Sun.COM if (check_count == GIVE_UP_WAITING)
18497836SJohn.Forte@Sun.COM cmn_err(CE_WARN,
18509093SRamana.Srikanth@Sun.COM "!_sd_flush_thread "
18517836SJohn.Forte@Sun.COM "exiting with %d IOs "
18527836SJohn.Forte@Sun.COM "pending", pending);
18537836SJohn.Forte@Sun.COM return;
18547836SJohn.Forte@Sun.COM }
18557836SJohn.Forte@Sun.COM last_pending = pending;
18567836SJohn.Forte@Sun.COM } else {
18577836SJohn.Forte@Sun.COM waiting_for_idle = 1;
18587836SJohn.Forte@Sun.COM last_pending = _sd_pending_iobuf();
18597836SJohn.Forte@Sun.COM }
18607836SJohn.Forte@Sun.COM }
18617836SJohn.Forte@Sun.COM
18627836SJohn.Forte@Sun.COM /*
18637836SJohn.Forte@Sun.COM * Normally wakeup every SD_LONG_SLEEP_TICS to flush.
18647836SJohn.Forte@Sun.COM */
18657836SJohn.Forte@Sun.COM
18667836SJohn.Forte@Sun.COM if (!short_sleep) {
18677836SJohn.Forte@Sun.COM ssioc_stats_t ss_stats;
18687836SJohn.Forte@Sun.COM int rc;
18697836SJohn.Forte@Sun.COM
18707836SJohn.Forte@Sun.COM if ((rc = SSOP_CTL(sdbc_safestore, SSIOC_STATS,
18719093SRamana.Srikanth@Sun.COM (uintptr_t)&ss_stats)) == 0) {
18727836SJohn.Forte@Sun.COM
18737836SJohn.Forte@Sun.COM if (ss_stats.wq_inq < _SD_WR_THRESHOLD)
18747836SJohn.Forte@Sun.COM short_sleep = 1;
18757836SJohn.Forte@Sun.COM } else {
18767836SJohn.Forte@Sun.COM if (rc == SS_ERR)
18777836SJohn.Forte@Sun.COM cmn_err(CE_WARN,
18789093SRamana.Srikanth@Sun.COM "!sdbc(_sd_flush_thread)"
18797836SJohn.Forte@Sun.COM "cannot get safestore inq");
18807836SJohn.Forte@Sun.COM }
18817836SJohn.Forte@Sun.COM }
18827836SJohn.Forte@Sun.COM
18837836SJohn.Forte@Sun.COM if (short_sleep)
18847836SJohn.Forte@Sun.COM tics = SD_SHORT_SLEEP_TICS;
18857836SJohn.Forte@Sun.COM else
18867836SJohn.Forte@Sun.COM tics = SD_LONG_SLEEP_TICS;
18877836SJohn.Forte@Sun.COM
18887836SJohn.Forte@Sun.COM _sd_timed_block(tics, &_sd_flush_cv);
18897836SJohn.Forte@Sun.COM cd = 0;
18907836SJohn.Forte@Sun.COM cnt = short_sleep = 0;
18917836SJohn.Forte@Sun.COM for (; (cnt < _sd_cache_stats->st_loc_count) &&
18929093SRamana.Srikanth@Sun.COM (cd < sdbc_max_devs); cd++) {
18937836SJohn.Forte@Sun.COM cdi = &_sd_cache_files[cd];
18947836SJohn.Forte@Sun.COM shi = cdi->cd_info;
18957836SJohn.Forte@Sun.COM
18967836SJohn.Forte@Sun.COM if (shi == NULL || (shi->sh_failed == 2))
18977836SJohn.Forte@Sun.COM continue;
18987836SJohn.Forte@Sun.COM
18997836SJohn.Forte@Sun.COM if (!(shi->sh_alloc & CD_ALLOCATED) ||
19007836SJohn.Forte@Sun.COM !(shi->sh_flag & CD_ATTACHED))
19017836SJohn.Forte@Sun.COM continue;
19027836SJohn.Forte@Sun.COM cnt++;
19037836SJohn.Forte@Sun.COM if (cdi->cd_writer)
19047836SJohn.Forte@Sun.COM continue;
19057836SJohn.Forte@Sun.COM if (!_SD_CD_WBLK_USED(cd)) {
19067836SJohn.Forte@Sun.COM if (cdi->cd_failover == 2) {
19077836SJohn.Forte@Sun.COM nsc_release(cdi->cd_rawfd);
19087836SJohn.Forte@Sun.COM cdi->cd_failover = 0;
19097836SJohn.Forte@Sun.COM }
19107836SJohn.Forte@Sun.COM continue;
19117836SJohn.Forte@Sun.COM }
19127836SJohn.Forte@Sun.COM if (cdi->cd_writer ||
19137836SJohn.Forte@Sun.COM xmem_bu(_SD_WRITER_CREATE, &cdi->cd_writer))
19147836SJohn.Forte@Sun.COM continue;
19157836SJohn.Forte@Sun.COM
19167836SJohn.Forte@Sun.COM t = NULL;
19177836SJohn.Forte@Sun.COM if (tset) {
19187836SJohn.Forte@Sun.COM t = nst_create(tset,
19197836SJohn.Forte@Sun.COM cd_write_thread, (blind_t)(unsigned long)cd,
19207836SJohn.Forte@Sun.COM 0);
19217836SJohn.Forte@Sun.COM }
19227836SJohn.Forte@Sun.COM if (!t)
19237836SJohn.Forte@Sun.COM cd_write_thread(cd);
19247836SJohn.Forte@Sun.COM }
19257836SJohn.Forte@Sun.COM }
19267836SJohn.Forte@Sun.COM }
19277836SJohn.Forte@Sun.COM
19287836SJohn.Forte@Sun.COM
19297836SJohn.Forte@Sun.COM #if defined(_SD_DEBUG_PATTERN)
check_write_consistency(cc_entry)19307836SJohn.Forte@Sun.COM check_write_consistency(cc_entry)
19317836SJohn.Forte@Sun.COM _sd_cctl_t *cc_entry;
19327836SJohn.Forte@Sun.COM {
19337836SJohn.Forte@Sun.COM int *data;
19347836SJohn.Forte@Sun.COM nsc_off_t fba_pos;
19357836SJohn.Forte@Sun.COM int i, dirty_bl;
19367836SJohn.Forte@Sun.COM
19377836SJohn.Forte@Sun.COM while (cc_entry) {
19387836SJohn.Forte@Sun.COM dirty_bl = CENTRY_DIRTY(cc_entry);
19397836SJohn.Forte@Sun.COM if (dirty_bl == 0) {
19409093SRamana.Srikanth@Sun.COM cmn_err(CE_WARN, "!check: no dirty");
19417836SJohn.Forte@Sun.COM }
19427836SJohn.Forte@Sun.COM data = (int *)cc_entry->cc_data;
19437836SJohn.Forte@Sun.COM fba_pos = BLK_TO_FBA_NUM(CENTRY_BLK(cc_entry));
19447836SJohn.Forte@Sun.COM
19457836SJohn.Forte@Sun.COM for (i = 0; i < 8; i++, data += 128, fba_pos++) {
19467836SJohn.Forte@Sun.COM if (dirty_bl & 1) {
19477836SJohn.Forte@Sun.COM if (*((int *)(data + 2)) != fba_pos) {
19489093SRamana.Srikanth@Sun.COM cmn_err(CE_WARN, "!wr exp %" NSC_SZFMT
19497836SJohn.Forte@Sun.COM " got %x", fba_pos, *(data + 2));
19507836SJohn.Forte@Sun.COM }
19517836SJohn.Forte@Sun.COM }
19527836SJohn.Forte@Sun.COM dirty_bl >>= 1;
19537836SJohn.Forte@Sun.COM }
19547836SJohn.Forte@Sun.COM cc_entry = cc_entry->cc_dirty_next;
19557836SJohn.Forte@Sun.COM }
19567836SJohn.Forte@Sun.COM }
19577836SJohn.Forte@Sun.COM
check_buf_consistency(handle,rw)19587836SJohn.Forte@Sun.COM check_buf_consistency(handle, rw)
19597836SJohn.Forte@Sun.COM _sd_buf_handle_t *handle;
19607836SJohn.Forte@Sun.COM char *rw;
19617836SJohn.Forte@Sun.COM {
19627836SJohn.Forte@Sun.COM _sd_bufvec_t *bvec1;
19637836SJohn.Forte@Sun.COM int *data;
19647836SJohn.Forte@Sun.COM nsc_off_t fpos;
19657836SJohn.Forte@Sun.COM nsc_size_t fba_len, i;
19667836SJohn.Forte@Sun.COM nsc_size_t len = 0;
19677836SJohn.Forte@Sun.COM
19687836SJohn.Forte@Sun.COM bvec1 = handle->bh_bufvec;
19697836SJohn.Forte@Sun.COM fpos = handle->bh_fba_pos;
19707836SJohn.Forte@Sun.COM
19717836SJohn.Forte@Sun.COM while (bvec1->bufaddr) {
19727836SJohn.Forte@Sun.COM fba_len = FBA_NUM(bvec1->buflen);
19737836SJohn.Forte@Sun.COM data = (int *)bvec1->bufaddr;
19747836SJohn.Forte@Sun.COM for (i = 0; i < fba_len; i++, data += 128, fpos++) {
19757836SJohn.Forte@Sun.COM len++;
19767836SJohn.Forte@Sun.COM if (*(data+2) != fpos) {
19779093SRamana.Srikanth@Sun.COM cmn_err(CE_WARN, "!%s exp%" NSC_SZFMT " got%x",
19789093SRamana.Srikanth@Sun.COM rw, fpos, *(data + 2));
19797836SJohn.Forte@Sun.COM }
19807836SJohn.Forte@Sun.COM }
19817836SJohn.Forte@Sun.COM bvec1++;
19827836SJohn.Forte@Sun.COM }
19837836SJohn.Forte@Sun.COM if (handle->bh_fba_len != len) {
19849093SRamana.Srikanth@Sun.COM cmn_err(CE_WARN, "!len %" NSC_SZFMT " real %" NSC_SZFMT, len,
19857836SJohn.Forte@Sun.COM handle->bh_fba_len);
19867836SJohn.Forte@Sun.COM }
19877836SJohn.Forte@Sun.COM }
19887836SJohn.Forte@Sun.COM #endif
19897836SJohn.Forte@Sun.COM
19907836SJohn.Forte@Sun.COM int
_sdbc_wait_pending(void)19917836SJohn.Forte@Sun.COM _sdbc_wait_pending(void)
19927836SJohn.Forte@Sun.COM {
19937836SJohn.Forte@Sun.COM int tries, pend, last;
19947836SJohn.Forte@Sun.COM
19957836SJohn.Forte@Sun.COM tries = 0;
19967836SJohn.Forte@Sun.COM last = _sd_pending_iobuf();
19977836SJohn.Forte@Sun.COM while ((pend = _sd_pending_iobuf()) > 0) {
19987836SJohn.Forte@Sun.COM if (pend == last) {
19997836SJohn.Forte@Sun.COM if (++tries > 60) {
20007836SJohn.Forte@Sun.COM return (pend);
20017836SJohn.Forte@Sun.COM }
20027836SJohn.Forte@Sun.COM } else {
20037836SJohn.Forte@Sun.COM pend = last;
20047836SJohn.Forte@Sun.COM tries = 0;
20057836SJohn.Forte@Sun.COM }
20067836SJohn.Forte@Sun.COM delay(HZ);
20077836SJohn.Forte@Sun.COM }
20087836SJohn.Forte@Sun.COM return (0);
20097836SJohn.Forte@Sun.COM }
2010