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 /*
22*9093SRamana.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/errno.h>
307836SJohn.Forte@Sun.COM #include <sys/kmem.h>
317836SJohn.Forte@Sun.COM #include <sys/cred.h>
327836SJohn.Forte@Sun.COM #include <sys/buf.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_ft.h"
457836SJohn.Forte@Sun.COM #include "sd_misc.h"
467836SJohn.Forte@Sun.COM #include "sd_pcu.h"
477836SJohn.Forte@Sun.COM
487836SJohn.Forte@Sun.COM #include <sys/unistat/spcs_s.h>
497836SJohn.Forte@Sun.COM #include <sys/unistat/spcs_s_k.h>
507836SJohn.Forte@Sun.COM #include <sys/unistat/spcs_errors.h>
517836SJohn.Forte@Sun.COM #include <sys/nsctl/safestore.h>
527836SJohn.Forte@Sun.COM #ifndef DS_DDICT
537836SJohn.Forte@Sun.COM #include <sys/ddi_impldefs.h>
547836SJohn.Forte@Sun.COM #endif
557836SJohn.Forte@Sun.COM
567836SJohn.Forte@Sun.COM
577836SJohn.Forte@Sun.COM /*
587836SJohn.Forte@Sun.COM * kstat interface
597836SJohn.Forte@Sun.COM */
607836SJohn.Forte@Sun.COM
617836SJohn.Forte@Sun.COM static kstat_t *sdbc_global_stats_kstat;
627836SJohn.Forte@Sun.COM static int sdbc_global_stats_update(kstat_t *ksp, int rw);
637836SJohn.Forte@Sun.COM
647836SJohn.Forte@Sun.COM typedef struct {
657836SJohn.Forte@Sun.COM kstat_named_t ci_sdbc_count;
667836SJohn.Forte@Sun.COM kstat_named_t ci_sdbc_loc_count;
677836SJohn.Forte@Sun.COM kstat_named_t ci_sdbc_rdhits;
687836SJohn.Forte@Sun.COM kstat_named_t ci_sdbc_rdmiss;
697836SJohn.Forte@Sun.COM kstat_named_t ci_sdbc_wrhits;
707836SJohn.Forte@Sun.COM kstat_named_t ci_sdbc_wrmiss;
717836SJohn.Forte@Sun.COM kstat_named_t ci_sdbc_blksize;
727836SJohn.Forte@Sun.COM kstat_named_t ci_sdbc_lru_blocks;
737836SJohn.Forte@Sun.COM #ifdef DEBUG
747836SJohn.Forte@Sun.COM kstat_named_t ci_sdbc_lru_noreq;
757836SJohn.Forte@Sun.COM kstat_named_t ci_sdbc_lru_req;
767836SJohn.Forte@Sun.COM #endif
777836SJohn.Forte@Sun.COM kstat_named_t ci_sdbc_wlru_inq;
787836SJohn.Forte@Sun.COM kstat_named_t ci_sdbc_cachesize;
797836SJohn.Forte@Sun.COM kstat_named_t ci_sdbc_numblocks;
807836SJohn.Forte@Sun.COM kstat_named_t ci_sdbc_num_shared;
817836SJohn.Forte@Sun.COM kstat_named_t ci_sdbc_wrcancelns;
827836SJohn.Forte@Sun.COM kstat_named_t ci_sdbc_destaged;
837836SJohn.Forte@Sun.COM kstat_named_t ci_sdbc_nodehints;
847836SJohn.Forte@Sun.COM } sdbc_global_stats_t;
857836SJohn.Forte@Sun.COM
867836SJohn.Forte@Sun.COM static sdbc_global_stats_t sdbc_global_stats = {
877836SJohn.Forte@Sun.COM {SDBC_GKSTAT_COUNT, KSTAT_DATA_ULONG},
887836SJohn.Forte@Sun.COM {SDBC_GKSTAT_LOC_COUNT, KSTAT_DATA_ULONG},
897836SJohn.Forte@Sun.COM {SDBC_GKSTAT_RDHITS, KSTAT_DATA_ULONG},
907836SJohn.Forte@Sun.COM {SDBC_GKSTAT_RDMISS, KSTAT_DATA_ULONG},
917836SJohn.Forte@Sun.COM {SDBC_GKSTAT_WRHITS, KSTAT_DATA_ULONG},
927836SJohn.Forte@Sun.COM {SDBC_GKSTAT_WRMISS, KSTAT_DATA_ULONG},
937836SJohn.Forte@Sun.COM {SDBC_GKSTAT_BLKSIZE, KSTAT_DATA_ULONG},
947836SJohn.Forte@Sun.COM {SDBC_GKSTAT_LRU_BLOCKS, KSTAT_DATA_ULONG},
957836SJohn.Forte@Sun.COM #ifdef DEBUG
967836SJohn.Forte@Sun.COM {SDBC_GKSTAT_LRU_NOREQ, KSTAT_DATA_ULONG},
977836SJohn.Forte@Sun.COM {SDBC_GKSTAT_LRU_REQ, KSTAT_DATA_ULONG},
987836SJohn.Forte@Sun.COM #endif
997836SJohn.Forte@Sun.COM {SDBC_GKSTAT_WLRU_INQ, KSTAT_DATA_ULONG},
1007836SJohn.Forte@Sun.COM {SDBC_GKSTAT_CACHESIZE, KSTAT_DATA_ULONG},
1017836SJohn.Forte@Sun.COM {SDBC_GKSTAT_NUMBLOCKS, KSTAT_DATA_ULONG},
1027836SJohn.Forte@Sun.COM {SDBC_GKSTAT_NUM_SHARED, KSTAT_DATA_ULONG},
1037836SJohn.Forte@Sun.COM {SDBC_GKSTAT_WRCANCELNS, KSTAT_DATA_ULONG},
1047836SJohn.Forte@Sun.COM {SDBC_GKSTAT_DESTAGED, KSTAT_DATA_ULONG},
1057836SJohn.Forte@Sun.COM {SDBC_GKSTAT_NODEHINTS, KSTAT_DATA_ULONG},
1067836SJohn.Forte@Sun.COM };
1077836SJohn.Forte@Sun.COM
1087836SJohn.Forte@Sun.COM static kstat_t **sdbc_cd_kstats;
1097836SJohn.Forte@Sun.COM static kstat_t **sdbc_cd_io_kstats;
1107836SJohn.Forte@Sun.COM static kmutex_t *sdbc_cd_io_kstats_mutexes;
1117836SJohn.Forte@Sun.COM static kstat_t *sdbc_global_io_kstat;
1127836SJohn.Forte@Sun.COM static kmutex_t sdbc_global_io_kstat_mutex;
1137836SJohn.Forte@Sun.COM static int sdbc_cd_stats_update(kstat_t *ksp, int rw);
1147836SJohn.Forte@Sun.COM static int cd_kstat_add(int cd);
1157836SJohn.Forte@Sun.COM static int cd_kstat_remove(int cd);
1167836SJohn.Forte@Sun.COM
1177836SJohn.Forte@Sun.COM typedef struct {
1187836SJohn.Forte@Sun.COM kstat_named_t ci_sdbc_vol_name;
1197836SJohn.Forte@Sun.COM kstat_named_t ci_sdbc_failed;
1207836SJohn.Forte@Sun.COM kstat_named_t ci_sdbc_cd;
1217836SJohn.Forte@Sun.COM kstat_named_t ci_sdbc_cache_read;
1227836SJohn.Forte@Sun.COM kstat_named_t ci_sdbc_cache_write;
1237836SJohn.Forte@Sun.COM kstat_named_t ci_sdbc_disk_read;
1247836SJohn.Forte@Sun.COM kstat_named_t ci_sdbc_disk_write;
1257836SJohn.Forte@Sun.COM kstat_named_t ci_sdbc_filesize;
1267836SJohn.Forte@Sun.COM kstat_named_t ci_sdbc_numdirty;
1277836SJohn.Forte@Sun.COM kstat_named_t ci_sdbc_numio;
1287836SJohn.Forte@Sun.COM kstat_named_t ci_sdbc_numfail;
1297836SJohn.Forte@Sun.COM kstat_named_t ci_sdbc_destaged;
1307836SJohn.Forte@Sun.COM kstat_named_t ci_sdbc_wrcancelns;
1317836SJohn.Forte@Sun.COM kstat_named_t ci_sdbc_cdhints;
1327836SJohn.Forte@Sun.COM } sdbc_cd_stats_t;
1337836SJohn.Forte@Sun.COM
1347836SJohn.Forte@Sun.COM static sdbc_cd_stats_t sdbc_cd_stats = {
1357836SJohn.Forte@Sun.COM {SDBC_CDKSTAT_VOL_NAME, KSTAT_DATA_CHAR},
1367836SJohn.Forte@Sun.COM {SDBC_CDKSTAT_FAILED, KSTAT_DATA_ULONG},
1377836SJohn.Forte@Sun.COM {SDBC_CDKSTAT_CD, KSTAT_DATA_ULONG},
1387836SJohn.Forte@Sun.COM {SDBC_CDKSTAT_CACHE_READ, KSTAT_DATA_ULONG},
1397836SJohn.Forte@Sun.COM {SDBC_CDKSTAT_CACHE_WRITE, KSTAT_DATA_ULONG},
1407836SJohn.Forte@Sun.COM {SDBC_CDKSTAT_DISK_READ, KSTAT_DATA_ULONG},
1417836SJohn.Forte@Sun.COM {SDBC_CDKSTAT_DISK_WRITE, KSTAT_DATA_ULONG},
1427836SJohn.Forte@Sun.COM #ifdef NSC_MULTI_TERABYTE
1437836SJohn.Forte@Sun.COM {SDBC_CDKSTAT_FILESIZE, KSTAT_DATA_UINT64},
1447836SJohn.Forte@Sun.COM #else
1457836SJohn.Forte@Sun.COM {SDBC_CDKSTAT_FILESIZE, KSTAT_DATA_ULONG},
1467836SJohn.Forte@Sun.COM #endif
1477836SJohn.Forte@Sun.COM {SDBC_CDKSTAT_NUMDIRTY, KSTAT_DATA_ULONG},
1487836SJohn.Forte@Sun.COM {SDBC_CDKSTAT_NUMIO, KSTAT_DATA_ULONG},
1497836SJohn.Forte@Sun.COM {SDBC_CDKSTAT_NUMFAIL, KSTAT_DATA_ULONG},
1507836SJohn.Forte@Sun.COM {SDBC_CDKSTAT_DESTAGED, KSTAT_DATA_ULONG},
1517836SJohn.Forte@Sun.COM {SDBC_CDKSTAT_WRCANCELNS, KSTAT_DATA_ULONG},
1527836SJohn.Forte@Sun.COM {SDBC_CDKSTAT_CDHINTS, KSTAT_DATA_ULONG},
1537836SJohn.Forte@Sun.COM };
1547836SJohn.Forte@Sun.COM
1557836SJohn.Forte@Sun.COM #ifdef DEBUG
1567836SJohn.Forte@Sun.COM /*
1577836SJohn.Forte@Sun.COM * dynmem kstat interface
1587836SJohn.Forte@Sun.COM */
1597836SJohn.Forte@Sun.COM static kstat_t *sdbc_dynmem_kstat_dm;
1607836SJohn.Forte@Sun.COM static int simplect_dm;
1617836SJohn.Forte@Sun.COM static int sdbc_dynmem_kstat_update_dm(kstat_t *ksp, int rw);
1627836SJohn.Forte@Sun.COM
1637836SJohn.Forte@Sun.COM typedef struct {
1647836SJohn.Forte@Sun.COM kstat_named_t ci_sdbc_monitor_dynmem;
1657836SJohn.Forte@Sun.COM kstat_named_t ci_sdbc_max_dyn_list;
1667836SJohn.Forte@Sun.COM kstat_named_t ci_sdbc_cache_aging_ct1;
1677836SJohn.Forte@Sun.COM kstat_named_t ci_sdbc_cache_aging_ct2;
1687836SJohn.Forte@Sun.COM kstat_named_t ci_sdbc_cache_aging_ct3;
1697836SJohn.Forte@Sun.COM kstat_named_t ci_sdbc_cache_aging_sec1;
1707836SJohn.Forte@Sun.COM kstat_named_t ci_sdbc_cache_aging_sec2;
1717836SJohn.Forte@Sun.COM kstat_named_t ci_sdbc_cache_aging_sec3;
1727836SJohn.Forte@Sun.COM kstat_named_t ci_sdbc_cache_aging_pcnt1;
1737836SJohn.Forte@Sun.COM kstat_named_t ci_sdbc_cache_aging_pcnt2;
1747836SJohn.Forte@Sun.COM kstat_named_t ci_sdbc_max_holds_pcnt;
1757836SJohn.Forte@Sun.COM
1767836SJohn.Forte@Sun.COM kstat_named_t ci_sdbc_alloc_ct;
1777836SJohn.Forte@Sun.COM kstat_named_t ci_sdbc_dealloc_ct;
1787836SJohn.Forte@Sun.COM kstat_named_t ci_sdbc_history;
1797836SJohn.Forte@Sun.COM kstat_named_t ci_sdbc_nodatas;
1807836SJohn.Forte@Sun.COM kstat_named_t ci_sdbc_candidates;
1817836SJohn.Forte@Sun.COM kstat_named_t ci_sdbc_deallocs;
1827836SJohn.Forte@Sun.COM kstat_named_t ci_sdbc_hosts;
1837836SJohn.Forte@Sun.COM kstat_named_t ci_sdbc_pests;
1847836SJohn.Forte@Sun.COM kstat_named_t ci_sdbc_metas;
1857836SJohn.Forte@Sun.COM kstat_named_t ci_sdbc_holds;
1867836SJohn.Forte@Sun.COM kstat_named_t ci_sdbc_others;
1877836SJohn.Forte@Sun.COM kstat_named_t ci_sdbc_notavail;
1887836SJohn.Forte@Sun.COM
1897836SJohn.Forte@Sun.COM kstat_named_t ci_sdbc_process_directive;
1907836SJohn.Forte@Sun.COM
1917836SJohn.Forte@Sun.COM kstat_named_t ci_sdbc_simplect;
1927836SJohn.Forte@Sun.COM } sdbc_dynmem_dm_t;
1937836SJohn.Forte@Sun.COM
1947836SJohn.Forte@Sun.COM static sdbc_dynmem_dm_t sdbc_dynmem_dm = {
1957836SJohn.Forte@Sun.COM {SDBC_DMKSTAT_MONITOR_DYNMEM, KSTAT_DATA_ULONG},
1967836SJohn.Forte@Sun.COM {SDBC_DMKSTAT_MAX_DYN_LIST, KSTAT_DATA_ULONG},
1977836SJohn.Forte@Sun.COM {SDBC_DMKSTAT_CACHE_AGING_CT1, KSTAT_DATA_ULONG},
1987836SJohn.Forte@Sun.COM {SDBC_DMKSTAT_CACHE_AGING_CT2, KSTAT_DATA_ULONG},
1997836SJohn.Forte@Sun.COM {SDBC_DMKSTAT_CACHE_AGING_CT3, KSTAT_DATA_ULONG},
2007836SJohn.Forte@Sun.COM {SDBC_DMKSTAT_CACHE_AGING_SEC1, KSTAT_DATA_ULONG},
2017836SJohn.Forte@Sun.COM {SDBC_DMKSTAT_CACHE_AGING_SEC2, KSTAT_DATA_ULONG},
2027836SJohn.Forte@Sun.COM {SDBC_DMKSTAT_CACHE_AGING_SEC3, KSTAT_DATA_ULONG},
2037836SJohn.Forte@Sun.COM {SDBC_DMKSTAT_CACHE_AGING_PCNT1, KSTAT_DATA_ULONG},
2047836SJohn.Forte@Sun.COM {SDBC_DMKSTAT_CACHE_AGING_PCNT2, KSTAT_DATA_ULONG},
2057836SJohn.Forte@Sun.COM {SDBC_DMKSTAT_MAX_HOLDS_PCNT, KSTAT_DATA_ULONG},
2067836SJohn.Forte@Sun.COM {SDBC_DMKSTAT_ALLOC_CNT, KSTAT_DATA_ULONG},
2077836SJohn.Forte@Sun.COM {SDBC_DMKSTAT_DEALLOC_CNT, KSTAT_DATA_ULONG},
2087836SJohn.Forte@Sun.COM {SDBC_DMKSTAT_HISTORY, KSTAT_DATA_ULONG},
2097836SJohn.Forte@Sun.COM {SDBC_DMKSTAT_NODATAS, KSTAT_DATA_ULONG},
2107836SJohn.Forte@Sun.COM {SDBC_DMKSTAT_CANDIDATES, KSTAT_DATA_ULONG},
2117836SJohn.Forte@Sun.COM {SDBC_DMKSTAT_DEALLOCS, KSTAT_DATA_ULONG},
2127836SJohn.Forte@Sun.COM {SDBC_DMKSTAT_HOSTS, KSTAT_DATA_ULONG},
2137836SJohn.Forte@Sun.COM {SDBC_DMKSTAT_PESTS, KSTAT_DATA_ULONG},
2147836SJohn.Forte@Sun.COM {SDBC_DMKSTAT_METAS, KSTAT_DATA_ULONG},
2157836SJohn.Forte@Sun.COM {SDBC_DMKSTAT_HOLDS, KSTAT_DATA_ULONG},
2167836SJohn.Forte@Sun.COM {SDBC_DMKSTAT_OTHERS, KSTAT_DATA_ULONG},
2177836SJohn.Forte@Sun.COM {SDBC_DMKSTAT_NOTAVAIL, KSTAT_DATA_ULONG},
2187836SJohn.Forte@Sun.COM {SDBC_DMKSTAT_PROCESS_DIRECTIVE, KSTAT_DATA_ULONG},
2197836SJohn.Forte@Sun.COM {SDBC_DMKSTAT_SIMPLECT, KSTAT_DATA_ULONG}
2207836SJohn.Forte@Sun.COM };
2217836SJohn.Forte@Sun.COM #endif
2227836SJohn.Forte@Sun.COM
2237836SJohn.Forte@Sun.COM /* End of dynmem kstats */
2247836SJohn.Forte@Sun.COM
2257836SJohn.Forte@Sun.COM #ifdef DEBUG
2267836SJohn.Forte@Sun.COM int *dmchainpull_table; /* dmchain wastage stats */
2277836SJohn.Forte@Sun.COM #endif
2287836SJohn.Forte@Sun.COM
2297836SJohn.Forte@Sun.COM /*
2307836SJohn.Forte@Sun.COM * dynmem process vars
2317836SJohn.Forte@Sun.COM */
2327836SJohn.Forte@Sun.COM extern _dm_process_vars_t dynmem_processing_dm;
2337836SJohn.Forte@Sun.COM
2347836SJohn.Forte@Sun.COM /* metadata for volumes */
2357836SJohn.Forte@Sun.COM ss_voldata_t *_sdbc_gl_file_info;
2367836SJohn.Forte@Sun.COM
2377836SJohn.Forte@Sun.COM size_t _sdbc_gl_file_info_size;
2387836SJohn.Forte@Sun.COM
2397836SJohn.Forte@Sun.COM /* metadata for cache write blocks */
2407836SJohn.Forte@Sun.COM static ss_centry_info_t *_sdbc_gl_centry_info;
2417836SJohn.Forte@Sun.COM
2427836SJohn.Forte@Sun.COM /* wblocks * sizeof(ss_centry_info_t) */
2437836SJohn.Forte@Sun.COM static size_t _sdbc_gl_centry_info_size;
2447836SJohn.Forte@Sun.COM
2457836SJohn.Forte@Sun.COM static int _SD_DELAY_QUEUE = 1;
2467836SJohn.Forte@Sun.COM static int sdbc_allocb_inuse, sdbc_allocb_lost, sdbc_allocb_hit;
2477836SJohn.Forte@Sun.COM static int sdbc_allocb_pageio1, sdbc_allocb_pageio2;
2487836SJohn.Forte@Sun.COM static int sdbc_centry_hit, sdbc_centry_inuse, sdbc_centry_lost;
2497836SJohn.Forte@Sun.COM static int sdbc_dmchain_not_avail;
2507836SJohn.Forte@Sun.COM static int sdbc_allocb_deallocd;
2517836SJohn.Forte@Sun.COM static int sdbc_centry_deallocd;
2527836SJohn.Forte@Sun.COM static int sdbc_check_cot;
2537836SJohn.Forte@Sun.COM static int sdbc_ra_hash; /* 1-block read-ahead fails due to hash hit */
2547836SJohn.Forte@Sun.COM static int sdbc_ra_none; /* 1-block read-ahead fails due to "would block" */
2557836SJohn.Forte@Sun.COM
2567836SJohn.Forte@Sun.COM
2577836SJohn.Forte@Sun.COM /*
2587836SJohn.Forte@Sun.COM * Set the following variable to 1 to enable pagelist io mutual
2597836SJohn.Forte@Sun.COM * exclusion on all _sd_alloc_buf() operations.
2607836SJohn.Forte@Sun.COM *
2617836SJohn.Forte@Sun.COM * This is set to ON to prevent front end / back end races between new
2627836SJohn.Forte@Sun.COM * NSC_WRTHRU io operations coming in through _sd_alloc_buf(), and
2637836SJohn.Forte@Sun.COM * previously written data being flushed out to disk by the sdbc
2647836SJohn.Forte@Sun.COM * flusher at the back end.
2657836SJohn.Forte@Sun.COM * -- see bugtraq 4287564
2667836SJohn.Forte@Sun.COM * -- Simon Crosland, Mon Nov 8 16:34:09 GMT 1999
2677836SJohn.Forte@Sun.COM */
2687836SJohn.Forte@Sun.COM static int sdbc_pageio_always = 1;
2697836SJohn.Forte@Sun.COM
2707836SJohn.Forte@Sun.COM int sdbc_use_dmchain = 0; /* start time switch for dm chaining */
2717836SJohn.Forte@Sun.COM int sdbc_prefetch1 = 1; /* do 1-block read-ahead */
2727836SJohn.Forte@Sun.COM /*
2737836SJohn.Forte@Sun.COM * if sdbc_static_cache is 1 allocate all cache memory at startup.
2747836SJohn.Forte@Sun.COM * deallocate only at shutdown.
2757836SJohn.Forte@Sun.COM */
2767836SJohn.Forte@Sun.COM int sdbc_static_cache = 1;
2777836SJohn.Forte@Sun.COM
2787836SJohn.Forte@Sun.COM #ifdef DEBUG
2797836SJohn.Forte@Sun.COM /*
2807836SJohn.Forte@Sun.COM * Pagelist io mutual exclusion debug facility.
2817836SJohn.Forte@Sun.COM */
2827836SJohn.Forte@Sun.COM #define SDBC_PAGEIO_OFF 0 /* no debug */
2837836SJohn.Forte@Sun.COM #define SDBC_PAGEIO_RDEV 1 /* force NSC_PAGEIO for specified dev */
2847836SJohn.Forte@Sun.COM #define SDBC_PAGEIO_RAND 2 /* randomly force NSC_PAGEIO */
2857836SJohn.Forte@Sun.COM #define SDBC_PAGEIO_ALL 3 /* always force NSC_PAGEIO */
2867836SJohn.Forte@Sun.COM static int sdbc_pageio_debug = SDBC_PAGEIO_OFF;
2877836SJohn.Forte@Sun.COM static dev_t sdbc_pageio_rdev = (dev_t)-1;
2887836SJohn.Forte@Sun.COM #endif
2897836SJohn.Forte@Sun.COM
2907836SJohn.Forte@Sun.COM /*
2917836SJohn.Forte@Sun.COM * INF SD cache global data
2927836SJohn.Forte@Sun.COM */
2937836SJohn.Forte@Sun.COM
2947836SJohn.Forte@Sun.COM _sd_cd_info_t *_sd_cache_files;
2957836SJohn.Forte@Sun.COM _sd_stats_t *_sd_cache_stats;
2967836SJohn.Forte@Sun.COM kmutex_t _sd_cache_lock;
2977836SJohn.Forte@Sun.COM
2987836SJohn.Forte@Sun.COM _sd_hash_table_t *_sd_htable;
2997836SJohn.Forte@Sun.COM _sd_queue_t _sd_lru_q;
3007836SJohn.Forte@Sun.COM
3017836SJohn.Forte@Sun.COM _sd_cctl_t *_sd_cctl[_SD_CCTL_GROUPS];
3027836SJohn.Forte@Sun.COM int _sd_cctl_groupsz;
3037836SJohn.Forte@Sun.COM
3047836SJohn.Forte@Sun.COM _sd_net_t _sd_net_config;
3057836SJohn.Forte@Sun.COM
3067836SJohn.Forte@Sun.COM extern krwlock_t sdbc_queue_lock;
3077836SJohn.Forte@Sun.COM
3087836SJohn.Forte@Sun.COM unsigned int _sd_node_hint;
3097836SJohn.Forte@Sun.COM
3107836SJohn.Forte@Sun.COM #define _SD_LRU_Q (&_sd_lru_q)
3117836SJohn.Forte@Sun.COM int BLK_FBAS; /* number of FBA's in a cache block */
3127836SJohn.Forte@Sun.COM int CACHE_BLOCK_SIZE; /* size in bytes of a cache block */
3137836SJohn.Forte@Sun.COM int CBLOCKS;
3147836SJohn.Forte@Sun.COM _sd_bitmap_t BLK_FBA_BITS;
3157836SJohn.Forte@Sun.COM static int sdbc_prefetch_valid_cnt;
3167836SJohn.Forte@Sun.COM static int sdbc_prefetch_busy_cnt;
3177836SJohn.Forte@Sun.COM static int sdbc_prefetch_trailing;
3187836SJohn.Forte@Sun.COM static int sdbc_prefetch_deallocd;
3197836SJohn.Forte@Sun.COM static int sdbc_prefetch_pageio1;
3207836SJohn.Forte@Sun.COM static int sdbc_prefetch_pageio2;
3217836SJohn.Forte@Sun.COM static int sdbc_prefetch_hit;
3227836SJohn.Forte@Sun.COM static int sdbc_prefetch_lost;
3237836SJohn.Forte@Sun.COM static int _sd_prefetch_opt = 1; /* 0 to disable & use _prefetch_sb_vec[] */
3247836SJohn.Forte@Sun.COM static nsc_vec_t _prefetch_sb_vec[_SD_MAX_BLKS + 1];
3257836SJohn.Forte@Sun.COM
3267836SJohn.Forte@Sun.COM _sd_bitmap_t _fba_bits[] = {
3277836SJohn.Forte@Sun.COM 0x0000, 0x0001, 0x0003, 0x0007,
3287836SJohn.Forte@Sun.COM 0x000f, 0x001f, 0x003f, 0x007f,
3297836SJohn.Forte@Sun.COM 0x00ff,
3307836SJohn.Forte@Sun.COM #if defined(_SD_8K_BLKSIZE)
3317836SJohn.Forte@Sun.COM 0x01ff, 0x03ff, 0x07ff,
3327836SJohn.Forte@Sun.COM 0x0fff, 0x1fff, 0x3fff, 0x7fff,
3337836SJohn.Forte@Sun.COM 0xffff,
3347836SJohn.Forte@Sun.COM #endif
3357836SJohn.Forte@Sun.COM };
3367836SJohn.Forte@Sun.COM
3377836SJohn.Forte@Sun.COM
3387836SJohn.Forte@Sun.COM static int _sd_ccsync_cnt = 256;
3397836SJohn.Forte@Sun.COM static _sd_cctl_sync_t *_sd_ccent_sync;
3407836SJohn.Forte@Sun.COM
3417836SJohn.Forte@Sun.COM nsc_io_t *sdbc_io;
3427836SJohn.Forte@Sun.COM
3437836SJohn.Forte@Sun.COM #ifdef _MULTI_DATAMODEL
3447836SJohn.Forte@Sun.COM _sd_stats32_t *_sd_cache_stats32 = NULL;
3457836SJohn.Forte@Sun.COM #endif
3467836SJohn.Forte@Sun.COM
3477836SJohn.Forte@Sun.COM
3487836SJohn.Forte@Sun.COM #ifdef DEBUG
3497836SJohn.Forte@Sun.COM int cmn_level = CE_PANIC;
3507836SJohn.Forte@Sun.COM #else
3517836SJohn.Forte@Sun.COM int cmn_level = CE_WARN;
3527836SJohn.Forte@Sun.COM #endif
3537836SJohn.Forte@Sun.COM
3547836SJohn.Forte@Sun.COM /*
3557836SJohn.Forte@Sun.COM * Forward declare all statics that are used before defined to enforce
3567836SJohn.Forte@Sun.COM * parameter checking
3577836SJohn.Forte@Sun.COM * Some (if not all) of these could be removed if the code were reordered
3587836SJohn.Forte@Sun.COM */
3597836SJohn.Forte@Sun.COM
3607836SJohn.Forte@Sun.COM static void _sdbc_stats_deconfigure(void);
3617836SJohn.Forte@Sun.COM static int _sdbc_stats_configure(int cblocks);
3627836SJohn.Forte@Sun.COM static int _sdbc_lruq_configure(_sd_queue_t *);
3637836SJohn.Forte@Sun.COM static void _sdbc_lruq_deconfigure(void);
3647836SJohn.Forte@Sun.COM static int _sdbc_mem_configure(int cblocks, spcs_s_info_t kstatus);
3657836SJohn.Forte@Sun.COM static void _sdbc_mem_deconfigure(int cblocks);
3667836SJohn.Forte@Sun.COM static void _sd_ins_queue(_sd_queue_t *, _sd_cctl_t *centry);
3677836SJohn.Forte@Sun.COM static int _sd_flush_cd(int cd);
3687836SJohn.Forte@Sun.COM static int _sd_check_buffer_alloc(int cd, nsc_off_t fba_pos, nsc_size_t fba_len,
3697836SJohn.Forte@Sun.COM _sd_buf_handle_t **hp);
3707836SJohn.Forte@Sun.COM static int _sd_doread(_sd_buf_handle_t *handle, _sd_cctl_t *cc_ent,
3717836SJohn.Forte@Sun.COM nsc_off_t fba_pos, nsc_size_t fba_len, int flag);
3727836SJohn.Forte@Sun.COM static void _sd_async_read_ea(blind_t xhandle, nsc_off_t fba_pos,
3737836SJohn.Forte@Sun.COM nsc_size_t fba_len, int error);
3747836SJohn.Forte@Sun.COM static void _sd_async_write_ea(blind_t xhandle, nsc_off_t fba_pos,
3757836SJohn.Forte@Sun.COM nsc_size_t fba_len, int error);
3767836SJohn.Forte@Sun.COM static void _sd_queue_write(_sd_buf_handle_t *handle, nsc_off_t fba_pos,
3777836SJohn.Forte@Sun.COM nsc_size_t fba_len);
3787836SJohn.Forte@Sun.COM static int _sd_remote_store(_sd_cctl_t *cc_ent, nsc_off_t fba_pos,
3797836SJohn.Forte@Sun.COM nsc_size_t fba_len);
3807836SJohn.Forte@Sun.COM static int _sd_copy_direct(_sd_buf_handle_t *handle1, _sd_buf_handle_t *handle2,
3817836SJohn.Forte@Sun.COM nsc_off_t fba_pos1, nsc_off_t fba_pos2, nsc_size_t fba_len);
3827836SJohn.Forte@Sun.COM static int _sd_sync_write(_sd_buf_handle_t *handle, nsc_off_t fba_pos,
3837836SJohn.Forte@Sun.COM nsc_size_t fba_len, int flag);
3847836SJohn.Forte@Sun.COM static int _sd_sync_write2(_sd_buf_handle_t *wr_handle, nsc_off_t wr_st_pos,
3857836SJohn.Forte@Sun.COM nsc_size_t fba_len, int flag, _sd_buf_handle_t *rd_handle,
3867836SJohn.Forte@Sun.COM nsc_off_t rd_st_pos);
3877836SJohn.Forte@Sun.COM static int sdbc_fd_attach_cd(blind_t xcd);
3887836SJohn.Forte@Sun.COM static int sdbc_fd_detach_cd(blind_t xcd);
3897836SJohn.Forte@Sun.COM static int sdbc_fd_flush_cd(blind_t xcd);
3907836SJohn.Forte@Sun.COM static int _sdbc_gl_centry_configure(spcs_s_info_t);
3917836SJohn.Forte@Sun.COM static int _sdbc_gl_file_configure(spcs_s_info_t);
3927836SJohn.Forte@Sun.COM static void _sdbc_gl_centry_deconfigure(void);
3937836SJohn.Forte@Sun.COM static void _sdbc_gl_file_deconfigure(void);
3947836SJohn.Forte@Sun.COM static int sdbc_doread_prefetch(_sd_cctl_t *cc_ent, nsc_off_t fba_pos,
3957836SJohn.Forte@Sun.COM nsc_size_t fba_len);
3967836SJohn.Forte@Sun.COM static _sd_bitmap_t update_dirty(_sd_cctl_t *cc_ent, sdbc_cblk_fba_t st_off,
3977836SJohn.Forte@Sun.COM sdbc_cblk_fba_t st_len);
3987836SJohn.Forte@Sun.COM static int _sd_prefetch_buf(int cd, nsc_off_t fba_pos, nsc_size_t fba_len,
3997836SJohn.Forte@Sun.COM int flag, _sd_buf_handle_t *handle, int locked);
4007836SJohn.Forte@Sun.COM
4017836SJohn.Forte@Sun.COM /* dynmem support */
4027836SJohn.Forte@Sun.COM static int _sd_setup_category_on_type(_sd_cctl_t *header);
4037836SJohn.Forte@Sun.COM static int _sd_setup_mem_chaining(_sd_cctl_t *header, int flag);
4047836SJohn.Forte@Sun.COM
4057836SJohn.Forte@Sun.COM static int sdbc_check_cctl_cot(_sd_cctl_t *);
4067836SJohn.Forte@Sun.COM
4077836SJohn.Forte@Sun.COM static int sdbc_dmqueues_configure();
4087836SJohn.Forte@Sun.COM static void sdbc_dmqueues_deconfigure();
4097836SJohn.Forte@Sun.COM static _sd_cctl_t *sdbc_get_dmchain(int, int *, int);
4107836SJohn.Forte@Sun.COM static int sdbc_dmchain_avail(_sd_cctl_t *);
4117836SJohn.Forte@Sun.COM void sdbc_requeue_dmchain(_sd_queue_t *, _sd_cctl_t *, int, int);
4127836SJohn.Forte@Sun.COM static void sdbc_ins_dmqueue_back(_sd_queue_t *, _sd_cctl_t *);
4137836SJohn.Forte@Sun.COM void sdbc_ins_dmqueue_front(_sd_queue_t *, _sd_cctl_t *);
4147836SJohn.Forte@Sun.COM void sdbc_remq_dmchain(_sd_queue_t *, _sd_cctl_t *);
4157836SJohn.Forte@Sun.COM static void sdbc_clear_dmchain(_sd_cctl_t *, _sd_cctl_t *);
4167836SJohn.Forte@Sun.COM void sdbc_requeue_head_dm_try(_sd_cctl_t *);
4177836SJohn.Forte@Sun.COM static _sd_cctl_t *sdbc_alloc_dmc(int, nsc_off_t, nsc_size_t, int *,
4187836SJohn.Forte@Sun.COM sdbc_allocbuf_t *, int);
4197836SJohn.Forte@Sun.COM static _sd_cctl_t *sdbc_alloc_lru(int, nsc_off_t, int *, int);
4207836SJohn.Forte@Sun.COM static _sd_cctl_t *sdbc_alloc_from_dmchain(int, nsc_off_t, sdbc_allocbuf_t *,
4217836SJohn.Forte@Sun.COM int);
4227836SJohn.Forte@Sun.COM static void sdbc_centry_init_dm(_sd_cctl_t *);
4237836SJohn.Forte@Sun.COM static int sdbc_centry_memalloc_dm(_sd_cctl_t *, int, int);
4247836SJohn.Forte@Sun.COM static void sdbc_centry_alloc_end(sdbc_allocbuf_t *);
4257836SJohn.Forte@Sun.COM
4267836SJohn.Forte@Sun.COM
4277836SJohn.Forte@Sun.COM
4287836SJohn.Forte@Sun.COM
4297836SJohn.Forte@Sun.COM /* _SD_DEBUG */
4307836SJohn.Forte@Sun.COM #if defined(_SD_DEBUG) || defined(DEBUG)
4317836SJohn.Forte@Sun.COM static int _sd_cctl_valid(_sd_cctl_t *);
4327836SJohn.Forte@Sun.COM #endif
4337836SJohn.Forte@Sun.COM
4347836SJohn.Forte@Sun.COM static
4357836SJohn.Forte@Sun.COM nsc_def_t _sdbc_fd_def[] = {
4367836SJohn.Forte@Sun.COM "Attach", (uintptr_t)sdbc_fd_attach_cd, 0,
4377836SJohn.Forte@Sun.COM "Detach", (uintptr_t)sdbc_fd_detach_cd, 0,
4387836SJohn.Forte@Sun.COM "Flush", (uintptr_t)sdbc_fd_flush_cd, 0,
4397836SJohn.Forte@Sun.COM 0, 0, 0
4407836SJohn.Forte@Sun.COM };
4417836SJohn.Forte@Sun.COM
4427836SJohn.Forte@Sun.COM
4437836SJohn.Forte@Sun.COM /*
4447836SJohn.Forte@Sun.COM * _sdbc_cache_configure - initialize cache blocks, queues etc.
4457836SJohn.Forte@Sun.COM *
4467836SJohn.Forte@Sun.COM * ARGUMENTS:
4477836SJohn.Forte@Sun.COM * cblocks - Number of cache blocks
4487836SJohn.Forte@Sun.COM *
4497836SJohn.Forte@Sun.COM * RETURNS:
4507836SJohn.Forte@Sun.COM * 0 on success.
4517836SJohn.Forte@Sun.COM * SDBC_EENABLEFAIL or SDBC_EMEMCONFIG on failure.
4527836SJohn.Forte@Sun.COM *
4537836SJohn.Forte@Sun.COM */
4547836SJohn.Forte@Sun.COM
4557836SJohn.Forte@Sun.COM
4567836SJohn.Forte@Sun.COM
4577836SJohn.Forte@Sun.COM int
_sdbc_cache_configure(int cblocks,spcs_s_info_t kstatus)4587836SJohn.Forte@Sun.COM _sdbc_cache_configure(int cblocks, spcs_s_info_t kstatus)
4597836SJohn.Forte@Sun.COM {
4607836SJohn.Forte@Sun.COM CBLOCKS = cblocks;
4617836SJohn.Forte@Sun.COM
4627836SJohn.Forte@Sun.COM _sd_cache_files = (_sd_cd_info_t *)
4637836SJohn.Forte@Sun.COM kmem_zalloc(sdbc_max_devs * sizeof (_sd_cd_info_t),
4647836SJohn.Forte@Sun.COM KM_SLEEP);
4657836SJohn.Forte@Sun.COM
4667836SJohn.Forte@Sun.COM if (_sdbc_stats_configure(cblocks))
4677836SJohn.Forte@Sun.COM return (SDBC_EENABLEFAIL);
4687836SJohn.Forte@Sun.COM
4697836SJohn.Forte@Sun.COM if (sdbc_use_dmchain) {
4707836SJohn.Forte@Sun.COM if (sdbc_dmqueues_configure())
4717836SJohn.Forte@Sun.COM return (SDBC_EENABLEFAIL);
4727836SJohn.Forte@Sun.COM } else {
4737836SJohn.Forte@Sun.COM if (_sdbc_lruq_configure(_SD_LRU_Q))
4747836SJohn.Forte@Sun.COM return (SDBC_EENABLEFAIL);
4757836SJohn.Forte@Sun.COM }
4767836SJohn.Forte@Sun.COM
4777836SJohn.Forte@Sun.COM
4787836SJohn.Forte@Sun.COM if (_sdbc_mem_configure(cblocks, kstatus))
4797836SJohn.Forte@Sun.COM return (SDBC_EMEMCONFIG);
4807836SJohn.Forte@Sun.COM
4817836SJohn.Forte@Sun.COM CACHE_BLOCK_SIZE = BLK_SIZE(1);
4827836SJohn.Forte@Sun.COM BLK_FBAS = FBA_NUM(CACHE_BLOCK_SIZE);
4837836SJohn.Forte@Sun.COM BLK_FBA_BITS = _fba_bits[BLK_FBAS];
4847836SJohn.Forte@Sun.COM
4857836SJohn.Forte@Sun.COM sdbc_allocb_pageio1 = 0;
4867836SJohn.Forte@Sun.COM sdbc_allocb_pageio2 = 0;
4877836SJohn.Forte@Sun.COM sdbc_allocb_hit = 0;
4887836SJohn.Forte@Sun.COM sdbc_allocb_inuse = 0;
4897836SJohn.Forte@Sun.COM sdbc_allocb_lost = 0;
4907836SJohn.Forte@Sun.COM sdbc_centry_inuse = 0;
4917836SJohn.Forte@Sun.COM sdbc_centry_lost = 0;
4927836SJohn.Forte@Sun.COM sdbc_centry_hit = 0;
4937836SJohn.Forte@Sun.COM sdbc_centry_deallocd = 0;
4947836SJohn.Forte@Sun.COM sdbc_dmchain_not_avail = 0;
4957836SJohn.Forte@Sun.COM sdbc_allocb_deallocd = 0;
4967836SJohn.Forte@Sun.COM
4977836SJohn.Forte@Sun.COM sdbc_prefetch_valid_cnt = 0;
4987836SJohn.Forte@Sun.COM sdbc_prefetch_busy_cnt = 0;
4997836SJohn.Forte@Sun.COM sdbc_prefetch_trailing = 0;
5007836SJohn.Forte@Sun.COM sdbc_prefetch_deallocd = 0;
5017836SJohn.Forte@Sun.COM sdbc_prefetch_pageio1 = 0;
5027836SJohn.Forte@Sun.COM sdbc_prefetch_pageio2 = 0;
5037836SJohn.Forte@Sun.COM sdbc_prefetch_hit = 0;
5047836SJohn.Forte@Sun.COM sdbc_prefetch_lost = 0;
5057836SJohn.Forte@Sun.COM
5067836SJohn.Forte@Sun.COM sdbc_check_cot = 0;
5077836SJohn.Forte@Sun.COM sdbc_prefetch1 = 1;
5087836SJohn.Forte@Sun.COM sdbc_ra_hash = 0;
5097836SJohn.Forte@Sun.COM sdbc_ra_none = 0;
5107836SJohn.Forte@Sun.COM
5117836SJohn.Forte@Sun.COM return (0);
5127836SJohn.Forte@Sun.COM }
5137836SJohn.Forte@Sun.COM
5147836SJohn.Forte@Sun.COM /*
5157836SJohn.Forte@Sun.COM * _sdbc_cache_deconfigure - cache is being deconfigured. Release any
5167836SJohn.Forte@Sun.COM * memory that we acquired during the configuration process and return
5177836SJohn.Forte@Sun.COM * to the unconfigured state.
5187836SJohn.Forte@Sun.COM *
5197836SJohn.Forte@Sun.COM * NOTE: all users of the cache should be inactive at this point,
5207836SJohn.Forte@Sun.COM * i.e. we are unregistered from sd and all cache daemons/threads are
5217836SJohn.Forte@Sun.COM * gone.
5227836SJohn.Forte@Sun.COM *
5237836SJohn.Forte@Sun.COM */
5247836SJohn.Forte@Sun.COM void
_sdbc_cache_deconfigure(void)5257836SJohn.Forte@Sun.COM _sdbc_cache_deconfigure(void)
5267836SJohn.Forte@Sun.COM {
5277836SJohn.Forte@Sun.COM /* CCIO shutdown must happen before memory is free'd */
5287836SJohn.Forte@Sun.COM
5297836SJohn.Forte@Sun.COM if (_sd_cache_files) {
5307836SJohn.Forte@Sun.COM kmem_free(_sd_cache_files,
5317836SJohn.Forte@Sun.COM sdbc_max_devs * sizeof (_sd_cd_info_t));
5327836SJohn.Forte@Sun.COM _sd_cache_files = (_sd_cd_info_t *)NULL;
5337836SJohn.Forte@Sun.COM }
5347836SJohn.Forte@Sun.COM
5357836SJohn.Forte@Sun.COM
5367836SJohn.Forte@Sun.COM BLK_FBA_BITS = 0;
5377836SJohn.Forte@Sun.COM BLK_FBAS = 0;
5387836SJohn.Forte@Sun.COM CACHE_BLOCK_SIZE = 0;
5397836SJohn.Forte@Sun.COM _sdbc_mem_deconfigure(CBLOCKS);
5407836SJohn.Forte@Sun.COM _sdbc_gl_centry_deconfigure();
5417836SJohn.Forte@Sun.COM _sdbc_gl_file_deconfigure();
5427836SJohn.Forte@Sun.COM
5437836SJohn.Forte@Sun.COM if (sdbc_use_dmchain)
5447836SJohn.Forte@Sun.COM sdbc_dmqueues_deconfigure();
5457836SJohn.Forte@Sun.COM else
5467836SJohn.Forte@Sun.COM _sdbc_lruq_deconfigure();
5477836SJohn.Forte@Sun.COM _sdbc_stats_deconfigure();
5487836SJohn.Forte@Sun.COM
5497836SJohn.Forte@Sun.COM CBLOCKS = 0;
5507836SJohn.Forte@Sun.COM }
5517836SJohn.Forte@Sun.COM
5527836SJohn.Forte@Sun.COM
5537836SJohn.Forte@Sun.COM /*
5547836SJohn.Forte@Sun.COM * _sdbc_stats_deconfigure - cache is being deconfigured turn off
5557836SJohn.Forte@Sun.COM * stats. This could seemingly do more but we leave most of the
5567836SJohn.Forte@Sun.COM * data intact until cache is configured again.
5577836SJohn.Forte@Sun.COM *
5587836SJohn.Forte@Sun.COM */
5597836SJohn.Forte@Sun.COM static void
_sdbc_stats_deconfigure(void)5607836SJohn.Forte@Sun.COM _sdbc_stats_deconfigure(void)
5617836SJohn.Forte@Sun.COM {
5627836SJohn.Forte@Sun.COM int i;
5637836SJohn.Forte@Sun.COM
5647836SJohn.Forte@Sun.COM #ifdef DEBUG
5657836SJohn.Forte@Sun.COM if (sdbc_dynmem_kstat_dm) {
5667836SJohn.Forte@Sun.COM kstat_delete(sdbc_dynmem_kstat_dm);
5677836SJohn.Forte@Sun.COM sdbc_dynmem_kstat_dm = NULL;
5687836SJohn.Forte@Sun.COM }
5697836SJohn.Forte@Sun.COM #endif
5707836SJohn.Forte@Sun.COM
5717836SJohn.Forte@Sun.COM if (sdbc_global_stats_kstat) {
5727836SJohn.Forte@Sun.COM kstat_delete(sdbc_global_stats_kstat);
5737836SJohn.Forte@Sun.COM sdbc_global_stats_kstat = NULL;
5747836SJohn.Forte@Sun.COM }
5757836SJohn.Forte@Sun.COM
5767836SJohn.Forte@Sun.COM if (sdbc_cd_kstats) {
5777836SJohn.Forte@Sun.COM for (i = 0; i < sdbc_max_devs; i++) {
5787836SJohn.Forte@Sun.COM if (sdbc_cd_kstats[i]) {
5797836SJohn.Forte@Sun.COM kstat_delete(sdbc_cd_kstats[i]);
5807836SJohn.Forte@Sun.COM sdbc_cd_kstats[i] = NULL;
5817836SJohn.Forte@Sun.COM }
5827836SJohn.Forte@Sun.COM }
5837836SJohn.Forte@Sun.COM kmem_free(sdbc_cd_kstats, sizeof (kstat_t *) * sdbc_max_devs);
5847836SJohn.Forte@Sun.COM sdbc_cd_kstats = NULL;
5857836SJohn.Forte@Sun.COM }
5867836SJohn.Forte@Sun.COM
5877836SJohn.Forte@Sun.COM if (sdbc_global_io_kstat) {
5887836SJohn.Forte@Sun.COM kstat_delete(sdbc_global_io_kstat);
5897836SJohn.Forte@Sun.COM mutex_destroy(&sdbc_global_io_kstat_mutex);
5907836SJohn.Forte@Sun.COM sdbc_global_io_kstat = NULL;
5917836SJohn.Forte@Sun.COM }
5927836SJohn.Forte@Sun.COM
5937836SJohn.Forte@Sun.COM if (sdbc_cd_io_kstats) {
5947836SJohn.Forte@Sun.COM for (i = 0; i < sdbc_max_devs; i++) {
5957836SJohn.Forte@Sun.COM if (sdbc_cd_io_kstats[i]) {
5967836SJohn.Forte@Sun.COM kstat_delete(sdbc_cd_io_kstats[i]);
5977836SJohn.Forte@Sun.COM sdbc_cd_io_kstats[i] = NULL;
5987836SJohn.Forte@Sun.COM }
5997836SJohn.Forte@Sun.COM }
6007836SJohn.Forte@Sun.COM kmem_free(sdbc_cd_io_kstats, sizeof (kstat_t *) *
6017836SJohn.Forte@Sun.COM sdbc_max_devs);
6027836SJohn.Forte@Sun.COM sdbc_cd_io_kstats = NULL;
6037836SJohn.Forte@Sun.COM }
6047836SJohn.Forte@Sun.COM
6057836SJohn.Forte@Sun.COM if (sdbc_cd_io_kstats_mutexes) {
6067836SJohn.Forte@Sun.COM /* mutexes are already destroyed in cd_kstat_remove() */
607*9093SRamana.Srikanth@Sun.COM kmem_free(sdbc_cd_io_kstats_mutexes,
608*9093SRamana.Srikanth@Sun.COM sizeof (kmutex_t) * sdbc_max_devs);
6097836SJohn.Forte@Sun.COM sdbc_cd_io_kstats_mutexes = NULL;
6107836SJohn.Forte@Sun.COM }
6117836SJohn.Forte@Sun.COM
6127836SJohn.Forte@Sun.COM
6137836SJohn.Forte@Sun.COM if (_sd_cache_stats) {
6147836SJohn.Forte@Sun.COM kmem_free(_sd_cache_stats,
6157836SJohn.Forte@Sun.COM sizeof (_sd_stats_t) +
6167836SJohn.Forte@Sun.COM (sdbc_max_devs - 1) * sizeof (_sd_shared_t));
6177836SJohn.Forte@Sun.COM _sd_cache_stats = NULL;
6187836SJohn.Forte@Sun.COM }
6197836SJohn.Forte@Sun.COM #ifdef _MULTI_DATAMODEL
6207836SJohn.Forte@Sun.COM if (_sd_cache_stats32) {
6217836SJohn.Forte@Sun.COM kmem_free(_sd_cache_stats32, sizeof (_sd_stats32_t) +
6227836SJohn.Forte@Sun.COM (sdbc_max_devs - 1) * sizeof (_sd_shared_t));
6237836SJohn.Forte@Sun.COM _sd_cache_stats32 = NULL;
6247836SJohn.Forte@Sun.COM }
6257836SJohn.Forte@Sun.COM #endif
6267836SJohn.Forte@Sun.COM }
6277836SJohn.Forte@Sun.COM
6287836SJohn.Forte@Sun.COM static int
_sdbc_stats_configure(int cblocks)6297836SJohn.Forte@Sun.COM _sdbc_stats_configure(int cblocks)
6307836SJohn.Forte@Sun.COM {
6317836SJohn.Forte@Sun.COM
6327836SJohn.Forte@Sun.COM _sd_cache_stats = kmem_zalloc(sizeof (_sd_stats_t) +
6337836SJohn.Forte@Sun.COM (sdbc_max_devs - 1) * sizeof (_sd_shared_t), KM_SLEEP);
6347836SJohn.Forte@Sun.COM _sd_cache_stats->st_blksize = (int)BLK_SIZE(1);
6357836SJohn.Forte@Sun.COM _sd_cache_stats->st_cachesize = cblocks * BLK_SIZE(1);
6367836SJohn.Forte@Sun.COM _sd_cache_stats->st_numblocks = cblocks;
6377836SJohn.Forte@Sun.COM _sd_cache_stats->st_wrcancelns = 0;
6387836SJohn.Forte@Sun.COM _sd_cache_stats->st_destaged = 0;
6397836SJohn.Forte@Sun.COM #ifdef _MULTI_DATAMODEL
6407836SJohn.Forte@Sun.COM _sd_cache_stats32 = kmem_zalloc(sizeof (_sd_stats32_t) +
6417836SJohn.Forte@Sun.COM (sdbc_max_devs - 1) * sizeof (_sd_shared_t), KM_SLEEP);
6427836SJohn.Forte@Sun.COM #endif
6437836SJohn.Forte@Sun.COM
6447836SJohn.Forte@Sun.COM /* kstat implementation - global stats */
6457836SJohn.Forte@Sun.COM sdbc_global_stats_kstat = kstat_create(SDBC_KSTAT_MODULE, 0,
6467836SJohn.Forte@Sun.COM SDBC_KSTAT_GSTATS, SDBC_KSTAT_CLASS, KSTAT_TYPE_NAMED,
6477836SJohn.Forte@Sun.COM sizeof (sdbc_global_stats)/sizeof (kstat_named_t),
6487836SJohn.Forte@Sun.COM KSTAT_FLAG_VIRTUAL|KSTAT_FLAG_WRITABLE);
6497836SJohn.Forte@Sun.COM
6507836SJohn.Forte@Sun.COM if (sdbc_global_stats_kstat != NULL) {
6517836SJohn.Forte@Sun.COM sdbc_global_stats_kstat->ks_data = &sdbc_global_stats;
6527836SJohn.Forte@Sun.COM sdbc_global_stats_kstat->ks_update = sdbc_global_stats_update;
6537836SJohn.Forte@Sun.COM sdbc_global_stats_kstat->ks_private = _sd_cache_stats;
6547836SJohn.Forte@Sun.COM kstat_install(sdbc_global_stats_kstat);
6557836SJohn.Forte@Sun.COM } else {
656*9093SRamana.Srikanth@Sun.COM cmn_err(CE_WARN, "!sdbc: gstats kstat failed");
6577836SJohn.Forte@Sun.COM }
6587836SJohn.Forte@Sun.COM
6597836SJohn.Forte@Sun.COM /* global I/O kstats */
6607836SJohn.Forte@Sun.COM sdbc_global_io_kstat = kstat_create(SDBC_KSTAT_MODULE, 0,
6617836SJohn.Forte@Sun.COM SDBC_IOKSTAT_GSTATS, "disk", KSTAT_TYPE_IO, 1, 0);
6627836SJohn.Forte@Sun.COM
6637836SJohn.Forte@Sun.COM if (sdbc_global_io_kstat) {
6647836SJohn.Forte@Sun.COM mutex_init(&sdbc_global_io_kstat_mutex, NULL, MUTEX_DRIVER,
6657836SJohn.Forte@Sun.COM NULL);
6667836SJohn.Forte@Sun.COM sdbc_global_io_kstat->ks_lock =
6677836SJohn.Forte@Sun.COM &sdbc_global_io_kstat_mutex;
6687836SJohn.Forte@Sun.COM kstat_install(sdbc_global_io_kstat);
6697836SJohn.Forte@Sun.COM }
6707836SJohn.Forte@Sun.COM
6717836SJohn.Forte@Sun.COM /*
6727836SJohn.Forte@Sun.COM * kstat implementation - cd stats
6737836SJohn.Forte@Sun.COM * NOTE: one kstat instance for each open cache descriptor
6747836SJohn.Forte@Sun.COM */
6757836SJohn.Forte@Sun.COM sdbc_cd_kstats = kmem_zalloc(sizeof (kstat_t *) * sdbc_max_devs,
6767836SJohn.Forte@Sun.COM KM_SLEEP);
6777836SJohn.Forte@Sun.COM
6787836SJohn.Forte@Sun.COM /*
6797836SJohn.Forte@Sun.COM * kstat implementation - i/o kstats per cache descriptor
6807836SJohn.Forte@Sun.COM * NOTE: one I/O kstat instance for each cd
6817836SJohn.Forte@Sun.COM */
6827836SJohn.Forte@Sun.COM sdbc_cd_io_kstats = kmem_zalloc(sizeof (kstat_t *) * sdbc_max_devs,
6837836SJohn.Forte@Sun.COM KM_SLEEP);
6847836SJohn.Forte@Sun.COM
6857836SJohn.Forte@Sun.COM sdbc_cd_io_kstats_mutexes = kmem_zalloc(sizeof (kmutex_t) *
6867836SJohn.Forte@Sun.COM sdbc_max_devs, KM_SLEEP);
6877836SJohn.Forte@Sun.COM
6887836SJohn.Forte@Sun.COM #ifdef DEBUG
6897836SJohn.Forte@Sun.COM /* kstat implementation - dynamic memory stats */
6907836SJohn.Forte@Sun.COM sdbc_dynmem_kstat_dm = kstat_create(SDBC_KSTAT_MODULE, 0,
6917836SJohn.Forte@Sun.COM SDBC_KSTAT_DYNMEM, SDBC_KSTAT_CLASS, KSTAT_TYPE_NAMED,
6927836SJohn.Forte@Sun.COM sizeof (sdbc_dynmem_dm)/sizeof (kstat_named_t),
6937836SJohn.Forte@Sun.COM KSTAT_FLAG_VIRTUAL|KSTAT_FLAG_WRITABLE);
6947836SJohn.Forte@Sun.COM
6957836SJohn.Forte@Sun.COM if (sdbc_dynmem_kstat_dm != NULL) {
6967836SJohn.Forte@Sun.COM sdbc_dynmem_kstat_dm->ks_data = &sdbc_dynmem_dm;
6977836SJohn.Forte@Sun.COM sdbc_dynmem_kstat_dm->ks_update = sdbc_dynmem_kstat_update_dm;
6987836SJohn.Forte@Sun.COM sdbc_dynmem_kstat_dm->ks_private = &dynmem_processing_dm;
6997836SJohn.Forte@Sun.COM kstat_install(sdbc_dynmem_kstat_dm);
7007836SJohn.Forte@Sun.COM } else {
701*9093SRamana.Srikanth@Sun.COM cmn_err(CE_WARN, "!sdbc: dynmem kstat failed");
7027836SJohn.Forte@Sun.COM }
7037836SJohn.Forte@Sun.COM #endif
7047836SJohn.Forte@Sun.COM
7057836SJohn.Forte@Sun.COM return (0);
7067836SJohn.Forte@Sun.COM }
7077836SJohn.Forte@Sun.COM
7087836SJohn.Forte@Sun.COM /*
7097836SJohn.Forte@Sun.COM * sdbc_dmqueues_configure()
7107836SJohn.Forte@Sun.COM * initialize the queues of dynamic memory chains.
7117836SJohn.Forte@Sun.COM */
7127836SJohn.Forte@Sun.COM
7137836SJohn.Forte@Sun.COM _sd_queue_t *sdbc_dm_queues;
7147836SJohn.Forte@Sun.COM static int max_dm_queues;
7157836SJohn.Forte@Sun.COM
7167836SJohn.Forte@Sun.COM
7177836SJohn.Forte@Sun.COM static int
sdbc_dmqueues_configure()7187836SJohn.Forte@Sun.COM sdbc_dmqueues_configure()
7197836SJohn.Forte@Sun.COM {
7207836SJohn.Forte@Sun.COM int i;
7217836SJohn.Forte@Sun.COM
7227836SJohn.Forte@Sun.COM /*
7237836SJohn.Forte@Sun.COM * CAUTION! this code depends on max_dyn_list not changing
7247836SJohn.Forte@Sun.COM * if it does change behavior may be incorrect, as cc_alloc_size_dm
7257836SJohn.Forte@Sun.COM * depends on max_dyn_list and indexes to dmqueues are derived from
7267836SJohn.Forte@Sun.COM * cc_alloc_size_dm.
7277836SJohn.Forte@Sun.COM * see _sd_setup_category_on_type() and _sd_dealloc_dm()
7287836SJohn.Forte@Sun.COM * TODO: prevent max_dyn_list from on-the-fly modification (easy) or
7297836SJohn.Forte@Sun.COM * allow for on-the-fly changes to number of dm queues (hard).
7307836SJohn.Forte@Sun.COM */
7317836SJohn.Forte@Sun.COM max_dm_queues = dynmem_processing_dm.max_dyn_list;
7327836SJohn.Forte@Sun.COM
7337836SJohn.Forte@Sun.COM ++max_dm_queues; /* need a "0" queue for centrys with no memory */
7347836SJohn.Forte@Sun.COM
7357836SJohn.Forte@Sun.COM sdbc_dm_queues = (_sd_queue_t *)
736*9093SRamana.Srikanth@Sun.COM kmem_zalloc(max_dm_queues * sizeof (_sd_queue_t), KM_SLEEP);
7377836SJohn.Forte@Sun.COM
7387836SJohn.Forte@Sun.COM #ifdef DEBUG
7397836SJohn.Forte@Sun.COM dmchainpull_table = (int *)kmem_zalloc(max_dm_queues *
740*9093SRamana.Srikanth@Sun.COM max_dm_queues * sizeof (int), KM_SLEEP);
7417836SJohn.Forte@Sun.COM #endif
7427836SJohn.Forte@Sun.COM
7437836SJohn.Forte@Sun.COM for (i = 0; i < max_dm_queues; ++i) {
7447836SJohn.Forte@Sun.COM (void) _sdbc_lruq_configure(&sdbc_dm_queues[i]);
7457836SJohn.Forte@Sun.COM sdbc_dm_queues[i].sq_dmchain_cblocks = i;
7467836SJohn.Forte@Sun.COM }
7477836SJohn.Forte@Sun.COM
7487836SJohn.Forte@Sun.COM return (0);
7497836SJohn.Forte@Sun.COM }
7507836SJohn.Forte@Sun.COM
7517836SJohn.Forte@Sun.COM static void
sdbc_dmqueues_deconfigure()7527836SJohn.Forte@Sun.COM sdbc_dmqueues_deconfigure()
7537836SJohn.Forte@Sun.COM {
7547836SJohn.Forte@Sun.COM /* CAUTION! this code depends on max_dyn_list not changing */
7557836SJohn.Forte@Sun.COM
7567836SJohn.Forte@Sun.COM if (sdbc_dm_queues)
7577836SJohn.Forte@Sun.COM kmem_free(sdbc_dm_queues, max_dm_queues * sizeof (_sd_queue_t));
7587836SJohn.Forte@Sun.COM sdbc_dm_queues = NULL;
7597836SJohn.Forte@Sun.COM max_dm_queues = 0;
7607836SJohn.Forte@Sun.COM }
7617836SJohn.Forte@Sun.COM
7627836SJohn.Forte@Sun.COM #define GOOD_LRUSIZE(q) ((q->sq_inq >= 0) || (q->sq_inq <= CBLOCKS))
7637836SJohn.Forte@Sun.COM
7647836SJohn.Forte@Sun.COM /*
7657836SJohn.Forte@Sun.COM * _sdbc_lruq_configure - initialize the lru queue
7667836SJohn.Forte@Sun.COM *
7677836SJohn.Forte@Sun.COM * ARGUMENTS: NONE
7687836SJohn.Forte@Sun.COM * RETURNS: 0
7697836SJohn.Forte@Sun.COM *
7707836SJohn.Forte@Sun.COM */
7717836SJohn.Forte@Sun.COM
7727836SJohn.Forte@Sun.COM static int
_sdbc_lruq_configure(_sd_queue_t * _sd_lru)7737836SJohn.Forte@Sun.COM _sdbc_lruq_configure(_sd_queue_t *_sd_lru)
7747836SJohn.Forte@Sun.COM {
7757836SJohn.Forte@Sun.COM
7767836SJohn.Forte@Sun.COM _sd_lru->sq_inq = 0;
7777836SJohn.Forte@Sun.COM
7787836SJohn.Forte@Sun.COM mutex_init(&_sd_lru->sq_qlock, NULL, MUTEX_DRIVER, NULL);
7797836SJohn.Forte@Sun.COM
7807836SJohn.Forte@Sun.COM _sd_lru->sq_qhead.cc_next = _sd_lru->sq_qhead.cc_prev
781*9093SRamana.Srikanth@Sun.COM = &(_sd_lru->sq_qhead);
7827836SJohn.Forte@Sun.COM return (0);
7837836SJohn.Forte@Sun.COM }
7847836SJohn.Forte@Sun.COM
7857836SJohn.Forte@Sun.COM /*
7867836SJohn.Forte@Sun.COM * _sdbc_lruq_deconfigure - deconfigure the lru queue
7877836SJohn.Forte@Sun.COM *
7887836SJohn.Forte@Sun.COM * ARGUMENTS: NONE
7897836SJohn.Forte@Sun.COM *
7907836SJohn.Forte@Sun.COM */
7917836SJohn.Forte@Sun.COM
7927836SJohn.Forte@Sun.COM static void
_sdbc_lruq_deconfigure(void)7937836SJohn.Forte@Sun.COM _sdbc_lruq_deconfigure(void)
7947836SJohn.Forte@Sun.COM {
7957836SJohn.Forte@Sun.COM _sd_queue_t *_sd_lru;
7967836SJohn.Forte@Sun.COM
7977836SJohn.Forte@Sun.COM _sd_lru = _SD_LRU_Q;
7987836SJohn.Forte@Sun.COM
7997836SJohn.Forte@Sun.COM mutex_destroy(&_sd_lru->sq_qlock);
8007836SJohn.Forte@Sun.COM bzero(_sd_lru, sizeof (_sd_queue_t));
8017836SJohn.Forte@Sun.COM
8027836SJohn.Forte@Sun.COM }
8037836SJohn.Forte@Sun.COM
8047836SJohn.Forte@Sun.COM /*
8057836SJohn.Forte@Sun.COM * _sdbc_mem_configure - initialize the cache memory.
8067836SJohn.Forte@Sun.COM * Create and initialize the hash table.
8077836SJohn.Forte@Sun.COM * Create cache control blocks and fill them with relevent
8087836SJohn.Forte@Sun.COM * information and enqueue onto the lru queue.
8097836SJohn.Forte@Sun.COM * Initialize the Write control blocks (blocks that contain
8107836SJohn.Forte@Sun.COM * information as to where the data will be mirrored)
8117836SJohn.Forte@Sun.COM * Initialize the Fault tolerant blocks (blocks that contain
8127836SJohn.Forte@Sun.COM * information about the mirror nodes dirty writes)
8137836SJohn.Forte@Sun.COM *
8147836SJohn.Forte@Sun.COM * ARGUMENTS:
8157836SJohn.Forte@Sun.COM * cblocks - Number of cache blocks.
8167836SJohn.Forte@Sun.COM * RETURNS: 0
8177836SJohn.Forte@Sun.COM *
8187836SJohn.Forte@Sun.COM */
8197836SJohn.Forte@Sun.COM static int
_sdbc_mem_configure(int cblocks,spcs_s_info_t kstatus)8207836SJohn.Forte@Sun.COM _sdbc_mem_configure(int cblocks, spcs_s_info_t kstatus)
8217836SJohn.Forte@Sun.COM {
8227836SJohn.Forte@Sun.COM int num_blks, i, blk;
8237836SJohn.Forte@Sun.COM _sd_cctl_t *centry;
8247836SJohn.Forte@Sun.COM _sd_net_t *netc;
8257836SJohn.Forte@Sun.COM _sd_cctl_t *prev_entry_dm, *first_entry_dm;
8267836SJohn.Forte@Sun.COM
8277836SJohn.Forte@Sun.COM if ((_sd_htable = _sdbc_hash_configure(cblocks)) == NULL) {
8287836SJohn.Forte@Sun.COM spcs_s_add(kstatus, SDBC_ENOHASH);
8297836SJohn.Forte@Sun.COM return (-1);
8307836SJohn.Forte@Sun.COM }
8317836SJohn.Forte@Sun.COM
8327836SJohn.Forte@Sun.COM _sd_cctl_groupsz = (cblocks / _SD_CCTL_GROUPS) +
8337836SJohn.Forte@Sun.COM ((cblocks % _SD_CCTL_GROUPS) != 0);
8347836SJohn.Forte@Sun.COM
8357836SJohn.Forte@Sun.COM for (i = 0; i < _SD_CCTL_GROUPS; i++) {
8367836SJohn.Forte@Sun.COM _sd_cctl[i] = (_sd_cctl_t *)
8377836SJohn.Forte@Sun.COM nsc_kmem_zalloc(_sd_cctl_groupsz * sizeof (_sd_cctl_t),
8387836SJohn.Forte@Sun.COM KM_SLEEP, sdbc_cache_mem);
8397836SJohn.Forte@Sun.COM
8407836SJohn.Forte@Sun.COM if (_sd_cctl[i] == NULL) {
8417836SJohn.Forte@Sun.COM spcs_s_add(kstatus, SDBC_ENOCB);
8427836SJohn.Forte@Sun.COM return (-1);
8437836SJohn.Forte@Sun.COM }
8447836SJohn.Forte@Sun.COM }
8457836SJohn.Forte@Sun.COM
8467836SJohn.Forte@Sun.COM _sd_ccent_sync = (_sd_cctl_sync_t *)
8477836SJohn.Forte@Sun.COM nsc_kmem_zalloc(_sd_ccsync_cnt * sizeof (_sd_cctl_sync_t),
8487836SJohn.Forte@Sun.COM KM_SLEEP, sdbc_local_mem);
8497836SJohn.Forte@Sun.COM
8507836SJohn.Forte@Sun.COM if (_sd_ccent_sync == NULL) {
8517836SJohn.Forte@Sun.COM spcs_s_add(kstatus, SDBC_ENOCCTL);
8527836SJohn.Forte@Sun.COM return (-1);
8537836SJohn.Forte@Sun.COM }
8547836SJohn.Forte@Sun.COM
8557836SJohn.Forte@Sun.COM for (i = 0; i < _sd_ccsync_cnt; i++) {
8567836SJohn.Forte@Sun.COM mutex_init(&_sd_ccent_sync[i]._cc_lock, NULL, MUTEX_DRIVER,
8577836SJohn.Forte@Sun.COM NULL);
8587836SJohn.Forte@Sun.COM cv_init(&_sd_ccent_sync[i]._cc_blkcv, NULL, CV_DRIVER, NULL);
8597836SJohn.Forte@Sun.COM }
8607836SJohn.Forte@Sun.COM
8617836SJohn.Forte@Sun.COM blk = 0;
8627836SJohn.Forte@Sun.COM
8637836SJohn.Forte@Sun.COM netc = &_sd_net_config;
8647836SJohn.Forte@Sun.COM
8657836SJohn.Forte@Sun.COM num_blks = (netc->sn_cpages * (int)netc->sn_psize)/BLK_SIZE(1);
8667836SJohn.Forte@Sun.COM
8677836SJohn.Forte@Sun.COM prev_entry_dm = 0;
8687836SJohn.Forte@Sun.COM first_entry_dm = 0;
8697836SJohn.Forte@Sun.COM for (i = 0; i < num_blks; i++, blk++) {
8707836SJohn.Forte@Sun.COM centry = _sd_cctl[(blk/_sd_cctl_groupsz)] +
871*9093SRamana.Srikanth@Sun.COM (blk%_sd_cctl_groupsz);
8727836SJohn.Forte@Sun.COM centry->cc_sync = &_sd_ccent_sync[blk % _sd_ccsync_cnt];
8737836SJohn.Forte@Sun.COM centry->cc_next = centry->cc_prev = NULL;
8747836SJohn.Forte@Sun.COM centry->cc_dirty_next = centry->cc_dirty_link = NULL;
8757836SJohn.Forte@Sun.COM centry->cc_await_use = centry->cc_await_page = 0;
8767836SJohn.Forte@Sun.COM centry->cc_inuse = centry->cc_pageio = 0;
8777836SJohn.Forte@Sun.COM centry->cc_flag = 0;
8787836SJohn.Forte@Sun.COM centry->cc_iocount = 0;
8797836SJohn.Forte@Sun.COM centry->cc_valid = 0;
8807836SJohn.Forte@Sun.COM
8817836SJohn.Forte@Sun.COM if (!first_entry_dm)
8827836SJohn.Forte@Sun.COM first_entry_dm = centry;
8837836SJohn.Forte@Sun.COM if (prev_entry_dm)
8847836SJohn.Forte@Sun.COM prev_entry_dm->cc_link_list_dm = centry;
8857836SJohn.Forte@Sun.COM prev_entry_dm = centry;
8867836SJohn.Forte@Sun.COM centry->cc_link_list_dm = first_entry_dm;
8877836SJohn.Forte@Sun.COM centry->cc_data = 0;
8887836SJohn.Forte@Sun.COM centry->cc_write = NULL;
8897836SJohn.Forte@Sun.COM centry->cc_dirty = 0;
8907836SJohn.Forte@Sun.COM
8917836SJohn.Forte@Sun.COM {
8927836SJohn.Forte@Sun.COM _sd_queue_t *q;
8937836SJohn.Forte@Sun.COM if (sdbc_use_dmchain) {
8947836SJohn.Forte@Sun.COM q = &sdbc_dm_queues[0];
8957836SJohn.Forte@Sun.COM centry->cc_cblocks = 0;
8967836SJohn.Forte@Sun.COM } else
8977836SJohn.Forte@Sun.COM q = _SD_LRU_Q;
8987836SJohn.Forte@Sun.COM
8997836SJohn.Forte@Sun.COM _sd_ins_queue(q, centry);
9007836SJohn.Forte@Sun.COM }
9017836SJohn.Forte@Sun.COM
9027836SJohn.Forte@Sun.COM }
9037836SJohn.Forte@Sun.COM
9047836SJohn.Forte@Sun.COM if (_sdbc_gl_centry_configure(kstatus) != 0)
9057836SJohn.Forte@Sun.COM return (-1);
9067836SJohn.Forte@Sun.COM
9077836SJohn.Forte@Sun.COM if (_sdbc_gl_file_configure(kstatus) != 0)
9087836SJohn.Forte@Sun.COM return (-1);
9097836SJohn.Forte@Sun.COM
9107836SJohn.Forte@Sun.COM return (0);
9117836SJohn.Forte@Sun.COM }
9127836SJohn.Forte@Sun.COM
9137836SJohn.Forte@Sun.COM /*
9147836SJohn.Forte@Sun.COM * _sdbc_gl_file_configure()
9157836SJohn.Forte@Sun.COM * allocate and initialize space for the global filename data.
9167836SJohn.Forte@Sun.COM *
9177836SJohn.Forte@Sun.COM */
9187836SJohn.Forte@Sun.COM static int
_sdbc_gl_file_configure(spcs_s_info_t kstatus)9197836SJohn.Forte@Sun.COM _sdbc_gl_file_configure(spcs_s_info_t kstatus)
9207836SJohn.Forte@Sun.COM {
9217836SJohn.Forte@Sun.COM ss_voldata_t *fileinfo;
9227836SJohn.Forte@Sun.COM ss_voldata_t tempfinfo;
9237836SJohn.Forte@Sun.COM ss_vdir_t vdir;
9247836SJohn.Forte@Sun.COM ss_vdirkey_t key;
9257836SJohn.Forte@Sun.COM int err = 0;
9267836SJohn.Forte@Sun.COM
9277836SJohn.Forte@Sun.COM _sdbc_gl_file_info_size = safestore_config.ssc_maxfiles *
928*9093SRamana.Srikanth@Sun.COM sizeof (ss_voldata_t);
9297836SJohn.Forte@Sun.COM
9307836SJohn.Forte@Sun.COM if ((_sdbc_gl_file_info = kmem_zalloc(_sdbc_gl_file_info_size,
931*9093SRamana.Srikanth@Sun.COM KM_NOSLEEP)) == NULL) {
9327836SJohn.Forte@Sun.COM spcs_s_add(kstatus, SDBC_ENOSFNV);
9337836SJohn.Forte@Sun.COM return (-1);
9347836SJohn.Forte@Sun.COM }
9357836SJohn.Forte@Sun.COM
9367836SJohn.Forte@Sun.COM /* setup the key to get a directory stream of all volumes */
9377836SJohn.Forte@Sun.COM key.vk_type = CDIR_ALL;
9387836SJohn.Forte@Sun.COM
9397836SJohn.Forte@Sun.COM fileinfo = _sdbc_gl_file_info;
9407836SJohn.Forte@Sun.COM
9417836SJohn.Forte@Sun.COM /*
9427836SJohn.Forte@Sun.COM * if coming up after a crash, "refresh" the host
9437836SJohn.Forte@Sun.COM * memory copy from safestore.
9447836SJohn.Forte@Sun.COM */
9457836SJohn.Forte@Sun.COM if (_sdbc_warm_start()) {
9467836SJohn.Forte@Sun.COM
9477836SJohn.Forte@Sun.COM if (SSOP_GETVDIR(sdbc_safestore, &key, &vdir)) {
948*9093SRamana.Srikanth@Sun.COM cmn_err(CE_WARN, "!sdbc(_sdbc_gl_file_configure): "
949*9093SRamana.Srikanth@Sun.COM "cannot read safestore");
9507836SJohn.Forte@Sun.COM return (-1);
9517836SJohn.Forte@Sun.COM }
9527836SJohn.Forte@Sun.COM
9537836SJohn.Forte@Sun.COM
9547836SJohn.Forte@Sun.COM /*
9557836SJohn.Forte@Sun.COM * cycle through the vdir getting volume data
9567836SJohn.Forte@Sun.COM * and volume tokens
9577836SJohn.Forte@Sun.COM */
9587836SJohn.Forte@Sun.COM
9597836SJohn.Forte@Sun.COM while ((err = SSOP_GETVDIRENT(sdbc_safestore, &vdir, fileinfo))
960*9093SRamana.Srikanth@Sun.COM == SS_OK) {
9617836SJohn.Forte@Sun.COM ++fileinfo;
9627836SJohn.Forte@Sun.COM }
9637836SJohn.Forte@Sun.COM
9647836SJohn.Forte@Sun.COM if (err != SS_EOF) {
9657836SJohn.Forte@Sun.COM /*
9667836SJohn.Forte@Sun.COM * fail to configure since
9677836SJohn.Forte@Sun.COM * recovery is not possible.
9687836SJohn.Forte@Sun.COM */
9697836SJohn.Forte@Sun.COM spcs_s_add(kstatus, SDBC_ENOREFRESH);
9707836SJohn.Forte@Sun.COM return (-1);
9717836SJohn.Forte@Sun.COM }
9727836SJohn.Forte@Sun.COM
9737836SJohn.Forte@Sun.COM } else { /* normal initialization, not a warm start */
9747836SJohn.Forte@Sun.COM
9757836SJohn.Forte@Sun.COM /*
9767836SJohn.Forte@Sun.COM * if this fails, continue: cache will start
9777836SJohn.Forte@Sun.COM * in writethru mode
9787836SJohn.Forte@Sun.COM */
9797836SJohn.Forte@Sun.COM
9807836SJohn.Forte@Sun.COM if (SSOP_GETVDIR(sdbc_safestore, &key, &vdir)) {
981*9093SRamana.Srikanth@Sun.COM cmn_err(CE_WARN, "!sdbc(_sdbc_gl_file_configure): "
982*9093SRamana.Srikanth@Sun.COM "cannot read safestore");
9837836SJohn.Forte@Sun.COM return (-1);
9847836SJohn.Forte@Sun.COM }
9857836SJohn.Forte@Sun.COM
9867836SJohn.Forte@Sun.COM /*
9877836SJohn.Forte@Sun.COM * cycle through the vdir getting just the volume tokens
9887836SJohn.Forte@Sun.COM * and initializing volume entries
9897836SJohn.Forte@Sun.COM */
9907836SJohn.Forte@Sun.COM
9917836SJohn.Forte@Sun.COM while ((err = SSOP_GETVDIRENT(sdbc_safestore, &vdir,
992*9093SRamana.Srikanth@Sun.COM &tempfinfo)) == 0) {
9937836SJohn.Forte@Sun.COM /*
9947836SJohn.Forte@Sun.COM * initialize the host memory copy of the
9957836SJohn.Forte@Sun.COM * global file region. this means setting the
9967836SJohn.Forte@Sun.COM * _pinned and _attached fields to _SD_NO_HOST
9977836SJohn.Forte@Sun.COM * because the default of zero conflicts with
9987836SJohn.Forte@Sun.COM * the min nodeid of zero.
9997836SJohn.Forte@Sun.COM */
10007836SJohn.Forte@Sun.COM fileinfo->sv_vol = tempfinfo.sv_vol;
10017836SJohn.Forte@Sun.COM fileinfo->sv_pinned = _SD_NO_HOST;
10027836SJohn.Forte@Sun.COM fileinfo->sv_attached = _SD_NO_HOST;
10037836SJohn.Forte@Sun.COM fileinfo->sv_cd = _SD_NO_CD;
10047836SJohn.Forte@Sun.COM
10057836SJohn.Forte@Sun.COM /* initialize the directory entry */
10067836SJohn.Forte@Sun.COM if ((err = SSOP_SETVOL(sdbc_safestore, fileinfo))
1007*9093SRamana.Srikanth@Sun.COM == SS_ERR) {
10087836SJohn.Forte@Sun.COM cmn_err(CE_WARN,
1009*9093SRamana.Srikanth@Sun.COM "!sdbc(_sdbc_gl_file_configure): "
1010*9093SRamana.Srikanth@Sun.COM "volume entry write failure %p",
1011*9093SRamana.Srikanth@Sun.COM (void *)fileinfo->sv_vol);
10127836SJohn.Forte@Sun.COM break;
10137836SJohn.Forte@Sun.COM }
10147836SJohn.Forte@Sun.COM
10157836SJohn.Forte@Sun.COM ++fileinfo;
10167836SJohn.Forte@Sun.COM }
10177836SJohn.Forte@Sun.COM
10187836SJohn.Forte@Sun.COM /* coming up clean, continue in w-t mode */
10197836SJohn.Forte@Sun.COM if (err != SS_EOF)
1020*9093SRamana.Srikanth@Sun.COM cmn_err(CE_WARN, "!sdbc(_sdbc_gl_file_configure) "
1021*9093SRamana.Srikanth@Sun.COM "unable to init safe store volinfo");
10227836SJohn.Forte@Sun.COM }
10237836SJohn.Forte@Sun.COM
10247836SJohn.Forte@Sun.COM return (0);
10257836SJohn.Forte@Sun.COM }
10267836SJohn.Forte@Sun.COM
10277836SJohn.Forte@Sun.COM static void
_sdbc_gl_centry_deconfigure(void)10287836SJohn.Forte@Sun.COM _sdbc_gl_centry_deconfigure(void)
10297836SJohn.Forte@Sun.COM {
10307836SJohn.Forte@Sun.COM if (_sdbc_gl_centry_info)
10317836SJohn.Forte@Sun.COM kmem_free(_sdbc_gl_centry_info, _sdbc_gl_centry_info_size);
10327836SJohn.Forte@Sun.COM
10337836SJohn.Forte@Sun.COM _sdbc_gl_centry_info = NULL;
10347836SJohn.Forte@Sun.COM _sdbc_gl_centry_info_size = 0;
10357836SJohn.Forte@Sun.COM }
10367836SJohn.Forte@Sun.COM
10377836SJohn.Forte@Sun.COM static int
_sdbc_gl_centry_configure(spcs_s_info_t kstatus)10387836SJohn.Forte@Sun.COM _sdbc_gl_centry_configure(spcs_s_info_t kstatus)
10397836SJohn.Forte@Sun.COM {
10407836SJohn.Forte@Sun.COM
10417836SJohn.Forte@Sun.COM int wblocks;
10427836SJohn.Forte@Sun.COM ss_centry_info_t *cinfo;
10437836SJohn.Forte@Sun.COM ss_cdirkey_t key;
10447836SJohn.Forte@Sun.COM ss_cdir_t cdir;
10457836SJohn.Forte@Sun.COM int err = 0;
10467836SJohn.Forte@Sun.COM
10477836SJohn.Forte@Sun.COM
10487836SJohn.Forte@Sun.COM wblocks = safestore_config.ssc_wsize / BLK_SIZE(1);
10497836SJohn.Forte@Sun.COM _sdbc_gl_centry_info_size = sizeof (ss_centry_info_t) * wblocks;
10507836SJohn.Forte@Sun.COM
10517836SJohn.Forte@Sun.COM if ((_sdbc_gl_centry_info = kmem_zalloc(_sdbc_gl_centry_info_size,
1052*9093SRamana.Srikanth@Sun.COM KM_NOSLEEP)) == NULL) {
1053*9093SRamana.Srikanth@Sun.COM cmn_err(CE_WARN, "!sdbc(_sdbc_gl_centry_configure) "
1054*9093SRamana.Srikanth@Sun.COM "alloc failed for gl_centry_info region");
10557836SJohn.Forte@Sun.COM
10567836SJohn.Forte@Sun.COM _sdbc_gl_centry_deconfigure();
10577836SJohn.Forte@Sun.COM return (-1);
10587836SJohn.Forte@Sun.COM }
10597836SJohn.Forte@Sun.COM
10607836SJohn.Forte@Sun.COM /*
10617836SJohn.Forte@Sun.COM * synchronize the centry info area with safe store
10627836SJohn.Forte@Sun.COM */
10637836SJohn.Forte@Sun.COM
10647836SJohn.Forte@Sun.COM /* setup the key to get a directory stream of all centrys */
10657836SJohn.Forte@Sun.COM key.ck_type = CDIR_ALL;
10667836SJohn.Forte@Sun.COM
10677836SJohn.Forte@Sun.COM cinfo = _sdbc_gl_centry_info;
10687836SJohn.Forte@Sun.COM
10697836SJohn.Forte@Sun.COM if (_sdbc_warm_start()) {
10707836SJohn.Forte@Sun.COM
10717836SJohn.Forte@Sun.COM if (SSOP_GETCDIR(sdbc_safestore, &key, &cdir)) {
1072*9093SRamana.Srikanth@Sun.COM cmn_err(CE_WARN, "!sdbc(_sdbc_gl_centry_configure): "
1073*9093SRamana.Srikanth@Sun.COM "cannot read safestore");
10747836SJohn.Forte@Sun.COM return (-1);
10757836SJohn.Forte@Sun.COM }
10767836SJohn.Forte@Sun.COM
10777836SJohn.Forte@Sun.COM
10787836SJohn.Forte@Sun.COM /*
10797836SJohn.Forte@Sun.COM * cycle through the cdir getting resource
10807836SJohn.Forte@Sun.COM * tokens and reading centrys
10817836SJohn.Forte@Sun.COM */
10827836SJohn.Forte@Sun.COM
10837836SJohn.Forte@Sun.COM while ((err = SSOP_GETCDIRENT(sdbc_safestore, &cdir, cinfo))
1084*9093SRamana.Srikanth@Sun.COM == 0) {
10857836SJohn.Forte@Sun.COM ++cinfo;
10867836SJohn.Forte@Sun.COM }
10877836SJohn.Forte@Sun.COM
10887836SJohn.Forte@Sun.COM if (err != SS_EOF) {
10897836SJohn.Forte@Sun.COM /*
10907836SJohn.Forte@Sun.COM * fail to configure since
10917836SJohn.Forte@Sun.COM * recovery is not possible.
10927836SJohn.Forte@Sun.COM */
10937836SJohn.Forte@Sun.COM _sdbc_gl_centry_deconfigure();
10947836SJohn.Forte@Sun.COM spcs_s_add(kstatus, SDBC_EGLDMAFAIL);
10957836SJohn.Forte@Sun.COM return (-1);
10967836SJohn.Forte@Sun.COM }
10977836SJohn.Forte@Sun.COM
10987836SJohn.Forte@Sun.COM } else {
10997836SJohn.Forte@Sun.COM
11007836SJohn.Forte@Sun.COM if (SSOP_GETCDIR(sdbc_safestore, &key, &cdir)) {
1101*9093SRamana.Srikanth@Sun.COM cmn_err(CE_WARN, "!sdbc(_sdbc_gl_centry_configure): "
1102*9093SRamana.Srikanth@Sun.COM "cannot read safestore");
11037836SJohn.Forte@Sun.COM return (-1);
11047836SJohn.Forte@Sun.COM }
11057836SJohn.Forte@Sun.COM
11067836SJohn.Forte@Sun.COM /*
11077836SJohn.Forte@Sun.COM * cycle through the cdir getting resource
11087836SJohn.Forte@Sun.COM * tokens and initializing centrys
11097836SJohn.Forte@Sun.COM */
11107836SJohn.Forte@Sun.COM
11117836SJohn.Forte@Sun.COM while ((err = SSOP_GETCDIRENT(sdbc_safestore, &cdir, cinfo))
1112*9093SRamana.Srikanth@Sun.COM == 0) {
11137836SJohn.Forte@Sun.COM cinfo->sc_cd = -1;
11147836SJohn.Forte@Sun.COM cinfo->sc_fpos = -1;
11157836SJohn.Forte@Sun.COM
11167836SJohn.Forte@Sun.COM if ((err = SSOP_SETCENTRY(sdbc_safestore, cinfo))
1117*9093SRamana.Srikanth@Sun.COM == SS_ERR) {
11187836SJohn.Forte@Sun.COM cmn_err(CE_WARN,
1119*9093SRamana.Srikanth@Sun.COM "!sdbc(_sdbc_gl_centry_configure): "
1120*9093SRamana.Srikanth@Sun.COM "cache entry write failure %p",
1121*9093SRamana.Srikanth@Sun.COM (void *)cinfo->sc_res);
11227836SJohn.Forte@Sun.COM break;
11237836SJohn.Forte@Sun.COM }
11247836SJohn.Forte@Sun.COM
11257836SJohn.Forte@Sun.COM ++cinfo;
11267836SJohn.Forte@Sun.COM }
11277836SJohn.Forte@Sun.COM
11287836SJohn.Forte@Sun.COM /* coming up clean, continue in w-t mode */
11297836SJohn.Forte@Sun.COM if (err != SS_EOF) {
1130*9093SRamana.Srikanth@Sun.COM cmn_err(CE_WARN, "!sdbc(sdbc_gl_centry_configure) "
1131*9093SRamana.Srikanth@Sun.COM "_sdbc_gl_centry_info initialization failed");
11327836SJohn.Forte@Sun.COM }
11337836SJohn.Forte@Sun.COM }
11347836SJohn.Forte@Sun.COM
11357836SJohn.Forte@Sun.COM return (0);
11367836SJohn.Forte@Sun.COM }
11377836SJohn.Forte@Sun.COM
11387836SJohn.Forte@Sun.COM
11397836SJohn.Forte@Sun.COM static void
_sdbc_gl_file_deconfigure(void)11407836SJohn.Forte@Sun.COM _sdbc_gl_file_deconfigure(void)
11417836SJohn.Forte@Sun.COM {
11427836SJohn.Forte@Sun.COM
11437836SJohn.Forte@Sun.COM if (_sdbc_gl_file_info)
11447836SJohn.Forte@Sun.COM kmem_free(_sdbc_gl_file_info, _sdbc_gl_file_info_size);
11457836SJohn.Forte@Sun.COM
11467836SJohn.Forte@Sun.COM _sdbc_gl_file_info = NULL;
11477836SJohn.Forte@Sun.COM
11487836SJohn.Forte@Sun.COM _sdbc_gl_file_info_size = 0;
11497836SJohn.Forte@Sun.COM }
11507836SJohn.Forte@Sun.COM
11517836SJohn.Forte@Sun.COM
11527836SJohn.Forte@Sun.COM /*
11537836SJohn.Forte@Sun.COM * _sdbc_mem_deconfigure - deconfigure the cache memory.
11547836SJohn.Forte@Sun.COM * Release any memory/locks/sv's acquired during _sdbc_mem_configure.
11557836SJohn.Forte@Sun.COM *
11567836SJohn.Forte@Sun.COM * ARGUMENTS:
11577836SJohn.Forte@Sun.COM * cblocks - Number of cache blocks.
11587836SJohn.Forte@Sun.COM *
11597836SJohn.Forte@Sun.COM */
11607836SJohn.Forte@Sun.COM /* ARGSUSED */
11617836SJohn.Forte@Sun.COM static void
_sdbc_mem_deconfigure(int cblocks)11627836SJohn.Forte@Sun.COM _sdbc_mem_deconfigure(int cblocks)
11637836SJohn.Forte@Sun.COM {
11647836SJohn.Forte@Sun.COM int i;
11657836SJohn.Forte@Sun.COM
11667836SJohn.Forte@Sun.COM if (_sd_ccent_sync) {
11677836SJohn.Forte@Sun.COM for (i = 0; i < _sd_ccsync_cnt; i++) {
11687836SJohn.Forte@Sun.COM mutex_destroy(&_sd_ccent_sync[i]._cc_lock);
11697836SJohn.Forte@Sun.COM cv_destroy(&_sd_ccent_sync[i]._cc_blkcv);
11707836SJohn.Forte@Sun.COM }
11717836SJohn.Forte@Sun.COM nsc_kmem_free(_sd_ccent_sync,
1172*9093SRamana.Srikanth@Sun.COM _sd_ccsync_cnt * sizeof (_sd_cctl_sync_t));
11737836SJohn.Forte@Sun.COM }
11747836SJohn.Forte@Sun.COM _sd_ccent_sync = NULL;
11757836SJohn.Forte@Sun.COM
11767836SJohn.Forte@Sun.COM for (i = 0; i < _SD_CCTL_GROUPS; i++) {
11777836SJohn.Forte@Sun.COM if (_sd_cctl[i] != NULL) {
11787836SJohn.Forte@Sun.COM nsc_kmem_free(_sd_cctl[i],
1179*9093SRamana.Srikanth@Sun.COM _sd_cctl_groupsz * sizeof (_sd_cctl_t));
11807836SJohn.Forte@Sun.COM _sd_cctl[i] = NULL;
11817836SJohn.Forte@Sun.COM }
11827836SJohn.Forte@Sun.COM }
11837836SJohn.Forte@Sun.COM _sd_cctl_groupsz = 0;
11847836SJohn.Forte@Sun.COM
11857836SJohn.Forte@Sun.COM _sdbc_hash_deconfigure(_sd_htable);
11867836SJohn.Forte@Sun.COM _sd_htable = NULL;
11877836SJohn.Forte@Sun.COM
11887836SJohn.Forte@Sun.COM }
11897836SJohn.Forte@Sun.COM
11907836SJohn.Forte@Sun.COM
11917836SJohn.Forte@Sun.COM #if defined(_SD_DEBUG) || defined(DEBUG)
11927836SJohn.Forte@Sun.COM static int
_sd_cctl_valid(_sd_cctl_t * addr)11937836SJohn.Forte@Sun.COM _sd_cctl_valid(_sd_cctl_t *addr)
11947836SJohn.Forte@Sun.COM {
11957836SJohn.Forte@Sun.COM _sd_cctl_t *end;
11967836SJohn.Forte@Sun.COM int i, valid;
11977836SJohn.Forte@Sun.COM
11987836SJohn.Forte@Sun.COM valid = 0;
11997836SJohn.Forte@Sun.COM for (i = 0; i < _SD_CCTL_GROUPS; i++) {
12007836SJohn.Forte@Sun.COM end = _sd_cctl[i] + _sd_cctl_groupsz;
12017836SJohn.Forte@Sun.COM if (addr >= _sd_cctl[i] && addr < end) {
12027836SJohn.Forte@Sun.COM valid = 1;
12037836SJohn.Forte@Sun.COM break;
12047836SJohn.Forte@Sun.COM }
12057836SJohn.Forte@Sun.COM }
12067836SJohn.Forte@Sun.COM
12077836SJohn.Forte@Sun.COM return (valid);
12087836SJohn.Forte@Sun.COM }
12097836SJohn.Forte@Sun.COM #endif
12107836SJohn.Forte@Sun.COM
12117836SJohn.Forte@Sun.COM
12127836SJohn.Forte@Sun.COM /*
12137836SJohn.Forte@Sun.COM * _sd_ins_queue - insert centry into LRU queue
12147836SJohn.Forte@Sun.COM * (during initialization, locking not required)
12157836SJohn.Forte@Sun.COM */
12167836SJohn.Forte@Sun.COM static void
_sd_ins_queue(_sd_queue_t * q,_sd_cctl_t * centry)12177836SJohn.Forte@Sun.COM _sd_ins_queue(_sd_queue_t *q, _sd_cctl_t *centry)
12187836SJohn.Forte@Sun.COM {
12197836SJohn.Forte@Sun.COM _sd_cctl_t *q_head;
12207836SJohn.Forte@Sun.COM
12217836SJohn.Forte@Sun.COM ASSERT(_sd_cctl_valid(centry));
12227836SJohn.Forte@Sun.COM
12237836SJohn.Forte@Sun.COM q_head = &q->sq_qhead;
12247836SJohn.Forte@Sun.COM centry->cc_prev = q_head;
12257836SJohn.Forte@Sun.COM centry->cc_next = q_head->cc_next;
12267836SJohn.Forte@Sun.COM q_head->cc_next->cc_prev = centry;
12277836SJohn.Forte@Sun.COM q_head->cc_next = centry;
12287836SJohn.Forte@Sun.COM q->sq_inq++;
12297836SJohn.Forte@Sun.COM
12307836SJohn.Forte@Sun.COM ASSERT(GOOD_LRUSIZE(q));
12317836SJohn.Forte@Sun.COM }
12327836SJohn.Forte@Sun.COM
12337836SJohn.Forte@Sun.COM
12347836SJohn.Forte@Sun.COM
12357836SJohn.Forte@Sun.COM void
_sd_requeue(_sd_cctl_t * centry)12367836SJohn.Forte@Sun.COM _sd_requeue(_sd_cctl_t *centry)
12377836SJohn.Forte@Sun.COM {
12387836SJohn.Forte@Sun.COM _sd_queue_t *q = _SD_LRU_Q;
12397836SJohn.Forte@Sun.COM
12407836SJohn.Forte@Sun.COM /* was FAST */
12417836SJohn.Forte@Sun.COM mutex_enter(&q->sq_qlock);
12427836SJohn.Forte@Sun.COM #if defined(_SD_DEBUG)
12437836SJohn.Forte@Sun.COM if (1) {
12447836SJohn.Forte@Sun.COM _sd_cctl_t *cp, *cn, *qp;
12457836SJohn.Forte@Sun.COM cp = centry->cc_prev;
12467836SJohn.Forte@Sun.COM cn = centry->cc_next;
12477836SJohn.Forte@Sun.COM qp = (q->sq_qhead).cc_prev;
12487836SJohn.Forte@Sun.COM if (!_sd_cctl_valid(centry) ||
12497836SJohn.Forte@Sun.COM (cp != &(q->sq_qhead) && !_sd_cctl_valid(cp)) ||
12507836SJohn.Forte@Sun.COM (cn != &(q->sq_qhead) && !_sd_cctl_valid(cn)) ||
12517836SJohn.Forte@Sun.COM !_sd_cctl_valid(qp))
12527836SJohn.Forte@Sun.COM cmn_err(CE_PANIC,
12537836SJohn.Forte@Sun.COM "_sd_requeue %x prev %x next %x qp %x",
12547836SJohn.Forte@Sun.COM centry, cp, cn, qp);
12557836SJohn.Forte@Sun.COM }
12567836SJohn.Forte@Sun.COM #endif
12577836SJohn.Forte@Sun.COM centry->cc_prev->cc_next = centry->cc_next;
12587836SJohn.Forte@Sun.COM centry->cc_next->cc_prev = centry->cc_prev;
12597836SJohn.Forte@Sun.COM centry->cc_next = &(q->sq_qhead);
12607836SJohn.Forte@Sun.COM centry->cc_prev = q->sq_qhead.cc_prev;
12617836SJohn.Forte@Sun.COM q->sq_qhead.cc_prev->cc_next = centry;
12627836SJohn.Forte@Sun.COM q->sq_qhead.cc_prev = centry;
12637836SJohn.Forte@Sun.COM centry->cc_seq = q->sq_seq++;
12647836SJohn.Forte@Sun.COM /* was FAST */
12657836SJohn.Forte@Sun.COM mutex_exit(&q->sq_qlock);
12667836SJohn.Forte@Sun.COM (q->sq_req_stat)++;
12677836SJohn.Forte@Sun.COM
12687836SJohn.Forte@Sun.COM }
12697836SJohn.Forte@Sun.COM
12707836SJohn.Forte@Sun.COM void
_sd_requeue_head(_sd_cctl_t * centry)12717836SJohn.Forte@Sun.COM _sd_requeue_head(_sd_cctl_t *centry)
12727836SJohn.Forte@Sun.COM {
12737836SJohn.Forte@Sun.COM _sd_queue_t *q = _SD_LRU_Q;
12747836SJohn.Forte@Sun.COM
12757836SJohn.Forte@Sun.COM /* was FAST */
12767836SJohn.Forte@Sun.COM mutex_enter(&q->sq_qlock);
12777836SJohn.Forte@Sun.COM #if defined(_SD_DEBUG)
12787836SJohn.Forte@Sun.COM if (1) {
12797836SJohn.Forte@Sun.COM _sd_cctl_t *cp, *cn, *qn;
12807836SJohn.Forte@Sun.COM cp = centry->cc_prev;
12817836SJohn.Forte@Sun.COM cn = centry->cc_next;
12827836SJohn.Forte@Sun.COM qn = (q->sq_qhead).cc_prev;
12837836SJohn.Forte@Sun.COM if (!_sd_cctl_valid(centry) ||
12847836SJohn.Forte@Sun.COM (cp != &(q->sq_qhead) && !_sd_cctl_valid(cp)) ||
12857836SJohn.Forte@Sun.COM (cn != &(q->sq_qhead) && !_sd_cctl_valid(cn)) ||
12867836SJohn.Forte@Sun.COM !_sd_cctl_valid(qn))
12877836SJohn.Forte@Sun.COM cmn_err(CE_PANIC,
12887836SJohn.Forte@Sun.COM "_sd_requeue_head %x prev %x next %x qn %x",
12897836SJohn.Forte@Sun.COM centry, cp, cn, qn);
12907836SJohn.Forte@Sun.COM }
12917836SJohn.Forte@Sun.COM #endif
12927836SJohn.Forte@Sun.COM centry->cc_prev->cc_next = centry->cc_next;
12937836SJohn.Forte@Sun.COM centry->cc_next->cc_prev = centry->cc_prev;
12947836SJohn.Forte@Sun.COM centry->cc_prev = &(q->sq_qhead);
12957836SJohn.Forte@Sun.COM centry->cc_next = q->sq_qhead.cc_next;
12967836SJohn.Forte@Sun.COM q->sq_qhead.cc_next->cc_prev = centry;
12977836SJohn.Forte@Sun.COM q->sq_qhead.cc_next = centry;
12987836SJohn.Forte@Sun.COM centry->cc_seq = q->sq_seq++;
12997836SJohn.Forte@Sun.COM centry->cc_flag &= ~CC_QHEAD;
13007836SJohn.Forte@Sun.COM /* was FAST */
13017836SJohn.Forte@Sun.COM mutex_exit(&q->sq_qlock);
13027836SJohn.Forte@Sun.COM }
13037836SJohn.Forte@Sun.COM
13047836SJohn.Forte@Sun.COM
13057836SJohn.Forte@Sun.COM
13067836SJohn.Forte@Sun.COM /*
13077836SJohn.Forte@Sun.COM * _sd_open - Open a file.
13087836SJohn.Forte@Sun.COM *
13097836SJohn.Forte@Sun.COM * ARGUMENTS:
13107836SJohn.Forte@Sun.COM * filename - Name of the file to be opened.
13117836SJohn.Forte@Sun.COM * flag - Flag associated with open.
13127836SJohn.Forte@Sun.COM * (currently used to determine a ckd device)
13137836SJohn.Forte@Sun.COM * RETURNS:
13147836SJohn.Forte@Sun.COM * cd - the cache descriptor.
13157836SJohn.Forte@Sun.COM */
13167836SJohn.Forte@Sun.COM
13177836SJohn.Forte@Sun.COM int
_sd_open(char * filename,int flag)13187836SJohn.Forte@Sun.COM _sd_open(char *filename, int flag)
13197836SJohn.Forte@Sun.COM {
13207836SJohn.Forte@Sun.COM int cd;
13217836SJohn.Forte@Sun.COM
13227836SJohn.Forte@Sun.COM if (!_sd_cache_initialized) {
1323*9093SRamana.Srikanth@Sun.COM cmn_err(CE_WARN, "!sdbc(_sd_open) cache not initialized");
13247836SJohn.Forte@Sun.COM return (-EINVAL);
13257836SJohn.Forte@Sun.COM }
13267836SJohn.Forte@Sun.COM cd = _sd_open_cd(filename, -1, flag);
13277836SJohn.Forte@Sun.COM SDTRACE(SDF_OPEN, (cd < 0) ? SDT_INV_CD : cd, 0, SDT_INV_BL, 0, cd);
13287836SJohn.Forte@Sun.COM
13297836SJohn.Forte@Sun.COM return (cd);
13307836SJohn.Forte@Sun.COM }
13317836SJohn.Forte@Sun.COM
13327836SJohn.Forte@Sun.COM
13337836SJohn.Forte@Sun.COM static int
_sd_open_io(char * filename,int flag,blind_t * cdp,nsc_iodev_t * iodev)13347836SJohn.Forte@Sun.COM _sd_open_io(char *filename, int flag, blind_t *cdp, nsc_iodev_t *iodev)
13357836SJohn.Forte@Sun.COM {
13367836SJohn.Forte@Sun.COM _sd_cd_info_t *cdi;
13377836SJohn.Forte@Sun.COM int cd;
13387836SJohn.Forte@Sun.COM int rc = 0;
13397836SJohn.Forte@Sun.COM
13407836SJohn.Forte@Sun.COM if ((cd = _sd_open(filename, flag)) >= 0) {
13417836SJohn.Forte@Sun.COM
13427836SJohn.Forte@Sun.COM cdi = &(_sd_cache_files[cd]);
13437836SJohn.Forte@Sun.COM cdi->cd_iodev = iodev;
13447836SJohn.Forte@Sun.COM nsc_set_owner(cdi->cd_rawfd, cdi->cd_iodev);
13457836SJohn.Forte@Sun.COM
13467836SJohn.Forte@Sun.COM *cdp = (blind_t)(unsigned long)cd;
13477836SJohn.Forte@Sun.COM } else
13487836SJohn.Forte@Sun.COM rc = -cd;
13497836SJohn.Forte@Sun.COM
13507836SJohn.Forte@Sun.COM return (rc);
13517836SJohn.Forte@Sun.COM }
13527836SJohn.Forte@Sun.COM
13537836SJohn.Forte@Sun.COM
13547836SJohn.Forte@Sun.COM
13557836SJohn.Forte@Sun.COM int
_sd_open_cd(char * filename,const int cd,const int flag)13567836SJohn.Forte@Sun.COM _sd_open_cd(char *filename, const int cd, const int flag)
13577836SJohn.Forte@Sun.COM {
13587836SJohn.Forte@Sun.COM int new_cd, rc = 0, alloc_cd = -1;
13597836SJohn.Forte@Sun.COM ss_voldata_t *cdg;
13607836SJohn.Forte@Sun.COM int preexists = 0;
13617836SJohn.Forte@Sun.COM _sd_cd_info_t *cdi;
13627836SJohn.Forte@Sun.COM int failover_open, open_failed;
13637836SJohn.Forte@Sun.COM major_t devmaj;
13647836SJohn.Forte@Sun.COM minor_t devmin;
13657836SJohn.Forte@Sun.COM
13667836SJohn.Forte@Sun.COM if (_sdbc_shutdown_in_progress)
13677836SJohn.Forte@Sun.COM return (-EIO);
13687836SJohn.Forte@Sun.COM
13697836SJohn.Forte@Sun.COM if (strlen(filename) > (NSC_MAXPATH-1))
13707836SJohn.Forte@Sun.COM return (-ENAMETOOLONG);
13717836SJohn.Forte@Sun.COM
13727836SJohn.Forte@Sun.COM /*
13737836SJohn.Forte@Sun.COM * If the cd is >= 0, then this is a open for a specific cd.
13747836SJohn.Forte@Sun.COM * This happens when the mirror node crashes, and we attempt to
13757836SJohn.Forte@Sun.COM * reopen the files with the same cache descriptors as existed on
13767836SJohn.Forte@Sun.COM * the other node
13777836SJohn.Forte@Sun.COM */
13787836SJohn.Forte@Sun.COM
13797836SJohn.Forte@Sun.COM retry_open:
13807836SJohn.Forte@Sun.COM failover_open = 0;
13817836SJohn.Forte@Sun.COM open_failed = 0;
13827836SJohn.Forte@Sun.COM if (cd >= 0) {
13837836SJohn.Forte@Sun.COM failover_open++;
13847836SJohn.Forte@Sun.COM cdi = &(_sd_cache_files[cd]);
13857836SJohn.Forte@Sun.COM mutex_enter(&_sd_cache_lock);
13867836SJohn.Forte@Sun.COM if (cdi->cd_info == NULL)
13877836SJohn.Forte@Sun.COM cdi->cd_info = &_sd_cache_stats->st_shared[cd];
13887836SJohn.Forte@Sun.COM else if (cdi->cd_info->sh_alloc &&
13897836SJohn.Forte@Sun.COM strcmp(cdi->cd_info->sh_filename, filename)) {
1390*9093SRamana.Srikanth@Sun.COM cmn_err(CE_WARN, "!sdbc(_sd_open_cd) cd %d mismatch",
13917836SJohn.Forte@Sun.COM cd);
13927836SJohn.Forte@Sun.COM mutex_exit(&_sd_cache_lock);
13937836SJohn.Forte@Sun.COM return (-EEXIST);
13947836SJohn.Forte@Sun.COM }
13957836SJohn.Forte@Sun.COM
13967836SJohn.Forte@Sun.COM if (cdi->cd_info->sh_failed != 2) {
13977836SJohn.Forte@Sun.COM if (cdi->cd_info->sh_alloc != 0)
13987836SJohn.Forte@Sun.COM preexists = 1;
13997836SJohn.Forte@Sun.COM else {
14007836SJohn.Forte@Sun.COM cdi->cd_info->sh_alloc = CD_ALLOC_IN_PROGRESS;
14017836SJohn.Forte@Sun.COM (void) strcpy(cdi->cd_info->sh_filename,
14027836SJohn.Forte@Sun.COM filename);
14037836SJohn.Forte@Sun.COM if (_sd_cache_stats->st_count < sdbc_max_devs)
14047836SJohn.Forte@Sun.COM _sd_cache_stats->st_count++;
14057836SJohn.Forte@Sun.COM }
14067836SJohn.Forte@Sun.COM }
14077836SJohn.Forte@Sun.COM
14087836SJohn.Forte@Sun.COM mutex_exit(&_sd_cache_lock);
14097836SJohn.Forte@Sun.COM alloc_cd = cd;
14107836SJohn.Forte@Sun.COM
14117836SJohn.Forte@Sun.COM goto known_cd;
14127836SJohn.Forte@Sun.COM }
14137836SJohn.Forte@Sun.COM
14147836SJohn.Forte@Sun.COM new_cd = 0;
14157836SJohn.Forte@Sun.COM mutex_enter(&_sd_cache_lock);
14167836SJohn.Forte@Sun.COM
14177836SJohn.Forte@Sun.COM for (cdi = &(_sd_cache_files[new_cd]),
1418*9093SRamana.Srikanth@Sun.COM cdg = _sdbc_gl_file_info + new_cd;
1419*9093SRamana.Srikanth@Sun.COM new_cd < (sdbc_max_devs); new_cd++, cdi++, cdg++) {
14207836SJohn.Forte@Sun.COM if (strlen(cdg->sv_volname) != 0)
14217836SJohn.Forte@Sun.COM if (strcmp(cdg->sv_volname, filename))
14227836SJohn.Forte@Sun.COM continue;
14237836SJohn.Forte@Sun.COM
14247836SJohn.Forte@Sun.COM if (cdi->cd_info == NULL)
14257836SJohn.Forte@Sun.COM cdi->cd_info = &_sd_cache_stats->st_shared[new_cd];
14267836SJohn.Forte@Sun.COM
14277836SJohn.Forte@Sun.COM if (cdi->cd_info->sh_failed != 2) {
14287836SJohn.Forte@Sun.COM if (cdi->cd_info->sh_alloc != 0)
14297836SJohn.Forte@Sun.COM preexists = 1;
14307836SJohn.Forte@Sun.COM else {
14317836SJohn.Forte@Sun.COM if (cd == -2) {
14327836SJohn.Forte@Sun.COM mutex_exit(&_sd_cache_lock);
14337836SJohn.Forte@Sun.COM return (-1);
14347836SJohn.Forte@Sun.COM }
14357836SJohn.Forte@Sun.COM cdi->cd_info->sh_alloc = CD_ALLOC_IN_PROGRESS;
14367836SJohn.Forte@Sun.COM (void) strcpy(cdi->cd_info->sh_filename,
1437*9093SRamana.Srikanth@Sun.COM filename);
14387836SJohn.Forte@Sun.COM (void) strcpy(cdg->sv_volname, filename);
14397836SJohn.Forte@Sun.COM
14407836SJohn.Forte@Sun.COM cdg->sv_cd = new_cd;
14417836SJohn.Forte@Sun.COM /* update safestore */
14427836SJohn.Forte@Sun.COM SSOP_SETVOL(sdbc_safestore, cdg);
14437836SJohn.Forte@Sun.COM if (_sd_cache_stats->st_count < sdbc_max_devs)
14447836SJohn.Forte@Sun.COM _sd_cache_stats->st_count++;
14457836SJohn.Forte@Sun.COM cdi->cd_flag = 0;
14467836SJohn.Forte@Sun.COM }
14477836SJohn.Forte@Sun.COM }
14487836SJohn.Forte@Sun.COM alloc_cd = new_cd;
14497836SJohn.Forte@Sun.COM break;
14507836SJohn.Forte@Sun.COM }
14517836SJohn.Forte@Sun.COM
14527836SJohn.Forte@Sun.COM mutex_exit(&_sd_cache_lock);
14537836SJohn.Forte@Sun.COM
14547836SJohn.Forte@Sun.COM if (alloc_cd == -1)
14557836SJohn.Forte@Sun.COM return (-ENOSPC);
14567836SJohn.Forte@Sun.COM
14577836SJohn.Forte@Sun.COM known_cd:
14587836SJohn.Forte@Sun.COM /*
14597836SJohn.Forte@Sun.COM * If preexists: someone else is attempting to open this file as
14607836SJohn.Forte@Sun.COM * well. Do only one open, but block everyone else here till the
14617836SJohn.Forte@Sun.COM * open is completed.
14627836SJohn.Forte@Sun.COM */
14637836SJohn.Forte@Sun.COM if (preexists) {
14647836SJohn.Forte@Sun.COM while (cdi->cd_info->sh_alloc == CD_ALLOC_IN_PROGRESS) {
14657836SJohn.Forte@Sun.COM delay(drv_usectohz(20000));
14667836SJohn.Forte@Sun.COM }
14677836SJohn.Forte@Sun.COM if ((cdi->cd_info->sh_alloc != CD_ALLOCATED))
14687836SJohn.Forte@Sun.COM goto retry_open;
14697836SJohn.Forte@Sun.COM return (alloc_cd);
14707836SJohn.Forte@Sun.COM }
14717836SJohn.Forte@Sun.COM
14727836SJohn.Forte@Sun.COM if (!(cdi->cd_rawfd =
14737836SJohn.Forte@Sun.COM nsc_open(filename, NSC_SDBC_ID|NSC_DEVICE, _sdbc_fd_def,
14747836SJohn.Forte@Sun.COM (blind_t)(unsigned long)alloc_cd, &rc)) ||
14757836SJohn.Forte@Sun.COM !nsc_getval(cdi->cd_rawfd, "DevMaj", (int *)&devmaj) ||
14767836SJohn.Forte@Sun.COM !nsc_getval(cdi->cd_rawfd, "DevMin", (int *)&devmin)) {
14777836SJohn.Forte@Sun.COM if (cdi->cd_rawfd) {
14787836SJohn.Forte@Sun.COM (void) nsc_close(cdi->cd_rawfd);
14797836SJohn.Forte@Sun.COM cdi->cd_rawfd = NULL;
14807836SJohn.Forte@Sun.COM }
14817836SJohn.Forte@Sun.COM /*
14827836SJohn.Forte@Sun.COM * take into account that there may be pinned data on a
14837836SJohn.Forte@Sun.COM * device that can no longer be opened
14847836SJohn.Forte@Sun.COM */
14857836SJohn.Forte@Sun.COM open_failed++;
14867836SJohn.Forte@Sun.COM if (!(cdi->cd_info->sh_failed) && !failover_open) {
14877836SJohn.Forte@Sun.COM cdi->cd_info->sh_alloc = 0;
14887836SJohn.Forte@Sun.COM mutex_enter(&_sd_cache_lock);
14897836SJohn.Forte@Sun.COM _sd_cache_stats->st_count--;
14907836SJohn.Forte@Sun.COM mutex_exit(&_sd_cache_lock);
14917836SJohn.Forte@Sun.COM if (!rc)
14927836SJohn.Forte@Sun.COM rc = EIO;
14937836SJohn.Forte@Sun.COM return (-rc);
14947836SJohn.Forte@Sun.COM }
14957836SJohn.Forte@Sun.COM }
14967836SJohn.Forte@Sun.COM
14977836SJohn.Forte@Sun.COM cdi->cd_strategy = nsc_get_strategy(devmaj);
14987836SJohn.Forte@Sun.COM cdi->cd_crdev = makedevice(devmaj, devmin);
14997836SJohn.Forte@Sun.COM cdi->cd_desc = alloc_cd;
15007836SJohn.Forte@Sun.COM cdi->cd_dirty_head = cdi->cd_dirty_tail = NULL;
15017836SJohn.Forte@Sun.COM cdi->cd_io_head = cdi->cd_io_tail = NULL;
15027836SJohn.Forte@Sun.COM cdi->cd_hint = 0;
15037836SJohn.Forte@Sun.COM #ifdef DEBUG
15047836SJohn.Forte@Sun.COM /* put the dev_t in the ioerr_inject_table */
15057836SJohn.Forte@Sun.COM _sdbc_ioj_set_dev(alloc_cd, cdi->cd_crdev);
15067836SJohn.Forte@Sun.COM #endif
15077836SJohn.Forte@Sun.COM
15087836SJohn.Forte@Sun.COM cdi->cd_global = (_sdbc_gl_file_info + alloc_cd);
15097836SJohn.Forte@Sun.COM if (open_failed) {
15107836SJohn.Forte@Sun.COM cdi->cd_info->sh_failed = 2;
15117836SJohn.Forte@Sun.COM } else if (cdi->cd_info->sh_failed != 2)
15127836SJohn.Forte@Sun.COM if ((cdi->cd_global->sv_pinned == _SD_SELF_HOST) &&
1513*9093SRamana.Srikanth@Sun.COM !failover_open)
15147836SJohn.Forte@Sun.COM cdi->cd_info->sh_failed = 1;
15157836SJohn.Forte@Sun.COM else
15167836SJohn.Forte@Sun.COM cdi->cd_info->sh_failed = 0;
15177836SJohn.Forte@Sun.COM
15187836SJohn.Forte@Sun.COM cdi->cd_flag |= flag;
15197836SJohn.Forte@Sun.COM mutex_init(&cdi->cd_lock, NULL, MUTEX_DRIVER, NULL);
15207836SJohn.Forte@Sun.COM
15217836SJohn.Forte@Sun.COM #ifndef _SD_NOTRACE
15227836SJohn.Forte@Sun.COM (void) _sdbc_tr_configure(alloc_cd);
15237836SJohn.Forte@Sun.COM #endif
15247836SJohn.Forte@Sun.COM cdi->cd_info->sh_alloc = CD_ALLOCATED;
15257836SJohn.Forte@Sun.COM cdi->cd_global = (_sdbc_gl_file_info + alloc_cd);
15267836SJohn.Forte@Sun.COM cdi->cd_info->sh_cd = (unsigned short) alloc_cd;
15277836SJohn.Forte@Sun.COM mutex_enter(&_sd_cache_lock);
15287836SJohn.Forte@Sun.COM _sd_cache_stats->st_loc_count++;
15297836SJohn.Forte@Sun.COM mutex_exit(&_sd_cache_lock);
15307836SJohn.Forte@Sun.COM
15317836SJohn.Forte@Sun.COM if (cd_kstat_add(alloc_cd) < 0) {
1532*9093SRamana.Srikanth@Sun.COM cmn_err(CE_WARN, "!Could not create kstats for cache descriptor"
1533*9093SRamana.Srikanth@Sun.COM " %d", alloc_cd);
15347836SJohn.Forte@Sun.COM }
15357836SJohn.Forte@Sun.COM
15367836SJohn.Forte@Sun.COM
15377836SJohn.Forte@Sun.COM return (open_failed ? -EIO : alloc_cd);
15387836SJohn.Forte@Sun.COM }
15397836SJohn.Forte@Sun.COM
15407836SJohn.Forte@Sun.COM
15417836SJohn.Forte@Sun.COM /*
15427836SJohn.Forte@Sun.COM * _sd_close - Close a cache descriptor.
15437836SJohn.Forte@Sun.COM *
15447836SJohn.Forte@Sun.COM * ARGUMENTS:
15457836SJohn.Forte@Sun.COM * cd - the cache descriptor to be closed.
15467836SJohn.Forte@Sun.COM * RETURNS:
15477836SJohn.Forte@Sun.COM * 0 on success.
15487836SJohn.Forte@Sun.COM * Error otherwise.
15497836SJohn.Forte@Sun.COM *
15507836SJohn.Forte@Sun.COM * Note: Under Construction.
15517836SJohn.Forte@Sun.COM */
15527836SJohn.Forte@Sun.COM
15537836SJohn.Forte@Sun.COM int
_sd_close(int cd)15547836SJohn.Forte@Sun.COM _sd_close(int cd)
15557836SJohn.Forte@Sun.COM {
15567836SJohn.Forte@Sun.COM int rc;
15577836SJohn.Forte@Sun.COM _sd_cd_info_t *cdi = &(_sd_cache_files[cd]);
15587836SJohn.Forte@Sun.COM
15597836SJohn.Forte@Sun.COM if (!FILE_OPENED(cd)) {
15607836SJohn.Forte@Sun.COM rc = EINVAL;
15617836SJohn.Forte@Sun.COM goto out;
15627836SJohn.Forte@Sun.COM }
15637836SJohn.Forte@Sun.COM
15647836SJohn.Forte@Sun.COM SDTRACE(ST_ENTER|SDF_CLOSE, cd, 0, SDT_INV_BL, 0, 0);
15657836SJohn.Forte@Sun.COM
15667836SJohn.Forte@Sun.COM mutex_enter(&_sd_cache_lock);
15677836SJohn.Forte@Sun.COM if ((cdi->cd_info->sh_alloc == 0) ||
15687836SJohn.Forte@Sun.COM (cdi->cd_info->sh_alloc & CD_CLOSE_IN_PROGRESS)) {
15697836SJohn.Forte@Sun.COM mutex_exit(&_sd_cache_lock);
15707836SJohn.Forte@Sun.COM SDTRACE(ST_EXIT|SDF_CLOSE, cd, 0, SDT_INV_BL, 0, EINVAL);
15717836SJohn.Forte@Sun.COM rc = EINVAL;
15727836SJohn.Forte@Sun.COM goto out;
15737836SJohn.Forte@Sun.COM }
15747836SJohn.Forte@Sun.COM cdi->cd_info->sh_alloc |= CD_CLOSE_IN_PROGRESS;
15757836SJohn.Forte@Sun.COM mutex_exit(&_sd_cache_lock);
15767836SJohn.Forte@Sun.COM
15777836SJohn.Forte@Sun.COM /*
15787836SJohn.Forte@Sun.COM * _sd_flush_cd() will return -1 for the case where pinned
15797836SJohn.Forte@Sun.COM * data is present, but has been transfered to the mirror
15807836SJohn.Forte@Sun.COM * node. In this case it is safe to close the device as
15817836SJohn.Forte@Sun.COM * though _sd_flush_cd() had returned 0.
15827836SJohn.Forte@Sun.COM */
15837836SJohn.Forte@Sun.COM
15847836SJohn.Forte@Sun.COM rc = _sd_flush_cd(cd);
15857836SJohn.Forte@Sun.COM if (rc == -1)
15867836SJohn.Forte@Sun.COM rc = 0;
15877836SJohn.Forte@Sun.COM
15887836SJohn.Forte@Sun.COM if (rc != 0) {
15897836SJohn.Forte@Sun.COM mutex_enter(&_sd_cache_lock);
15907836SJohn.Forte@Sun.COM if ((rc == EAGAIN) &&
1591*9093SRamana.Srikanth@Sun.COM (cdi->cd_global->sv_pinned == _SD_NO_HOST)) {
1592*9093SRamana.Srikanth@Sun.COM cdi->cd_global->sv_pinned = _SD_SELF_HOST;
1593*9093SRamana.Srikanth@Sun.COM SSOP_SETVOL(sdbc_safestore, cdi->cd_global);
15947836SJohn.Forte@Sun.COM }
15957836SJohn.Forte@Sun.COM
15967836SJohn.Forte@Sun.COM cdi->cd_info->sh_alloc &= ~CD_CLOSE_IN_PROGRESS;
15977836SJohn.Forte@Sun.COM mutex_exit(&_sd_cache_lock);
15987836SJohn.Forte@Sun.COM SDTRACE(ST_EXIT|SDF_CLOSE, cd, 0, SDT_INV_BL,
1599*9093SRamana.Srikanth@Sun.COM _SD_CD_WBLK_USED(cd), rc);
16007836SJohn.Forte@Sun.COM goto out;
16017836SJohn.Forte@Sun.COM }
16027836SJohn.Forte@Sun.COM
16037836SJohn.Forte@Sun.COM rc = nsc_close(cdi->cd_rawfd);
16047836SJohn.Forte@Sun.COM if (rc) {
16057836SJohn.Forte@Sun.COM mutex_enter(&_sd_cache_lock);
16067836SJohn.Forte@Sun.COM cdi->cd_info->sh_alloc &= ~CD_CLOSE_IN_PROGRESS;
16077836SJohn.Forte@Sun.COM mutex_exit(&_sd_cache_lock);
16087836SJohn.Forte@Sun.COM SDTRACE(ST_EXIT|SDF_CLOSE, cd, 0, SDT_INV_BL, 0, rc);
16097836SJohn.Forte@Sun.COM goto out;
16107836SJohn.Forte@Sun.COM }
16117836SJohn.Forte@Sun.COM mutex_enter(&_sd_cache_lock);
16127836SJohn.Forte@Sun.COM _sd_cache_stats->st_loc_count--;
16137836SJohn.Forte@Sun.COM mutex_exit(&_sd_cache_lock);
16147836SJohn.Forte@Sun.COM
16157836SJohn.Forte@Sun.COM if (cd_kstat_remove(cd) < 0) {
1616*9093SRamana.Srikanth@Sun.COM cmn_err(CE_WARN, "!Could not remove kstat for cache descriptor "
16177836SJohn.Forte@Sun.COM "%d", cd);
16187836SJohn.Forte@Sun.COM }
16197836SJohn.Forte@Sun.COM
16207836SJohn.Forte@Sun.COM cdi->cd_info->sh_alloc = 0;
16217836SJohn.Forte@Sun.COM cdi->cd_info->sh_failed = 0;
16227836SJohn.Forte@Sun.COM /* cdi->cd_info = NULL; */
16237836SJohn.Forte@Sun.COM cdi->cd_flag = 0;
16247836SJohn.Forte@Sun.COM SDTRACE(ST_EXIT|SDF_CLOSE, cd, 0, SDT_INV_BL, 0, NSC_DONE);
16257836SJohn.Forte@Sun.COM rc = NSC_DONE;
16267836SJohn.Forte@Sun.COM goto out;
16277836SJohn.Forte@Sun.COM
16287836SJohn.Forte@Sun.COM out:
16297836SJohn.Forte@Sun.COM return (rc);
16307836SJohn.Forte@Sun.COM }
16317836SJohn.Forte@Sun.COM
16327836SJohn.Forte@Sun.COM
16337836SJohn.Forte@Sun.COM static int
_sd_close_io(blind_t xcd)16347836SJohn.Forte@Sun.COM _sd_close_io(blind_t xcd)
16357836SJohn.Forte@Sun.COM {
16367836SJohn.Forte@Sun.COM _sd_cd_info_t *cdi;
16377836SJohn.Forte@Sun.COM int cd = (int)(unsigned long)xcd;
16387836SJohn.Forte@Sun.COM int rc = 0;
16397836SJohn.Forte@Sun.COM
16407836SJohn.Forte@Sun.COM if ((rc = _sd_close((int)cd)) == NSC_DONE) {
16417836SJohn.Forte@Sun.COM cdi = &(_sd_cache_files[cd]);
16427836SJohn.Forte@Sun.COM cdi->cd_iodev = NULL;
16437836SJohn.Forte@Sun.COM }
16447836SJohn.Forte@Sun.COM
16457836SJohn.Forte@Sun.COM return (rc);
16467836SJohn.Forte@Sun.COM }
16477836SJohn.Forte@Sun.COM
16487836SJohn.Forte@Sun.COM
16497836SJohn.Forte@Sun.COM /*
16507836SJohn.Forte@Sun.COM * _sdbc_remote_store_pinned - reflect pinned/failed blocks for cd
16517836SJohn.Forte@Sun.COM * to our remote mirror. Returns count of blocks reflected or -1 on error.
16527836SJohn.Forte@Sun.COM *
16537836SJohn.Forte@Sun.COM */
16547836SJohn.Forte@Sun.COM int
_sdbc_remote_store_pinned(int cd)16557836SJohn.Forte@Sun.COM _sdbc_remote_store_pinned(int cd)
16567836SJohn.Forte@Sun.COM {
16577836SJohn.Forte@Sun.COM int cnt = 0;
16587836SJohn.Forte@Sun.COM _sd_cd_info_t *cdi = &(_sd_cache_files[cd]);
16597836SJohn.Forte@Sun.COM _sd_cctl_t *cc_ent, *cc_list;
16607836SJohn.Forte@Sun.COM
16617836SJohn.Forte@Sun.COM ASSERT(cd >= 0);
16627836SJohn.Forte@Sun.COM if (cdi->cd_info->sh_failed) {
16637836SJohn.Forte@Sun.COM
16647836SJohn.Forte@Sun.COM if (cdi->cd_global->sv_pinned == _SD_NO_HOST) {
16657836SJohn.Forte@Sun.COM cdi->cd_global->sv_pinned = _SD_SELF_HOST;
16667836SJohn.Forte@Sun.COM SSOP_SETVOL(sdbc_safestore, cdi->cd_global);
16677836SJohn.Forte@Sun.COM }
16687836SJohn.Forte@Sun.COM
16697836SJohn.Forte@Sun.COM mutex_enter(&cdi->cd_lock);
16707836SJohn.Forte@Sun.COM cc_ent = cc_list = cdi->cd_fail_head;
16717836SJohn.Forte@Sun.COM while (cc_ent) {
16727836SJohn.Forte@Sun.COM cnt++;
16737836SJohn.Forte@Sun.COM
16747836SJohn.Forte@Sun.COM /* is this always necessary? jgk */
16757836SJohn.Forte@Sun.COM
16767836SJohn.Forte@Sun.COM if (SSOP_WRITE_CBLOCK(sdbc_safestore,
1677*9093SRamana.Srikanth@Sun.COM cc_ent->cc_write->sc_res, cc_ent->cc_data,
1678*9093SRamana.Srikanth@Sun.COM CACHE_BLOCK_SIZE, 0)) {
16797836SJohn.Forte@Sun.COM mutex_exit(&cdi->cd_lock);
16807836SJohn.Forte@Sun.COM return (-1);
16817836SJohn.Forte@Sun.COM }
16827836SJohn.Forte@Sun.COM
16837836SJohn.Forte@Sun.COM /* update the cache block metadata */
16847836SJohn.Forte@Sun.COM CENTRY_SET_FTPOS(cc_ent);
16857836SJohn.Forte@Sun.COM cc_ent->cc_write->sc_flag = cc_ent->cc_flag;
16867836SJohn.Forte@Sun.COM
16877836SJohn.Forte@Sun.COM cc_ent->cc_write->sc_dirty = CENTRY_DIRTY(cc_ent);
16887836SJohn.Forte@Sun.COM
16897836SJohn.Forte@Sun.COM SSOP_SETCENTRY(sdbc_safestore, cc_ent->cc_write);
16907836SJohn.Forte@Sun.COM
16917836SJohn.Forte@Sun.COM cc_ent = cc_ent->cc_dirty_next;
16927836SJohn.Forte@Sun.COM if (!cc_ent)
16937836SJohn.Forte@Sun.COM cc_ent = cc_list = cc_list->cc_dirty_link;
16947836SJohn.Forte@Sun.COM }
16957836SJohn.Forte@Sun.COM mutex_exit(&cdi->cd_lock);
16967836SJohn.Forte@Sun.COM }
16977836SJohn.Forte@Sun.COM
16987836SJohn.Forte@Sun.COM return (cnt);
16997836SJohn.Forte@Sun.COM }
17007836SJohn.Forte@Sun.COM
17017836SJohn.Forte@Sun.COM /*
17027836SJohn.Forte@Sun.COM * _sd_flush_cd()
17037836SJohn.Forte@Sun.COM * reflect pinned blocks to mirrored node
17047836SJohn.Forte@Sun.COM * wait for dirty blocks to be flushed
17057836SJohn.Forte@Sun.COM * returns:
17067836SJohn.Forte@Sun.COM * EIO I/O failure, or pinned blocks and no mirror
17077836SJohn.Forte@Sun.COM * EAGAIN Hang: count of outstanding writes isn't decreasing
17087836SJohn.Forte@Sun.COM * -1 pinned blocks, reflected to mirror
17097836SJohn.Forte@Sun.COM * 0 success
17107836SJohn.Forte@Sun.COM */
17117836SJohn.Forte@Sun.COM static int
_sd_flush_cd(int cd)17127836SJohn.Forte@Sun.COM _sd_flush_cd(int cd)
17137836SJohn.Forte@Sun.COM {
17147836SJohn.Forte@Sun.COM int rc;
17157836SJohn.Forte@Sun.COM
17167836SJohn.Forte@Sun.COM if ((rc = _sd_wait_for_flush(cd)) == 0)
17177836SJohn.Forte@Sun.COM return (0);
17187836SJohn.Forte@Sun.COM
17197836SJohn.Forte@Sun.COM /*
17207836SJohn.Forte@Sun.COM * if we timed out simply return otherwise
17217836SJohn.Forte@Sun.COM * it must be an i/o type of error
17227836SJohn.Forte@Sun.COM */
17237836SJohn.Forte@Sun.COM if (rc == EAGAIN)
17247836SJohn.Forte@Sun.COM return (rc);
17257836SJohn.Forte@Sun.COM
17267836SJohn.Forte@Sun.COM if (_sd_is_mirror_down())
17277836SJohn.Forte@Sun.COM return (EIO); /* already failed, no mirror */
17287836SJohn.Forte@Sun.COM
17297836SJohn.Forte@Sun.COM /* flush any pinned/failed blocks to mirror */
17307836SJohn.Forte@Sun.COM if (_sdbc_remote_store_pinned(cd) >= 0)
17317836SJohn.Forte@Sun.COM /*
17327836SJohn.Forte@Sun.COM * At this point it looks like we have blocks on the
17337836SJohn.Forte@Sun.COM * failed list and taking up space on this node but
17347836SJohn.Forte@Sun.COM * no longer have responsibility for the blocks.
17357836SJohn.Forte@Sun.COM * These blocks will in fact be freed from the cache
17367836SJohn.Forte@Sun.COM * and the failed list when the mirror picks them up
17377836SJohn.Forte@Sun.COM * from safe storage and then calls _sd_cd_discard_mirror
17387836SJohn.Forte@Sun.COM * which will issue an rpc telling us to finish up.
17397836SJohn.Forte@Sun.COM *
17407836SJohn.Forte@Sun.COM * Should the other node die before sending the rpc then
17417836SJohn.Forte@Sun.COM * we are safe with these blocks simply waiting on the
17427836SJohn.Forte@Sun.COM * failed list.
17437836SJohn.Forte@Sun.COM */
17447836SJohn.Forte@Sun.COM return (-1);
17457836SJohn.Forte@Sun.COM else
17467836SJohn.Forte@Sun.COM return (rc);
17477836SJohn.Forte@Sun.COM }
17487836SJohn.Forte@Sun.COM
17497836SJohn.Forte@Sun.COM /*
17507836SJohn.Forte@Sun.COM * _sdbc_io_attach_cd -- set up for client access to device, reserve raw device
17517836SJohn.Forte@Sun.COM *
17527836SJohn.Forte@Sun.COM * ARGUMENTS:
17537836SJohn.Forte@Sun.COM * cd - the cache descriptor to attach.
17547836SJohn.Forte@Sun.COM *
17557836SJohn.Forte@Sun.COM * RETURNS:
17567836SJohn.Forte@Sun.COM * 0 on success.
17577836SJohn.Forte@Sun.COM * Error otherwise.
17587836SJohn.Forte@Sun.COM */
17597836SJohn.Forte@Sun.COM int
_sdbc_io_attach_cd(blind_t xcd)17607836SJohn.Forte@Sun.COM _sdbc_io_attach_cd(blind_t xcd)
17617836SJohn.Forte@Sun.COM {
17627836SJohn.Forte@Sun.COM int rc = 0;
17637836SJohn.Forte@Sun.COM _sd_cd_info_t *cdi;
17647836SJohn.Forte@Sun.COM int cd = (int)(unsigned long)xcd;
17657836SJohn.Forte@Sun.COM
17667836SJohn.Forte@Sun.COM SDTRACE(ST_ENTER|SDF_ATTACH, cd, 0, SDT_INV_BL, 0, 0);
17677836SJohn.Forte@Sun.COM if (!_sd_cache_initialized ||
17687836SJohn.Forte@Sun.COM _sdbc_shutdown_in_progress ||
17697836SJohn.Forte@Sun.COM !FILE_OPENED(cd)) {
17707836SJohn.Forte@Sun.COM SDTRACE(ST_EXIT|SDF_ATTACH, cd, 0, SDT_INV_BL, 0, EINVAL);
17717836SJohn.Forte@Sun.COM
17727836SJohn.Forte@Sun.COM DTRACE_PROBE(_sdbc_io_attach_cd_end1);
17737836SJohn.Forte@Sun.COM
17747836SJohn.Forte@Sun.COM return (EINVAL);
17757836SJohn.Forte@Sun.COM }
17767836SJohn.Forte@Sun.COM cdi = &(_sd_cache_files[cd]);
17777836SJohn.Forte@Sun.COM
17787836SJohn.Forte@Sun.COM /*
17797836SJohn.Forte@Sun.COM * check if disk is failed without raw device open. If it is,
17807836SJohn.Forte@Sun.COM * it has to be recovered using _sd_disk_online
17817836SJohn.Forte@Sun.COM */
17827836SJohn.Forte@Sun.COM
17837836SJohn.Forte@Sun.COM if (cdi->cd_global->sv_pinned == _SD_SELF_HOST) {
17847836SJohn.Forte@Sun.COM _sd_print(3,
17857836SJohn.Forte@Sun.COM "_sdbc_io_attach_cd: pinned data. returning EINVAL");
17867836SJohn.Forte@Sun.COM
17877836SJohn.Forte@Sun.COM DTRACE_PROBE(_sdbc_io_attach_cd_end2);
17887836SJohn.Forte@Sun.COM
17897836SJohn.Forte@Sun.COM return (EINVAL);
17907836SJohn.Forte@Sun.COM }
17917836SJohn.Forte@Sun.COM
17927836SJohn.Forte@Sun.COM if ((cdi->cd_info == NULL) || (cdi->cd_info->sh_failed)) {
17937836SJohn.Forte@Sun.COM DTRACE_PROBE1(_sdbc_io_attach_cd_end3,
1794*9093SRamana.Srikanth@Sun.COM struct _sd_shared *, cdi->cd_info);
17957836SJohn.Forte@Sun.COM
17967836SJohn.Forte@Sun.COM return (EINVAL);
17977836SJohn.Forte@Sun.COM }
17987836SJohn.Forte@Sun.COM
17997836SJohn.Forte@Sun.COM #if defined(_SD_FAULT_RES)
18007836SJohn.Forte@Sun.COM /* wait for node recovery to finish */
1801*9093SRamana.Srikanth@Sun.COM if (_sd_node_recovery)
1802*9093SRamana.Srikanth@Sun.COM (void) _sd_recovery_wait();
18037836SJohn.Forte@Sun.COM #endif
18047836SJohn.Forte@Sun.COM
18057836SJohn.Forte@Sun.COM /* this will provoke a sdbc_fd_attach_cd call .. */
18067836SJohn.Forte@Sun.COM
18077836SJohn.Forte@Sun.COM rc = nsc_reserve(cdi->cd_rawfd, NSC_MULTI);
18087836SJohn.Forte@Sun.COM SDTRACE(ST_EXIT|SDF_ATTACH, cd, 0, SDT_INV_BL, 0, rc);
18097836SJohn.Forte@Sun.COM
18107836SJohn.Forte@Sun.COM return (rc);
18117836SJohn.Forte@Sun.COM }
18127836SJohn.Forte@Sun.COM
18137836SJohn.Forte@Sun.COM /*
18147836SJohn.Forte@Sun.COM * sdbc_fd_attach_cd -- setup cache for access to raw device underlying cd.
18157836SJohn.Forte@Sun.COM * This is provoked by some piece of sdbc doing a reserve on the raw device.
18167836SJohn.Forte@Sun.COM *
18177836SJohn.Forte@Sun.COM * ARGUMENTS:
18187836SJohn.Forte@Sun.COM * cd - the cache descriptor to attach.
18197836SJohn.Forte@Sun.COM *
18207836SJohn.Forte@Sun.COM * RETURNS:
18217836SJohn.Forte@Sun.COM * 0 on success.
18227836SJohn.Forte@Sun.COM * Error otherwise.
18237836SJohn.Forte@Sun.COM */
18247836SJohn.Forte@Sun.COM static int
sdbc_fd_attach_cd(blind_t xcd)18257836SJohn.Forte@Sun.COM sdbc_fd_attach_cd(blind_t xcd)
18267836SJohn.Forte@Sun.COM {
18277836SJohn.Forte@Sun.COM int rc = 0;
18287836SJohn.Forte@Sun.COM int cd = (int)(unsigned long)xcd;
18297836SJohn.Forte@Sun.COM _sd_cd_info_t *cdi;
18307836SJohn.Forte@Sun.COM
18317836SJohn.Forte@Sun.COM if (!_sd_cache_initialized || !FILE_OPENED(cd)) {
18327836SJohn.Forte@Sun.COM SDTRACE(ST_INFO|SDF_ATTACH, cd, 0, SDT_INV_BL, 0, EINVAL);
18337836SJohn.Forte@Sun.COM
18347836SJohn.Forte@Sun.COM DTRACE_PROBE(sdbc_fd_attach_cd_end1);
18357836SJohn.Forte@Sun.COM
18367836SJohn.Forte@Sun.COM return (EINVAL);
18377836SJohn.Forte@Sun.COM }
18387836SJohn.Forte@Sun.COM cdi = &(_sd_cache_files[cd]);
18397836SJohn.Forte@Sun.COM
18407836SJohn.Forte@Sun.COM #if defined(_SD_FAULT_RES)
18417836SJohn.Forte@Sun.COM /* retrieve pinned/failed data */
18427836SJohn.Forte@Sun.COM if (!_sd_node_recovery) {
18437836SJohn.Forte@Sun.COM (void) _sd_repin_cd(cd);
18447836SJohn.Forte@Sun.COM }
18457836SJohn.Forte@Sun.COM #endif
18467836SJohn.Forte@Sun.COM
18477836SJohn.Forte@Sun.COM rc = nsc_partsize(cdi->cd_rawfd, &cdi->cd_info->sh_filesize);
18487836SJohn.Forte@Sun.COM if (rc != 0) {
18497836SJohn.Forte@Sun.COM SDTRACE(ST_INFO|SDF_ATTACH, cd, 0, SDT_INV_BL, 0, rc);
18507836SJohn.Forte@Sun.COM
18517836SJohn.Forte@Sun.COM DTRACE_PROBE(sdbc_fd_attach_cd_end3);
18527836SJohn.Forte@Sun.COM
18537836SJohn.Forte@Sun.COM return (rc);
18547836SJohn.Forte@Sun.COM }
18557836SJohn.Forte@Sun.COM
18567836SJohn.Forte@Sun.COM cdi->cd_global->sv_attached = _SD_SELF_HOST;
18577836SJohn.Forte@Sun.COM
18587836SJohn.Forte@Sun.COM SSOP_SETVOL(sdbc_safestore, cdi->cd_global);
18597836SJohn.Forte@Sun.COM
18607836SJohn.Forte@Sun.COM mutex_enter(&_sd_cache_lock);
18617836SJohn.Forte@Sun.COM cdi->cd_info->sh_flag |= CD_ATTACHED;
18627836SJohn.Forte@Sun.COM mutex_exit(&_sd_cache_lock);
18637836SJohn.Forte@Sun.COM
18647836SJohn.Forte@Sun.COM return (0);
18657836SJohn.Forte@Sun.COM }
18667836SJohn.Forte@Sun.COM
18677836SJohn.Forte@Sun.COM /*
18687836SJohn.Forte@Sun.COM * _sdbc_io_detach_cd -- release raw device
18697836SJohn.Forte@Sun.COM * Called when a cache client is being detached from this cd.
18707836SJohn.Forte@Sun.COM *
18717836SJohn.Forte@Sun.COM * ARGUMENTS:
18727836SJohn.Forte@Sun.COM * cd - the cache descriptor to detach.
18737836SJohn.Forte@Sun.COM * RETURNS:
18747836SJohn.Forte@Sun.COM * 0 on success.
18757836SJohn.Forte@Sun.COM * Error otherwise.
18767836SJohn.Forte@Sun.COM */
18777836SJohn.Forte@Sun.COM int
_sdbc_io_detach_cd(blind_t xcd)18787836SJohn.Forte@Sun.COM _sdbc_io_detach_cd(blind_t xcd)
18797836SJohn.Forte@Sun.COM {
18807836SJohn.Forte@Sun.COM int cd = (int)(unsigned long)xcd;
18817836SJohn.Forte@Sun.COM _sd_cd_info_t *cdi;
18827836SJohn.Forte@Sun.COM
18837836SJohn.Forte@Sun.COM
18847836SJohn.Forte@Sun.COM SDTRACE(ST_ENTER|SDF_DETACH, cd, 0, SDT_INV_BL, 0, 0);
18857836SJohn.Forte@Sun.COM if (!_sd_cache_initialized || !FILE_OPENED(cd)) {
18867836SJohn.Forte@Sun.COM SDTRACE(ST_EXIT|SDF_DETACH, cd, 0, SDT_INV_BL, 0, EINVAL);
18877836SJohn.Forte@Sun.COM
18887836SJohn.Forte@Sun.COM DTRACE_PROBE(_sdbc_io_detach_cd_end1);
18897836SJohn.Forte@Sun.COM
18907836SJohn.Forte@Sun.COM return (EINVAL);
18917836SJohn.Forte@Sun.COM }
18927836SJohn.Forte@Sun.COM
18937836SJohn.Forte@Sun.COM #if defined(_SD_FAULT_RES)
1894*9093SRamana.Srikanth@Sun.COM if (_sd_node_recovery)
1895*9093SRamana.Srikanth@Sun.COM (void) _sd_recovery_wait();
18967836SJohn.Forte@Sun.COM #endif
18977836SJohn.Forte@Sun.COM /* relinquish responsibility for device */
18987836SJohn.Forte@Sun.COM cdi = &(_sd_cache_files[cd]);
18997836SJohn.Forte@Sun.COM if (!(cdi->cd_rawfd) || !nsc_held(cdi->cd_rawfd)) {
1900*9093SRamana.Srikanth@Sun.COM cmn_err(CE_WARN, "!sdbc(_sdbc_detach_cd)(%d) not attached", cd);
19017836SJohn.Forte@Sun.COM SDTRACE(ST_EXIT|SDF_DETACH, cd, 0, SDT_INV_BL, 0, EPROTO);
19027836SJohn.Forte@Sun.COM DTRACE_PROBE1(_sdbc_io_detach_cd_end2,
1903*9093SRamana.Srikanth@Sun.COM nsc_fd_t *, cdi->cd_rawfd);
19047836SJohn.Forte@Sun.COM
19057836SJohn.Forte@Sun.COM return (EPROTO);
19067836SJohn.Forte@Sun.COM }
19077836SJohn.Forte@Sun.COM /* this will provoke/allow a call to sdbc_fd_detach_cd */
19087836SJohn.Forte@Sun.COM nsc_release(cdi->cd_rawfd);
19097836SJohn.Forte@Sun.COM
19107836SJohn.Forte@Sun.COM SDTRACE(ST_EXIT|SDF_DETACH, cd, 0, SDT_INV_BL, 0, 0);
19117836SJohn.Forte@Sun.COM
19127836SJohn.Forte@Sun.COM return (0);
19137836SJohn.Forte@Sun.COM }
19147836SJohn.Forte@Sun.COM
19157836SJohn.Forte@Sun.COM /*
19167836SJohn.Forte@Sun.COM * _sdbc_detach_cd -- flush dirty writes to disk, release raw device
19177836SJohn.Forte@Sun.COM * Called when raw device is being detached from this cd.
19187836SJohn.Forte@Sun.COM *
19197836SJohn.Forte@Sun.COM * ARGUMENTS:
19207836SJohn.Forte@Sun.COM * cd - the cache descriptor to detach.
19217836SJohn.Forte@Sun.COM * rd_only - non-zero if detach is for read access.
19227836SJohn.Forte@Sun.COM * RETURNS:
19237836SJohn.Forte@Sun.COM * 0 on success.
19247836SJohn.Forte@Sun.COM * Error otherwise.
19257836SJohn.Forte@Sun.COM */
19267836SJohn.Forte@Sun.COM static int
sdbc_detach_cd(blind_t xcd,int rd_only)19277836SJohn.Forte@Sun.COM sdbc_detach_cd(blind_t xcd, int rd_only)
19287836SJohn.Forte@Sun.COM {
19297836SJohn.Forte@Sun.COM int rc;
19307836SJohn.Forte@Sun.COM int cd = (int)(unsigned long)xcd;
19317836SJohn.Forte@Sun.COM _sd_cd_info_t *cdi;
19327836SJohn.Forte@Sun.COM
19337836SJohn.Forte@Sun.COM SDTRACE(ST_INFO|SDF_DETACH, cd, 0, SDT_INV_BL, 0, 0);
19347836SJohn.Forte@Sun.COM
19357836SJohn.Forte@Sun.COM if (!_sd_cache_initialized || !FILE_OPENED(cd)) {
19367836SJohn.Forte@Sun.COM SDTRACE(ST_INFO|SDF_DETACH, cd, 0, SDT_INV_BL, 0, EINVAL);
19377836SJohn.Forte@Sun.COM
19387836SJohn.Forte@Sun.COM DTRACE_PROBE(sdbc_detach_cd_end1);
19397836SJohn.Forte@Sun.COM
19407836SJohn.Forte@Sun.COM return (EINVAL);
19417836SJohn.Forte@Sun.COM }
19427836SJohn.Forte@Sun.COM
19437836SJohn.Forte@Sun.COM
19447836SJohn.Forte@Sun.COM rc = _sd_flush_cd(cd);
19457836SJohn.Forte@Sun.COM if (rc > 0) {
19467836SJohn.Forte@Sun.COM SDTRACE(ST_INFO|SDF_DETACH, cd, 0, SDT_INV_BL, 0, rc);
19477836SJohn.Forte@Sun.COM
19487836SJohn.Forte@Sun.COM DTRACE_PROBE(sdbc_detach_cd_end2);
19497836SJohn.Forte@Sun.COM
19507836SJohn.Forte@Sun.COM return (rc);
19517836SJohn.Forte@Sun.COM }
19527836SJohn.Forte@Sun.COM
19537836SJohn.Forte@Sun.COM if (!rd_only) {
19547836SJohn.Forte@Sun.COM _sd_hash_invalidate_cd(cd);
19557836SJohn.Forte@Sun.COM cdi = &(_sd_cache_files[cd]);
19567836SJohn.Forte@Sun.COM
19577836SJohn.Forte@Sun.COM if (cdi->cd_global->sv_attached == _SD_SELF_HOST) {
19587836SJohn.Forte@Sun.COM cdi->cd_global->sv_attached = _SD_NO_HOST;
19597836SJohn.Forte@Sun.COM SSOP_SETVOL(sdbc_safestore, cdi->cd_global);
19607836SJohn.Forte@Sun.COM } else {
19617836SJohn.Forte@Sun.COM cmn_err(CE_WARN,
1962*9093SRamana.Srikanth@Sun.COM "!sdbc(_sdbc_detach_cd) (%d) attached by node %d",
19637836SJohn.Forte@Sun.COM cd, cdi->cd_global->sv_attached);
19647836SJohn.Forte@Sun.COM SDTRACE(SDF_DETACH, cd, 0, SDT_INV_BL, 0, EPROTO);
19657836SJohn.Forte@Sun.COM
19667836SJohn.Forte@Sun.COM DTRACE_PROBE1(sdbc_detach_cd_end3,
1967*9093SRamana.Srikanth@Sun.COM int, cdi->cd_global->sv_attached);
19687836SJohn.Forte@Sun.COM
19697836SJohn.Forte@Sun.COM return (EPROTO);
19707836SJohn.Forte@Sun.COM }
19717836SJohn.Forte@Sun.COM
19727836SJohn.Forte@Sun.COM mutex_enter(&_sd_cache_lock);
19737836SJohn.Forte@Sun.COM cdi->cd_info->sh_flag &= ~CD_ATTACHED;
19747836SJohn.Forte@Sun.COM mutex_exit(&_sd_cache_lock);
19757836SJohn.Forte@Sun.COM }
19767836SJohn.Forte@Sun.COM
19777836SJohn.Forte@Sun.COM SDTRACE(ST_INFO|SDF_DETACH, cd, 0, SDT_INV_BL, 0, 0);
19787836SJohn.Forte@Sun.COM
19797836SJohn.Forte@Sun.COM return (0);
19807836SJohn.Forte@Sun.COM }
19817836SJohn.Forte@Sun.COM
19827836SJohn.Forte@Sun.COM /*
19837836SJohn.Forte@Sun.COM * _sdbc_fd_detach_cd -- flush dirty writes to disk, release raw device
19847836SJohn.Forte@Sun.COM * Called when raw device is being detached from this cd.
19857836SJohn.Forte@Sun.COM *
19867836SJohn.Forte@Sun.COM * ARGUMENTS:
19877836SJohn.Forte@Sun.COM * xcd - the cache descriptor to detach.
19887836SJohn.Forte@Sun.COM * RETURNS:
19897836SJohn.Forte@Sun.COM * 0 on success.
19907836SJohn.Forte@Sun.COM * Error otherwise.
19917836SJohn.Forte@Sun.COM */
19927836SJohn.Forte@Sun.COM static int
sdbc_fd_detach_cd(blind_t xcd)19937836SJohn.Forte@Sun.COM sdbc_fd_detach_cd(blind_t xcd)
19947836SJohn.Forte@Sun.COM {
19957836SJohn.Forte@Sun.COM return (sdbc_detach_cd(xcd, 0));
19967836SJohn.Forte@Sun.COM }
19977836SJohn.Forte@Sun.COM
19987836SJohn.Forte@Sun.COM /*
19997836SJohn.Forte@Sun.COM * sdbc_fd_flush_cd - raw device "xcd" is being detached and needs
20007836SJohn.Forte@Sun.COM * flushing. We only need to flush we don't need to hash invalidate
20017836SJohn.Forte@Sun.COM * this file.
20027836SJohn.Forte@Sun.COM */
20037836SJohn.Forte@Sun.COM static int
sdbc_fd_flush_cd(blind_t xcd)20047836SJohn.Forte@Sun.COM sdbc_fd_flush_cd(blind_t xcd)
20057836SJohn.Forte@Sun.COM {
20067836SJohn.Forte@Sun.COM return (sdbc_detach_cd(xcd, 1));
20077836SJohn.Forte@Sun.COM }
20087836SJohn.Forte@Sun.COM
20097836SJohn.Forte@Sun.COM /*
20107836SJohn.Forte@Sun.COM * _sd_get_pinned - re-issue PINNED callbacks for cache device
20117836SJohn.Forte@Sun.COM *
20127836SJohn.Forte@Sun.COM * ARGUMENTS:
20137836SJohn.Forte@Sun.COM * cd - the cache descriptor to reissue pinned calbacks from.
20147836SJohn.Forte@Sun.COM * RETURNS:
20157836SJohn.Forte@Sun.COM * 0 on success.
20167836SJohn.Forte@Sun.COM * Error otherwise.
20177836SJohn.Forte@Sun.COM */
20187836SJohn.Forte@Sun.COM int
_sd_get_pinned(blind_t xcd)20197836SJohn.Forte@Sun.COM _sd_get_pinned(blind_t xcd)
20207836SJohn.Forte@Sun.COM {
20217836SJohn.Forte@Sun.COM _sd_cd_info_t *cdi;
20227836SJohn.Forte@Sun.COM _sd_cctl_t *cc_list, *cc_ent;
20237836SJohn.Forte@Sun.COM int cd = (int)(unsigned long)xcd;
20247836SJohn.Forte@Sun.COM
20257836SJohn.Forte@Sun.COM cdi = &_sd_cache_files[cd];
20267836SJohn.Forte@Sun.COM
20277836SJohn.Forte@Sun.COM if (cd < 0 || cd >= sdbc_max_devs) {
20287836SJohn.Forte@Sun.COM DTRACE_PROBE(_sd_get_pinned_end1);
20297836SJohn.Forte@Sun.COM return (EINVAL);
20307836SJohn.Forte@Sun.COM }
20317836SJohn.Forte@Sun.COM
20327836SJohn.Forte@Sun.COM if (!FILE_OPENED(cd)) {
20337836SJohn.Forte@Sun.COM DTRACE_PROBE(_sd_get_pinned_end2);
20347836SJohn.Forte@Sun.COM return (0);
20357836SJohn.Forte@Sun.COM }
20367836SJohn.Forte@Sun.COM
20377836SJohn.Forte@Sun.COM mutex_enter(&cdi->cd_lock);
20387836SJohn.Forte@Sun.COM
20397836SJohn.Forte@Sun.COM if (!cdi->cd_info->sh_failed) {
20407836SJohn.Forte@Sun.COM mutex_exit(&cdi->cd_lock);
20417836SJohn.Forte@Sun.COM
20427836SJohn.Forte@Sun.COM DTRACE_PROBE(_sd_get_pinned_end3);
20437836SJohn.Forte@Sun.COM return (0);
20447836SJohn.Forte@Sun.COM }
20457836SJohn.Forte@Sun.COM
20467836SJohn.Forte@Sun.COM cc_ent = cc_list = cdi->cd_fail_head;
20477836SJohn.Forte@Sun.COM while (cc_ent) {
20487836SJohn.Forte@Sun.COM if (CENTRY_PINNED(cc_ent))
20497836SJohn.Forte@Sun.COM nsc_pinned_data(cdi->cd_iodev,
2050*9093SRamana.Srikanth@Sun.COM BLK_TO_FBA_NUM(CENTRY_BLK(cc_ent)), BLK_FBAS);
20517836SJohn.Forte@Sun.COM cc_ent = cc_ent->cc_dirty_next;
20527836SJohn.Forte@Sun.COM if (!cc_ent)
20537836SJohn.Forte@Sun.COM cc_ent = cc_list = cc_list->cc_dirty_link;
20547836SJohn.Forte@Sun.COM }
20557836SJohn.Forte@Sun.COM
20567836SJohn.Forte@Sun.COM mutex_exit(&cdi->cd_lock);
20577836SJohn.Forte@Sun.COM
20587836SJohn.Forte@Sun.COM return (0);
20597836SJohn.Forte@Sun.COM }
20607836SJohn.Forte@Sun.COM
20617836SJohn.Forte@Sun.COM /*
20627836SJohn.Forte@Sun.COM * _sd_allocate_buf - allocate a vector of buffers for io.
20637836SJohn.Forte@Sun.COM * *This call has been replaced by _sd_alloc_buf*
20647836SJohn.Forte@Sun.COM */
20657836SJohn.Forte@Sun.COM
20667836SJohn.Forte@Sun.COM _sd_buf_handle_t *
_sd_allocate_buf(int cd,nsc_off_t fba_pos,nsc_size_t fba_len,int flag,int * sts)20677836SJohn.Forte@Sun.COM _sd_allocate_buf(int cd, nsc_off_t fba_pos, nsc_size_t fba_len, int flag,
20687836SJohn.Forte@Sun.COM int *sts)
20697836SJohn.Forte@Sun.COM {
20707836SJohn.Forte@Sun.COM _sd_buf_handle_t *handle = NULL;
20717836SJohn.Forte@Sun.COM
20727836SJohn.Forte@Sun.COM *sts = _sd_alloc_buf((blind_t)(unsigned long)cd, fba_pos, fba_len,
20737836SJohn.Forte@Sun.COM flag, &handle);
20747836SJohn.Forte@Sun.COM if (*sts == NSC_HIT)
20757836SJohn.Forte@Sun.COM *sts = NSC_DONE;
20767836SJohn.Forte@Sun.COM return (handle);
20777836SJohn.Forte@Sun.COM }
20787836SJohn.Forte@Sun.COM
20797836SJohn.Forte@Sun.COM
20807836SJohn.Forte@Sun.COM /*
20817836SJohn.Forte@Sun.COM * _sd_prefetch_buf - _sd_alloc_buf w/flag = NSC_RDAHEAD|NSC_RDBUF
20827836SJohn.Forte@Sun.COM * no 'bufvec' (data is not read by caller)
20837836SJohn.Forte@Sun.COM * skip leading valid or busy entries (data available sooner)
20847836SJohn.Forte@Sun.COM * truncate on busy block (to avoid deadlock)
20857836SJohn.Forte@Sun.COM * release trailing valid entries, adjust length before starting I/O.
20867836SJohn.Forte@Sun.COM */
20877836SJohn.Forte@Sun.COM static int
_sd_prefetch_buf(int cd,nsc_off_t fba_pos,nsc_size_t fba_len,int flag,_sd_buf_handle_t * handle,int locked)20887836SJohn.Forte@Sun.COM _sd_prefetch_buf(int cd, nsc_off_t fba_pos, nsc_size_t fba_len, int flag,
20897836SJohn.Forte@Sun.COM _sd_buf_handle_t *handle, int locked)
20907836SJohn.Forte@Sun.COM {
20917836SJohn.Forte@Sun.COM _sd_cd_info_t *cdi;
20927836SJohn.Forte@Sun.COM nsc_off_t cblk; /* position of temp cache block */
20937836SJohn.Forte@Sun.COM sdbc_cblk_fba_t st_cblk_len; /* FBA len of starting cache block */
20947836SJohn.Forte@Sun.COM sdbc_cblk_fba_t end_cblk_len; /* FBA len of ending cache block */
20957836SJohn.Forte@Sun.COM sdbc_cblk_fba_t st_cblk_off; /* FBA offset into starting cblock */
20967836SJohn.Forte@Sun.COM nsc_off_t io_pos; /* offset in FBA's */
20977836SJohn.Forte@Sun.COM nsc_size_t fba_orig_len;
20987836SJohn.Forte@Sun.COM int sts, stall;
20997836SJohn.Forte@Sun.COM _sd_cctl_t *centry = NULL;
21007836SJohn.Forte@Sun.COM _sd_cctl_t *lentry = NULL;
21017836SJohn.Forte@Sun.COM _sd_cctl_t *ioent = NULL;
21027836SJohn.Forte@Sun.COM _sd_cctl_t *last_ioent = NULL;
21037836SJohn.Forte@Sun.COM sdbc_allocbuf_t alloc_tok = {0};
21047836SJohn.Forte@Sun.COM int this_entry_type = 0;
21057836SJohn.Forte@Sun.COM nsc_size_t request_blocks = 0; /* number of cache blocks required */
21067836SJohn.Forte@Sun.COM int pageio;
21077836SJohn.Forte@Sun.COM
21087836SJohn.Forte@Sun.COM handle->bh_flag |= NSC_HACTIVE;
21097836SJohn.Forte@Sun.COM ASSERT(cd >= 0);
21107836SJohn.Forte@Sun.COM cdi = &_sd_cache_files[cd];
21117836SJohn.Forte@Sun.COM
21127836SJohn.Forte@Sun.COM /* prefetch: truncate if req'd */
21137836SJohn.Forte@Sun.COM if (fba_len > sdbc_max_fbas)
21147836SJohn.Forte@Sun.COM fba_len = sdbc_max_fbas;
21157836SJohn.Forte@Sun.COM if ((fba_pos + fba_len) > cdi->cd_info->sh_filesize) {
21167836SJohn.Forte@Sun.COM if (fba_pos >= cdi->cd_info->sh_filesize) {
21177836SJohn.Forte@Sun.COM sts = EIO;
21187836SJohn.Forte@Sun.COM goto done;
21197836SJohn.Forte@Sun.COM }
21207836SJohn.Forte@Sun.COM fba_len = cdi->cd_info->sh_filesize - fba_pos;
21217836SJohn.Forte@Sun.COM }
21227836SJohn.Forte@Sun.COM
21237836SJohn.Forte@Sun.COM fba_orig_len = fba_len;
21247836SJohn.Forte@Sun.COM
21257836SJohn.Forte@Sun.COM _SD_SETUP_HANDLE(handle, cd, fba_pos, fba_len, flag);
21267836SJohn.Forte@Sun.COM handle->bh_centry = NULL;
21277836SJohn.Forte@Sun.COM
21287836SJohn.Forte@Sun.COM cblk = FBA_TO_BLK_NUM(fba_pos);
21297836SJohn.Forte@Sun.COM st_cblk_off = BLK_FBA_OFF(fba_pos);
21307836SJohn.Forte@Sun.COM st_cblk_len = BLK_FBAS - st_cblk_off;
21317836SJohn.Forte@Sun.COM
21327836SJohn.Forte@Sun.COM /*
21337836SJohn.Forte@Sun.COM * count number of blocks on chain that is required
21347836SJohn.Forte@Sun.COM */
21357836SJohn.Forte@Sun.COM if ((nsc_size_t)st_cblk_len >= fba_len) {
21367836SJohn.Forte@Sun.COM st_cblk_len = (sdbc_cblk_fba_t)fba_len;
21377836SJohn.Forte@Sun.COM end_cblk_len = 0;
21387836SJohn.Forte@Sun.COM } else {
21397836SJohn.Forte@Sun.COM end_cblk_len = BLK_FBA_OFF(fba_pos + fba_len);
21407836SJohn.Forte@Sun.COM }
21417836SJohn.Forte@Sun.COM
21427836SJohn.Forte@Sun.COM request_blocks = 1; /* at least one */
21437836SJohn.Forte@Sun.COM
21447836SJohn.Forte@Sun.COM /* middle piece */
21457836SJohn.Forte@Sun.COM request_blocks += (fba_len - (st_cblk_len + end_cblk_len)) >>
21467836SJohn.Forte@Sun.COM BLK_FBA_SHFT;
21477836SJohn.Forte@Sun.COM
21487836SJohn.Forte@Sun.COM if (end_cblk_len)
21497836SJohn.Forte@Sun.COM ++request_blocks;
21507836SJohn.Forte@Sun.COM
21517836SJohn.Forte@Sun.COM stall = 0;
21527836SJohn.Forte@Sun.COM do {
21537836SJohn.Forte@Sun.COM pageio = ((flag & NSC_PAGEIO) != 0 || sdbc_pageio_always != 0);
21547836SJohn.Forte@Sun.COM cget:
21557836SJohn.Forte@Sun.COM if (centry = (_sd_cctl_t *)
21567836SJohn.Forte@Sun.COM _sd_hash_search(cd, cblk, _sd_htable)) {
21577836SJohn.Forte@Sun.COM try:
21587836SJohn.Forte@Sun.COM /* prefetch: skip leading valid blocks */
21597836SJohn.Forte@Sun.COM if ((ioent == NULL) &&
21607836SJohn.Forte@Sun.COM SDBC_VALID_BITS(st_cblk_off, st_cblk_len, centry)) {
21617836SJohn.Forte@Sun.COM skip:
21627836SJohn.Forte@Sun.COM sdbc_prefetch_valid_cnt++;
21637836SJohn.Forte@Sun.COM --request_blocks;
21647836SJohn.Forte@Sun.COM lentry = centry;
21657836SJohn.Forte@Sun.COM centry = NULL;
21667836SJohn.Forte@Sun.COM cblk++;
21677836SJohn.Forte@Sun.COM fba_len -= st_cblk_len;
21687836SJohn.Forte@Sun.COM st_cblk_off = 0;
21697836SJohn.Forte@Sun.COM st_cblk_len = (sdbc_cblk_fba_t)
21707836SJohn.Forte@Sun.COM ((fba_len > (nsc_size_t)BLK_FBAS) ?
2171*9093SRamana.Srikanth@Sun.COM BLK_FBAS : fba_len);
21727836SJohn.Forte@Sun.COM continue;
21737836SJohn.Forte@Sun.COM }
21747836SJohn.Forte@Sun.COM
21757836SJohn.Forte@Sun.COM if (SET_CENTRY_INUSE(centry)) {
21767836SJohn.Forte@Sun.COM /*
21777836SJohn.Forte@Sun.COM * prefetch: skip leading busy
21787836SJohn.Forte@Sun.COM * or truncate at busy block
21797836SJohn.Forte@Sun.COM */
21807836SJohn.Forte@Sun.COM if (ioent == NULL)
21817836SJohn.Forte@Sun.COM goto skip;
21827836SJohn.Forte@Sun.COM sdbc_prefetch_busy_cnt++;
21837836SJohn.Forte@Sun.COM fba_orig_len -= fba_len;
21847836SJohn.Forte@Sun.COM fba_len = 0;
21857836SJohn.Forte@Sun.COM centry = lentry; /* backup */
21867836SJohn.Forte@Sun.COM break;
21877836SJohn.Forte@Sun.COM }
21887836SJohn.Forte@Sun.COM
21897836SJohn.Forte@Sun.COM /*
21907836SJohn.Forte@Sun.COM * bug 4529671
21917836SJohn.Forte@Sun.COM * now that we own the centry make sure that
21927836SJohn.Forte@Sun.COM * it is still good. it could have been processed
21937836SJohn.Forte@Sun.COM * by _sd_dealloc_dm() in the window between
21947836SJohn.Forte@Sun.COM * _sd_hash_search() and SET_CENTRY_INUSE().
21957836SJohn.Forte@Sun.COM */
21967836SJohn.Forte@Sun.COM if ((_sd_cctl_t *)
21977836SJohn.Forte@Sun.COM _sd_hash_search(cd, cblk, _sd_htable) != centry) {
21987836SJohn.Forte@Sun.COM sdbc_prefetch_deallocd++;
21997836SJohn.Forte@Sun.COM #ifdef DEBUG
22007836SJohn.Forte@Sun.COM cmn_err(CE_WARN,
2201*9093SRamana.Srikanth@Sun.COM "!prefetch centry %p cd %d cblk %" NSC_SZFMT
22027836SJohn.Forte@Sun.COM " fba_len %" NSC_SZFMT " lost to dealloc?! "
22037836SJohn.Forte@Sun.COM "cc_data %p",
22047836SJohn.Forte@Sun.COM (void *)centry, cd, cblk, fba_orig_len,
22057836SJohn.Forte@Sun.COM (void *)centry->cc_data);
22067836SJohn.Forte@Sun.COM #endif
22077836SJohn.Forte@Sun.COM
22087836SJohn.Forte@Sun.COM CLEAR_CENTRY_INUSE(centry);
22097836SJohn.Forte@Sun.COM continue;
22107836SJohn.Forte@Sun.COM }
22117836SJohn.Forte@Sun.COM
22127836SJohn.Forte@Sun.COM if (CC_CD_BLK_MATCH(cd, cblk, centry)) {
22137836SJohn.Forte@Sun.COM /*
22147836SJohn.Forte@Sun.COM * Do pagelist io mutual exclusion
22157836SJohn.Forte@Sun.COM * before messing with the centry.
22167836SJohn.Forte@Sun.COM */
22177836SJohn.Forte@Sun.COM if (pageio && SET_CENTRY_PAGEIO(centry)) {
22187836SJohn.Forte@Sun.COM /* flusher not done with pageio */
22197836SJohn.Forte@Sun.COM /*
22207836SJohn.Forte@Sun.COM * prefetch: skip leading busy
22217836SJohn.Forte@Sun.COM * or truncate at busy block
22227836SJohn.Forte@Sun.COM */
22237836SJohn.Forte@Sun.COM CLEAR_CENTRY_INUSE(centry);
22247836SJohn.Forte@Sun.COM if (ioent == NULL)
22257836SJohn.Forte@Sun.COM goto skip;
22267836SJohn.Forte@Sun.COM sdbc_prefetch_pageio1++;
22277836SJohn.Forte@Sun.COM fba_orig_len -= fba_len;
22287836SJohn.Forte@Sun.COM fba_len = 0;
22297836SJohn.Forte@Sun.COM centry = lentry; /* backup */
22307836SJohn.Forte@Sun.COM break;
22317836SJohn.Forte@Sun.COM
22327836SJohn.Forte@Sun.COM }
22337836SJohn.Forte@Sun.COM
22347836SJohn.Forte@Sun.COM sdbc_prefetch_hit++;
22357836SJohn.Forte@Sun.COM this_entry_type = HASH_ENTRY_DM;
22367836SJohn.Forte@Sun.COM pageio = 0;
22377836SJohn.Forte@Sun.COM centry->cc_toflush = 0;
22387836SJohn.Forte@Sun.COM
22397836SJohn.Forte@Sun.COM centry->cc_hits++;
22407836SJohn.Forte@Sun.COM
22417836SJohn.Forte@Sun.COM /* this will reset the age flag */
22427836SJohn.Forte@Sun.COM sdbc_centry_init_dm(centry);
22437836SJohn.Forte@Sun.COM
22447836SJohn.Forte@Sun.COM DTRACE_PROBE1(_sd_prefetch_buf,
2245*9093SRamana.Srikanth@Sun.COM _sd_cctl_t *, centry);
22467836SJohn.Forte@Sun.COM } else {
22477836SJohn.Forte@Sun.COM /* block mismatch */
22487836SJohn.Forte@Sun.COM sdbc_prefetch_lost++;
22497836SJohn.Forte@Sun.COM
22507836SJohn.Forte@Sun.COM CLEAR_CENTRY_INUSE(centry);
22517836SJohn.Forte@Sun.COM continue;
22527836SJohn.Forte@Sun.COM }
22537836SJohn.Forte@Sun.COM } else {
22547836SJohn.Forte@Sun.COM centry = sdbc_centry_alloc(cd, cblk, request_blocks,
2255*9093SRamana.Srikanth@Sun.COM &stall, &alloc_tok, ALLOC_NOWAIT);
22567836SJohn.Forte@Sun.COM
22577836SJohn.Forte@Sun.COM if (centry == NULL) {
22587836SJohn.Forte@Sun.COM /*
22597836SJohn.Forte@Sun.COM * prefetch: cache is very busy. just do
22607836SJohn.Forte@Sun.COM * the i/o for the blocks already acquired,
22617836SJohn.Forte@Sun.COM * if any.
22627836SJohn.Forte@Sun.COM */
22637836SJohn.Forte@Sun.COM fba_orig_len -= fba_len;
22647836SJohn.Forte@Sun.COM fba_len = 0;
22657836SJohn.Forte@Sun.COM /*
22667836SJohn.Forte@Sun.COM * if we have a chain of centry's
22677836SJohn.Forte@Sun.COM * then back up (set centry to lentry).
22687836SJohn.Forte@Sun.COM * if there is no chain (ioent == NULL)
22697836SJohn.Forte@Sun.COM * then centry remains NULL. this can occur
22707836SJohn.Forte@Sun.COM * if all previous centrys were hash hits
22717836SJohn.Forte@Sun.COM * on valid blocks that were processed in
22727836SJohn.Forte@Sun.COM * the skip logic above.
22737836SJohn.Forte@Sun.COM */
22747836SJohn.Forte@Sun.COM if (ioent)
22757836SJohn.Forte@Sun.COM centry = lentry; /* backup */
22767836SJohn.Forte@Sun.COM break;
22777836SJohn.Forte@Sun.COM }
22787836SJohn.Forte@Sun.COM
22797836SJohn.Forte@Sun.COM /*
22807836SJohn.Forte@Sun.COM * dmchaining adjustment.
22817836SJohn.Forte@Sun.COM * if centry was obtained from the dmchain
22827836SJohn.Forte@Sun.COM * then clear local pageio variable because the
22837836SJohn.Forte@Sun.COM * centry already has cc_pageio set.
22847836SJohn.Forte@Sun.COM */
22857836SJohn.Forte@Sun.COM if (CENTRY_PAGEIO(centry))
22867836SJohn.Forte@Sun.COM pageio = 0;
22877836SJohn.Forte@Sun.COM
2288*9093SRamana.Srikanth@Sun.COM DTRACE_PROBE1(_sd_alloc_buf, _sd_cctl_t *, centry);
22897836SJohn.Forte@Sun.COM
22907836SJohn.Forte@Sun.COM this_entry_type = ELIGIBLE_ENTRY_DM;
22917836SJohn.Forte@Sun.COM if (centry->cc_aging_dm & FOUND_IN_HASH_DM)
22927836SJohn.Forte@Sun.COM this_entry_type = HASH_ENTRY_DM;
22937836SJohn.Forte@Sun.COM else {
22947836SJohn.Forte@Sun.COM if (centry->cc_aging_dm & FOUND_HOLD_OVER_DM)
22957836SJohn.Forte@Sun.COM this_entry_type = HOLD_ENTRY_DM;
22967836SJohn.Forte@Sun.COM }
22977836SJohn.Forte@Sun.COM }
22987836SJohn.Forte@Sun.COM
22997836SJohn.Forte@Sun.COM centry->cc_chain = NULL;
23007836SJohn.Forte@Sun.COM
23017836SJohn.Forte@Sun.COM centry->cc_aging_dm &= ~(FOUND_IN_HASH_DM|FOUND_HOLD_OVER_DM);
23027836SJohn.Forte@Sun.COM
23037836SJohn.Forte@Sun.COM /*
23047836SJohn.Forte@Sun.COM * Do pagelist io mutual exclusion now if we did not do
23057836SJohn.Forte@Sun.COM * it above.
23067836SJohn.Forte@Sun.COM */
23077836SJohn.Forte@Sun.COM
23087836SJohn.Forte@Sun.COM if (pageio && SET_CENTRY_PAGEIO(centry)) {
23097836SJohn.Forte@Sun.COM /* flusher not done with pageio */
23107836SJohn.Forte@Sun.COM sdbc_prefetch_pageio2++;
23117836SJohn.Forte@Sun.COM
23127836SJohn.Forte@Sun.COM /*
23137836SJohn.Forte@Sun.COM * prefetch: skip leading busy
23147836SJohn.Forte@Sun.COM * or truncate at busy block
23157836SJohn.Forte@Sun.COM */
23167836SJohn.Forte@Sun.COM CLEAR_CENTRY_INUSE(centry);
23177836SJohn.Forte@Sun.COM if (ioent == NULL)
23187836SJohn.Forte@Sun.COM goto skip;
23197836SJohn.Forte@Sun.COM sdbc_prefetch_busy_cnt++;
23207836SJohn.Forte@Sun.COM fba_orig_len -= fba_len;
23217836SJohn.Forte@Sun.COM fba_len = 0;
23227836SJohn.Forte@Sun.COM centry = lentry; /* backup */
23237836SJohn.Forte@Sun.COM break;
23247836SJohn.Forte@Sun.COM }
23257836SJohn.Forte@Sun.COM
23267836SJohn.Forte@Sun.COM pageio = 0;
23277836SJohn.Forte@Sun.COM
23287836SJohn.Forte@Sun.COM fba_len -= st_cblk_len;
23297836SJohn.Forte@Sun.COM
23307836SJohn.Forte@Sun.COM if (ioent == NULL) {
23317836SJohn.Forte@Sun.COM if (!SDBC_VALID_BITS(st_cblk_off, st_cblk_len,
23327836SJohn.Forte@Sun.COM centry)) {
23337836SJohn.Forte@Sun.COM io_pos = BLK_TO_FBA_NUM(cblk) + st_cblk_off;
23347836SJohn.Forte@Sun.COM ioent = last_ioent = centry;
23357836SJohn.Forte@Sun.COM } else {
23367836SJohn.Forte@Sun.COM DATA_LOG(SDF_ALLOC, centry, st_cblk_off,
23377836SJohn.Forte@Sun.COM st_cblk_len);
23387836SJohn.Forte@Sun.COM DTRACE_PROBE4(_sd_prefetch_buf_data1,
23397836SJohn.Forte@Sun.COM uint64_t, (uint64_t)(BLK_TO_FBA_NUM(cblk) +
2340*9093SRamana.Srikanth@Sun.COM st_cblk_off), int, st_cblk_len,
23417836SJohn.Forte@Sun.COM char *, *(int64_t *)(centry->cc_data +
2342*9093SRamana.Srikanth@Sun.COM FBA_SIZE(st_cblk_off)), char *,
2343*9093SRamana.Srikanth@Sun.COM *(int64_t *)(centry->cc_data +
2344*9093SRamana.Srikanth@Sun.COM FBA_SIZE(st_cblk_off + st_cblk_len) - 8));
23457836SJohn.Forte@Sun.COM }
23467836SJohn.Forte@Sun.COM
23477836SJohn.Forte@Sun.COM handle->bh_centry = centry;
23487836SJohn.Forte@Sun.COM st_cblk_off = 0;
23497836SJohn.Forte@Sun.COM st_cblk_len = (sdbc_cblk_fba_t)
23507836SJohn.Forte@Sun.COM ((fba_len > (nsc_size_t)BLK_FBAS) ?
2351*9093SRamana.Srikanth@Sun.COM BLK_FBAS : fba_len);
23527836SJohn.Forte@Sun.COM } else {
23537836SJohn.Forte@Sun.COM if (!SDBC_VALID_BITS(st_cblk_off, st_cblk_len, centry))
23547836SJohn.Forte@Sun.COM last_ioent = centry;
23557836SJohn.Forte@Sun.COM else {
23567836SJohn.Forte@Sun.COM DTRACE_PROBE4(_sd_prefetch_buf_data2,
23577836SJohn.Forte@Sun.COM uint64_t, (uint64_t)(BLK_TO_FBA_NUM(cblk) +
2358*9093SRamana.Srikanth@Sun.COM st_cblk_off), int, st_cblk_len,
2359*9093SRamana.Srikanth@Sun.COM char *, *(int64_t *)(centry->cc_data +
2360*9093SRamana.Srikanth@Sun.COM FBA_SIZE(st_cblk_off)), char *,
2361*9093SRamana.Srikanth@Sun.COM *(int64_t *)(centry->cc_data +
2362*9093SRamana.Srikanth@Sun.COM FBA_SIZE(st_cblk_off + st_cblk_len) - 8));
23637836SJohn.Forte@Sun.COM }
23647836SJohn.Forte@Sun.COM
23657836SJohn.Forte@Sun.COM lentry->cc_chain = centry;
23667836SJohn.Forte@Sun.COM if (fba_len < (nsc_size_t)BLK_FBAS)
23677836SJohn.Forte@Sun.COM st_cblk_len = (sdbc_cblk_fba_t)fba_len;
23687836SJohn.Forte@Sun.COM }
23697836SJohn.Forte@Sun.COM lentry = centry;
23707836SJohn.Forte@Sun.COM cblk++;
23717836SJohn.Forte@Sun.COM
23727836SJohn.Forte@Sun.COM /* if this block has a new identity clear prefetch history */
23737836SJohn.Forte@Sun.COM if (this_entry_type != HASH_ENTRY_DM)
2374*9093SRamana.Srikanth@Sun.COM centry->cc_aging_dm &=
2375*9093SRamana.Srikanth@Sun.COM ~(PREFETCH_BUF_I | PREFETCH_BUF_E);
23767836SJohn.Forte@Sun.COM
23777836SJohn.Forte@Sun.COM centry->cc_aging_dm &= ~(ENTRY_FIELD_DM);
23787836SJohn.Forte@Sun.COM centry->cc_aging_dm |= this_entry_type | PREFETCH_BUF_E;
23797836SJohn.Forte@Sun.COM if (flag & NSC_METADATA)
23807836SJohn.Forte@Sun.COM centry->cc_aging_dm |= STICKY_METADATA_DM;
23817836SJohn.Forte@Sun.COM
23827836SJohn.Forte@Sun.COM --request_blocks;
23837836SJohn.Forte@Sun.COM } while (fba_len > 0);
23847836SJohn.Forte@Sun.COM
23857836SJohn.Forte@Sun.COM
23867836SJohn.Forte@Sun.COM if (locked) {
23877836SJohn.Forte@Sun.COM rw_exit(&sdbc_queue_lock);
23887836SJohn.Forte@Sun.COM locked = 0;
23897836SJohn.Forte@Sun.COM }
23907836SJohn.Forte@Sun.COM
23917836SJohn.Forte@Sun.COM sdbc_centry_alloc_end(&alloc_tok);
23927836SJohn.Forte@Sun.COM
23937836SJohn.Forte@Sun.COM if (centry) {
23947836SJohn.Forte@Sun.COM centry->cc_chain = NULL;
23957836SJohn.Forte@Sun.COM if (sts = _sd_setup_category_on_type(handle->bh_centry)) {
23967836SJohn.Forte@Sun.COM (void) _sd_free_buf(handle);
23977836SJohn.Forte@Sun.COM goto done;
23987836SJohn.Forte@Sun.COM }
23997836SJohn.Forte@Sun.COM
24007836SJohn.Forte@Sun.COM (void) _sd_setup_mem_chaining(handle->bh_centry, 0);
24017836SJohn.Forte@Sun.COM }
24027836SJohn.Forte@Sun.COM
24037836SJohn.Forte@Sun.COM
24047836SJohn.Forte@Sun.COM if (ioent) {
24057836SJohn.Forte@Sun.COM /* prefetch: trailing valid can be released, adjust len */
24067836SJohn.Forte@Sun.COM if ((centry != last_ioent)) {
24077836SJohn.Forte@Sun.COM centry = last_ioent->cc_chain;
24087836SJohn.Forte@Sun.COM last_ioent->cc_chain = NULL;
24097836SJohn.Forte@Sun.COM while (centry) {
24107836SJohn.Forte@Sun.COM lentry = centry->cc_chain;
24117836SJohn.Forte@Sun.COM centry->cc_aging_dm &= ~PREFETCH_BUF_E;
24127836SJohn.Forte@Sun.COM _sd_centry_release(centry);
24137836SJohn.Forte@Sun.COM centry = lentry;
24147836SJohn.Forte@Sun.COM sdbc_prefetch_trailing++;
24157836SJohn.Forte@Sun.COM }
24167836SJohn.Forte@Sun.COM fba_len = (CENTRY_BLK(last_ioent) -
2417*9093SRamana.Srikanth@Sun.COM CENTRY_BLK(ioent) + 1) * BLK_FBAS -
2418*9093SRamana.Srikanth@Sun.COM BLK_FBA_OFF(io_pos);
24197836SJohn.Forte@Sun.COM fba_orig_len = fba_len + (io_pos - fba_pos);
24207836SJohn.Forte@Sun.COM }
24217836SJohn.Forte@Sun.COM
24227836SJohn.Forte@Sun.COM _SD_DISCONNECT_CALLBACK(handle);
24237836SJohn.Forte@Sun.COM sts = _sd_doread(handle, ioent, io_pos,
2424*9093SRamana.Srikanth@Sun.COM (fba_pos + fba_orig_len - io_pos), flag);
24257836SJohn.Forte@Sun.COM if (sts > 0)
24267836SJohn.Forte@Sun.COM (void) _sd_free_buf(handle);
24277836SJohn.Forte@Sun.COM } else {
24287836SJohn.Forte@Sun.COM CACHE_FBA_READ(cd, fba_orig_len);
24297836SJohn.Forte@Sun.COM CACHE_READ_HIT;
24307836SJohn.Forte@Sun.COM FBA_READ_IO_KSTATS(cd, FBA_SIZE(fba_orig_len));
24317836SJohn.Forte@Sun.COM
24327836SJohn.Forte@Sun.COM sts = NSC_HIT;
24337836SJohn.Forte@Sun.COM }
24347836SJohn.Forte@Sun.COM done:
24357836SJohn.Forte@Sun.COM if (locked)
24367836SJohn.Forte@Sun.COM rw_exit(&sdbc_queue_lock);
24377836SJohn.Forte@Sun.COM
24387836SJohn.Forte@Sun.COM return (sts);
24397836SJohn.Forte@Sun.COM }
24407836SJohn.Forte@Sun.COM
24417836SJohn.Forte@Sun.COM
24427836SJohn.Forte@Sun.COM /*
24437836SJohn.Forte@Sun.COM * _sd_cc_wait - wait for inuse cache block to become available
24447836SJohn.Forte@Sun.COM * Usage:
24457836SJohn.Forte@Sun.COM * if (SET_CENTRY_INUSE(centry)) {
24467836SJohn.Forte@Sun.COM * _sd_cc_wait(cd, blk, centry, CC_INUSE);
24477836SJohn.Forte@Sun.COM * goto try_again;
24487836SJohn.Forte@Sun.COM * }
24497836SJohn.Forte@Sun.COM * -or-
24507836SJohn.Forte@Sun.COM * if (SET_CENTRY_PAGEIO(centry)) {
24517836SJohn.Forte@Sun.COM * _sd_cc_wait(cd, blk, centry, CC_PAGEIO);
24527836SJohn.Forte@Sun.COM * goto try_again;
24537836SJohn.Forte@Sun.COM * }
24547836SJohn.Forte@Sun.COM */
24557836SJohn.Forte@Sun.COM void
_sd_cc_wait(int cd,nsc_off_t cblk,_sd_cctl_t * centry,int flag)24567836SJohn.Forte@Sun.COM _sd_cc_wait(int cd, nsc_off_t cblk, _sd_cctl_t *centry, int flag)
24577836SJohn.Forte@Sun.COM {
24587836SJohn.Forte@Sun.COM volatile ushort_t *waiters;
24597836SJohn.Forte@Sun.COM volatile uchar_t *uflag;
24607836SJohn.Forte@Sun.COM
24617836SJohn.Forte@Sun.COM if (flag == CC_INUSE) {
24627836SJohn.Forte@Sun.COM waiters = &(centry->cc_await_use);
24637836SJohn.Forte@Sun.COM uflag = &(CENTRY_INUSE(centry));
24647836SJohn.Forte@Sun.COM } else if (flag == CC_PAGEIO) {
24657836SJohn.Forte@Sun.COM waiters = &(centry->cc_await_page);
24667836SJohn.Forte@Sun.COM uflag = &(CENTRY_PAGEIO(centry));
24677836SJohn.Forte@Sun.COM } else {
24687836SJohn.Forte@Sun.COM /* Oops! */
24697836SJohn.Forte@Sun.COM #ifdef DEBUG
2470*9093SRamana.Srikanth@Sun.COM cmn_err(CE_WARN, "!_sd_cc_wait: unknown flag value (%x)", flag);
24717836SJohn.Forte@Sun.COM #endif
24727836SJohn.Forte@Sun.COM return;
24737836SJohn.Forte@Sun.COM }
24747836SJohn.Forte@Sun.COM
24757836SJohn.Forte@Sun.COM mutex_enter(¢ry->cc_lock);
24767836SJohn.Forte@Sun.COM if (CC_CD_BLK_MATCH(cd, cblk, centry) && (*uflag) != 0) {
24777836SJohn.Forte@Sun.COM (*waiters)++;
24787836SJohn.Forte@Sun.COM sd_serialize();
24797836SJohn.Forte@Sun.COM if ((*uflag) != 0) {
24807836SJohn.Forte@Sun.COM unsigned stime = nsc_usec();
24817836SJohn.Forte@Sun.COM cv_wait(¢ry->cc_blkcv, ¢ry->cc_lock);
24827836SJohn.Forte@Sun.COM (*waiters)--;
24837836SJohn.Forte@Sun.COM mutex_exit(¢ry->cc_lock);
24847836SJohn.Forte@Sun.COM SDTRACE(ST_INFO|SDF_ENT_GET,
2485*9093SRamana.Srikanth@Sun.COM cd, 0, BLK_TO_FBA_NUM(cblk), (nsc_usec()-stime), 0);
24867836SJohn.Forte@Sun.COM } else {
24877836SJohn.Forte@Sun.COM (*waiters)--;
24887836SJohn.Forte@Sun.COM mutex_exit(¢ry->cc_lock);
24897836SJohn.Forte@Sun.COM }
24907836SJohn.Forte@Sun.COM } else
24917836SJohn.Forte@Sun.COM mutex_exit(¢ry->cc_lock);
24927836SJohn.Forte@Sun.COM
24937836SJohn.Forte@Sun.COM }
24947836SJohn.Forte@Sun.COM
24957836SJohn.Forte@Sun.COM /*
24967836SJohn.Forte@Sun.COM * _sd_alloc_buf - Allocate a vector of buffers for io.
24977836SJohn.Forte@Sun.COM *
24987836SJohn.Forte@Sun.COM * ARGUMENTS:
24997836SJohn.Forte@Sun.COM * cd - Cache descriptor (from a previous open)
25007836SJohn.Forte@Sun.COM * fba_pos - disk position (512-byte FBAs)
25017836SJohn.Forte@Sun.COM * fba_len - length in disk FBAs.
25027836SJohn.Forte@Sun.COM * flag - allocation type. Flag is one or more of
25037836SJohn.Forte@Sun.COM * NSC_RDBUF, NSC_WRBUF, NSC_NOBLOCK and hints.
25047836SJohn.Forte@Sun.COM * NSC_RDAHEAD - prefetch for future read.
25057836SJohn.Forte@Sun.COM * handle_p - pointer to a handle pointer.
25067836SJohn.Forte@Sun.COM * If the handle pointer is non-null, its used as a
25077836SJohn.Forte@Sun.COM * pre-allocated handle. Else a new handle will be allocated
25087836SJohn.Forte@Sun.COM * and stored in *handle_p
25097836SJohn.Forte@Sun.COM *
25107836SJohn.Forte@Sun.COM * RETURNS:
25117836SJohn.Forte@Sun.COM * errno if return > 0.
25127836SJohn.Forte@Sun.COM * else NSC_HIT or NSC_DONE on success
25137836SJohn.Forte@Sun.COM * or NSC_PENDING on io in progress and NSC_NOBLOCK
25147836SJohn.Forte@Sun.COM * specified in the flag.
25157836SJohn.Forte@Sun.COM * USAGE:
25167836SJohn.Forte@Sun.COM * This routine allocates the cache blocks requested and creates a list
25177836SJohn.Forte@Sun.COM * of entries for this request.
25187836SJohn.Forte@Sun.COM * If NSC_NOBLOCK was not specified, this call could block on read io.
25197836SJohn.Forte@Sun.COM * If flag specified NSC_RDBUF and the request is not an entire
25207836SJohn.Forte@Sun.COM * hit, an io is initiated.
25217836SJohn.Forte@Sun.COM */
25227836SJohn.Forte@Sun.COM int
_sd_alloc_buf(blind_t xcd,nsc_off_t fba_pos,nsc_size_t fba_len,int flag,_sd_buf_handle_t ** handle_p)25237836SJohn.Forte@Sun.COM _sd_alloc_buf(blind_t xcd, nsc_off_t fba_pos, nsc_size_t fba_len, int flag,
25247836SJohn.Forte@Sun.COM _sd_buf_handle_t **handle_p)
25257836SJohn.Forte@Sun.COM {
25267836SJohn.Forte@Sun.COM int cd = (int)(unsigned long)xcd;
25277836SJohn.Forte@Sun.COM _sd_cd_info_t *cdi;
25287836SJohn.Forte@Sun.COM _sd_buf_handle_t *handle;
25297836SJohn.Forte@Sun.COM int sts;
25307836SJohn.Forte@Sun.COM nsc_off_t st_cblk, cblk; /* position of start and temp cache block */
25317836SJohn.Forte@Sun.COM sdbc_cblk_fba_t st_cblk_len; /* FBA len of starting cache block */
25327836SJohn.Forte@Sun.COM sdbc_cblk_fba_t end_cblk_len; /* FBA len of ending cache block */
25337836SJohn.Forte@Sun.COM sdbc_cblk_fba_t st_cblk_off; /* FBA offset into starting cblock */
25347836SJohn.Forte@Sun.COM nsc_off_t io_pos; /* offset in FBA's */
25357836SJohn.Forte@Sun.COM _sd_bufvec_t *bufvec;
25367836SJohn.Forte@Sun.COM _sd_cctl_t *centry, *lentry, *ioent = NULL;
25377836SJohn.Forte@Sun.COM nsc_size_t fba_orig_len = fba_len; /* FBA length of orig request */
25387836SJohn.Forte@Sun.COM int stall, pageio;
25397836SJohn.Forte@Sun.COM unsigned char cc_flag;
25407836SJohn.Forte@Sun.COM int this_entry_type;
25417836SJohn.Forte@Sun.COM int locked = 0;
25427836SJohn.Forte@Sun.COM nsc_size_t dmchain_request_blocks; /* size of dmchain in cache blocks */
25437836SJohn.Forte@Sun.COM sdbc_allocbuf_t alloc_tok = {0};
25447836SJohn.Forte@Sun.COM int min_frag = 0; /* frag statistics */
25457836SJohn.Forte@Sun.COM int max_frag = 0; /* frag statistics */
25467836SJohn.Forte@Sun.COM int nfrags = 0; /* frag statistics */
25477836SJohn.Forte@Sun.COM #ifdef DEBUG
25487836SJohn.Forte@Sun.COM int err = 0;
25497836SJohn.Forte@Sun.COM #endif
25507836SJohn.Forte@Sun.COM
25517836SJohn.Forte@Sun.COM
25527836SJohn.Forte@Sun.COM ASSERT(*handle_p != NULL);
25537836SJohn.Forte@Sun.COM handle = *handle_p;
25547836SJohn.Forte@Sun.COM
25557836SJohn.Forte@Sun.COM if (_sdbc_shutdown_in_progress)
25567836SJohn.Forte@Sun.COM return (EIO);
25577836SJohn.Forte@Sun.COM
25587836SJohn.Forte@Sun.COM if (xcd == NSC_ANON_CD)
25597836SJohn.Forte@Sun.COM cd = _CD_NOHASH;
25607836SJohn.Forte@Sun.COM
25617836SJohn.Forte@Sun.COM KSTAT_RUNQ_ENTER(cd);
25627836SJohn.Forte@Sun.COM
25637836SJohn.Forte@Sun.COM /*
25647836SJohn.Forte@Sun.COM * Force large writes on nvram systems to be write-through to
25657836SJohn.Forte@Sun.COM * avoid the (slow) bcopy into nvram.
25667836SJohn.Forte@Sun.COM */
25677836SJohn.Forte@Sun.COM
25687836SJohn.Forte@Sun.COM if (flag & NSC_WRBUF) {
25697836SJohn.Forte@Sun.COM if (fba_len > (nsc_size_t)sdbc_wrthru_len) {
25707836SJohn.Forte@Sun.COM flag |= NSC_WRTHRU;
25717836SJohn.Forte@Sun.COM }
25727836SJohn.Forte@Sun.COM }
25737836SJohn.Forte@Sun.COM
25747836SJohn.Forte@Sun.COM #ifdef DEBUG
25757836SJohn.Forte@Sun.COM if (sdbc_pageio_debug != SDBC_PAGEIO_OFF) {
25767836SJohn.Forte@Sun.COM switch (sdbc_pageio_debug) {
25777836SJohn.Forte@Sun.COM case SDBC_PAGEIO_RDEV:
25787836SJohn.Forte@Sun.COM if (cd != _CD_NOHASH &&
25797836SJohn.Forte@Sun.COM sdbc_pageio_rdev != (dev_t)-1 &&
25807836SJohn.Forte@Sun.COM _sd_cache_files[cd].cd_crdev == sdbc_pageio_rdev)
25817836SJohn.Forte@Sun.COM flag |= NSC_PAGEIO;
25827836SJohn.Forte@Sun.COM break;
25837836SJohn.Forte@Sun.COM
25847836SJohn.Forte@Sun.COM case SDBC_PAGEIO_RAND:
25857836SJohn.Forte@Sun.COM if ((nsc_lbolt() % 3) == 0)
25867836SJohn.Forte@Sun.COM flag |= NSC_PAGEIO;
25877836SJohn.Forte@Sun.COM break;
25887836SJohn.Forte@Sun.COM
25897836SJohn.Forte@Sun.COM case SDBC_PAGEIO_ALL:
25907836SJohn.Forte@Sun.COM flag |= NSC_PAGEIO;
25917836SJohn.Forte@Sun.COM break;
25927836SJohn.Forte@Sun.COM }
25937836SJohn.Forte@Sun.COM }
25947836SJohn.Forte@Sun.COM #endif /* DEBUG */
25957836SJohn.Forte@Sun.COM
25967836SJohn.Forte@Sun.COM if (fba_len > (nsc_size_t)BLK_FBAS) {
25977836SJohn.Forte@Sun.COM rw_enter(&sdbc_queue_lock, RW_WRITER);
25987836SJohn.Forte@Sun.COM locked = 1;
25997836SJohn.Forte@Sun.COM }
26007836SJohn.Forte@Sun.COM
26017836SJohn.Forte@Sun.COM /*
26027836SJohn.Forte@Sun.COM * _CD_NOHASH: client wants temporary (not hashed) cache memory
26037836SJohn.Forte@Sun.COM * not associated with a local disk. Skip local disk checks.
26047836SJohn.Forte@Sun.COM */
26057836SJohn.Forte@Sun.COM if (cd == _CD_NOHASH) {
26067836SJohn.Forte@Sun.COM flag &= ~(NSC_RDBUF | NSC_WRBUF | NSC_RDAHEAD);
26077836SJohn.Forte@Sun.COM handle = *handle_p;
26087836SJohn.Forte@Sun.COM handle->bh_flag |= NSC_HACTIVE;
26097836SJohn.Forte@Sun.COM goto setup;
26107836SJohn.Forte@Sun.COM }
26117836SJohn.Forte@Sun.COM
26127836SJohn.Forte@Sun.COM SDTRACE(ST_ENTER|SDF_ALLOCBUF, cd, fba_len, fba_pos, flag, 0);
26137836SJohn.Forte@Sun.COM
26147836SJohn.Forte@Sun.COM
26157836SJohn.Forte@Sun.COM if ((flag & NSC_RDAHEAD) && _sd_prefetch_opt) {
26167836SJohn.Forte@Sun.COM sts = _sd_prefetch_buf(cd, fba_pos, fba_len, flag, handle,
26177836SJohn.Forte@Sun.COM locked);
26187836SJohn.Forte@Sun.COM goto done;
26197836SJohn.Forte@Sun.COM }
26207836SJohn.Forte@Sun.COM
26217836SJohn.Forte@Sun.COM #if !defined(_SD_NOCHECKS)
26227836SJohn.Forte@Sun.COM if (flag & NSC_RDAHEAD) { /* _sd_prefetch_opt == 0 */
26237836SJohn.Forte@Sun.COM nsc_size_t file_size; /* file_size in FBA's */
26247836SJohn.Forte@Sun.COM /* prefetch: truncate if req'd */
26257836SJohn.Forte@Sun.COM if (fba_len > sdbc_max_fbas)
26267836SJohn.Forte@Sun.COM fba_len = sdbc_max_fbas;
26277836SJohn.Forte@Sun.COM file_size = _sd_cache_files[(cd)].cd_info->sh_filesize;
26287836SJohn.Forte@Sun.COM if ((fba_pos + fba_len) > file_size) {
26297836SJohn.Forte@Sun.COM fba_len = file_size - fba_pos;
26307836SJohn.Forte@Sun.COM #ifdef NSC_MULTI_TERABYTE
26317836SJohn.Forte@Sun.COM if ((int64_t)fba_len <= 0) {
26327836SJohn.Forte@Sun.COM #else
26337836SJohn.Forte@Sun.COM if ((int32_t)fba_len <= 0) {
26347836SJohn.Forte@Sun.COM #endif
26357836SJohn.Forte@Sun.COM sts = EIO;
26367836SJohn.Forte@Sun.COM SDTRACE(ST_EXIT|SDF_ALLOCBUF, cd, fba_len,
26377836SJohn.Forte@Sun.COM fba_pos, flag, sts);
26387836SJohn.Forte@Sun.COM goto done;
26397836SJohn.Forte@Sun.COM }
26407836SJohn.Forte@Sun.COM }
26417836SJohn.Forte@Sun.COM } else
26427836SJohn.Forte@Sun.COM if (sts = _sd_check_buffer_alloc(cd, fba_pos, fba_len, handle_p)) {
26437836SJohn.Forte@Sun.COM SDTRACE(ST_EXIT|SDF_ALLOCBUF, cd, fba_len, fba_pos, flag, sts);
26447836SJohn.Forte@Sun.COM goto done;
26457836SJohn.Forte@Sun.COM }
26467836SJohn.Forte@Sun.COM #endif
26477836SJohn.Forte@Sun.COM if (fba_len == 0) {
26487836SJohn.Forte@Sun.COM SDTRACE(ST_EXIT|SDF_ALLOCBUF, cd, fba_len, fba_pos,
2649*9093SRamana.Srikanth@Sun.COM flag, EINVAL);
26507836SJohn.Forte@Sun.COM sts = EINVAL;
26517836SJohn.Forte@Sun.COM goto done;
26527836SJohn.Forte@Sun.COM }
26537836SJohn.Forte@Sun.COM
26547836SJohn.Forte@Sun.COM handle->bh_flag |= NSC_HACTIVE;
26557836SJohn.Forte@Sun.COM cdi = &_sd_cache_files[cd];
26567836SJohn.Forte@Sun.COM
26577836SJohn.Forte@Sun.COM if (cdi->cd_recovering) {
26587836SJohn.Forte@Sun.COM /*
26597836SJohn.Forte@Sun.COM * If recovering this device, then block all allocates
26607836SJohn.Forte@Sun.COM * for reading or writing. If we allow reads then
26617836SJohn.Forte@Sun.COM * this path could see old data before we recover.
26627836SJohn.Forte@Sun.COM * If we allow writes then new data could be overwritten
26637836SJohn.Forte@Sun.COM * by old data.
26647836SJohn.Forte@Sun.COM * This is clearly still not a complete solution as
26657836SJohn.Forte@Sun.COM * the thread doing this allocate could conceivably be
26667836SJohn.Forte@Sun.COM * by this point (and in _sd_write/_sd_read for that matter
26677836SJohn.Forte@Sun.COM * which don't even have this protection). But this type
26687836SJohn.Forte@Sun.COM * of path seems to only exist in a failover situation
26697836SJohn.Forte@Sun.COM * where a device has failed on the other node and works
26707836SJohn.Forte@Sun.COM * on this node so the problem is not a huge one but exists
26717836SJohn.Forte@Sun.COM * never the less.
26727836SJohn.Forte@Sun.COM */
26737836SJohn.Forte@Sun.COM if (sts = _sd_recovery_wblk_wait(cd)) {
26747836SJohn.Forte@Sun.COM handle->bh_flag &= ~NSC_HACTIVE;
26757836SJohn.Forte@Sun.COM SDTRACE(ST_EXIT|SDF_ALLOCBUF, cd, fba_len, fba_pos,
26767836SJohn.Forte@Sun.COM flag, sts);
26777836SJohn.Forte@Sun.COM goto done;
26787836SJohn.Forte@Sun.COM }
26797836SJohn.Forte@Sun.COM }
26807836SJohn.Forte@Sun.COM
26817836SJohn.Forte@Sun.COM /* write & disk failed, return error immediately */
26827836SJohn.Forte@Sun.COM if ((flag & NSC_WRBUF) && cdi->cd_info->sh_failed) {
26837836SJohn.Forte@Sun.COM handle->bh_flag &= ~NSC_HACTIVE;
26847836SJohn.Forte@Sun.COM SDTRACE(ST_EXIT|SDF_ALLOCBUF, cd, fba_len, fba_pos, flag, EIO);
26857836SJohn.Forte@Sun.COM sts = EIO;
26867836SJohn.Forte@Sun.COM goto done;
26877836SJohn.Forte@Sun.COM }
26887836SJohn.Forte@Sun.COM
26897836SJohn.Forte@Sun.COM setup:
26907836SJohn.Forte@Sun.COM
26917836SJohn.Forte@Sun.COM _SD_SETUP_HANDLE(handle, cd, fba_pos, fba_len, flag);
26927836SJohn.Forte@Sun.COM handle->bh_centry = NULL;
26937836SJohn.Forte@Sun.COM bufvec = handle->bh_bufvec;
26947836SJohn.Forte@Sun.COM if (flag & NSC_RDAHEAD) { /* _sd_prefetch_opt == 0 */
26957836SJohn.Forte@Sun.COM /* CKD prefetch: bufvec not req'd, use placeholder */
26967836SJohn.Forte@Sun.COM bufvec->bufaddr = NULL;
26977836SJohn.Forte@Sun.COM bufvec->bufvmeaddr = NULL;
26987836SJohn.Forte@Sun.COM bufvec->buflen = 0;
26997836SJohn.Forte@Sun.COM bufvec = _prefetch_sb_vec;
27007836SJohn.Forte@Sun.COM }
27017836SJohn.Forte@Sun.COM st_cblk = FBA_TO_BLK_NUM(fba_pos);
27027836SJohn.Forte@Sun.COM st_cblk_off = BLK_FBA_OFF(fba_pos);
27037836SJohn.Forte@Sun.COM st_cblk_len = BLK_FBAS - st_cblk_off;
27047836SJohn.Forte@Sun.COM if ((nsc_size_t)st_cblk_len >= fba_len) {
27057836SJohn.Forte@Sun.COM end_cblk_len = 0;
27067836SJohn.Forte@Sun.COM st_cblk_len = (sdbc_cblk_fba_t)fba_len;
27077836SJohn.Forte@Sun.COM } else
27087836SJohn.Forte@Sun.COM end_cblk_len = BLK_FBA_OFF(fba_pos + fba_len);
27097836SJohn.Forte@Sun.COM cblk = st_cblk;
27107836SJohn.Forte@Sun.COM
27117836SJohn.Forte@Sun.COM
27127836SJohn.Forte@Sun.COM /*
27137836SJohn.Forte@Sun.COM * count number of blocks on chain that is required
27147836SJohn.Forte@Sun.COM */
27157836SJohn.Forte@Sun.COM
27167836SJohn.Forte@Sun.COM /* middle piece */
27177836SJohn.Forte@Sun.COM dmchain_request_blocks =
27187836SJohn.Forte@Sun.COM (fba_len - (st_cblk_len + end_cblk_len)) >> BLK_FBA_SHFT;
27197836SJohn.Forte@Sun.COM
27207836SJohn.Forte@Sun.COM /* start piece */
27217836SJohn.Forte@Sun.COM ++dmchain_request_blocks;
27227836SJohn.Forte@Sun.COM
27237836SJohn.Forte@Sun.COM /* end piece */
27247836SJohn.Forte@Sun.COM if (end_cblk_len)
27257836SJohn.Forte@Sun.COM ++dmchain_request_blocks;
27267836SJohn.Forte@Sun.COM
27277836SJohn.Forte@Sun.COM
27287836SJohn.Forte@Sun.COM cc_flag = 0;
27297836SJohn.Forte@Sun.COM if ((handle->bh_flag & NSC_PINNABLE) && (handle->bh_flag & NSC_WRBUF))
27307836SJohn.Forte@Sun.COM cc_flag |= CC_PINNABLE;
27317836SJohn.Forte@Sun.COM if (handle->bh_flag & (NSC_NOCACHE|NSC_SEQ_IO))
27327836SJohn.Forte@Sun.COM cc_flag |= CC_QHEAD;
27337836SJohn.Forte@Sun.COM lentry = NULL;
27347836SJohn.Forte@Sun.COM stall = 0;
27357836SJohn.Forte@Sun.COM
27367836SJohn.Forte@Sun.COM do {
27377836SJohn.Forte@Sun.COM pageio = ((flag & NSC_PAGEIO) != 0 || sdbc_pageio_always != 0);
27387836SJohn.Forte@Sun.COM cget:
27397836SJohn.Forte@Sun.COM if ((centry = (_sd_cctl_t *)
27407836SJohn.Forte@Sun.COM _sd_hash_search(cd, cblk, _sd_htable)) != 0) {
27417836SJohn.Forte@Sun.COM
27427836SJohn.Forte@Sun.COM if (SET_CENTRY_INUSE(centry)) {
27437836SJohn.Forte@Sun.COM /* already inuse: wait for block, retry */
27447836SJohn.Forte@Sun.COM sdbc_allocb_inuse++;
27457836SJohn.Forte@Sun.COM if (locked)
27467836SJohn.Forte@Sun.COM rw_exit(&sdbc_queue_lock);
27477836SJohn.Forte@Sun.COM _sd_cc_wait(cd, cblk, centry, CC_INUSE);
27487836SJohn.Forte@Sun.COM if (locked)
27497836SJohn.Forte@Sun.COM rw_enter(&sdbc_queue_lock, RW_WRITER);
27507836SJohn.Forte@Sun.COM goto cget;
27517836SJohn.Forte@Sun.COM }
27527836SJohn.Forte@Sun.COM
27537836SJohn.Forte@Sun.COM /*
27547836SJohn.Forte@Sun.COM * bug 4529671
27557836SJohn.Forte@Sun.COM * now that we own the centry make sure that
27567836SJohn.Forte@Sun.COM * it is still good. it could have been processed
27577836SJohn.Forte@Sun.COM * by _sd_dealloc_dm() in the window between
27587836SJohn.Forte@Sun.COM * _sd_hash_search() and SET_CENTRY_INUSE().
27597836SJohn.Forte@Sun.COM */
27607836SJohn.Forte@Sun.COM if ((_sd_cctl_t *)
27617836SJohn.Forte@Sun.COM _sd_hash_search(cd, cblk, _sd_htable) != centry) {
27627836SJohn.Forte@Sun.COM sdbc_allocb_deallocd++;
27637836SJohn.Forte@Sun.COM #ifdef DEBUG
27647836SJohn.Forte@Sun.COM cmn_err(CE_WARN,
2765*9093SRamana.Srikanth@Sun.COM "!centry %p cd %d cblk %" NSC_SZFMT
27667836SJohn.Forte@Sun.COM " fba_len %" NSC_SZFMT " lost to dealloc?! "
27677836SJohn.Forte@Sun.COM "cc_data %p", (void *)centry, cd, cblk,
27687836SJohn.Forte@Sun.COM fba_orig_len, (void *)centry->cc_data);
27697836SJohn.Forte@Sun.COM #endif
27707836SJohn.Forte@Sun.COM
27717836SJohn.Forte@Sun.COM CLEAR_CENTRY_INUSE(centry);
27727836SJohn.Forte@Sun.COM goto cget;
27737836SJohn.Forte@Sun.COM }
27747836SJohn.Forte@Sun.COM
27757836SJohn.Forte@Sun.COM if (CC_CD_BLK_MATCH(cd, cblk, centry)) {
27767836SJohn.Forte@Sun.COM /*
27777836SJohn.Forte@Sun.COM * Do pagelist io mutual exclusion
27787836SJohn.Forte@Sun.COM * before messing with the centry.
27797836SJohn.Forte@Sun.COM */
27807836SJohn.Forte@Sun.COM if (pageio && SET_CENTRY_PAGEIO(centry)) {
27817836SJohn.Forte@Sun.COM /* wait for flusher to finish pageio */
27827836SJohn.Forte@Sun.COM sdbc_allocb_pageio1++;
27837836SJohn.Forte@Sun.COM
27847836SJohn.Forte@Sun.COM CLEAR_CENTRY_INUSE(centry);
27857836SJohn.Forte@Sun.COM if (locked)
27867836SJohn.Forte@Sun.COM rw_exit(&sdbc_queue_lock);
27877836SJohn.Forte@Sun.COM _sd_cc_wait(cd, cblk, centry,
27887836SJohn.Forte@Sun.COM CC_PAGEIO);
27897836SJohn.Forte@Sun.COM if (locked)
27907836SJohn.Forte@Sun.COM rw_enter(&sdbc_queue_lock,
27917836SJohn.Forte@Sun.COM RW_WRITER);
27927836SJohn.Forte@Sun.COM goto cget;
27937836SJohn.Forte@Sun.COM }
27947836SJohn.Forte@Sun.COM
27957836SJohn.Forte@Sun.COM sdbc_allocb_hit++;
27967836SJohn.Forte@Sun.COM this_entry_type = HASH_ENTRY_DM;
27977836SJohn.Forte@Sun.COM pageio = 0;
27987836SJohn.Forte@Sun.COM centry->cc_toflush = 0;
27997836SJohn.Forte@Sun.COM
28007836SJohn.Forte@Sun.COM centry->cc_hits++;
28017836SJohn.Forte@Sun.COM
28027836SJohn.Forte@Sun.COM /* this will reset the age flag */
28037836SJohn.Forte@Sun.COM sdbc_centry_init_dm(centry);
28047836SJohn.Forte@Sun.COM
28057836SJohn.Forte@Sun.COM DTRACE_PROBE1(_sd_alloc_buf1,
2806*9093SRamana.Srikanth@Sun.COM _sd_cctl_t *, centry);
28077836SJohn.Forte@Sun.COM } else {
28087836SJohn.Forte@Sun.COM /* block mismatch: release, alloc new block */
28097836SJohn.Forte@Sun.COM sdbc_allocb_lost++;
28107836SJohn.Forte@Sun.COM
28117836SJohn.Forte@Sun.COM CLEAR_CENTRY_INUSE(centry);
28127836SJohn.Forte@Sun.COM
28137836SJohn.Forte@Sun.COM goto cget;
28147836SJohn.Forte@Sun.COM
28157836SJohn.Forte@Sun.COM }
28167836SJohn.Forte@Sun.COM } else {
28177836SJohn.Forte@Sun.COM centry = sdbc_centry_alloc(cd, cblk,
2818*9093SRamana.Srikanth@Sun.COM dmchain_request_blocks, &stall,
2819*9093SRamana.Srikanth@Sun.COM &alloc_tok, locked ? ALLOC_LOCKED : 0);
28207836SJohn.Forte@Sun.COM
28217836SJohn.Forte@Sun.COM /*
28227836SJohn.Forte@Sun.COM * dmchaining adjustment.
28237836SJohn.Forte@Sun.COM * if centry was obtained from the dmchain
28247836SJohn.Forte@Sun.COM * then clear local pageio variable because the
28257836SJohn.Forte@Sun.COM * centry already has cc_pageio set.
28267836SJohn.Forte@Sun.COM */
28277836SJohn.Forte@Sun.COM if (CENTRY_PAGEIO(centry))
28287836SJohn.Forte@Sun.COM pageio = 0;
28297836SJohn.Forte@Sun.COM
2830*9093SRamana.Srikanth@Sun.COM DTRACE_PROBE1(_sd_alloc_buf2, _sd_cctl_t *, centry);
28317836SJohn.Forte@Sun.COM
28327836SJohn.Forte@Sun.COM this_entry_type = ELIGIBLE_ENTRY_DM;
28337836SJohn.Forte@Sun.COM if (centry->cc_aging_dm & FOUND_IN_HASH_DM)
28347836SJohn.Forte@Sun.COM this_entry_type = HASH_ENTRY_DM;
28357836SJohn.Forte@Sun.COM else {
28367836SJohn.Forte@Sun.COM if (centry->cc_aging_dm & FOUND_HOLD_OVER_DM)
28377836SJohn.Forte@Sun.COM this_entry_type = HOLD_ENTRY_DM;
28387836SJohn.Forte@Sun.COM }
28397836SJohn.Forte@Sun.COM }
28407836SJohn.Forte@Sun.COM
28417836SJohn.Forte@Sun.COM centry->cc_aging_dm &= ~(FOUND_IN_HASH_DM|FOUND_HOLD_OVER_DM);
28427836SJohn.Forte@Sun.COM
28437836SJohn.Forte@Sun.COM /*
28447836SJohn.Forte@Sun.COM * Do pagelist io mutual exclusion now if we did not do
28457836SJohn.Forte@Sun.COM * it above.
28467836SJohn.Forte@Sun.COM */
28477836SJohn.Forte@Sun.COM
28487836SJohn.Forte@Sun.COM if (pageio && SET_CENTRY_PAGEIO(centry)) {
28497836SJohn.Forte@Sun.COM /* wait for flusher to finish pageio */
28507836SJohn.Forte@Sun.COM sdbc_allocb_pageio2++;
28517836SJohn.Forte@Sun.COM
28527836SJohn.Forte@Sun.COM
28537836SJohn.Forte@Sun.COM CLEAR_CENTRY_INUSE(centry);
28547836SJohn.Forte@Sun.COM if (locked)
28557836SJohn.Forte@Sun.COM rw_exit(&sdbc_queue_lock);
28567836SJohn.Forte@Sun.COM _sd_cc_wait(cd, cblk, centry, CC_PAGEIO);
28577836SJohn.Forte@Sun.COM if (locked)
28587836SJohn.Forte@Sun.COM rw_enter(&sdbc_queue_lock, RW_WRITER);
28597836SJohn.Forte@Sun.COM goto cget;
28607836SJohn.Forte@Sun.COM }
28617836SJohn.Forte@Sun.COM
28627836SJohn.Forte@Sun.COM pageio = 0;
28637836SJohn.Forte@Sun.COM
28647836SJohn.Forte@Sun.COM if (CENTRY_DIRTY(centry)) {
28657836SJohn.Forte@Sun.COM /*
28667836SJohn.Forte@Sun.COM * end action might set PEND_DIRTY flag
28677836SJohn.Forte@Sun.COM * must lock if need to change flag bits
28687836SJohn.Forte@Sun.COM */
28697836SJohn.Forte@Sun.COM if (centry->cc_flag != (centry->cc_flag | cc_flag)) {
28707836SJohn.Forte@Sun.COM /* was FAST */
28717836SJohn.Forte@Sun.COM mutex_enter(¢ry->cc_lock);
28727836SJohn.Forte@Sun.COM centry->cc_flag |= cc_flag;
28737836SJohn.Forte@Sun.COM /* was FAST */
28747836SJohn.Forte@Sun.COM mutex_exit(¢ry->cc_lock);
28757836SJohn.Forte@Sun.COM }
28767836SJohn.Forte@Sun.COM } else
28777836SJohn.Forte@Sun.COM centry->cc_flag |= cc_flag;
28787836SJohn.Forte@Sun.COM
28797836SJohn.Forte@Sun.COM centry->cc_chain = NULL;
28807836SJohn.Forte@Sun.COM
28817836SJohn.Forte@Sun.COM /*
28827836SJohn.Forte@Sun.COM * step 0:check valid bits in each cache ele as
28837836SJohn.Forte@Sun.COM * the chain grows - set ioent/io_pos to first
28847836SJohn.Forte@Sun.COM * instance of invalid data
28857836SJohn.Forte@Sun.COM */
28867836SJohn.Forte@Sun.COM if (cblk == st_cblk) {
28877836SJohn.Forte@Sun.COM handle->bh_centry = centry;
28887836SJohn.Forte@Sun.COM fba_len -= st_cblk_len;
28897836SJohn.Forte@Sun.COM lentry = centry;
28907836SJohn.Forte@Sun.COM if (flag & NSC_RDBUF) {
28917836SJohn.Forte@Sun.COM if (!SDBC_VALID_BITS(st_cblk_off, st_cblk_len,
28927836SJohn.Forte@Sun.COM centry)) {
28937836SJohn.Forte@Sun.COM io_pos = fba_pos;
28947836SJohn.Forte@Sun.COM ioent = centry;
28957836SJohn.Forte@Sun.COM } else {
28967836SJohn.Forte@Sun.COM DATA_LOG(SDF_ALLOC, centry, st_cblk_off,
28977836SJohn.Forte@Sun.COM st_cblk_len);
28987836SJohn.Forte@Sun.COM
28997836SJohn.Forte@Sun.COM DTRACE_PROBE4(_sd_alloc_data1,
2900*9093SRamana.Srikanth@Sun.COM uint64_t, (uint64_t)
2901*9093SRamana.Srikanth@Sun.COM (BLK_TO_FBA_NUM(cblk) +
2902*9093SRamana.Srikanth@Sun.COM st_cblk_off), int, st_cblk_len,
29037836SJohn.Forte@Sun.COM char *, *(int64_t *)
2904*9093SRamana.Srikanth@Sun.COM (centry->cc_data +
2905*9093SRamana.Srikanth@Sun.COM FBA_SIZE(st_cblk_off)),
29067836SJohn.Forte@Sun.COM char *, *(int64_t *)
2907*9093SRamana.Srikanth@Sun.COM (centry->cc_data +
2908*9093SRamana.Srikanth@Sun.COM FBA_SIZE(st_cblk_off + st_cblk_len)
2909*9093SRamana.Srikanth@Sun.COM - 8));
29107836SJohn.Forte@Sun.COM }
29117836SJohn.Forte@Sun.COM }
29127836SJohn.Forte@Sun.COM cblk++;
29137836SJohn.Forte@Sun.COM } else if (fba_len == (nsc_size_t)end_cblk_len) {
29147836SJohn.Forte@Sun.COM lentry->cc_chain = centry;
29157836SJohn.Forte@Sun.COM fba_len -= end_cblk_len;
29167836SJohn.Forte@Sun.COM if (flag & NSC_RDBUF) {
29177836SJohn.Forte@Sun.COM if (ioent == NULL) {
29187836SJohn.Forte@Sun.COM if (!SDBC_VALID_BITS(0, end_cblk_len,
29197836SJohn.Forte@Sun.COM centry)) {
29207836SJohn.Forte@Sun.COM io_pos = BLK_TO_FBA_NUM(cblk);
29217836SJohn.Forte@Sun.COM ioent = centry;
29227836SJohn.Forte@Sun.COM } else {
29237836SJohn.Forte@Sun.COM DATA_LOG(SDF_ALLOC, centry, 0,
29247836SJohn.Forte@Sun.COM end_cblk_len);
29257836SJohn.Forte@Sun.COM
2926*9093SRamana.Srikanth@Sun.COM DTRACE_PROBE4(_sd_alloc_data2,
29277836SJohn.Forte@Sun.COM uint64_t,
2928*9093SRamana.Srikanth@Sun.COM BLK_TO_FBA_NUM(cblk),
29297836SJohn.Forte@Sun.COM int, end_cblk_len,
2930*9093SRamana.Srikanth@Sun.COM char *, *(int64_t *)
2931*9093SRamana.Srikanth@Sun.COM (centry->cc_data),
2932*9093SRamana.Srikanth@Sun.COM char *, *(int64_t *)
2933*9093SRamana.Srikanth@Sun.COM (centry->cc_data +
2934*9093SRamana.Srikanth@Sun.COM FBA_SIZE(end_cblk_len)
2935*9093SRamana.Srikanth@Sun.COM - 8));
29367836SJohn.Forte@Sun.COM }
29377836SJohn.Forte@Sun.COM }
29387836SJohn.Forte@Sun.COM }
29397836SJohn.Forte@Sun.COM } else {
29407836SJohn.Forte@Sun.COM lentry->cc_chain = centry;
29417836SJohn.Forte@Sun.COM lentry = centry;
29427836SJohn.Forte@Sun.COM fba_len -= BLK_FBAS;
29437836SJohn.Forte@Sun.COM if (flag & NSC_RDBUF) {
29447836SJohn.Forte@Sun.COM if (ioent == NULL) {
29457836SJohn.Forte@Sun.COM if (!FULLY_VALID(centry)) {
29467836SJohn.Forte@Sun.COM io_pos = BLK_TO_FBA_NUM(cblk);
29477836SJohn.Forte@Sun.COM ioent = centry;
29487836SJohn.Forte@Sun.COM } else {
29497836SJohn.Forte@Sun.COM DATA_LOG(SDF_ALLOC, centry, 0,
29507836SJohn.Forte@Sun.COM BLK_FBAS);
29517836SJohn.Forte@Sun.COM
2952*9093SRamana.Srikanth@Sun.COM DTRACE_PROBE4(_sd_alloc_data3,
2953*9093SRamana.Srikanth@Sun.COM uint64_t, (uint64_t)
2954*9093SRamana.Srikanth@Sun.COM BLK_TO_FBA_NUM(cblk),
29557836SJohn.Forte@Sun.COM int, BLK_FBAS,
2956*9093SRamana.Srikanth@Sun.COM char *, *(int64_t *)
2957*9093SRamana.Srikanth@Sun.COM (centry->cc_data),
2958*9093SRamana.Srikanth@Sun.COM char *, *(int64_t *)
2959*9093SRamana.Srikanth@Sun.COM (centry->cc_data +
2960*9093SRamana.Srikanth@Sun.COM FBA_SIZE(BLK_FBAS) - 8));
29617836SJohn.Forte@Sun.COM }
29627836SJohn.Forte@Sun.COM }
29637836SJohn.Forte@Sun.COM }
29647836SJohn.Forte@Sun.COM cblk++;
29657836SJohn.Forte@Sun.COM }
29667836SJohn.Forte@Sun.COM
29677836SJohn.Forte@Sun.COM /* if this block has a new identity clear prefetch history */
29687836SJohn.Forte@Sun.COM if (this_entry_type != HASH_ENTRY_DM)
2969*9093SRamana.Srikanth@Sun.COM centry->cc_aging_dm &=
2970*9093SRamana.Srikanth@Sun.COM ~(PREFETCH_BUF_I | PREFETCH_BUF_E);
29717836SJohn.Forte@Sun.COM
29727836SJohn.Forte@Sun.COM centry->cc_aging_dm &= ~(ENTRY_FIELD_DM);
29737836SJohn.Forte@Sun.COM centry->cc_aging_dm |= this_entry_type;
29747836SJohn.Forte@Sun.COM if (flag & NSC_METADATA)
29757836SJohn.Forte@Sun.COM centry->cc_aging_dm |= STICKY_METADATA_DM;
29767836SJohn.Forte@Sun.COM
29777836SJohn.Forte@Sun.COM --dmchain_request_blocks;
29787836SJohn.Forte@Sun.COM } while (fba_len);
29797836SJohn.Forte@Sun.COM
29807836SJohn.Forte@Sun.COM if (locked) {
29817836SJohn.Forte@Sun.COM rw_exit(&sdbc_queue_lock);
29827836SJohn.Forte@Sun.COM locked = 0;
29837836SJohn.Forte@Sun.COM }
29847836SJohn.Forte@Sun.COM
29857836SJohn.Forte@Sun.COM ASSERT(dmchain_request_blocks == 0);
29867836SJohn.Forte@Sun.COM
29877836SJohn.Forte@Sun.COM /*
29887836SJohn.Forte@Sun.COM * do any necessary cleanup now that all the blocks are allocated.
29897836SJohn.Forte@Sun.COM */
29907836SJohn.Forte@Sun.COM sdbc_centry_alloc_end(&alloc_tok);
29917836SJohn.Forte@Sun.COM
29927836SJohn.Forte@Sun.COM /* be sure you nul term. the chain */
29937836SJohn.Forte@Sun.COM centry->cc_chain = NULL;
29947836SJohn.Forte@Sun.COM
29957836SJohn.Forte@Sun.COM /*
29967836SJohn.Forte@Sun.COM * step one: establish HOST/PARASITE/OTHER relationships
29977836SJohn.Forte@Sun.COM * between the centry ele in the list and calc the alloc size
29987836SJohn.Forte@Sun.COM * (fill in CATAGORY based on TYPE and immediate neighbors)
29997836SJohn.Forte@Sun.COM */
30007836SJohn.Forte@Sun.COM if (sts = _sd_setup_category_on_type(handle->bh_centry)) {
30017836SJohn.Forte@Sun.COM #ifdef DEBUG
30027836SJohn.Forte@Sun.COM err = _sd_free_buf(handle);
30037836SJohn.Forte@Sun.COM if (err) {
3004*9093SRamana.Srikanth@Sun.COM cmn_err(CE_WARN, "!sdbc(_sd_alloc_buf): _sd_free_buf "
30057836SJohn.Forte@Sun.COM "failed: err:%d handle:%p", err, (void *)handle);
30067836SJohn.Forte@Sun.COM }
30077836SJohn.Forte@Sun.COM #else
30087836SJohn.Forte@Sun.COM (void) _sd_free_buf(handle);
30097836SJohn.Forte@Sun.COM #endif
30107836SJohn.Forte@Sun.COM goto done;
30117836SJohn.Forte@Sun.COM }
30127836SJohn.Forte@Sun.COM
30137836SJohn.Forte@Sun.COM /*
30147836SJohn.Forte@Sun.COM * step two: alloc the needed mem and fill in the data and chaining
30157836SJohn.Forte@Sun.COM * fields (leave bufvec for step three)
30167836SJohn.Forte@Sun.COM */
30177836SJohn.Forte@Sun.COM (void) _sd_setup_mem_chaining(handle->bh_centry, 0);
30187836SJohn.Forte@Sun.COM
30197836SJohn.Forte@Sun.COM /*
30207836SJohn.Forte@Sun.COM * step three: do the bufvec
30217836SJohn.Forte@Sun.COM */
30227836SJohn.Forte@Sun.COM fba_len = fba_orig_len;
30237836SJohn.Forte@Sun.COM centry = handle->bh_centry;
30247836SJohn.Forte@Sun.COM bufvec = handle->bh_bufvec;
30257836SJohn.Forte@Sun.COM
30267836SJohn.Forte@Sun.COM while (centry) {
3027*9093SRamana.Srikanth@Sun.COM DTRACE_PROBE3(_sd_alloc_buf_centrys, _sd_cctl_t *, centry,
3028*9093SRamana.Srikanth@Sun.COM int, cd, uint64_t,
3029*9093SRamana.Srikanth@Sun.COM (uint64_t)BLK_TO_FBA_NUM(CENTRY_BLK(centry)));
30307836SJohn.Forte@Sun.COM
30317836SJohn.Forte@Sun.COM if (fba_len == fba_orig_len) {
30327836SJohn.Forte@Sun.COM bufvec->bufaddr = (centry->cc_data +
30337836SJohn.Forte@Sun.COM FBA_SIZE(st_cblk_off));
30347836SJohn.Forte@Sun.COM bufvec->bufvmeaddr = 0; /* not used */
30357836SJohn.Forte@Sun.COM bufvec->buflen = FBA_SIZE(st_cblk_len);
30367836SJohn.Forte@Sun.COM bufvec++;
30377836SJohn.Forte@Sun.COM fba_len -= st_cblk_len;
30387836SJohn.Forte@Sun.COM } else if (fba_len == (nsc_size_t)end_cblk_len) {
30397836SJohn.Forte@Sun.COM _sd_bufvec_t *pbufvec = bufvec - 1;
30407836SJohn.Forte@Sun.COM
30417836SJohn.Forte@Sun.COM if ((pbufvec->bufaddr + pbufvec->buflen) ==
30427836SJohn.Forte@Sun.COM centry->cc_data) {
30437836SJohn.Forte@Sun.COM /* contiguous */
30447836SJohn.Forte@Sun.COM pbufvec->buflen += FBA_SIZE(end_cblk_len);
30457836SJohn.Forte@Sun.COM } else {
30467836SJohn.Forte@Sun.COM
30477836SJohn.Forte@Sun.COM bufvec->bufaddr = centry->cc_data;
30487836SJohn.Forte@Sun.COM bufvec->bufvmeaddr = 0; /* not used */
30497836SJohn.Forte@Sun.COM bufvec->buflen = FBA_SIZE(end_cblk_len);
30507836SJohn.Forte@Sun.COM bufvec++;
30517836SJohn.Forte@Sun.COM }
30527836SJohn.Forte@Sun.COM
30537836SJohn.Forte@Sun.COM fba_len -= end_cblk_len;
30547836SJohn.Forte@Sun.COM } else {
30557836SJohn.Forte@Sun.COM _sd_bufvec_t *pbufvec = bufvec - 1;
30567836SJohn.Forte@Sun.COM
30577836SJohn.Forte@Sun.COM if ((pbufvec->bufaddr + pbufvec->buflen) ==
30587836SJohn.Forte@Sun.COM centry->cc_data) {
30597836SJohn.Forte@Sun.COM /* contiguous */
30607836SJohn.Forte@Sun.COM pbufvec->buflen += CACHE_BLOCK_SIZE;
30617836SJohn.Forte@Sun.COM } else {
30627836SJohn.Forte@Sun.COM
30637836SJohn.Forte@Sun.COM bufvec->bufaddr = centry->cc_data;
30647836SJohn.Forte@Sun.COM bufvec->bufvmeaddr = 0; /* not used */
30657836SJohn.Forte@Sun.COM bufvec->buflen = CACHE_BLOCK_SIZE;
30667836SJohn.Forte@Sun.COM bufvec++;
30677836SJohn.Forte@Sun.COM }
30687836SJohn.Forte@Sun.COM
30697836SJohn.Forte@Sun.COM fba_len -= BLK_FBAS;
30707836SJohn.Forte@Sun.COM }
30717836SJohn.Forte@Sun.COM
30727836SJohn.Forte@Sun.COM centry = centry->cc_chain;
30737836SJohn.Forte@Sun.COM }
30747836SJohn.Forte@Sun.COM
30757836SJohn.Forte@Sun.COM /* be sure you nul term. the chain */
30767836SJohn.Forte@Sun.COM bufvec->bufaddr = NULL;
30777836SJohn.Forte@Sun.COM bufvec->bufvmeaddr = 0;
30787836SJohn.Forte@Sun.COM bufvec->buflen = 0;
30797836SJohn.Forte@Sun.COM
30807836SJohn.Forte@Sun.COM /* frag statistics */
30817836SJohn.Forte@Sun.COM {
30827836SJohn.Forte@Sun.COM _sd_bufvec_t *tbufvec;
30837836SJohn.Forte@Sun.COM
30847836SJohn.Forte@Sun.COM for (tbufvec = handle->bh_bufvec; tbufvec != bufvec;
3085*9093SRamana.Srikanth@Sun.COM ++tbufvec) {
30867836SJohn.Forte@Sun.COM if ((min_frag > tbufvec->buflen) || (min_frag == 0))
30877836SJohn.Forte@Sun.COM min_frag = tbufvec->buflen;
30887836SJohn.Forte@Sun.COM
30897836SJohn.Forte@Sun.COM if (max_frag < tbufvec->buflen)
30907836SJohn.Forte@Sun.COM max_frag = tbufvec->buflen;
30917836SJohn.Forte@Sun.COM }
30927836SJohn.Forte@Sun.COM
30937836SJohn.Forte@Sun.COM nfrags = bufvec - handle->bh_bufvec;
30947836SJohn.Forte@Sun.COM min_frag = FBA_LEN(min_frag);
30957836SJohn.Forte@Sun.COM max_frag = FBA_LEN(max_frag);
30967836SJohn.Forte@Sun.COM }
30977836SJohn.Forte@Sun.COM
30987836SJohn.Forte@Sun.COM /* buffer memory frag stats */
3099*9093SRamana.Srikanth@Sun.COM DTRACE_PROBE4(_sd_alloc_buf_frag, uint64_t, (uint64_t)fba_orig_len,
3100*9093SRamana.Srikanth@Sun.COM int, nfrags, int, min_frag, int, max_frag);
31017836SJohn.Forte@Sun.COM
31027836SJohn.Forte@Sun.COM
31037836SJohn.Forte@Sun.COM if (flag & NSC_WRBUF) {
31047836SJohn.Forte@Sun.COM if (_SD_IS_WRTHRU(handle))
31057836SJohn.Forte@Sun.COM goto alloc_done;
31067836SJohn.Forte@Sun.COM if (_sd_alloc_write(handle->bh_centry, &stall)) {
31077836SJohn.Forte@Sun.COM _sd_unblock(&_sd_flush_cv);
31087836SJohn.Forte@Sun.COM handle->bh_flag |= NSC_FORCED_WRTHRU;
31097836SJohn.Forte@Sun.COM } else {
31107836SJohn.Forte@Sun.COM for (centry = handle->bh_centry;
3111*9093SRamana.Srikanth@Sun.COM centry; centry = centry->cc_chain) {
31127836SJohn.Forte@Sun.COM
31137836SJohn.Forte@Sun.COM CENTRY_SET_FTPOS(centry);
31147836SJohn.Forte@Sun.COM SSOP_SETCENTRY(sdbc_safestore,
3115*9093SRamana.Srikanth@Sun.COM centry->cc_write);
31167836SJohn.Forte@Sun.COM }
31177836SJohn.Forte@Sun.COM }
31187836SJohn.Forte@Sun.COM }
31197836SJohn.Forte@Sun.COM
31207836SJohn.Forte@Sun.COM alloc_done:
31217836SJohn.Forte@Sun.COM if (locked) {
31227836SJohn.Forte@Sun.COM rw_exit(&sdbc_queue_lock);
31237836SJohn.Forte@Sun.COM locked = 0;
31247836SJohn.Forte@Sun.COM }
31257836SJohn.Forte@Sun.COM if (ioent) {
31267836SJohn.Forte@Sun.COM _SD_DISCONNECT_CALLBACK(handle);
31277836SJohn.Forte@Sun.COM sts = _sd_doread(handle, ioent, io_pos,
3128*9093SRamana.Srikanth@Sun.COM (fba_pos + fba_orig_len - io_pos), flag);
31297836SJohn.Forte@Sun.COM if (sts > 0)
31307836SJohn.Forte@Sun.COM (void) _sd_free_buf(handle);
31317836SJohn.Forte@Sun.COM } else
31327836SJohn.Forte@Sun.COM if (flag & NSC_RDBUF) {
31337836SJohn.Forte@Sun.COM CACHE_FBA_READ(cd, fba_orig_len);
31347836SJohn.Forte@Sun.COM CACHE_READ_HIT;
31357836SJohn.Forte@Sun.COM FBA_READ_IO_KSTATS(cd, FBA_SIZE(fba_orig_len));
31367836SJohn.Forte@Sun.COM
31377836SJohn.Forte@Sun.COM sts = NSC_HIT;
31387836SJohn.Forte@Sun.COM } else
31397836SJohn.Forte@Sun.COM sts = (stall) ? NSC_DONE : NSC_HIT;
31407836SJohn.Forte@Sun.COM
31417836SJohn.Forte@Sun.COM SDTRACE(ST_EXIT|SDF_ALLOCBUF, cd, fba_orig_len, fba_pos, flag, sts);
31427836SJohn.Forte@Sun.COM
31437836SJohn.Forte@Sun.COM done:
31447836SJohn.Forte@Sun.COM if (locked)
31457836SJohn.Forte@Sun.COM rw_exit(&sdbc_queue_lock);
31467836SJohn.Forte@Sun.COM
31477836SJohn.Forte@Sun.COM KSTAT_RUNQ_EXIT(cd);
31487836SJohn.Forte@Sun.COM
31497836SJohn.Forte@Sun.COM return (sts);
31507836SJohn.Forte@Sun.COM }
31517836SJohn.Forte@Sun.COM
31527836SJohn.Forte@Sun.COM /*
31537836SJohn.Forte@Sun.COM * consistency checking for ccents
31547836SJohn.Forte@Sun.COM */
31557836SJohn.Forte@Sun.COM
31567836SJohn.Forte@Sun.COM #define ELIGIBLE(p) (p & ELIGIBLE_ENTRY_DM)
31577836SJohn.Forte@Sun.COM #define HOLD(p) (p & HOLD_ENTRY_DM)
31587836SJohn.Forte@Sun.COM #define HASHE(p) (p & HASH_ENTRY_DM)
31597836SJohn.Forte@Sun.COM
31607836SJohn.Forte@Sun.COM #define HOST(p) (p & HOST_ENTRY_DM)
31617836SJohn.Forte@Sun.COM #define PARA(p) (p & PARASITIC_ENTRY_DM)
31627836SJohn.Forte@Sun.COM #define OTHER(p) \
31637836SJohn.Forte@Sun.COM (!(p & (HOST_ENTRY_DM | PARASITIC_ENTRY_DM | ELIGIBLE_ENTRY_DM)))
31647836SJohn.Forte@Sun.COM
31657836SJohn.Forte@Sun.COM #define AVAIL(p) (p & AVAIL_ENTRY_DM)
31667836SJohn.Forte@Sun.COM
31677836SJohn.Forte@Sun.COM /*
31687836SJohn.Forte@Sun.COM * sdbc_check_cctl_cot -- consistency check for _sd_setup_category_on_type()
31697836SJohn.Forte@Sun.COM * may only be called on entry to state machine (when ccent is either
31707836SJohn.Forte@Sun.COM * ELIGIBLE_ENTRY_DM, HOLD_ENTRY_DM or HASH_ENTRY_DM).
31717836SJohn.Forte@Sun.COM *
31727836SJohn.Forte@Sun.COM * print message or panic (DEBUG) if inconsistency detected.
31737836SJohn.Forte@Sun.COM */
31747836SJohn.Forte@Sun.COM static int
31757836SJohn.Forte@Sun.COM sdbc_check_cctl_cot(_sd_cctl_t *centry)
31767836SJohn.Forte@Sun.COM {
31777836SJohn.Forte@Sun.COM uint_t age;
31787836SJohn.Forte@Sun.COM int size;
31797836SJohn.Forte@Sun.COM uchar_t *data;
31807836SJohn.Forte@Sun.COM int host_or_other;
31817836SJohn.Forte@Sun.COM int para;
31827836SJohn.Forte@Sun.COM int ccent_ok = 1;
31837836SJohn.Forte@Sun.COM
31847836SJohn.Forte@Sun.COM age = centry->cc_aging_dm;
31857836SJohn.Forte@Sun.COM size = centry->cc_alloc_size_dm;
31867836SJohn.Forte@Sun.COM data = centry->cc_data;
31877836SJohn.Forte@Sun.COM host_or_other = size && data;
31887836SJohn.Forte@Sun.COM para = !size && data;
31897836SJohn.Forte@Sun.COM
31907836SJohn.Forte@Sun.COM /*
31917836SJohn.Forte@Sun.COM * on entry to _sd_setup_category_on_type(),
31927836SJohn.Forte@Sun.COM * one of three mutually exclusive entry field bits must be set
31937836SJohn.Forte@Sun.COM */
31947836SJohn.Forte@Sun.COM
31957836SJohn.Forte@Sun.COM switch ((age & (ELIGIBLE_ENTRY_DM | HOLD_ENTRY_DM | HASH_ENTRY_DM))) {
31967836SJohn.Forte@Sun.COM case ELIGIBLE_ENTRY_DM:
31977836SJohn.Forte@Sun.COM case HOLD_ENTRY_DM:
31987836SJohn.Forte@Sun.COM case HASH_ENTRY_DM:
31997836SJohn.Forte@Sun.COM /* ok */
32007836SJohn.Forte@Sun.COM break;
32017836SJohn.Forte@Sun.COM default:
32027836SJohn.Forte@Sun.COM /* zero or multiple flag bits */
32037836SJohn.Forte@Sun.COM ccent_ok = 0;
32047836SJohn.Forte@Sun.COM break;
32057836SJohn.Forte@Sun.COM }
32067836SJohn.Forte@Sun.COM
32077836SJohn.Forte@Sun.COM /* categories are mutually exclusive */
32087836SJohn.Forte@Sun.COM if (HOST(age) && PARA(age))
32097836SJohn.Forte@Sun.COM ccent_ok = 0;
32107836SJohn.Forte@Sun.COM
32117836SJohn.Forte@Sun.COM /* these bits should be cleared out (STICKY_METADATA_DM not used) */
32127836SJohn.Forte@Sun.COM if (age & (AVAIL_ENTRY_DM | FOUND_HOLD_OVER_DM | FOUND_IN_HASH_DM |
3213*9093SRamana.Srikanth@Sun.COM STICKY_METADATA_DM))
32147836SJohn.Forte@Sun.COM ccent_ok = 0;
32157836SJohn.Forte@Sun.COM
32167836SJohn.Forte@Sun.COM /* eligible has no data and no size */
32177836SJohn.Forte@Sun.COM if (ELIGIBLE(age) && (size || data))
32187836SJohn.Forte@Sun.COM ccent_ok = 0;
32197836SJohn.Forte@Sun.COM
32207836SJohn.Forte@Sun.COM /* parasite has zero size and non-zero data */
32217836SJohn.Forte@Sun.COM if (PARA(age) && !para)
32227836SJohn.Forte@Sun.COM ccent_ok = 0;
32237836SJohn.Forte@Sun.COM
32247836SJohn.Forte@Sun.COM /* host has non-zero size and non-zero data */
32257836SJohn.Forte@Sun.COM if (HOST(age) && !host_or_other)
32267836SJohn.Forte@Sun.COM ccent_ok = 0;
32277836SJohn.Forte@Sun.COM
32287836SJohn.Forte@Sun.COM /* "other" is just like a host */
32297836SJohn.Forte@Sun.COM if (OTHER(age) && !host_or_other)
32307836SJohn.Forte@Sun.COM ccent_ok = 0;
32317836SJohn.Forte@Sun.COM
32327836SJohn.Forte@Sun.COM /* a HOLD or a HASH must have a size */
32337836SJohn.Forte@Sun.COM if ((size) && !(age & (HASH_ENTRY_DM | HOLD_ENTRY_DM)))
32347836SJohn.Forte@Sun.COM ccent_ok = 0;
32357836SJohn.Forte@Sun.COM
32367836SJohn.Forte@Sun.COM if (!ccent_ok)
32377836SJohn.Forte@Sun.COM cmn_err(cmn_level,
3238*9093SRamana.Srikanth@Sun.COM "!sdbc(sdbc_check_cctl_cot): inconsistent ccent %p "
32397836SJohn.Forte@Sun.COM "age %x size %d data %p", (void *)centry, age, size,
32407836SJohn.Forte@Sun.COM (void *)data);
32417836SJohn.Forte@Sun.COM
32427836SJohn.Forte@Sun.COM return (ccent_ok);
32437836SJohn.Forte@Sun.COM }
32447836SJohn.Forte@Sun.COM
32457836SJohn.Forte@Sun.COM /*
32467836SJohn.Forte@Sun.COM * sdbc_mark_cctl_cot -- mark cctls bad and invalidate when
32477836SJohn.Forte@Sun.COM * inconsistency found in _sd_setup_category_on_type()
32487836SJohn.Forte@Sun.COM * returns nothing
32497836SJohn.Forte@Sun.COM *
32507836SJohn.Forte@Sun.COM * Note: this is an error recovery path that is triggered when an
32517836SJohn.Forte@Sun.COM * inconsistency in a cctl is detected. _sd_centry_release() will take
32527836SJohn.Forte@Sun.COM * these cache entries out of circulation and place them on a separate list
32537836SJohn.Forte@Sun.COM * for debugging purposes.
32547836SJohn.Forte@Sun.COM */
32557836SJohn.Forte@Sun.COM void
32567836SJohn.Forte@Sun.COM sdbc_mark_cctl_cot(_sd_cctl_t *header, _sd_cctl_t *centry)
32577836SJohn.Forte@Sun.COM {
32587836SJohn.Forte@Sun.COM _sd_cctl_t *cur_ent = header;
32597836SJohn.Forte@Sun.COM
32607836SJohn.Forte@Sun.COM /* the entire chain is guilty by association */
32617836SJohn.Forte@Sun.COM while (cur_ent) {
32627836SJohn.Forte@Sun.COM
32637836SJohn.Forte@Sun.COM (void) _sd_hash_delete((struct _sd_hash_hd *)cur_ent,
32647836SJohn.Forte@Sun.COM _sd_htable);
32657836SJohn.Forte@Sun.COM
32667836SJohn.Forte@Sun.COM cur_ent->cc_aging_dm |= BAD_CHAIN_DM;
32677836SJohn.Forte@Sun.COM
32687836SJohn.Forte@Sun.COM cur_ent = cur_ent->cc_chain;
32697836SJohn.Forte@Sun.COM }
32707836SJohn.Forte@Sun.COM
32717836SJohn.Forte@Sun.COM centry->cc_aging_dm |= BAD_ENTRY_DM; /* this is the problem child */
32727836SJohn.Forte@Sun.COM }
32737836SJohn.Forte@Sun.COM
32747836SJohn.Forte@Sun.COM /*
32757836SJohn.Forte@Sun.COM * _sd_setup_category_on_type(_sd_cctl_t *) - Setup the centry CATEGORY based on
32767836SJohn.Forte@Sun.COM * centry TYPE and immediate neighbors. Identify each eligible (ie not HASH)
32777836SJohn.Forte@Sun.COM * centry as a host/parasite. host actually have memory allocated to
32787836SJohn.Forte@Sun.COM * them and parasites are chained to the host and point to page offsets within
32797836SJohn.Forte@Sun.COM * the host's memory.
32807836SJohn.Forte@Sun.COM *
32817836SJohn.Forte@Sun.COM * RETURNS:
32827836SJohn.Forte@Sun.COM * 0 on success, EINTR if inconsistency detected in centry
32837836SJohn.Forte@Sun.COM *
32847836SJohn.Forte@Sun.COM * Note:
32857836SJohn.Forte@Sun.COM * none
32867836SJohn.Forte@Sun.COM */
32877836SJohn.Forte@Sun.COM static int
32887836SJohn.Forte@Sun.COM _sd_setup_category_on_type(_sd_cctl_t *header)
32897836SJohn.Forte@Sun.COM {
32907836SJohn.Forte@Sun.COM _sd_cctl_t *prev_ent, *next_ent, *centry;
32917836SJohn.Forte@Sun.COM _sd_cctl_t *anchor = NULL;
32927836SJohn.Forte@Sun.COM int current_pest_count, local_max_dyn_list;
32937836SJohn.Forte@Sun.COM int cl;
32947836SJohn.Forte@Sun.COM int ret = 0;
32957836SJohn.Forte@Sun.COM
32967836SJohn.Forte@Sun.COM ASSERT(header);
32977836SJohn.Forte@Sun.COM
32987836SJohn.Forte@Sun.COM if (sdbc_use_dmchain)
32997836SJohn.Forte@Sun.COM local_max_dyn_list = max_dm_queues - 1;
33007836SJohn.Forte@Sun.COM else {
33017836SJohn.Forte@Sun.COM /* pickup a fresh copy - has the world changed */
33027836SJohn.Forte@Sun.COM local_max_dyn_list = dynmem_processing_dm.max_dyn_list;
33037836SJohn.Forte@Sun.COM }
33047836SJohn.Forte@Sun.COM
33057836SJohn.Forte@Sun.COM prev_ent = 0;
33067836SJohn.Forte@Sun.COM centry = header;
33077836SJohn.Forte@Sun.COM next_ent = centry->cc_chain;
33087836SJohn.Forte@Sun.COM current_pest_count = 0;
33097836SJohn.Forte@Sun.COM cl = 2;
33107836SJohn.Forte@Sun.COM
33117836SJohn.Forte@Sun.COM /* try to recover from bad cctl */
33127836SJohn.Forte@Sun.COM if (sdbc_check_cot && !sdbc_check_cctl_cot(centry))
33137836SJohn.Forte@Sun.COM ret = EINTR;
33147836SJohn.Forte@Sun.COM
33157836SJohn.Forte@Sun.COM while (cl && (ret == 0)) {
33167836SJohn.Forte@Sun.COM switch (cl) {
33177836SJohn.Forte@Sun.COM case (1): /* chain to next/monitor for completion */
33187836SJohn.Forte@Sun.COM prev_ent = centry;
33197836SJohn.Forte@Sun.COM centry = next_ent;
33207836SJohn.Forte@Sun.COM next_ent = 0;
33217836SJohn.Forte@Sun.COM cl = 0;
33227836SJohn.Forte@Sun.COM if (centry) {
33237836SJohn.Forte@Sun.COM
33247836SJohn.Forte@Sun.COM if (sdbc_check_cot &&
3325*9093SRamana.Srikanth@Sun.COM !sdbc_check_cctl_cot(centry)) {
33267836SJohn.Forte@Sun.COM ret = EINTR;
33277836SJohn.Forte@Sun.COM break;
33287836SJohn.Forte@Sun.COM }
33297836SJohn.Forte@Sun.COM
33307836SJohn.Forte@Sun.COM next_ent = centry->cc_chain;
33317836SJohn.Forte@Sun.COM cl = 2;
33327836SJohn.Forte@Sun.COM }
33337836SJohn.Forte@Sun.COM break;
33347836SJohn.Forte@Sun.COM
33357836SJohn.Forte@Sun.COM case (2): /* vector to appropriate routine */
33367836SJohn.Forte@Sun.COM if (!(centry->cc_aging_dm & ELIGIBLE_ENTRY_DM))
33377836SJohn.Forte@Sun.COM cl = 5;
33387836SJohn.Forte@Sun.COM else if (prev_ent && (prev_ent->cc_aging_dm &
3339*9093SRamana.Srikanth@Sun.COM ELIGIBLE_ENTRY_DM))
33407836SJohn.Forte@Sun.COM cl = 15;
33417836SJohn.Forte@Sun.COM else
33427836SJohn.Forte@Sun.COM cl = 10;
33437836SJohn.Forte@Sun.COM break;
33447836SJohn.Forte@Sun.COM
33457836SJohn.Forte@Sun.COM case (5): /* process NON-ELIGIBLE entries */
33467836SJohn.Forte@Sun.COM if (!(centry->cc_aging_dm &
3347*9093SRamana.Srikanth@Sun.COM (HASH_ENTRY_DM|HOLD_ENTRY_DM))) {
33487836SJohn.Forte@Sun.COM /* no catagory */
33497836SJohn.Forte@Sun.COM
33507836SJohn.Forte@Sun.COM /* consistency check */
33517836SJohn.Forte@Sun.COM if (centry->cc_alloc_size_dm ||
3352*9093SRamana.Srikanth@Sun.COM centry->cc_data) {
33537836SJohn.Forte@Sun.COM cmn_err(cmn_level,
3354*9093SRamana.Srikanth@Sun.COM "!sdbc(setup_cot): "
33557836SJohn.Forte@Sun.COM "OTHER with data/size %p",
33567836SJohn.Forte@Sun.COM (void *)centry);
33577836SJohn.Forte@Sun.COM
33587836SJohn.Forte@Sun.COM ret = EINTR;
33597836SJohn.Forte@Sun.COM break;
33607836SJohn.Forte@Sun.COM }
33617836SJohn.Forte@Sun.COM
33627836SJohn.Forte@Sun.COM centry->cc_aging_dm &=
33637836SJohn.Forte@Sun.COM ~CATAGORY_ENTRY_DM;
33647836SJohn.Forte@Sun.COM centry->cc_alloc_size_dm = BLK_SIZE(1);
33657836SJohn.Forte@Sun.COM DTRACE_PROBE1(_sd_setup_category,
3366*9093SRamana.Srikanth@Sun.COM _sd_cctl_t *, centry);
33677836SJohn.Forte@Sun.COM }
33687836SJohn.Forte@Sun.COM cl = 1;
33697836SJohn.Forte@Sun.COM break;
33707836SJohn.Forte@Sun.COM
33717836SJohn.Forte@Sun.COM /*
33727836SJohn.Forte@Sun.COM * no prev entry (ie top of list) or no prev
33737836SJohn.Forte@Sun.COM * ELIGIBLE entry
33747836SJohn.Forte@Sun.COM */
33757836SJohn.Forte@Sun.COM case (10):
33767836SJohn.Forte@Sun.COM /*
33777836SJohn.Forte@Sun.COM * this is an eligible entry, does it start
33787836SJohn.Forte@Sun.COM * a list or is it a loner
33797836SJohn.Forte@Sun.COM */
33807836SJohn.Forte@Sun.COM /* consistency check */
33817836SJohn.Forte@Sun.COM if (centry->cc_alloc_size_dm ||
3382*9093SRamana.Srikanth@Sun.COM centry->cc_data) {
3383*9093SRamana.Srikanth@Sun.COM cmn_err(cmn_level, "!sdbc(setup_cot): "
33847836SJohn.Forte@Sun.COM "HOST with data/size %p",
33857836SJohn.Forte@Sun.COM (void *)centry);
33867836SJohn.Forte@Sun.COM ret = EINTR;
33877836SJohn.Forte@Sun.COM break;
33887836SJohn.Forte@Sun.COM }
33897836SJohn.Forte@Sun.COM
33907836SJohn.Forte@Sun.COM if (next_ent && (next_ent->cc_aging_dm &
33917836SJohn.Forte@Sun.COM ELIGIBLE_ENTRY_DM)) {
33927836SJohn.Forte@Sun.COM
33937836SJohn.Forte@Sun.COM
33947836SJohn.Forte@Sun.COM /* it starts a list */
33957836SJohn.Forte@Sun.COM /* host catagory */
33967836SJohn.Forte@Sun.COM centry->cc_aging_dm |= HOST_ENTRY_DM;
33977836SJohn.Forte@Sun.COM /* start out with one page */
33987836SJohn.Forte@Sun.COM centry->cc_alloc_size_dm = BLK_SIZE(1);
33997836SJohn.Forte@Sun.COM anchor = centry;
34007836SJohn.Forte@Sun.COM DTRACE_PROBE1(_sd_setup_category,
3401*9093SRamana.Srikanth@Sun.COM _sd_cctl_t *, anchor);
34027836SJohn.Forte@Sun.COM cl = 1;
34037836SJohn.Forte@Sun.COM } else {
34047836SJohn.Forte@Sun.COM /*
34057836SJohn.Forte@Sun.COM * it's a loner
34067836SJohn.Forte@Sun.COM * drop status to no category and
34077836SJohn.Forte@Sun.COM * restart
34087836SJohn.Forte@Sun.COM */
34097836SJohn.Forte@Sun.COM cl = 2;
34107836SJohn.Forte@Sun.COM centry->cc_aging_dm &=
34117836SJohn.Forte@Sun.COM ~ELIGIBLE_ENTRY_DM;
34127836SJohn.Forte@Sun.COM }
34137836SJohn.Forte@Sun.COM break;
34147836SJohn.Forte@Sun.COM
34157836SJohn.Forte@Sun.COM case (15): /* default to parasite catagory */
34167836SJohn.Forte@Sun.COM
34177836SJohn.Forte@Sun.COM /* consistency check */
34187836SJohn.Forte@Sun.COM if (centry->cc_alloc_size_dm ||
3419*9093SRamana.Srikanth@Sun.COM centry->cc_data) {
3420*9093SRamana.Srikanth@Sun.COM cmn_err(cmn_level, "!sdbc(setup_cot): "
34217836SJohn.Forte@Sun.COM "PARA with data/size %p",
34227836SJohn.Forte@Sun.COM (void *)centry);
34237836SJohn.Forte@Sun.COM
34247836SJohn.Forte@Sun.COM ret = EINTR;
34257836SJohn.Forte@Sun.COM break;
34267836SJohn.Forte@Sun.COM }
34277836SJohn.Forte@Sun.COM
34287836SJohn.Forte@Sun.COM if (current_pest_count < local_max_dyn_list-1) {
34297836SJohn.Forte@Sun.COM /* continue to grow the pest list */
34307836SJohn.Forte@Sun.COM current_pest_count++;
34317836SJohn.Forte@Sun.COM centry->cc_aging_dm |=
34327836SJohn.Forte@Sun.COM PARASITIC_ENTRY_DM;
34337836SJohn.Forte@Sun.COM
34347836SJohn.Forte@Sun.COM /*
34357836SJohn.Forte@Sun.COM * offset of host ent mem this will pt
34367836SJohn.Forte@Sun.COM * to
34377836SJohn.Forte@Sun.COM */
34387836SJohn.Forte@Sun.COM centry->cc_alloc_size_dm =
34397836SJohn.Forte@Sun.COM anchor->cc_alloc_size_dm;
34407836SJohn.Forte@Sun.COM /*
34417836SJohn.Forte@Sun.COM * up the host mem req by one for
34427836SJohn.Forte@Sun.COM * this parasite
34437836SJohn.Forte@Sun.COM */
34447836SJohn.Forte@Sun.COM DTRACE_PROBE1(_sd_setup_category,
3445*9093SRamana.Srikanth@Sun.COM _sd_cctl_t *, centry);
34467836SJohn.Forte@Sun.COM
34477836SJohn.Forte@Sun.COM anchor->cc_alloc_size_dm += BLK_SIZE(1);
34487836SJohn.Forte@Sun.COM
34497836SJohn.Forte@Sun.COM cl = 1;
34507836SJohn.Forte@Sun.COM } else {
34517836SJohn.Forte@Sun.COM /*
34527836SJohn.Forte@Sun.COM * term this pest list - restart fresh
34537836SJohn.Forte@Sun.COM * on this entry
34547836SJohn.Forte@Sun.COM */
34557836SJohn.Forte@Sun.COM current_pest_count = 0;
34567836SJohn.Forte@Sun.COM prev_ent->cc_aging_dm &=
34577836SJohn.Forte@Sun.COM ~(HOST_ENTRY_DM|ELIGIBLE_ENTRY_DM);
34587836SJohn.Forte@Sun.COM cl = 2;
34597836SJohn.Forte@Sun.COM }
34607836SJohn.Forte@Sun.COM break;
34617836SJohn.Forte@Sun.COM } /* switch(cl) */
34627836SJohn.Forte@Sun.COM } /* while (cl) */
34637836SJohn.Forte@Sun.COM
34647836SJohn.Forte@Sun.COM if (ret != 0)
34657836SJohn.Forte@Sun.COM sdbc_mark_cctl_cot(header, centry);
34667836SJohn.Forte@Sun.COM
34677836SJohn.Forte@Sun.COM return (ret);
34687836SJohn.Forte@Sun.COM }
34697836SJohn.Forte@Sun.COM
34707836SJohn.Forte@Sun.COM /*
34717836SJohn.Forte@Sun.COM * _sd_setup_mem_chaining(_sd_cctl_t *) - Allocate memory, setup
34727836SJohn.Forte@Sun.COM * mem ptrs an host/pest chaining. Do the actual allocation as described in
34737836SJohn.Forte@Sun.COM * sd_setup_category_on_type().
34747836SJohn.Forte@Sun.COM *
34757836SJohn.Forte@Sun.COM * RETURNS:
34767836SJohn.Forte@Sun.COM * 0 on success
34777836SJohn.Forte@Sun.COM * non-zero on error
34787836SJohn.Forte@Sun.COM *
34797836SJohn.Forte@Sun.COM * Note:
34807836SJohn.Forte@Sun.COM * if called with ALLOC_NOWAIT, caller must check for non-zero return
34817836SJohn.Forte@Sun.COM */
34827836SJohn.Forte@Sun.COM static int
34837836SJohn.Forte@Sun.COM _sd_setup_mem_chaining(_sd_cctl_t *header, int flag)
34847836SJohn.Forte@Sun.COM {
34857836SJohn.Forte@Sun.COM _sd_cctl_t *prev_ent, *next_ent, *centry;
34867836SJohn.Forte@Sun.COM _sd_cctl_t *anchor = NULL;
34877836SJohn.Forte@Sun.COM int cl, rc = 0;
34887836SJohn.Forte@Sun.COM
34897836SJohn.Forte@Sun.COM ASSERT(header);
34907836SJohn.Forte@Sun.COM
34917836SJohn.Forte@Sun.COM if (!header)
34927836SJohn.Forte@Sun.COM return (0);
34937836SJohn.Forte@Sun.COM
34947836SJohn.Forte@Sun.COM prev_ent = 0;
34957836SJohn.Forte@Sun.COM centry = header;
34967836SJohn.Forte@Sun.COM next_ent = centry->cc_chain;
34977836SJohn.Forte@Sun.COM cl = 2;
34987836SJohn.Forte@Sun.COM while (cl) {
34997836SJohn.Forte@Sun.COM switch (cl) {
35007836SJohn.Forte@Sun.COM case (1): /* chain to next/monitor for completion */
35017836SJohn.Forte@Sun.COM centry->cc_aging_dm &= ~ELIGIBLE_ENTRY_DM;
35027836SJohn.Forte@Sun.COM prev_ent = centry;
35037836SJohn.Forte@Sun.COM centry = next_ent;
35047836SJohn.Forte@Sun.COM next_ent = 0;
35057836SJohn.Forte@Sun.COM cl = 0;
35067836SJohn.Forte@Sun.COM if (centry) {
35077836SJohn.Forte@Sun.COM next_ent = centry->cc_chain;
35087836SJohn.Forte@Sun.COM cl = 2;
35097836SJohn.Forte@Sun.COM }
35107836SJohn.Forte@Sun.COM break;
35117836SJohn.Forte@Sun.COM
35127836SJohn.Forte@Sun.COM case (2): /* vector to appropriate routine */
35137836SJohn.Forte@Sun.COM if (centry->cc_aging_dm & HOST_ENTRY_DM)
35147836SJohn.Forte@Sun.COM cl = 10;
35157836SJohn.Forte@Sun.COM else if (centry->cc_aging_dm &
35167836SJohn.Forte@Sun.COM PARASITIC_ENTRY_DM)
35177836SJohn.Forte@Sun.COM cl = 15;
35187836SJohn.Forte@Sun.COM else
35197836SJohn.Forte@Sun.COM cl = 5;
35207836SJohn.Forte@Sun.COM break;
35217836SJohn.Forte@Sun.COM
35227836SJohn.Forte@Sun.COM case (5): /* OTHER processing - alloc mem */
35237836SJohn.Forte@Sun.COM if (rc = sdbc_centry_memalloc_dm(centry,
35247836SJohn.Forte@Sun.COM centry->cc_alloc_size_dm, flag))
35257836SJohn.Forte@Sun.COM /* The allocation failed */
35267836SJohn.Forte@Sun.COM cl = 0;
35277836SJohn.Forte@Sun.COM else
35287836SJohn.Forte@Sun.COM cl = 1;
35297836SJohn.Forte@Sun.COM break;
35307836SJohn.Forte@Sun.COM
35317836SJohn.Forte@Sun.COM /*
35327836SJohn.Forte@Sun.COM * HOST entry processing - save the anchor pt,
35337836SJohn.Forte@Sun.COM * alloc the memory,
35347836SJohn.Forte@Sun.COM */
35357836SJohn.Forte@Sun.COM case (10): /* setup head and nxt ptrs */
35367836SJohn.Forte@Sun.COM anchor = centry;
35377836SJohn.Forte@Sun.COM if (rc = sdbc_centry_memalloc_dm(centry,
35387836SJohn.Forte@Sun.COM centry->cc_alloc_size_dm, flag))
35397836SJohn.Forte@Sun.COM /* The allocation failed */
35407836SJohn.Forte@Sun.COM cl = 0;
35417836SJohn.Forte@Sun.COM else
35427836SJohn.Forte@Sun.COM cl = 1;
35437836SJohn.Forte@Sun.COM break;
35447836SJohn.Forte@Sun.COM
35457836SJohn.Forte@Sun.COM /*
35467836SJohn.Forte@Sun.COM * PARASITIC entry processing - setup w/no
35477836SJohn.Forte@Sun.COM * memory, setup head/next ptrs,
35487836SJohn.Forte@Sun.COM */
35497836SJohn.Forte@Sun.COM case (15):
35507836SJohn.Forte@Sun.COM /*
35517836SJohn.Forte@Sun.COM * fudge the data mem ptr to an offset from
35527836SJohn.Forte@Sun.COM * the anchor alloc
35537836SJohn.Forte@Sun.COM */
35547836SJohn.Forte@Sun.COM if (!(centry->cc_aging_dm &
3555*9093SRamana.Srikanth@Sun.COM (HASH_ENTRY_DM| HOLD_ENTRY_DM))) {
35567836SJohn.Forte@Sun.COM centry->cc_head_dm = anchor;
35577836SJohn.Forte@Sun.COM
35587836SJohn.Forte@Sun.COM /* chain prev to this */
35597836SJohn.Forte@Sun.COM prev_ent->cc_next_dm = centry;
35607836SJohn.Forte@Sun.COM
35617836SJohn.Forte@Sun.COM /*
35627836SJohn.Forte@Sun.COM * generate the actual data ptr into
35637836SJohn.Forte@Sun.COM * host entry memory
35647836SJohn.Forte@Sun.COM */
35657836SJohn.Forte@Sun.COM centry->cc_data = anchor->cc_data +
3566*9093SRamana.Srikanth@Sun.COM centry->cc_alloc_size_dm;
35677836SJohn.Forte@Sun.COM centry->cc_alloc_size_dm = 0;
35687836SJohn.Forte@Sun.COM }
35697836SJohn.Forte@Sun.COM cl = 1;
35707836SJohn.Forte@Sun.COM break;
35717836SJohn.Forte@Sun.COM } /* switch(cl) */
35727836SJohn.Forte@Sun.COM } /* while (cl) */
35737836SJohn.Forte@Sun.COM
35747836SJohn.Forte@Sun.COM return (rc);
35757836SJohn.Forte@Sun.COM }
35767836SJohn.Forte@Sun.COM
35777836SJohn.Forte@Sun.COM /*
35787836SJohn.Forte@Sun.COM * _sd_check_buffer_alloc - Check if buffer allocation is invalid.
35797836SJohn.Forte@Sun.COM *
35807836SJohn.Forte@Sun.COM * RETURNS:
35817836SJohn.Forte@Sun.COM * 0 if its ok to continue with allocation.
35827836SJohn.Forte@Sun.COM * Else errno to be returned to the user.
35837836SJohn.Forte@Sun.COM *
35847836SJohn.Forte@Sun.COM * Note:
35857836SJohn.Forte@Sun.COM * This routine could block if the device is not local and
35867836SJohn.Forte@Sun.COM * recovery is in progress.
35877836SJohn.Forte@Sun.COM */
35887836SJohn.Forte@Sun.COM
35897836SJohn.Forte@Sun.COM /* ARGSUSED */
35907836SJohn.Forte@Sun.COM static int
35917836SJohn.Forte@Sun.COM _sd_check_buffer_alloc(int cd, nsc_off_t fba_pos, nsc_size_t fba_len,
35927836SJohn.Forte@Sun.COM _sd_buf_handle_t **hp)
35937836SJohn.Forte@Sun.COM {
35947836SJohn.Forte@Sun.COM /*
35957836SJohn.Forte@Sun.COM * This check exists to ensure that someone will not pass in an
35967836SJohn.Forte@Sun.COM * arbitrary pointer and try to pass it off as a handle.
35977836SJohn.Forte@Sun.COM */
35987836SJohn.Forte@Sun.COM if ((*hp)->bh_flag & (~_SD_VALID_FLAGS)) {
3599*9093SRamana.Srikanth@Sun.COM cmn_err(CE_WARN, "!sdbc(_sd_check_buffer_alloc) "
36007836SJohn.Forte@Sun.COM "cd %d invalid handle %p flags %x",
36017836SJohn.Forte@Sun.COM cd, (void *)*hp, (*hp)->bh_flag);
36027836SJohn.Forte@Sun.COM return (EINVAL);
36037836SJohn.Forte@Sun.COM }
36047836SJohn.Forte@Sun.COM
36057836SJohn.Forte@Sun.COM if ((_sd_cache_initialized == 0) || (FILE_OPENED(cd) == 0)) {
3606*9093SRamana.Srikanth@Sun.COM cmn_err(CE_WARN, "!sdbc(_sd_check_buffer_alloc) "
36077836SJohn.Forte@Sun.COM "cd %d not open. Cache init %d",
36087836SJohn.Forte@Sun.COM cd, _sd_cache_initialized);
36097836SJohn.Forte@Sun.COM return (EINVAL);
36107836SJohn.Forte@Sun.COM }
36117836SJohn.Forte@Sun.COM ASSERT(cd >= 0);
36127836SJohn.Forte@Sun.COM if (!(_sd_cache_files[cd].cd_rawfd) ||
36137836SJohn.Forte@Sun.COM !nsc_held(_sd_cache_files[cd].cd_rawfd)) {
36147836SJohn.Forte@Sun.COM cmn_err(CE_WARN,
3615*9093SRamana.Srikanth@Sun.COM "!sdbc(_sd_check_buffer_alloc) cd %d is not attached", cd);
36167836SJohn.Forte@Sun.COM return (EINVAL);
36177836SJohn.Forte@Sun.COM }
36187836SJohn.Forte@Sun.COM
36197836SJohn.Forte@Sun.COM ASSERT_IO_SIZE(fba_pos, fba_len, cd);
36207836SJohn.Forte@Sun.COM ASSERT_LEN(fba_len);
36217836SJohn.Forte@Sun.COM
36227836SJohn.Forte@Sun.COM return (0);
36237836SJohn.Forte@Sun.COM }
36247836SJohn.Forte@Sun.COM
36257836SJohn.Forte@Sun.COM /*
36267836SJohn.Forte@Sun.COM * sdbc_check_handle -- check that handle is valid
36277836SJohn.Forte@Sun.COM * return 1 if ok, 0 otherwise (if debug then panic).
36287836SJohn.Forte@Sun.COM */
36297836SJohn.Forte@Sun.COM static int
36307836SJohn.Forte@Sun.COM sdbc_check_handle(_sd_buf_handle_t *handle)
36317836SJohn.Forte@Sun.COM {
36327836SJohn.Forte@Sun.COM int ret = 1;
36337836SJohn.Forte@Sun.COM
36347836SJohn.Forte@Sun.COM if (!_SD_HANDLE_ACTIVE(handle)) {
36357836SJohn.Forte@Sun.COM
3636*9093SRamana.Srikanth@Sun.COM cmn_err(cmn_level, "!sdbc(_sd_free_buf): invalid handle %p"
36377836SJohn.Forte@Sun.COM "cd %d fpos %" NSC_SZFMT " flen %" NSC_SZFMT " flag %x",
36387836SJohn.Forte@Sun.COM (void *)handle, HANDLE_CD(handle), handle->bh_fba_pos,
36397836SJohn.Forte@Sun.COM handle->bh_fba_len, handle->bh_flag);
36407836SJohn.Forte@Sun.COM
36417836SJohn.Forte@Sun.COM ret = 0;
36427836SJohn.Forte@Sun.COM }
36437836SJohn.Forte@Sun.COM
36447836SJohn.Forte@Sun.COM return (ret);
36457836SJohn.Forte@Sun.COM }
36467836SJohn.Forte@Sun.COM
36477836SJohn.Forte@Sun.COM /*
36487836SJohn.Forte@Sun.COM * _sd_free_buf - Free the buffers allocated in _sd_alloc_buf.
36497836SJohn.Forte@Sun.COM *
36507836SJohn.Forte@Sun.COM * ARGUMENTS:
36517836SJohn.Forte@Sun.COM * handle - The handle allocated in _sd_alloc_buf.
36527836SJohn.Forte@Sun.COM *
36537836SJohn.Forte@Sun.COM * RETURNS:
36547836SJohn.Forte@Sun.COM * 0 on success.
36557836SJohn.Forte@Sun.COM * Else errno.
36567836SJohn.Forte@Sun.COM *
36577836SJohn.Forte@Sun.COM * NOTE:
36587836SJohn.Forte@Sun.COM * If handle was allocated through _sd_alloc_buf, the handle allocated
36597836SJohn.Forte@Sun.COM * flag (NSC_HALLOCATED) will be reset by _sd_alloc_buf. This indicates
36607836SJohn.Forte@Sun.COM * that _sd_free_buf should free up the handle as well.
36617836SJohn.Forte@Sun.COM * All other handles directly allocated from _sd_alloc_handle will have
36627836SJohn.Forte@Sun.COM * that flag set. Any handle with valid blocks will have the handle
36637836SJohn.Forte@Sun.COM * active flag. It is an error if the active flag is not set.
36647836SJohn.Forte@Sun.COM * (if free_buf were called without going through alloc_buf)
36657836SJohn.Forte@Sun.COM */
36667836SJohn.Forte@Sun.COM
36677836SJohn.Forte@Sun.COM int
36687836SJohn.Forte@Sun.COM _sd_free_buf(_sd_buf_handle_t *handle)
36697836SJohn.Forte@Sun.COM {
36707836SJohn.Forte@Sun.COM _sd_cctl_t *centry, *cc_chain;
36717836SJohn.Forte@Sun.COM int cd = HANDLE_CD(handle);
36727836SJohn.Forte@Sun.COM int flen = handle->bh_fba_len;
36737836SJohn.Forte@Sun.COM int fpos = handle->bh_fba_pos;
36747836SJohn.Forte@Sun.COM
36757836SJohn.Forte@Sun.COM SDTRACE(ST_ENTER|SDF_FREEBUF, HANDLE_CD(handle),
3676*9093SRamana.Srikanth@Sun.COM handle->bh_fba_len, handle->bh_fba_pos, 0, 0);
36777836SJohn.Forte@Sun.COM
36787836SJohn.Forte@Sun.COM if (sdbc_check_handle(handle) == 0)
36797836SJohn.Forte@Sun.COM return (EINVAL);
36807836SJohn.Forte@Sun.COM
36817836SJohn.Forte@Sun.COM if (handle->bh_flag & NSC_MIXED) {
36827836SJohn.Forte@Sun.COM /*
36837836SJohn.Forte@Sun.COM * Data in this handle will be a mix of data from the
36847836SJohn.Forte@Sun.COM * source device and data from another device, so
36857836SJohn.Forte@Sun.COM * invalidate all the blocks.
36867836SJohn.Forte@Sun.COM */
36877836SJohn.Forte@Sun.COM handle->bh_flag &= ~NSC_QUEUE;
36887836SJohn.Forte@Sun.COM centry = handle->bh_centry;
36897836SJohn.Forte@Sun.COM while (centry) {
36907836SJohn.Forte@Sun.COM centry->cc_valid = 0;
36917836SJohn.Forte@Sun.COM centry = centry->cc_chain;
36927836SJohn.Forte@Sun.COM }
36937836SJohn.Forte@Sun.COM }
36947836SJohn.Forte@Sun.COM
36957836SJohn.Forte@Sun.COM if ((handle->bh_flag & NSC_QUEUE)) {
36967836SJohn.Forte@Sun.COM handle->bh_flag &= ~NSC_QUEUE;
36977836SJohn.Forte@Sun.COM _sd_queue_write(handle, handle->bh_fba_pos, handle->bh_fba_len);
36987836SJohn.Forte@Sun.COM }
36997836SJohn.Forte@Sun.COM
37007836SJohn.Forte@Sun.COM handle->bh_flag &= ~NSC_HACTIVE;
37017836SJohn.Forte@Sun.COM
37027836SJohn.Forte@Sun.COM centry = handle->bh_centry;
37037836SJohn.Forte@Sun.COM while (centry) {
37047836SJohn.Forte@Sun.COM cc_chain = centry->cc_chain;
37057836SJohn.Forte@Sun.COM _sd_centry_release(centry);
37067836SJohn.Forte@Sun.COM centry = cc_chain;
37077836SJohn.Forte@Sun.COM }
37087836SJohn.Forte@Sun.COM
37097836SJohn.Forte@Sun.COM /*
37107836SJohn.Forte@Sun.COM * help prevent dup call to _sd_centry_release if this handle
37117836SJohn.Forte@Sun.COM * is erroneously _sd_free_buf'd twice. (should not happen).
37127836SJohn.Forte@Sun.COM */
37137836SJohn.Forte@Sun.COM handle->bh_centry = NULL;
37147836SJohn.Forte@Sun.COM
37157836SJohn.Forte@Sun.COM if ((handle->bh_flag & NSC_HALLOCATED) == 0) {
37167836SJohn.Forte@Sun.COM handle->bh_flag |= NSC_HALLOCATED;
37177836SJohn.Forte@Sun.COM (void) _sd_free_handle(handle);
37187836SJohn.Forte@Sun.COM } else {
37197836SJohn.Forte@Sun.COM handle->bh_flag = NSC_HALLOCATED;
37207836SJohn.Forte@Sun.COM }
37217836SJohn.Forte@Sun.COM
37227836SJohn.Forte@Sun.COM SDTRACE(ST_EXIT|SDF_FREEBUF, cd, flen, fpos, 0, 0);
37237836SJohn.Forte@Sun.COM
37247836SJohn.Forte@Sun.COM return (0);
37257836SJohn.Forte@Sun.COM }
37267836SJohn.Forte@Sun.COM
37277836SJohn.Forte@Sun.COM
37287836SJohn.Forte@Sun.COM static int _sd_lruq_srch = 0x2000;
37297836SJohn.Forte@Sun.COM
37307836SJohn.Forte@Sun.COM /*
37317836SJohn.Forte@Sun.COM * sdbc_get_dmchain -- get a candidate centry chain pointing to
37327836SJohn.Forte@Sun.COM * contiguous memory
37337836SJohn.Forte@Sun.COM * ARGUMENTS:
37347836SJohn.Forte@Sun.COM * cblocks - number of cache blocks requested
37357836SJohn.Forte@Sun.COM * stall - pointer to stall count (no blocks avail)
37367836SJohn.Forte@Sun.COM * flag - ALLOC_NOWAIT flag
37377836SJohn.Forte@Sun.COM *
37387836SJohn.Forte@Sun.COM * RETURNS:
37397836SJohn.Forte@Sun.COM * a cache entry or possible NULL if ALLOC_NOWAIT set
37407836SJohn.Forte@Sun.COM * USAGE:
37417836SJohn.Forte@Sun.COM * attempt to satisfy entire request from queue
37427836SJohn.Forte@Sun.COM * that has no memory allocated.
37437836SJohn.Forte@Sun.COM * if this fails then attempt a partial allocation
37447836SJohn.Forte@Sun.COM * with a preallocated block of requested size up to
37457836SJohn.Forte@Sun.COM * max_dyn_list.
37467836SJohn.Forte@Sun.COM * then look for largest chain less than max_dyn_list.
37477836SJohn.Forte@Sun.COM */
37487836SJohn.Forte@Sun.COM static _sd_cctl_t *
37497836SJohn.Forte@Sun.COM sdbc_get_dmchain(int cblocks, int *stall, int flag)
37507836SJohn.Forte@Sun.COM {
37517836SJohn.Forte@Sun.COM _sd_cctl_t *cc_dmchain = NULL;
37527836SJohn.Forte@Sun.COM _sd_queue_t *q;
37537836SJohn.Forte@Sun.COM _sd_cctl_t *qhead;
37547836SJohn.Forte@Sun.COM int num_tries;
37557836SJohn.Forte@Sun.COM int cblocks_orig = cblocks;
37567836SJohn.Forte@Sun.COM int nowait = flag & ALLOC_NOWAIT;
37577836SJohn.Forte@Sun.COM int i;
37587836SJohn.Forte@Sun.COM
37597836SJohn.Forte@Sun.COM num_tries = _sd_lruq_srch;
37607836SJohn.Forte@Sun.COM
37617836SJohn.Forte@Sun.COM ASSERT(cblocks != 0);
37627836SJohn.Forte@Sun.COM
37637836SJohn.Forte@Sun.COM while (!cc_dmchain) {
37647836SJohn.Forte@Sun.COM /* get it from the os if possible */
37657836SJohn.Forte@Sun.COM q = &sdbc_dm_queues[0];
37667836SJohn.Forte@Sun.COM qhead = &(q->sq_qhead);
37677836SJohn.Forte@Sun.COM
37687836SJohn.Forte@Sun.COM if (q->sq_inq >= cblocks) {
37697836SJohn.Forte@Sun.COM mutex_enter(&q->sq_qlock);
37707836SJohn.Forte@Sun.COM if (q->sq_inq >= cblocks) {
37717836SJohn.Forte@Sun.COM _sd_cctl_t *cc_ent;
37727836SJohn.Forte@Sun.COM
37737836SJohn.Forte@Sun.COM cc_dmchain = qhead->cc_next;
37747836SJohn.Forte@Sun.COM
37757836SJohn.Forte@Sun.COM /*
37767836SJohn.Forte@Sun.COM * set the inuse and pageio bits
37777836SJohn.Forte@Sun.COM * Note: this code expects the cc_ent to
37787836SJohn.Forte@Sun.COM * be available. no other thread may set the
37797836SJohn.Forte@Sun.COM * inuse or pageio bit for an entry on the
37807836SJohn.Forte@Sun.COM * 0 queue.
37817836SJohn.Forte@Sun.COM */
37827836SJohn.Forte@Sun.COM cc_ent = qhead;
37837836SJohn.Forte@Sun.COM for (i = 0; i < cblocks; ++i) {
37847836SJohn.Forte@Sun.COM cc_ent = cc_ent->cc_next;
37857836SJohn.Forte@Sun.COM
37867836SJohn.Forte@Sun.COM if (SET_CENTRY_INUSE(cc_ent)) {
37877836SJohn.Forte@Sun.COM cmn_err(CE_PANIC,
37887836SJohn.Forte@Sun.COM "centry inuse on 0 q! %p",
37897836SJohn.Forte@Sun.COM (void *)cc_ent);
37907836SJohn.Forte@Sun.COM }
37917836SJohn.Forte@Sun.COM
37927836SJohn.Forte@Sun.COM if (SET_CENTRY_PAGEIO(cc_ent)) {
37937836SJohn.Forte@Sun.COM cmn_err(CE_PANIC,
37947836SJohn.Forte@Sun.COM "centry pageio on 0 q! %p",
37957836SJohn.Forte@Sun.COM (void *)cc_ent);
37967836SJohn.Forte@Sun.COM }
37977836SJohn.Forte@Sun.COM }
37987836SJohn.Forte@Sun.COM /* got a dmchain */
37997836SJohn.Forte@Sun.COM
38007836SJohn.Forte@Sun.COM /* remove this chain from the 0 queue */
38017836SJohn.Forte@Sun.COM cc_dmchain->cc_prev->cc_next = cc_ent->cc_next;
38027836SJohn.Forte@Sun.COM cc_ent->cc_next->cc_prev = cc_dmchain->cc_prev;
38037836SJohn.Forte@Sun.COM cc_dmchain->cc_prev = NULL;
38047836SJohn.Forte@Sun.COM cc_ent->cc_next = NULL;
38057836SJohn.Forte@Sun.COM
38067836SJohn.Forte@Sun.COM q->sq_inq -= cblocks;
38077836SJohn.Forte@Sun.COM
38087836SJohn.Forte@Sun.COM ASSERT(GOOD_LRUSIZE(q));
38097836SJohn.Forte@Sun.COM
38107836SJohn.Forte@Sun.COM }
38117836SJohn.Forte@Sun.COM mutex_exit(&q->sq_qlock);
38127836SJohn.Forte@Sun.COM if (cc_dmchain)
38137836SJohn.Forte@Sun.COM continue;
38147836SJohn.Forte@Sun.COM }
38157836SJohn.Forte@Sun.COM
38167836SJohn.Forte@Sun.COM /* look for a pre-allocated block of the requested size */
38177836SJohn.Forte@Sun.COM
38187836SJohn.Forte@Sun.COM
38197836SJohn.Forte@Sun.COM if (cblocks > (max_dm_queues - 1))
38207836SJohn.Forte@Sun.COM cblocks = max_dm_queues - 1;
38217836SJohn.Forte@Sun.COM
38227836SJohn.Forte@Sun.COM q = &sdbc_dm_queues[cblocks];
38237836SJohn.Forte@Sun.COM qhead = &(q->sq_qhead);
38247836SJohn.Forte@Sun.COM
38257836SJohn.Forte@Sun.COM if (q->sq_inq != 0) {
38267836SJohn.Forte@Sun.COM _sd_cctl_t *tmp_dmchain;
38277836SJohn.Forte@Sun.COM
38287836SJohn.Forte@Sun.COM mutex_enter(&q->sq_qlock);
38297836SJohn.Forte@Sun.COM
38307836SJohn.Forte@Sun.COM for (tmp_dmchain = qhead->cc_next; tmp_dmchain != qhead;
3831*9093SRamana.Srikanth@Sun.COM tmp_dmchain = tmp_dmchain->cc_next) {
38327836SJohn.Forte@Sun.COM
38337836SJohn.Forte@Sun.COM /*
38347836SJohn.Forte@Sun.COM * get a dmchain
38357836SJohn.Forte@Sun.COM * set the inuse and pageio bits
38367836SJohn.Forte@Sun.COM */
38377836SJohn.Forte@Sun.COM if (sdbc_dmchain_avail(tmp_dmchain)) {
38387836SJohn.Forte@Sun.COM /* put on MRU end of queue */
38397836SJohn.Forte@Sun.COM sdbc_requeue_dmchain(q, tmp_dmchain,
3840*9093SRamana.Srikanth@Sun.COM 1, 0);
38417836SJohn.Forte@Sun.COM cc_dmchain = tmp_dmchain;
38427836SJohn.Forte@Sun.COM break;
38437836SJohn.Forte@Sun.COM }
38447836SJohn.Forte@Sun.COM sdbc_dmchain_not_avail++;
38457836SJohn.Forte@Sun.COM }
38467836SJohn.Forte@Sun.COM
38477836SJohn.Forte@Sun.COM mutex_exit(&q->sq_qlock);
38487836SJohn.Forte@Sun.COM if (cc_dmchain)
38497836SJohn.Forte@Sun.COM continue;
38507836SJohn.Forte@Sun.COM }
38517836SJohn.Forte@Sun.COM
38527836SJohn.Forte@Sun.COM /*
38537836SJohn.Forte@Sun.COM * spin block
38547836SJohn.Forte@Sun.COM * nudge the deallocator, accelerate ageing
38557836SJohn.Forte@Sun.COM */
38567836SJohn.Forte@Sun.COM
38577836SJohn.Forte@Sun.COM mutex_enter(&dynmem_processing_dm.thread_dm_lock);
38587836SJohn.Forte@Sun.COM cv_broadcast(&dynmem_processing_dm.thread_dm_cv);
38597836SJohn.Forte@Sun.COM mutex_exit(&dynmem_processing_dm.thread_dm_lock);
38607836SJohn.Forte@Sun.COM
38617836SJohn.Forte@Sun.COM if (nowait)
38627836SJohn.Forte@Sun.COM break;
38637836SJohn.Forte@Sun.COM
38647836SJohn.Forte@Sun.COM if (!(--num_tries)) {
38657836SJohn.Forte@Sun.COM delay(drv_usectohz(20000));
38667836SJohn.Forte@Sun.COM (void) (*stall)++;
38677836SJohn.Forte@Sun.COM num_tries = _sd_lruq_srch;
38687836SJohn.Forte@Sun.COM cblocks = cblocks_orig;
38697836SJohn.Forte@Sun.COM } else { /* see if smaller request size is available */
38707836SJohn.Forte@Sun.COM if (!(--cblocks))
38717836SJohn.Forte@Sun.COM cblocks = cblocks_orig;
38727836SJohn.Forte@Sun.COM }
38737836SJohn.Forte@Sun.COM
38747836SJohn.Forte@Sun.COM } /* while (!cc_dmchain) */
38757836SJohn.Forte@Sun.COM
38767836SJohn.Forte@Sun.COM return (cc_dmchain);
38777836SJohn.Forte@Sun.COM }
38787836SJohn.Forte@Sun.COM
38797836SJohn.Forte@Sun.COM static int
38807836SJohn.Forte@Sun.COM sdbc_dmchain_avail(_sd_cctl_t *cc_ent)
38817836SJohn.Forte@Sun.COM {
38827836SJohn.Forte@Sun.COM int chain_avail = 1;
38837836SJohn.Forte@Sun.COM _sd_cctl_t *anchor = cc_ent;
38847836SJohn.Forte@Sun.COM
38857836SJohn.Forte@Sun.COM while (cc_ent) {
38867836SJohn.Forte@Sun.COM
38877836SJohn.Forte@Sun.COM ASSERT(_sd_cctl_valid(cc_ent));
38887836SJohn.Forte@Sun.COM
38897836SJohn.Forte@Sun.COM if (cc_ent->cc_aging_dm & BAD_CHAIN_DM) {
38907836SJohn.Forte@Sun.COM chain_avail = 0;
38917836SJohn.Forte@Sun.COM break;
38927836SJohn.Forte@Sun.COM }
38937836SJohn.Forte@Sun.COM
38947836SJohn.Forte@Sun.COM if (CENTRY_DIRTY(cc_ent)) {
38957836SJohn.Forte@Sun.COM chain_avail = 0;
38967836SJohn.Forte@Sun.COM break;
38977836SJohn.Forte@Sun.COM }
38987836SJohn.Forte@Sun.COM if (SET_CENTRY_INUSE(cc_ent)) {
38997836SJohn.Forte@Sun.COM chain_avail = 0;
39007836SJohn.Forte@Sun.COM break;
39017836SJohn.Forte@Sun.COM }
39027836SJohn.Forte@Sun.COM
39037836SJohn.Forte@Sun.COM if ((SET_CENTRY_PAGEIO(cc_ent))) {
39047836SJohn.Forte@Sun.COM
39057836SJohn.Forte@Sun.COM CLEAR_CENTRY_INUSE(cc_ent);
39067836SJohn.Forte@Sun.COM chain_avail = 0;
39077836SJohn.Forte@Sun.COM break;
39087836SJohn.Forte@Sun.COM }
39097836SJohn.Forte@Sun.COM
39107836SJohn.Forte@Sun.COM if (CENTRY_DIRTY(cc_ent)) {
39117836SJohn.Forte@Sun.COM
39127836SJohn.Forte@Sun.COM CLEAR_CENTRY_PAGEIO(cc_ent);
39137836SJohn.Forte@Sun.COM CLEAR_CENTRY_INUSE(cc_ent);
39147836SJohn.Forte@Sun.COM chain_avail = 0;
39157836SJohn.Forte@Sun.COM break;
39167836SJohn.Forte@Sun.COM }
39177836SJohn.Forte@Sun.COM
39187836SJohn.Forte@Sun.COM cc_ent->cc_flag = 0;
39197836SJohn.Forte@Sun.COM cc_ent->cc_toflush = 0;
39207836SJohn.Forte@Sun.COM
39217836SJohn.Forte@Sun.COM cc_ent = cc_ent->cc_next_dm;
39227836SJohn.Forte@Sun.COM }
39237836SJohn.Forte@Sun.COM
39247836SJohn.Forte@Sun.COM if (!chain_avail)
39257836SJohn.Forte@Sun.COM sdbc_clear_dmchain(anchor, cc_ent);
39267836SJohn.Forte@Sun.COM else {
39277836SJohn.Forte@Sun.COM cc_ent = anchor;
39287836SJohn.Forte@Sun.COM
39297836SJohn.Forte@Sun.COM /*
39307836SJohn.Forte@Sun.COM * prevent possible deadlocks in _sd_cc_wait():
39317836SJohn.Forte@Sun.COM * remove from hash and wakeup any waiters now that we
39327836SJohn.Forte@Sun.COM * have acquired the chain.
39337836SJohn.Forte@Sun.COM */
39347836SJohn.Forte@Sun.COM while (cc_ent) {
39357836SJohn.Forte@Sun.COM (void) _sd_hash_delete((struct _sd_hash_hd *)cc_ent,
3936*9093SRamana.Srikanth@Sun.COM _sd_htable);
39377836SJohn.Forte@Sun.COM
39387836SJohn.Forte@Sun.COM mutex_enter(&cc_ent->cc_lock);
39397836SJohn.Forte@Sun.COM if (cc_ent->cc_await_use) {
39407836SJohn.Forte@Sun.COM cv_broadcast(&cc_ent->cc_blkcv);
39417836SJohn.Forte@Sun.COM }
39427836SJohn.Forte@Sun.COM mutex_exit(&cc_ent->cc_lock);
39437836SJohn.Forte@Sun.COM
39447836SJohn.Forte@Sun.COM cc_ent->cc_creat = nsc_lbolt();
39457836SJohn.Forte@Sun.COM cc_ent->cc_hits = 0;
39467836SJohn.Forte@Sun.COM
39477836SJohn.Forte@Sun.COM cc_ent = cc_ent->cc_next_dm;
39487836SJohn.Forte@Sun.COM }
39497836SJohn.Forte@Sun.COM }
39507836SJohn.Forte@Sun.COM
39517836SJohn.Forte@Sun.COM return (chain_avail);
39527836SJohn.Forte@Sun.COM }
39537836SJohn.Forte@Sun.COM
39547836SJohn.Forte@Sun.COM static void
39557836SJohn.Forte@Sun.COM sdbc_clear_dmchain(_sd_cctl_t *cc_ent_start, _sd_cctl_t *cc_ent_end)
39567836SJohn.Forte@Sun.COM {
39577836SJohn.Forte@Sun.COM _sd_cctl_t *cc_ent = cc_ent_start;
39587836SJohn.Forte@Sun.COM _sd_cctl_t *prev_ent;
39597836SJohn.Forte@Sun.COM
39607836SJohn.Forte@Sun.COM ASSERT(_sd_cctl_valid(cc_ent));
39617836SJohn.Forte@Sun.COM
39627836SJohn.Forte@Sun.COM while (cc_ent != cc_ent_end) {
39637836SJohn.Forte@Sun.COM
39647836SJohn.Forte@Sun.COM ASSERT(_sd_cctl_valid(cc_ent));
39657836SJohn.Forte@Sun.COM
39667836SJohn.Forte@Sun.COM prev_ent = cc_ent;
39677836SJohn.Forte@Sun.COM cc_ent = cc_ent->cc_next_dm;
39687836SJohn.Forte@Sun.COM
39697836SJohn.Forte@Sun.COM CLEAR_CENTRY_PAGEIO(prev_ent);
39707836SJohn.Forte@Sun.COM CLEAR_CENTRY_INUSE(prev_ent);
39717836SJohn.Forte@Sun.COM }
39727836SJohn.Forte@Sun.COM
39737836SJohn.Forte@Sun.COM }
39747836SJohn.Forte@Sun.COM
39757836SJohn.Forte@Sun.COM /*
39767836SJohn.Forte@Sun.COM * put a dmchain on the LRU end of a queue
39777836SJohn.Forte@Sun.COM */
39787836SJohn.Forte@Sun.COM void
39797836SJohn.Forte@Sun.COM sdbc_ins_dmqueue_front(_sd_queue_t *q, _sd_cctl_t *cc_ent)
39807836SJohn.Forte@Sun.COM {
39817836SJohn.Forte@Sun.COM _sd_cctl_t *qhead = &(q->sq_qhead);
39827836SJohn.Forte@Sun.COM
39837836SJohn.Forte@Sun.COM ASSERT(_sd_cctl_valid(cc_ent));
39847836SJohn.Forte@Sun.COM
39857836SJohn.Forte@Sun.COM mutex_enter(&q->sq_qlock);
39867836SJohn.Forte@Sun.COM cc_ent->cc_next = qhead->cc_next;
39877836SJohn.Forte@Sun.COM cc_ent->cc_prev = qhead;
39887836SJohn.Forte@Sun.COM qhead->cc_next->cc_prev = cc_ent;
39897836SJohn.Forte@Sun.COM qhead->cc_next = cc_ent;
39907836SJohn.Forte@Sun.COM q->sq_inq++;
39917836SJohn.Forte@Sun.COM cc_ent->cc_cblocks = q->sq_dmchain_cblocks;
39927836SJohn.Forte@Sun.COM
39937836SJohn.Forte@Sun.COM ASSERT(GOOD_LRUSIZE(q));
39947836SJohn.Forte@Sun.COM
39957836SJohn.Forte@Sun.COM mutex_exit(&q->sq_qlock);
39967836SJohn.Forte@Sun.COM
39977836SJohn.Forte@Sun.COM }
39987836SJohn.Forte@Sun.COM
39997836SJohn.Forte@Sun.COM /*
40007836SJohn.Forte@Sun.COM * put a dmchain on the MRU end of a queue
40017836SJohn.Forte@Sun.COM */
40027836SJohn.Forte@Sun.COM static void
40037836SJohn.Forte@Sun.COM sdbc_ins_dmqueue_back(_sd_queue_t *q, _sd_cctl_t *cc_ent)
40047836SJohn.Forte@Sun.COM {
40057836SJohn.Forte@Sun.COM _sd_cctl_t *qhead = &(q->sq_qhead);
40067836SJohn.Forte@Sun.COM
40077836SJohn.Forte@Sun.COM ASSERT(_sd_cctl_valid(cc_ent));
40087836SJohn.Forte@Sun.COM
40097836SJohn.Forte@Sun.COM mutex_enter(&q->sq_qlock);
40107836SJohn.Forte@Sun.COM cc_ent->cc_next = qhead;
40117836SJohn.Forte@Sun.COM cc_ent->cc_prev = qhead->cc_prev;
40127836SJohn.Forte@Sun.COM qhead->cc_prev->cc_next = cc_ent;
40137836SJohn.Forte@Sun.COM qhead->cc_prev = cc_ent;
40147836SJohn.Forte@Sun.COM cc_ent->cc_seq = q->sq_seq++;
40157836SJohn.Forte@Sun.COM q->sq_inq++;
40167836SJohn.Forte@Sun.COM cc_ent->cc_cblocks = q->sq_dmchain_cblocks;
40177836SJohn.Forte@Sun.COM
40187836SJohn.Forte@Sun.COM ASSERT(GOOD_LRUSIZE(q));
40197836SJohn.Forte@Sun.COM
40207836SJohn.Forte@Sun.COM mutex_exit(&q->sq_qlock);
40217836SJohn.Forte@Sun.COM
40227836SJohn.Forte@Sun.COM }
40237836SJohn.Forte@Sun.COM
40247836SJohn.Forte@Sun.COM /*
40257836SJohn.Forte@Sun.COM * remove dmchain from a queue
40267836SJohn.Forte@Sun.COM */
40277836SJohn.Forte@Sun.COM void
40287836SJohn.Forte@Sun.COM sdbc_remq_dmchain(_sd_queue_t *q, _sd_cctl_t *cc_ent)
40297836SJohn.Forte@Sun.COM {
40307836SJohn.Forte@Sun.COM
40317836SJohn.Forte@Sun.COM ASSERT(_sd_cctl_valid(cc_ent));
40327836SJohn.Forte@Sun.COM
40337836SJohn.Forte@Sun.COM mutex_enter(&q->sq_qlock);
40347836SJohn.Forte@Sun.COM cc_ent->cc_prev->cc_next = cc_ent->cc_next;
40357836SJohn.Forte@Sun.COM cc_ent->cc_next->cc_prev = cc_ent->cc_prev;
40367836SJohn.Forte@Sun.COM cc_ent->cc_next = cc_ent->cc_prev = NULL; /* defensive programming */
40377836SJohn.Forte@Sun.COM cc_ent->cc_cblocks = -1; /* indicate not on any queue */
40387836SJohn.Forte@Sun.COM
40397836SJohn.Forte@Sun.COM q->sq_inq--;
40407836SJohn.Forte@Sun.COM
40417836SJohn.Forte@Sun.COM ASSERT(GOOD_LRUSIZE(q));
40427836SJohn.Forte@Sun.COM
40437836SJohn.Forte@Sun.COM mutex_exit(&q->sq_qlock);
40447836SJohn.Forte@Sun.COM
40457836SJohn.Forte@Sun.COM }
40467836SJohn.Forte@Sun.COM
40477836SJohn.Forte@Sun.COM /*
40487836SJohn.Forte@Sun.COM * requeue a dmchain to the MRU end of its queue.
40497836SJohn.Forte@Sun.COM * if getlock is 0 on entry the queue lock (sq_qlock) must be held
40507836SJohn.Forte@Sun.COM */
40517836SJohn.Forte@Sun.COM void
40527836SJohn.Forte@Sun.COM sdbc_requeue_dmchain(_sd_queue_t *q, _sd_cctl_t *cc_ent, int mru,
40537836SJohn.Forte@Sun.COM int getlock)
40547836SJohn.Forte@Sun.COM {
40557836SJohn.Forte@Sun.COM _sd_cctl_t *qhead = &(q->sq_qhead);
40567836SJohn.Forte@Sun.COM
40577836SJohn.Forte@Sun.COM
40587836SJohn.Forte@Sun.COM ASSERT(_sd_cctl_valid(cc_ent));
40597836SJohn.Forte@Sun.COM
40607836SJohn.Forte@Sun.COM if (getlock)
40617836SJohn.Forte@Sun.COM mutex_enter(&q->sq_qlock);
40627836SJohn.Forte@Sun.COM
40637836SJohn.Forte@Sun.COM /* inline of sdbc_remq_dmchain() */
40647836SJohn.Forte@Sun.COM cc_ent->cc_prev->cc_next = cc_ent->cc_next;
40657836SJohn.Forte@Sun.COM cc_ent->cc_next->cc_prev = cc_ent->cc_prev;
40667836SJohn.Forte@Sun.COM
40677836SJohn.Forte@Sun.COM if (mru) { /* put on MRU end of queue */
40687836SJohn.Forte@Sun.COM /* inline of sdbc_ins_dmqueue_back */
40697836SJohn.Forte@Sun.COM cc_ent->cc_next = qhead;
40707836SJohn.Forte@Sun.COM cc_ent->cc_prev = qhead->cc_prev;
40717836SJohn.Forte@Sun.COM qhead->cc_prev->cc_next = cc_ent;
40727836SJohn.Forte@Sun.COM qhead->cc_prev = cc_ent;
40737836SJohn.Forte@Sun.COM cc_ent->cc_seq = q->sq_seq++;
40747836SJohn.Forte@Sun.COM (q->sq_req_stat)++;
40757836SJohn.Forte@Sun.COM } else { /* put on LRU end of queue i.e. requeue to head */
40767836SJohn.Forte@Sun.COM /* inline of sdbc_ins_dmqueue_front */
40777836SJohn.Forte@Sun.COM cc_ent->cc_next = qhead->cc_next;
40787836SJohn.Forte@Sun.COM cc_ent->cc_prev = qhead;
40797836SJohn.Forte@Sun.COM qhead->cc_next->cc_prev = cc_ent;
40807836SJohn.Forte@Sun.COM qhead->cc_next = cc_ent;
40817836SJohn.Forte@Sun.COM cc_ent->cc_seq = q->sq_seq++;
40827836SJohn.Forte@Sun.COM
40837836SJohn.Forte@Sun.COM /*
40847836SJohn.Forte@Sun.COM * clear the CC_QHEAD bit on all members of the chain
40857836SJohn.Forte@Sun.COM */
40867836SJohn.Forte@Sun.COM {
40877836SJohn.Forte@Sun.COM _sd_cctl_t *tcent;
40887836SJohn.Forte@Sun.COM
40897836SJohn.Forte@Sun.COM for (tcent = cc_ent; tcent; tcent = tcent->cc_next_dm)
40907836SJohn.Forte@Sun.COM tcent->cc_flag &= ~CC_QHEAD;
40917836SJohn.Forte@Sun.COM }
40927836SJohn.Forte@Sun.COM }
40937836SJohn.Forte@Sun.COM
40947836SJohn.Forte@Sun.COM if (getlock)
40957836SJohn.Forte@Sun.COM mutex_exit(&q->sq_qlock);
40967836SJohn.Forte@Sun.COM
40977836SJohn.Forte@Sun.COM }
40987836SJohn.Forte@Sun.COM
40997836SJohn.Forte@Sun.COM /*
41007836SJohn.Forte@Sun.COM * sdbc_dmchain_dirty(cc_ent)
41017836SJohn.Forte@Sun.COM * return first dirty cc_ent in dmchain, NULL if chain is not dirty
41027836SJohn.Forte@Sun.COM */
41037836SJohn.Forte@Sun.COM static _sd_cctl_t *
41047836SJohn.Forte@Sun.COM sdbc_dmchain_dirty(_sd_cctl_t *cc_ent)
41057836SJohn.Forte@Sun.COM {
41067836SJohn.Forte@Sun.COM for (/* CSTYLED */; cc_ent; cc_ent = cc_ent->cc_next_dm)
41077836SJohn.Forte@Sun.COM if (CENTRY_DIRTY(cc_ent))
41087836SJohn.Forte@Sun.COM break;
41097836SJohn.Forte@Sun.COM
41107836SJohn.Forte@Sun.COM return (cc_ent);
41117836SJohn.Forte@Sun.COM }
41127836SJohn.Forte@Sun.COM
41137836SJohn.Forte@Sun.COM /*
41147836SJohn.Forte@Sun.COM * sdbc_requeue_head_dm_try()
41157836SJohn.Forte@Sun.COM * attempt to requeue a dmchain to the head of the queue
41167836SJohn.Forte@Sun.COM */
41177836SJohn.Forte@Sun.COM void
41187836SJohn.Forte@Sun.COM sdbc_requeue_head_dm_try(_sd_cctl_t *cc_ent)
41197836SJohn.Forte@Sun.COM {
41207836SJohn.Forte@Sun.COM int qidx;
41217836SJohn.Forte@Sun.COM _sd_queue_t *q;
41227836SJohn.Forte@Sun.COM
41237836SJohn.Forte@Sun.COM if (!sdbc_dmchain_dirty(cc_ent)) {
41247836SJohn.Forte@Sun.COM qidx = cc_ent->cc_cblocks;
41257836SJohn.Forte@Sun.COM q = &sdbc_dm_queues[qidx];
41267836SJohn.Forte@Sun.COM sdbc_requeue_dmchain(q, cc_ent, 0, 1); /* requeue head */
41277836SJohn.Forte@Sun.COM }
41287836SJohn.Forte@Sun.COM }
41297836SJohn.Forte@Sun.COM
41307836SJohn.Forte@Sun.COM /*
41317836SJohn.Forte@Sun.COM * sdbc_centry_alloc_blks -- allocate cache entries with memory
41327836SJohn.Forte@Sun.COM *
41337836SJohn.Forte@Sun.COM * ARGUMENTS:
41347836SJohn.Forte@Sun.COM * cd - Cache descriptor (from a previous open)
41357836SJohn.Forte@Sun.COM * cblk - cache block number.
41367836SJohn.Forte@Sun.COM * reqblks - number of cache blocks to be allocated
41377836SJohn.Forte@Sun.COM * flag - can be ALLOC_NOWAIT
41387836SJohn.Forte@Sun.COM * RETURNS:
41397836SJohn.Forte@Sun.COM * A cache block chain or NULL if ALLOC_NOWAIT and request fails
41407836SJohn.Forte@Sun.COM *
41417836SJohn.Forte@Sun.COM * Note: caller must check for null return if called with
41427836SJohn.Forte@Sun.COM * ALLOC_NOWAIT set.
41437836SJohn.Forte@Sun.COM */
41447836SJohn.Forte@Sun.COM _sd_cctl_t *
41457836SJohn.Forte@Sun.COM sdbc_centry_alloc_blks(int cd, nsc_off_t cblk, nsc_size_t reqblks, int flag)
41467836SJohn.Forte@Sun.COM {
41477836SJohn.Forte@Sun.COM sdbc_allocbuf_t alloc_tok = {0}; /* must be 0 */
41487836SJohn.Forte@Sun.COM int stall = 0;
41497836SJohn.Forte@Sun.COM _sd_cctl_t *centry = NULL;
41507836SJohn.Forte@Sun.COM _sd_cctl_t *lentry = NULL;
41517836SJohn.Forte@Sun.COM _sd_cctl_t *anchor = NULL;
41527836SJohn.Forte@Sun.COM _sd_cctl_t *next_centry;
41537836SJohn.Forte@Sun.COM
41547836SJohn.Forte@Sun.COM ASSERT(reqblks);
41557836SJohn.Forte@Sun.COM
41567836SJohn.Forte@Sun.COM while (reqblks) {
41577836SJohn.Forte@Sun.COM centry = sdbc_centry_alloc(cd, cblk, reqblks, &stall,
4158*9093SRamana.Srikanth@Sun.COM &alloc_tok, flag);
41597836SJohn.Forte@Sun.COM
41607836SJohn.Forte@Sun.COM if (!centry)
41617836SJohn.Forte@Sun.COM break;
41627836SJohn.Forte@Sun.COM
41637836SJohn.Forte@Sun.COM centry->cc_chain = NULL;
41647836SJohn.Forte@Sun.COM
41657836SJohn.Forte@Sun.COM if (lentry == NULL)
41667836SJohn.Forte@Sun.COM anchor = centry;
41677836SJohn.Forte@Sun.COM else
41687836SJohn.Forte@Sun.COM lentry->cc_chain = centry;
41697836SJohn.Forte@Sun.COM
41707836SJohn.Forte@Sun.COM lentry = centry;
41717836SJohn.Forte@Sun.COM
41727836SJohn.Forte@Sun.COM centry->cc_aging_dm &= ~(ENTRY_FIELD_DM);
41737836SJohn.Forte@Sun.COM
41747836SJohn.Forte@Sun.COM if (centry->cc_aging_dm & FOUND_IN_HASH_DM)
41757836SJohn.Forte@Sun.COM centry->cc_aging_dm |= HASH_ENTRY_DM;
41767836SJohn.Forte@Sun.COM else
41777836SJohn.Forte@Sun.COM if (centry->cc_aging_dm & FOUND_HOLD_OVER_DM)
41787836SJohn.Forte@Sun.COM centry->cc_aging_dm |= HOLD_ENTRY_DM;
41797836SJohn.Forte@Sun.COM else
41807836SJohn.Forte@Sun.COM centry->cc_aging_dm |= ELIGIBLE_ENTRY_DM;
41817836SJohn.Forte@Sun.COM
41827836SJohn.Forte@Sun.COM centry->cc_aging_dm &= ~(FOUND_IN_HASH_DM|FOUND_HOLD_OVER_DM);
41837836SJohn.Forte@Sun.COM --reqblks;
41847836SJohn.Forte@Sun.COM }
41857836SJohn.Forte@Sun.COM
41867836SJohn.Forte@Sun.COM sdbc_centry_alloc_end(&alloc_tok);
41877836SJohn.Forte@Sun.COM
41887836SJohn.Forte@Sun.COM if (reqblks || (_sd_setup_category_on_type(anchor))) {
41897836SJohn.Forte@Sun.COM centry = anchor;
41907836SJohn.Forte@Sun.COM while (centry) {
41917836SJohn.Forte@Sun.COM next_centry = centry->cc_chain;
41927836SJohn.Forte@Sun.COM _sd_centry_release(centry);
41937836SJohn.Forte@Sun.COM centry = next_centry;
41947836SJohn.Forte@Sun.COM }
41957836SJohn.Forte@Sun.COM anchor = NULL;
41967836SJohn.Forte@Sun.COM
41977836SJohn.Forte@Sun.COM } else
41987836SJohn.Forte@Sun.COM /* This is where the memory is actually allocated */
41997836SJohn.Forte@Sun.COM if (_sd_setup_mem_chaining(anchor, flag))
42007836SJohn.Forte@Sun.COM anchor = NULL;
42017836SJohn.Forte@Sun.COM
42027836SJohn.Forte@Sun.COM return (anchor);
42037836SJohn.Forte@Sun.COM }
42047836SJohn.Forte@Sun.COM
42057836SJohn.Forte@Sun.COM
42067836SJohn.Forte@Sun.COM /*
42077836SJohn.Forte@Sun.COM * sdbc_centry_alloc - sdbc internal function to allocate a new cache block.
42087836SJohn.Forte@Sun.COM *
42097836SJohn.Forte@Sun.COM * ARGUMENTS:
42107836SJohn.Forte@Sun.COM * cd - Cache descriptor (from a previous open)
42117836SJohn.Forte@Sun.COM * cblk - cache block number.
42127836SJohn.Forte@Sun.COM * stall - pointer to stall count (no blocks avail)
42137836SJohn.Forte@Sun.COM * req_blocks - number of cache blocks remaining in caller's i/o request
42147836SJohn.Forte@Sun.COM * alloc_tok - pointer to token initialized to 0 on first call to function
42157836SJohn.Forte@Sun.COM * flag - lock status of sdbc_queue_lock or ALLOC_NOWAIT flag
42167836SJohn.Forte@Sun.COM * RETURNS:
42177836SJohn.Forte@Sun.COM * A cache block, or possibly NULL if ALLOC_NOWAIT set .
42187836SJohn.Forte@Sun.COM *
42197836SJohn.Forte@Sun.COM * USAGE:
42207836SJohn.Forte@Sun.COM * switch to the appropriate allocation function.
42217836SJohn.Forte@Sun.COM * this function is used when callers need more than one cache block.
42227836SJohn.Forte@Sun.COM * it is called repeatedly until the entire request is satisfied,
42237836SJohn.Forte@Sun.COM * at which time the caller will then do the memory allocation.
42247836SJohn.Forte@Sun.COM * if only one cache block is needed callers may use
42257836SJohn.Forte@Sun.COM * sdbc_centry_alloc_blks() which also allocates memory.
42267836SJohn.Forte@Sun.COM *
42277836SJohn.Forte@Sun.COM * Note: caller must check for null return if called with
42287836SJohn.Forte@Sun.COM * ALLOC_NOWAIT set.
42297836SJohn.Forte@Sun.COM */
42307836SJohn.Forte@Sun.COM
42317836SJohn.Forte@Sun.COM _sd_cctl_t *
42327836SJohn.Forte@Sun.COM sdbc_centry_alloc(int cd, nsc_off_t cblk, nsc_size_t req_blocks, int *stall,
42337836SJohn.Forte@Sun.COM sdbc_allocbuf_t *alloc_tok, int flag)
42347836SJohn.Forte@Sun.COM {
42357836SJohn.Forte@Sun.COM _sd_cctl_t *centry;
42367836SJohn.Forte@Sun.COM
42377836SJohn.Forte@Sun.COM if (sdbc_use_dmchain)
42387836SJohn.Forte@Sun.COM centry = sdbc_alloc_dmc(cd, cblk, req_blocks, stall, alloc_tok,
4239*9093SRamana.Srikanth@Sun.COM flag);
42407836SJohn.Forte@Sun.COM else
42417836SJohn.Forte@Sun.COM centry = sdbc_alloc_lru(cd, cblk, stall, flag);
42427836SJohn.Forte@Sun.COM
42437836SJohn.Forte@Sun.COM return (centry);
42447836SJohn.Forte@Sun.COM }
42457836SJohn.Forte@Sun.COM
42467836SJohn.Forte@Sun.COM /*
42477836SJohn.Forte@Sun.COM * sdbc_alloc_dmc -- allocate a centry from a dmchain
42487836SJohn.Forte@Sun.COM *
42497836SJohn.Forte@Sun.COM * ARGUMENTS:
42507836SJohn.Forte@Sun.COM * cd - Cache descriptor (from a previous open)
42517836SJohn.Forte@Sun.COM * cblk - cache block number.
42527836SJohn.Forte@Sun.COM * stall - pointer to stall count (no blocks avail)
42537836SJohn.Forte@Sun.COM * req_blocks - number of cache blocks in clients i/o request
42547836SJohn.Forte@Sun.COM * alloc_tok - pointer to token initialized to 0 on first call to function
42557836SJohn.Forte@Sun.COM * flag - lock status of sdbc_queue_lock, or ALLOC_NOWAIT flag
42567836SJohn.Forte@Sun.COM * RETURNS:
42577836SJohn.Forte@Sun.COM * A cache block or possibly NULL if ALLOC_NOWAIT set
42587836SJohn.Forte@Sun.COM *
42597836SJohn.Forte@Sun.COM * USAGE:
42607836SJohn.Forte@Sun.COM * if dmchain is empty, allocate one.
42617836SJohn.Forte@Sun.COM */
42627836SJohn.Forte@Sun.COM static _sd_cctl_t *
42637836SJohn.Forte@Sun.COM sdbc_alloc_dmc(int cd, nsc_off_t cblk, nsc_size_t req_blocks, int *stall,
42647836SJohn.Forte@Sun.COM sdbc_allocbuf_t *alloc_tok, int flag)
42657836SJohn.Forte@Sun.COM {
42667836SJohn.Forte@Sun.COM sdbc_allocbuf_impl_t *dmc = (sdbc_allocbuf_impl_t *)alloc_tok;
42677836SJohn.Forte@Sun.COM _sd_cctl_t *centry = NULL;
42687836SJohn.Forte@Sun.COM
42697836SJohn.Forte@Sun.COM if (!dmc->sab_dmchain) {
42707836SJohn.Forte@Sun.COM /*
42717836SJohn.Forte@Sun.COM * Note - sdbc_get_dmchain() returns
42727836SJohn.Forte@Sun.COM * with cc_inuse and cc_pageio set
42737836SJohn.Forte@Sun.COM * for all members of dmchain.
42747836SJohn.Forte@Sun.COM */
42757836SJohn.Forte@Sun.COM if (dmc->sab_dmchain =
4276*9093SRamana.Srikanth@Sun.COM sdbc_get_dmchain(req_blocks, stall, flag)) {
42777836SJohn.Forte@Sun.COM
42787836SJohn.Forte@Sun.COM /* remember q it came from */
42797836SJohn.Forte@Sun.COM if (dmc->sab_dmchain->cc_alloc_size_dm)
42807836SJohn.Forte@Sun.COM dmc->sab_q = dmc->sab_dmchain->cc_cblocks;
42817836SJohn.Forte@Sun.COM }
42827836SJohn.Forte@Sun.COM }
42837836SJohn.Forte@Sun.COM
42847836SJohn.Forte@Sun.COM /*
42857836SJohn.Forte@Sun.COM * Note: dmchain pointer is advanced in sdbc_alloc_from_dmchain()
42867836SJohn.Forte@Sun.COM */
42877836SJohn.Forte@Sun.COM if (dmc->sab_dmchain) /* could be NULL if ALLOC_NOWAIT set */
42887836SJohn.Forte@Sun.COM centry = sdbc_alloc_from_dmchain(cd, cblk, alloc_tok, flag);
42897836SJohn.Forte@Sun.COM
42907836SJohn.Forte@Sun.COM return (centry);
42917836SJohn.Forte@Sun.COM }
42927836SJohn.Forte@Sun.COM
42937836SJohn.Forte@Sun.COM /*
42947836SJohn.Forte@Sun.COM * sdbc_alloc_from_dmchain -- allocate centry from a dmchain of centrys
42957836SJohn.Forte@Sun.COM *
42967836SJohn.Forte@Sun.COM * ARGUMENTS:
42977836SJohn.Forte@Sun.COM * cd - Cache descriptor (from a previous open)
42987836SJohn.Forte@Sun.COM * cblk - cache block number.
42997836SJohn.Forte@Sun.COM * alloc_tok - pointer to token
43007836SJohn.Forte@Sun.COM * flag - lock status of sdbc_queue_lock or ALLOC_NOWAIT
43017836SJohn.Forte@Sun.COM *
43027836SJohn.Forte@Sun.COM * RETURNS:
43037836SJohn.Forte@Sun.COM * A cache block or possibly NULL if ALLOC_NOWAIT set.
43047836SJohn.Forte@Sun.COM *
43057836SJohn.Forte@Sun.COM * USAGE:
43067836SJohn.Forte@Sun.COM * This routine allocates a new cache block from the supplied dmchain.
43077836SJohn.Forte@Sun.COM * Assumes that dmchain is non-NULL and that all cache entries in
43087836SJohn.Forte@Sun.COM * the dmchain have been removed from hash and have their cc_inuse and
43097836SJohn.Forte@Sun.COM * cc_pageio bits set.
43107836SJohn.Forte@Sun.COM */
43117836SJohn.Forte@Sun.COM static _sd_cctl_t *
43127836SJohn.Forte@Sun.COM sdbc_alloc_from_dmchain(int cd, nsc_off_t cblk, sdbc_allocbuf_t *alloc_tok,
43137836SJohn.Forte@Sun.COM int flag)
43147836SJohn.Forte@Sun.COM {
43157836SJohn.Forte@Sun.COM _sd_cctl_t *cc_ent, *old_ent;
43167836SJohn.Forte@Sun.COM int categorize_centry;
43177836SJohn.Forte@Sun.COM int locked = flag & ALLOC_LOCKED;
43187836SJohn.Forte@Sun.COM int nowait = flag & ALLOC_NOWAIT;
43197836SJohn.Forte@Sun.COM sdbc_allocbuf_impl_t *dmc = (sdbc_allocbuf_impl_t *)alloc_tok;
43207836SJohn.Forte@Sun.COM
43217836SJohn.Forte@Sun.COM SDTRACE(ST_ENTER|SDF_ENT_ALLOC, cd, 0, BLK_TO_FBA_NUM(cblk), 0, 0);
43227836SJohn.Forte@Sun.COM
43237836SJohn.Forte@Sun.COM ASSERT(dmc->sab_dmchain);
43247836SJohn.Forte@Sun.COM
43257836SJohn.Forte@Sun.COM cc_ent = dmc->sab_dmchain;
43267836SJohn.Forte@Sun.COM
43277836SJohn.Forte@Sun.COM ASSERT(_sd_cctl_valid(cc_ent));
43287836SJohn.Forte@Sun.COM
43297836SJohn.Forte@Sun.COM cc_ent->cc_valid = 0;
43307836SJohn.Forte@Sun.COM categorize_centry = 0;
43317836SJohn.Forte@Sun.COM if (cc_ent->cc_data)
43327836SJohn.Forte@Sun.COM categorize_centry = FOUND_HOLD_OVER_DM;
43337836SJohn.Forte@Sun.COM
43347836SJohn.Forte@Sun.COM alloc_try:
43357836SJohn.Forte@Sun.COM if (cd == _CD_NOHASH)
43367836SJohn.Forte@Sun.COM CENTRY_BLK(cc_ent) = cblk;
43377836SJohn.Forte@Sun.COM else if ((old_ent = (_sd_cctl_t *)
43387836SJohn.Forte@Sun.COM _sd_hash_insert(cd, cblk, (struct _sd_hash_hd *)cc_ent,
43397836SJohn.Forte@Sun.COM _sd_htable)) != cc_ent) {
43407836SJohn.Forte@Sun.COM
43417836SJohn.Forte@Sun.COM if (SET_CENTRY_INUSE(old_ent)) {
43427836SJohn.Forte@Sun.COM sdbc_centry_inuse++;
43437836SJohn.Forte@Sun.COM
43447836SJohn.Forte@Sun.COM if (nowait) {
43457836SJohn.Forte@Sun.COM cc_ent = NULL;
43467836SJohn.Forte@Sun.COM goto out;
43477836SJohn.Forte@Sun.COM }
43487836SJohn.Forte@Sun.COM
43497836SJohn.Forte@Sun.COM if (locked)
43507836SJohn.Forte@Sun.COM rw_exit(&sdbc_queue_lock);
43517836SJohn.Forte@Sun.COM _sd_cc_wait(cd, cblk, old_ent, CC_INUSE);
43527836SJohn.Forte@Sun.COM if (locked)
43537836SJohn.Forte@Sun.COM rw_enter(&sdbc_queue_lock, RW_WRITER);
43547836SJohn.Forte@Sun.COM goto alloc_try;
43557836SJohn.Forte@Sun.COM }
43567836SJohn.Forte@Sun.COM
43577836SJohn.Forte@Sun.COM /*
43587836SJohn.Forte@Sun.COM * bug 4529671
43597836SJohn.Forte@Sun.COM * now that we own the centry make sure that
43607836SJohn.Forte@Sun.COM * it is still good. it could have been processed
43617836SJohn.Forte@Sun.COM * by _sd_dealloc_dm() in the window between
43627836SJohn.Forte@Sun.COM * _sd_hash_insert() and SET_CENTRY_INUSE().
43637836SJohn.Forte@Sun.COM */
43647836SJohn.Forte@Sun.COM if ((_sd_cctl_t *)_sd_hash_search(cd, cblk, _sd_htable)
4365*9093SRamana.Srikanth@Sun.COM != old_ent) {
43667836SJohn.Forte@Sun.COM sdbc_centry_deallocd++;
43677836SJohn.Forte@Sun.COM #ifdef DEBUG
4368*9093SRamana.Srikanth@Sun.COM cmn_err(CE_WARN, "!cc_ent %p cd %d cblk %" NSC_SZFMT
43697836SJohn.Forte@Sun.COM " lost to dealloc?! cc_data %p", (void *)old_ent,
43707836SJohn.Forte@Sun.COM cd, cblk, (void *)old_ent->cc_data);
43717836SJohn.Forte@Sun.COM #endif
43727836SJohn.Forte@Sun.COM
43737836SJohn.Forte@Sun.COM CLEAR_CENTRY_INUSE(old_ent);
43747836SJohn.Forte@Sun.COM
43757836SJohn.Forte@Sun.COM if (nowait) {
43767836SJohn.Forte@Sun.COM cc_ent = NULL;
43777836SJohn.Forte@Sun.COM goto out;
43787836SJohn.Forte@Sun.COM }
43797836SJohn.Forte@Sun.COM
43807836SJohn.Forte@Sun.COM goto alloc_try;
43817836SJohn.Forte@Sun.COM }
43827836SJohn.Forte@Sun.COM
43837836SJohn.Forte@Sun.COM if (CC_CD_BLK_MATCH(cd, cblk, old_ent)) {
43847836SJohn.Forte@Sun.COM sdbc_centry_hit++;
43857836SJohn.Forte@Sun.COM old_ent->cc_toflush = 0;
43867836SJohn.Forte@Sun.COM /* _sd_centry_release(cc_ent); */
43877836SJohn.Forte@Sun.COM cc_ent = old_ent;
43887836SJohn.Forte@Sun.COM categorize_centry = FOUND_IN_HASH_DM;
43897836SJohn.Forte@Sun.COM } else {
43907836SJohn.Forte@Sun.COM sdbc_centry_lost++;
43917836SJohn.Forte@Sun.COM
43927836SJohn.Forte@Sun.COM CLEAR_CENTRY_INUSE(old_ent);
43937836SJohn.Forte@Sun.COM
43947836SJohn.Forte@Sun.COM if (nowait) {
43957836SJohn.Forte@Sun.COM cc_ent = NULL;
43967836SJohn.Forte@Sun.COM goto out;
43977836SJohn.Forte@Sun.COM }
43987836SJohn.Forte@Sun.COM
43997836SJohn.Forte@Sun.COM goto alloc_try;
44007836SJohn.Forte@Sun.COM }
44017836SJohn.Forte@Sun.COM }
44027836SJohn.Forte@Sun.COM
44037836SJohn.Forte@Sun.COM /*
44047836SJohn.Forte@Sun.COM * advance the dmchain pointer, but only if we got the
44057836SJohn.Forte@Sun.COM * cc_ent from the dmchain
44067836SJohn.Forte@Sun.COM */
44077836SJohn.Forte@Sun.COM if (categorize_centry != FOUND_IN_HASH_DM) {
44087836SJohn.Forte@Sun.COM if (cc_ent->cc_data)
44097836SJohn.Forte@Sun.COM dmc->sab_dmchain = dmc->sab_dmchain->cc_next_dm;
44107836SJohn.Forte@Sun.COM else
44117836SJohn.Forte@Sun.COM dmc->sab_dmchain = dmc->sab_dmchain->cc_next;
44127836SJohn.Forte@Sun.COM }
44137836SJohn.Forte@Sun.COM
44147836SJohn.Forte@Sun.COM
4415*9093SRamana.Srikanth@Sun.COM SDTRACE(ST_EXIT|SDF_ENT_ALLOC, cd, 0, BLK_TO_FBA_NUM(cblk), 0, 0);
44167836SJohn.Forte@Sun.COM
44177836SJohn.Forte@Sun.COM mutex_enter(&cc_ent->cc_lock);
44187836SJohn.Forte@Sun.COM if (cc_ent->cc_await_use) {
44197836SJohn.Forte@Sun.COM cv_broadcast(&cc_ent->cc_blkcv);
44207836SJohn.Forte@Sun.COM }
44217836SJohn.Forte@Sun.COM mutex_exit(&cc_ent->cc_lock);
44227836SJohn.Forte@Sun.COM
44237836SJohn.Forte@Sun.COM sdbc_centry_init_dm(cc_ent);
44247836SJohn.Forte@Sun.COM
44257836SJohn.Forte@Sun.COM cc_ent->cc_aging_dm |= categorize_centry;
44267836SJohn.Forte@Sun.COM
44277836SJohn.Forte@Sun.COM out:
44287836SJohn.Forte@Sun.COM
44297836SJohn.Forte@Sun.COM SDTRACE(ST_INFO|SDF_ENT_ALLOC, cd, 0, BLK_TO_FBA_NUM(cblk), 0, 0);
44307836SJohn.Forte@Sun.COM
44317836SJohn.Forte@Sun.COM return (cc_ent);
44327836SJohn.Forte@Sun.COM }
44337836SJohn.Forte@Sun.COM
44347836SJohn.Forte@Sun.COM /*
44357836SJohn.Forte@Sun.COM * sdbc_centry_alloc_end -- tidy up after all cache blocks have been
44367836SJohn.Forte@Sun.COM * allocated for a request
44377836SJohn.Forte@Sun.COM * ARGUMENTS:
44387836SJohn.Forte@Sun.COM * alloc_tok - pointer to allocation token
44397836SJohn.Forte@Sun.COM * RETURNS
44407836SJohn.Forte@Sun.COM * nothing
44417836SJohn.Forte@Sun.COM * USAGE:
44427836SJohn.Forte@Sun.COM * at this time only useful when sdbc_use_dmchain is true.
44437836SJohn.Forte@Sun.COM * if there are cache blocks remaining on the chain then the inuse and
44447836SJohn.Forte@Sun.COM * pageio bits must be cleared (they were set in sdbc_get_dmchain().
44457836SJohn.Forte@Sun.COM *
44467836SJohn.Forte@Sun.COM */
44477836SJohn.Forte@Sun.COM static void
44487836SJohn.Forte@Sun.COM sdbc_centry_alloc_end(sdbc_allocbuf_t *alloc_tok)
44497836SJohn.Forte@Sun.COM {
44507836SJohn.Forte@Sun.COM _sd_cctl_t *next_centry;
44517836SJohn.Forte@Sun.COM _sd_cctl_t *prev_centry;
44527836SJohn.Forte@Sun.COM _sd_queue_t *q;
44537836SJohn.Forte@Sun.COM sdbc_allocbuf_impl_t *dmc = (sdbc_allocbuf_impl_t *)alloc_tok;
44547836SJohn.Forte@Sun.COM #ifdef DEBUG
44557836SJohn.Forte@Sun.COM int chainpull = 0;
44567836SJohn.Forte@Sun.COM #endif
44577836SJohn.Forte@Sun.COM
44587836SJohn.Forte@Sun.COM if (!sdbc_use_dmchain)
44597836SJohn.Forte@Sun.COM return;
44607836SJohn.Forte@Sun.COM
44617836SJohn.Forte@Sun.COM next_centry = dmc->sab_dmchain;
44627836SJohn.Forte@Sun.COM
44637836SJohn.Forte@Sun.COM while (next_centry != NULL) {
44647836SJohn.Forte@Sun.COM CLEAR_CENTRY_PAGEIO(next_centry);
44657836SJohn.Forte@Sun.COM
44667836SJohn.Forte@Sun.COM prev_centry = next_centry;
44677836SJohn.Forte@Sun.COM
44687836SJohn.Forte@Sun.COM if (next_centry->cc_data) {
44697836SJohn.Forte@Sun.COM #ifdef DEBUG
44707836SJohn.Forte@Sun.COM ++chainpull;
44717836SJohn.Forte@Sun.COM #endif
44727836SJohn.Forte@Sun.COM next_centry = next_centry->cc_next_dm;
44737836SJohn.Forte@Sun.COM
44747836SJohn.Forte@Sun.COM /* clear bit after final reference */
44757836SJohn.Forte@Sun.COM
44767836SJohn.Forte@Sun.COM CLEAR_CENTRY_INUSE(prev_centry);
44777836SJohn.Forte@Sun.COM } else {
44787836SJohn.Forte@Sun.COM next_centry = next_centry->cc_next;
44797836SJohn.Forte@Sun.COM
44807836SJohn.Forte@Sun.COM /*
44817836SJohn.Forte@Sun.COM * a floater from the 0 queue, insert on q.
44827836SJohn.Forte@Sun.COM *
44837836SJohn.Forte@Sun.COM * since this centry is not on any queue
44847836SJohn.Forte@Sun.COM * the inuse bit can be cleared before
44857836SJohn.Forte@Sun.COM * inserting on the q. this is also required
44867836SJohn.Forte@Sun.COM * since sdbc_get_dmchain() does not expect
44877836SJohn.Forte@Sun.COM * inuse bits to be set on 0 queue entry's.
44887836SJohn.Forte@Sun.COM */
44897836SJohn.Forte@Sun.COM
44907836SJohn.Forte@Sun.COM CLEAR_CENTRY_INUSE(prev_centry);
44917836SJohn.Forte@Sun.COM q = &sdbc_dm_queues[0];
44927836SJohn.Forte@Sun.COM sdbc_ins_dmqueue_front(q, prev_centry);
44937836SJohn.Forte@Sun.COM }
44947836SJohn.Forte@Sun.COM }
44957836SJohn.Forte@Sun.COM
44967836SJohn.Forte@Sun.COM #ifdef DEBUG
44977836SJohn.Forte@Sun.COM /* compute wastage stats */
44987836SJohn.Forte@Sun.COM ASSERT((chainpull >= 0) && (chainpull < max_dm_queues));
44997836SJohn.Forte@Sun.COM if (chainpull)
45007836SJohn.Forte@Sun.COM (*(dmchainpull_table + (dmc->sab_q *
4501*9093SRamana.Srikanth@Sun.COM max_dm_queues + chainpull)))++;
45027836SJohn.Forte@Sun.COM #endif
45037836SJohn.Forte@Sun.COM
45047836SJohn.Forte@Sun.COM }
45057836SJohn.Forte@Sun.COM
45067836SJohn.Forte@Sun.COM
45077836SJohn.Forte@Sun.COM /*
45087836SJohn.Forte@Sun.COM * sdbc_alloc_lru - allocate a new cache block from the lru queue
45097836SJohn.Forte@Sun.COM *
45107836SJohn.Forte@Sun.COM * ARGUMENTS:
45117836SJohn.Forte@Sun.COM * cd - Cache descriptor (from a previous open)
45127836SJohn.Forte@Sun.COM * cblk - cache block number.
45137836SJohn.Forte@Sun.COM * stall - pointer to stall count (no blocks avail)
45147836SJohn.Forte@Sun.COM * flag - lock status of sdbc_queue_lock or ALLOC_NOWAIT
45157836SJohn.Forte@Sun.COM *
45167836SJohn.Forte@Sun.COM * RETURNS:
45177836SJohn.Forte@Sun.COM * A cache block or NULL if ALLOC_NOWAIT specified
45187836SJohn.Forte@Sun.COM *
45197836SJohn.Forte@Sun.COM * USAGE:
45207836SJohn.Forte@Sun.COM * This routine allocates a new cache block from the lru.
45217836SJohn.Forte@Sun.COM * If an allocation cannot be done, we block, unless ALLOC_NOWAIT is set.
45227836SJohn.Forte@Sun.COM */
45237836SJohn.Forte@Sun.COM
45247836SJohn.Forte@Sun.COM static _sd_cctl_t *
45257836SJohn.Forte@Sun.COM sdbc_alloc_lru(int cd, nsc_off_t cblk, int *stall, int flag)
45267836SJohn.Forte@Sun.COM {
45277836SJohn.Forte@Sun.COM _sd_cctl_t *cc_ent, *old_ent, *ccnext;
45287836SJohn.Forte@Sun.COM _sd_queue_t *q = _SD_LRU_Q;
45297836SJohn.Forte@Sun.COM _sd_cctl_t *qhead = &(q->sq_qhead);
45307836SJohn.Forte@Sun.COM int tries = 0, num_tries;
45317836SJohn.Forte@Sun.COM int categorize_centry;
45327836SJohn.Forte@Sun.COM int locked = flag & ALLOC_LOCKED;
45337836SJohn.Forte@Sun.COM int nowait = flag & ALLOC_NOWAIT;
45347836SJohn.Forte@Sun.COM
45357836SJohn.Forte@Sun.COM if (nowait) {
45367836SJohn.Forte@Sun.COM num_tries = q->sq_inq / 100; /* only search 1% of q */
45377836SJohn.Forte@Sun.COM
45387836SJohn.Forte@Sun.COM if (num_tries <= 0) /* ensure num_tries is non-zero */
45397836SJohn.Forte@Sun.COM num_tries = q->sq_inq;
45407836SJohn.Forte@Sun.COM } else
45417836SJohn.Forte@Sun.COM num_tries = _sd_lruq_srch;
45427836SJohn.Forte@Sun.COM
45437836SJohn.Forte@Sun.COM SDTRACE(ST_ENTER|SDF_ENT_ALLOC, cd, 0, BLK_TO_FBA_NUM(cblk), 0, 0);
45447836SJohn.Forte@Sun.COM retry_alloc_centry:
45457836SJohn.Forte@Sun.COM
45467836SJohn.Forte@Sun.COM for (cc_ent = (qhead->cc_next); cc_ent != qhead; cc_ent = ccnext) {
45477836SJohn.Forte@Sun.COM if (--num_tries <= 0)
45487836SJohn.Forte@Sun.COM if (nowait) {
45497836SJohn.Forte@Sun.COM cc_ent = NULL;
45507836SJohn.Forte@Sun.COM goto out;
45517836SJohn.Forte@Sun.COM } else
45527836SJohn.Forte@Sun.COM break;
45537836SJohn.Forte@Sun.COM
45547836SJohn.Forte@Sun.COM ccnext = cc_ent->cc_next;
45557836SJohn.Forte@Sun.COM
45567836SJohn.Forte@Sun.COM if (cc_ent->cc_aging_dm & BAD_CHAIN_DM)
45577836SJohn.Forte@Sun.COM continue;
45587836SJohn.Forte@Sun.COM
45597836SJohn.Forte@Sun.COM if (CENTRY_DIRTY(cc_ent))
45607836SJohn.Forte@Sun.COM continue;
45617836SJohn.Forte@Sun.COM if (SET_CENTRY_INUSE(cc_ent))
45627836SJohn.Forte@Sun.COM continue;
45637836SJohn.Forte@Sun.COM
45647836SJohn.Forte@Sun.COM if (CENTRY_DIRTY(cc_ent)) {
45657836SJohn.Forte@Sun.COM sdbc_centry_lost++;
45667836SJohn.Forte@Sun.COM
45677836SJohn.Forte@Sun.COM CLEAR_CENTRY_INUSE(cc_ent);
45687836SJohn.Forte@Sun.COM continue;
45697836SJohn.Forte@Sun.COM }
45707836SJohn.Forte@Sun.COM cc_ent->cc_flag = 0; /* CC_INUSE */
45717836SJohn.Forte@Sun.COM cc_ent->cc_toflush = 0;
45727836SJohn.Forte@Sun.COM
45737836SJohn.Forte@Sun.COM /*
45747836SJohn.Forte@Sun.COM * Inlined requeue of the LRU. (should match _sd_requeue)
45757836SJohn.Forte@Sun.COM */
45767836SJohn.Forte@Sun.COM /* was FAST */
45777836SJohn.Forte@Sun.COM mutex_enter(&q->sq_qlock);
45787836SJohn.Forte@Sun.COM #if defined(_SD_DEBUG)
45797836SJohn.Forte@Sun.COM if (1) {
45807836SJohn.Forte@Sun.COM _sd_cctl_t *cp, *cn, *qp;
45817836SJohn.Forte@Sun.COM cp = cc_ent->cc_prev;
45827836SJohn.Forte@Sun.COM cn = cc_ent->cc_next;
45837836SJohn.Forte@Sun.COM qp = (q->sq_qhead).cc_prev;
45847836SJohn.Forte@Sun.COM if (!_sd_cctl_valid(cc_ent) ||
45857836SJohn.Forte@Sun.COM (cp != &(q->sq_qhead) && !_sd_cctl_valid(cp)) ||
45867836SJohn.Forte@Sun.COM (cn != &(q->sq_qhead) && !_sd_cctl_valid(cn)) ||
45877836SJohn.Forte@Sun.COM !_sd_cctl_valid(qp))
45887836SJohn.Forte@Sun.COM cmn_err(CE_PANIC,
45897836SJohn.Forte@Sun.COM "_sd_centry_alloc %x prev %x next %x qp %x",
45907836SJohn.Forte@Sun.COM cc_ent, cp, cn, qp);
45917836SJohn.Forte@Sun.COM }
45927836SJohn.Forte@Sun.COM #endif
45937836SJohn.Forte@Sun.COM cc_ent->cc_prev->cc_next = cc_ent->cc_next;
45947836SJohn.Forte@Sun.COM cc_ent->cc_next->cc_prev = cc_ent->cc_prev;
45957836SJohn.Forte@Sun.COM cc_ent->cc_next = qhead;
45967836SJohn.Forte@Sun.COM cc_ent->cc_prev = qhead->cc_prev;
45977836SJohn.Forte@Sun.COM qhead->cc_prev->cc_next = cc_ent;
45987836SJohn.Forte@Sun.COM qhead->cc_prev = cc_ent;
45997836SJohn.Forte@Sun.COM cc_ent->cc_seq = q->sq_seq++;
46007836SJohn.Forte@Sun.COM /* was FAST */
46017836SJohn.Forte@Sun.COM mutex_exit(&q->sq_qlock);
46027836SJohn.Forte@Sun.COM /*
46037836SJohn.Forte@Sun.COM * End inlined requeue.
46047836SJohn.Forte@Sun.COM */
46057836SJohn.Forte@Sun.COM
46067836SJohn.Forte@Sun.COM #if defined(_SD_STATS)
46077836SJohn.Forte@Sun.COM if (_sd_hash_delete(cc_ent, _sd_htable) == 0)
46087836SJohn.Forte@Sun.COM SDTRACE(SDF_REPLACE,
46097836SJohn.Forte@Sun.COM CENTRY_CD(cc_ent), cc_ent->cc_hits,
46107836SJohn.Forte@Sun.COM BLK_TO_FBA_NUM(CENTRY_BLK(cc_ent)),
46117836SJohn.Forte@Sun.COM nsc_lbolt(), cc_ent->cc_creat);
46127836SJohn.Forte@Sun.COM cc_ent->cc_creat = nsc_lbolt();
46137836SJohn.Forte@Sun.COM cc_ent->cc_hits = 0;
46147836SJohn.Forte@Sun.COM #else
46157836SJohn.Forte@Sun.COM #if defined(_SD_DEBUG)
46167836SJohn.Forte@Sun.COM if (_sd_hash_delete(cc_ent, _sd_htable) == 0) {
46177836SJohn.Forte@Sun.COM SDTRACE(SDF_REPLACE|ST_DL,
46187836SJohn.Forte@Sun.COM CENTRY_CD(cc_ent),
46197836SJohn.Forte@Sun.COM cc_ent->cc_valid,
46207836SJohn.Forte@Sun.COM BLK_TO_FBA_NUM(CENTRY_BLK(cc_ent)),
46217836SJohn.Forte@Sun.COM cd, BLK_TO_FBA_NUM(cblk));
46227836SJohn.Forte@Sun.COM if (cc_ent->cc_await_use ||
46237836SJohn.Forte@Sun.COM ((cd == CENTRY_CD(cc_ent)) &&
46247836SJohn.Forte@Sun.COM (cblk == CENTRY_BLK(cc_ent))))
46257836SJohn.Forte@Sun.COM DATA_LOG(SDF_REPLACE|ST_DL, cc_ent, 0,
46267836SJohn.Forte@Sun.COM BLK_FBAS);
46277836SJohn.Forte@Sun.COM }
46287836SJohn.Forte@Sun.COM #else
46297836SJohn.Forte@Sun.COM (void) _sd_hash_delete((struct _sd_hash_hd *)cc_ent,
46307836SJohn.Forte@Sun.COM _sd_htable);
46317836SJohn.Forte@Sun.COM #endif
46327836SJohn.Forte@Sun.COM #endif
46337836SJohn.Forte@Sun.COM cc_ent->cc_creat = nsc_lbolt();
46347836SJohn.Forte@Sun.COM cc_ent->cc_hits = 0;
46357836SJohn.Forte@Sun.COM
46367836SJohn.Forte@Sun.COM cc_ent->cc_valid = 0;
46377836SJohn.Forte@Sun.COM categorize_centry = 0;
46387836SJohn.Forte@Sun.COM if (cc_ent->cc_data)
46397836SJohn.Forte@Sun.COM categorize_centry = FOUND_HOLD_OVER_DM;
46407836SJohn.Forte@Sun.COM
46417836SJohn.Forte@Sun.COM alloc_try:
46427836SJohn.Forte@Sun.COM if (cd == _CD_NOHASH)
46437836SJohn.Forte@Sun.COM CENTRY_BLK(cc_ent) = cblk;
46447836SJohn.Forte@Sun.COM else if ((old_ent = (_sd_cctl_t *)
46457836SJohn.Forte@Sun.COM _sd_hash_insert(cd, cblk, (struct _sd_hash_hd *)cc_ent,
46467836SJohn.Forte@Sun.COM _sd_htable)) != cc_ent) {
46477836SJohn.Forte@Sun.COM
46487836SJohn.Forte@Sun.COM if (SET_CENTRY_INUSE(old_ent)) {
46497836SJohn.Forte@Sun.COM sdbc_centry_inuse++;
46507836SJohn.Forte@Sun.COM
46517836SJohn.Forte@Sun.COM if (nowait) {
46527836SJohn.Forte@Sun.COM _sd_centry_release(cc_ent);
46537836SJohn.Forte@Sun.COM cc_ent = NULL;
46547836SJohn.Forte@Sun.COM goto out;
46557836SJohn.Forte@Sun.COM }
46567836SJohn.Forte@Sun.COM
46577836SJohn.Forte@Sun.COM if (locked)
46587836SJohn.Forte@Sun.COM rw_exit(&sdbc_queue_lock);
46597836SJohn.Forte@Sun.COM _sd_cc_wait(cd, cblk, old_ent, CC_INUSE);
46607836SJohn.Forte@Sun.COM if (locked)
46617836SJohn.Forte@Sun.COM rw_enter(&sdbc_queue_lock, RW_WRITER);
46627836SJohn.Forte@Sun.COM goto alloc_try;
46637836SJohn.Forte@Sun.COM }
46647836SJohn.Forte@Sun.COM
46657836SJohn.Forte@Sun.COM /*
46667836SJohn.Forte@Sun.COM * bug 4529671
46677836SJohn.Forte@Sun.COM * now that we own the centry make sure that
46687836SJohn.Forte@Sun.COM * it is still good. it could have been processed
46697836SJohn.Forte@Sun.COM * by _sd_dealloc_dm() in the window between
46707836SJohn.Forte@Sun.COM * _sd_hash_insert() and SET_CENTRY_INUSE().
46717836SJohn.Forte@Sun.COM */
46727836SJohn.Forte@Sun.COM if ((_sd_cctl_t *)
46737836SJohn.Forte@Sun.COM _sd_hash_search(cd, cblk, _sd_htable) != old_ent) {
46747836SJohn.Forte@Sun.COM sdbc_centry_deallocd++;
46757836SJohn.Forte@Sun.COM #ifdef DEBUG
4676*9093SRamana.Srikanth@Sun.COM cmn_err(CE_WARN, "!cc_ent %p cd %d cblk %"
46777836SJohn.Forte@Sun.COM NSC_SZFMT " lost to dealloc?! cc_data %p",
46787836SJohn.Forte@Sun.COM (void *)old_ent, cd, cblk,
46797836SJohn.Forte@Sun.COM (void *)old_ent->cc_data);
46807836SJohn.Forte@Sun.COM #endif
46817836SJohn.Forte@Sun.COM
46827836SJohn.Forte@Sun.COM CLEAR_CENTRY_INUSE(old_ent);
46837836SJohn.Forte@Sun.COM
46847836SJohn.Forte@Sun.COM if (nowait) {
46857836SJohn.Forte@Sun.COM _sd_centry_release(cc_ent);
46867836SJohn.Forte@Sun.COM cc_ent = NULL;
46877836SJohn.Forte@Sun.COM goto out;
46887836SJohn.Forte@Sun.COM }
46897836SJohn.Forte@Sun.COM
46907836SJohn.Forte@Sun.COM goto alloc_try;
46917836SJohn.Forte@Sun.COM }
46927836SJohn.Forte@Sun.COM
46937836SJohn.Forte@Sun.COM if (CC_CD_BLK_MATCH(cd, cblk, old_ent)) {
46947836SJohn.Forte@Sun.COM sdbc_centry_hit++;
46957836SJohn.Forte@Sun.COM old_ent->cc_toflush = 0;
46967836SJohn.Forte@Sun.COM _sd_centry_release(cc_ent);
46977836SJohn.Forte@Sun.COM cc_ent = old_ent;
46987836SJohn.Forte@Sun.COM categorize_centry = FOUND_IN_HASH_DM;
46997836SJohn.Forte@Sun.COM } else {
47007836SJohn.Forte@Sun.COM sdbc_centry_lost++;
47017836SJohn.Forte@Sun.COM
47027836SJohn.Forte@Sun.COM CLEAR_CENTRY_INUSE(old_ent);
47037836SJohn.Forte@Sun.COM
47047836SJohn.Forte@Sun.COM if (nowait) {
47057836SJohn.Forte@Sun.COM _sd_centry_release(cc_ent);
47067836SJohn.Forte@Sun.COM cc_ent = NULL;
47077836SJohn.Forte@Sun.COM goto out;
47087836SJohn.Forte@Sun.COM }
47097836SJohn.Forte@Sun.COM
47107836SJohn.Forte@Sun.COM goto alloc_try;
47117836SJohn.Forte@Sun.COM }
47127836SJohn.Forte@Sun.COM }
47137836SJohn.Forte@Sun.COM
47147836SJohn.Forte@Sun.COM SDTRACE(ST_EXIT|SDF_ENT_ALLOC, cd, tries,
4715*9093SRamana.Srikanth@Sun.COM BLK_TO_FBA_NUM(cblk), 0, 0);
47167836SJohn.Forte@Sun.COM
47177836SJohn.Forte@Sun.COM if (cc_ent->cc_await_use) {
47187836SJohn.Forte@Sun.COM mutex_enter(&cc_ent->cc_lock);
47197836SJohn.Forte@Sun.COM cv_broadcast(&cc_ent->cc_blkcv);
47207836SJohn.Forte@Sun.COM mutex_exit(&cc_ent->cc_lock);
47217836SJohn.Forte@Sun.COM }
47227836SJohn.Forte@Sun.COM
47237836SJohn.Forte@Sun.COM sdbc_centry_init_dm(cc_ent);
47247836SJohn.Forte@Sun.COM
47257836SJohn.Forte@Sun.COM cc_ent->cc_aging_dm |= categorize_centry;
47267836SJohn.Forte@Sun.COM
47277836SJohn.Forte@Sun.COM out:
47287836SJohn.Forte@Sun.COM return (cc_ent);
47297836SJohn.Forte@Sun.COM }
47307836SJohn.Forte@Sun.COM
47317836SJohn.Forte@Sun.COM SDTRACE(ST_INFO|SDF_ENT_ALLOC, cd, ++tries, BLK_TO_FBA_NUM(cblk), 0, 0);
47327836SJohn.Forte@Sun.COM
47337836SJohn.Forte@Sun.COM delay(drv_usectohz(20000));
47347836SJohn.Forte@Sun.COM (void) (*stall)++;
47357836SJohn.Forte@Sun.COM num_tries = _sd_lruq_srch;
47367836SJohn.Forte@Sun.COM goto retry_alloc_centry;
47377836SJohn.Forte@Sun.COM }
47387836SJohn.Forte@Sun.COM
47397836SJohn.Forte@Sun.COM /*
47407836SJohn.Forte@Sun.COM * sdbc_centry_init_dm - setup the cache block for dynamic memory allocation
47417836SJohn.Forte@Sun.COM *
47427836SJohn.Forte@Sun.COM * ARGUMENTS:
47437836SJohn.Forte@Sun.COM * centry - Cache block.
47447836SJohn.Forte@Sun.COM *
47457836SJohn.Forte@Sun.COM * RETURNS:
47467836SJohn.Forte@Sun.COM * NONE
47477836SJohn.Forte@Sun.COM *
47487836SJohn.Forte@Sun.COM * USAGE:
47497836SJohn.Forte@Sun.COM * This routine is the central point in which cache entry blocks are setup
47507836SJohn.Forte@Sun.COM */
47517836SJohn.Forte@Sun.COM static void
47527836SJohn.Forte@Sun.COM sdbc_centry_init_dm(_sd_cctl_t *centry)
47537836SJohn.Forte@Sun.COM {
47547836SJohn.Forte@Sun.COM
47557836SJohn.Forte@Sun.COM /* an entry already setup - don't touch simply refresh age */
47567836SJohn.Forte@Sun.COM if (centry->cc_data) {
47577836SJohn.Forte@Sun.COM centry->cc_aging_dm &= ~(FINAL_AGING_DM);
47587836SJohn.Forte@Sun.COM
47597836SJohn.Forte@Sun.COM DTRACE_PROBE1(sdbc_centry_init_dm_end,
4760*9093SRamana.Srikanth@Sun.COM char *, centry->cc_data);
47617836SJohn.Forte@Sun.COM return;
47627836SJohn.Forte@Sun.COM }
47637836SJohn.Forte@Sun.COM
47647836SJohn.Forte@Sun.COM centry->cc_aging_dm &= ~(FINAL_AGING_DM | CATAGORY_ENTRY_DM);
47657836SJohn.Forte@Sun.COM
47667836SJohn.Forte@Sun.COM if (centry->cc_head_dm || centry->cc_next_dm)
4767*9093SRamana.Srikanth@Sun.COM cmn_err(cmn_level, "!sdbc(sdbc_centry_init_dm): "
47687836SJohn.Forte@Sun.COM "non-zero mem chain in ccent %p", (void *)centry);
47697836SJohn.Forte@Sun.COM
47707836SJohn.Forte@Sun.COM centry->cc_head_dm = 0;
47717836SJohn.Forte@Sun.COM
47727836SJohn.Forte@Sun.COM if (!sdbc_use_dmchain)
47737836SJohn.Forte@Sun.COM centry->cc_next_dm = 0;
47747836SJohn.Forte@Sun.COM
47757836SJohn.Forte@Sun.COM centry->cc_data = 0;
47767836SJohn.Forte@Sun.COM
47777836SJohn.Forte@Sun.COM }
47787836SJohn.Forte@Sun.COM
47797836SJohn.Forte@Sun.COM /*
47807836SJohn.Forte@Sun.COM * sdbc_centry_memalloc_dm
47817836SJohn.Forte@Sun.COM *
47827836SJohn.Forte@Sun.COM * Actually allocate the cache memory, storing it in the cc_data field for
47837836SJohn.Forte@Sun.COM * the cctl
47847836SJohn.Forte@Sun.COM *
47857836SJohn.Forte@Sun.COM * ARGS:
47867836SJohn.Forte@Sun.COM * centry: cache control block for which to allocate the memory
47877836SJohn.Forte@Sun.COM * alloc_request: number of bytes to allocate
47887836SJohn.Forte@Sun.COM * flag: if called with ALLOC_NOWAIT, caller must check for non-zero return
47897836SJohn.Forte@Sun.COM *
47907836SJohn.Forte@Sun.COM * RETURNS:
47917836SJohn.Forte@Sun.COM * 0 on success
47927836SJohn.Forte@Sun.COM * non-zero on error
47937836SJohn.Forte@Sun.COM */
47947836SJohn.Forte@Sun.COM static int
47957836SJohn.Forte@Sun.COM sdbc_centry_memalloc_dm(_sd_cctl_t *centry, int alloc_request, int flag)
47967836SJohn.Forte@Sun.COM {
47977836SJohn.Forte@Sun.COM int cblocks;
47987836SJohn.Forte@Sun.COM _sd_queue_t *newq;
47997836SJohn.Forte@Sun.COM int sleep;
48007836SJohn.Forte@Sun.COM sleep = (flag & ALLOC_NOWAIT) ? KM_NOSLEEP : KM_SLEEP;
48017836SJohn.Forte@Sun.COM
48027836SJohn.Forte@Sun.COM if (!centry->cc_data && (alloc_request > 0)) {
48037836SJohn.Forte@Sun.COM /* host or other */
48047836SJohn.Forte@Sun.COM dynmem_processing_dm.alloc_ct++;
48057836SJohn.Forte@Sun.COM centry->cc_data = (unsigned char *)
48067836SJohn.Forte@Sun.COM kmem_alloc((size_t)centry->cc_alloc_size_dm, sleep);
48077836SJohn.Forte@Sun.COM
48087836SJohn.Forte@Sun.COM
48097836SJohn.Forte@Sun.COM if (sdbc_use_dmchain) {
48107836SJohn.Forte@Sun.COM cblocks = centry->cc_alloc_size_dm >> _sd_cblock_shift;
48117836SJohn.Forte@Sun.COM newq = &sdbc_dm_queues[cblocks];
48127836SJohn.Forte@Sun.COM
48137836SJohn.Forte@Sun.COM /* set the dmqueue index */
48147836SJohn.Forte@Sun.COM centry->cc_cblocks = cblocks;
48157836SJohn.Forte@Sun.COM
48167836SJohn.Forte@Sun.COM /* put on appropriate queue */
48177836SJohn.Forte@Sun.COM sdbc_ins_dmqueue_back(newq, centry);
48187836SJohn.Forte@Sun.COM }
48197836SJohn.Forte@Sun.COM
48207836SJohn.Forte@Sun.COM /*
48217836SJohn.Forte@Sun.COM * for KM_NOSLEEP (should never happen with KM_SLEEP)
48227836SJohn.Forte@Sun.COM */
48237836SJohn.Forte@Sun.COM if (!centry->cc_data)
48247836SJohn.Forte@Sun.COM return (LOW_RESOURCES_DM);
48257836SJohn.Forte@Sun.COM centry->cc_head_dm = centry;
48267836SJohn.Forte@Sun.COM centry->cc_alloc_ct_dm++;
48277836SJohn.Forte@Sun.COM }
48287836SJohn.Forte@Sun.COM
48297836SJohn.Forte@Sun.COM return (0);
48307836SJohn.Forte@Sun.COM }
48317836SJohn.Forte@Sun.COM
48327836SJohn.Forte@Sun.COM /*
48337836SJohn.Forte@Sun.COM * _sd_centry_release - release a cache block
48347836SJohn.Forte@Sun.COM *
48357836SJohn.Forte@Sun.COM * ARGUMENTS:
48367836SJohn.Forte@Sun.COM * centry - Cache block.
48377836SJohn.Forte@Sun.COM *
48387836SJohn.Forte@Sun.COM * RETURNS:
48397836SJohn.Forte@Sun.COM * NONE
48407836SJohn.Forte@Sun.COM *
48417836SJohn.Forte@Sun.COM * USAGE:
48427836SJohn.Forte@Sun.COM * This routine frees up a cache block. It also frees up a write
48437836SJohn.Forte@Sun.COM * block if allocated and its valid to release it.
48447836SJohn.Forte@Sun.COM */
48457836SJohn.Forte@Sun.COM
48467836SJohn.Forte@Sun.COM void
48477836SJohn.Forte@Sun.COM _sd_centry_release(_sd_cctl_t *centry)
48487836SJohn.Forte@Sun.COM {
48497836SJohn.Forte@Sun.COM ss_centry_info_t *wctl;
48507836SJohn.Forte@Sun.COM
48517836SJohn.Forte@Sun.COM SDTRACE(ST_ENTER|SDF_ENT_FREE, CENTRY_CD(centry), 0,
4852*9093SRamana.Srikanth@Sun.COM BLK_TO_FBA_NUM(CENTRY_BLK(centry)), 0, 0);
48537836SJohn.Forte@Sun.COM
48547836SJohn.Forte@Sun.COM CLEAR_CENTRY_PAGEIO(centry);
48557836SJohn.Forte@Sun.COM
48567836SJohn.Forte@Sun.COM if ((wctl = centry->cc_write) != 0) {
48577836SJohn.Forte@Sun.COM /* was FAST */
48587836SJohn.Forte@Sun.COM mutex_enter(¢ry->cc_lock);
48597836SJohn.Forte@Sun.COM if (CENTRY_DIRTY(centry))
48607836SJohn.Forte@Sun.COM wctl = NULL;
48617836SJohn.Forte@Sun.COM else {
48627836SJohn.Forte@Sun.COM centry->cc_write = NULL;
48637836SJohn.Forte@Sun.COM centry->cc_flag &= ~(CC_PINNABLE);
48647836SJohn.Forte@Sun.COM }
48657836SJohn.Forte@Sun.COM /* was FAST */
48667836SJohn.Forte@Sun.COM mutex_exit(¢ry->cc_lock);
48677836SJohn.Forte@Sun.COM if (wctl) {
48687836SJohn.Forte@Sun.COM wctl->sc_dirty = 0;
48697836SJohn.Forte@Sun.COM SSOP_SETCENTRY(sdbc_safestore, wctl);
48707836SJohn.Forte@Sun.COM SSOP_DEALLOCRESOURCE(sdbc_safestore, wctl->sc_res);
48717836SJohn.Forte@Sun.COM }
48727836SJohn.Forte@Sun.COM }
48737836SJohn.Forte@Sun.COM
48747836SJohn.Forte@Sun.COM if (!(centry->cc_aging_dm & BAD_CHAIN_DM)) {
48757836SJohn.Forte@Sun.COM if (sdbc_use_dmchain) {
48767836SJohn.Forte@Sun.COM if (centry->cc_alloc_size_dm) {
48777836SJohn.Forte@Sun.COM
48787836SJohn.Forte@Sun.COM /* see if this can be queued to head */
48797836SJohn.Forte@Sun.COM if (CENTRY_QHEAD(centry)) {
48807836SJohn.Forte@Sun.COM sdbc_requeue_head_dm_try(centry);
48817836SJohn.Forte@Sun.COM } else {
48827836SJohn.Forte@Sun.COM int qidx;
48837836SJohn.Forte@Sun.COM _sd_queue_t *q;
48847836SJohn.Forte@Sun.COM
48857836SJohn.Forte@Sun.COM qidx = centry->cc_cblocks;
48867836SJohn.Forte@Sun.COM q = &sdbc_dm_queues[qidx];
48877836SJohn.Forte@Sun.COM
48887836SJohn.Forte@Sun.COM if (_sd_lru_reinsert(q, centry)) {
48897836SJohn.Forte@Sun.COM sdbc_requeue_dmchain(q,
4890*9093SRamana.Srikanth@Sun.COM centry, 1, 1);
48917836SJohn.Forte@Sun.COM }
48927836SJohn.Forte@Sun.COM }
48937836SJohn.Forte@Sun.COM } else {
48947836SJohn.Forte@Sun.COM /*
48957836SJohn.Forte@Sun.COM * Fix for bug 4949134:
48967836SJohn.Forte@Sun.COM * If an internal block is marked with CC_QHEAD
48977836SJohn.Forte@Sun.COM * but the HOST block is not, the chain will
48987836SJohn.Forte@Sun.COM * never age properly, and will never be made
48997836SJohn.Forte@Sun.COM * available. Only the HOST of the dmchain is
49007836SJohn.Forte@Sun.COM * checked for CC_QHEAD, so clearing an internal
49017836SJohn.Forte@Sun.COM * block indiscriminately (as is being done
49027836SJohn.Forte@Sun.COM * here) does no damage.
49037836SJohn.Forte@Sun.COM *
49047836SJohn.Forte@Sun.COM * The same result could instead be achieved by
49057836SJohn.Forte@Sun.COM * not setting the CC_QHEAD flag in the first
49067836SJohn.Forte@Sun.COM * place, if the block is an internal dmchain
49077836SJohn.Forte@Sun.COM * block, and if it is found in the hash table.
49087836SJohn.Forte@Sun.COM * The current solution was chosen since it is
49097836SJohn.Forte@Sun.COM * the least intrusive.
49107836SJohn.Forte@Sun.COM */
49117836SJohn.Forte@Sun.COM centry->cc_flag &= ~CC_QHEAD;
49127836SJohn.Forte@Sun.COM }
49137836SJohn.Forte@Sun.COM } else {
49147836SJohn.Forte@Sun.COM if (CENTRY_QHEAD(centry)) {
49157836SJohn.Forte@Sun.COM if (!CENTRY_DIRTY(centry))
49167836SJohn.Forte@Sun.COM _sd_requeue_head(centry);
49177836SJohn.Forte@Sun.COM } else if (_sd_lru_reinsert(_SD_LRU_Q, centry))
49187836SJohn.Forte@Sun.COM _sd_requeue(centry);
49197836SJohn.Forte@Sun.COM }
49207836SJohn.Forte@Sun.COM }
49217836SJohn.Forte@Sun.COM
49227836SJohn.Forte@Sun.COM SDTRACE(ST_EXIT|SDF_ENT_FREE, CENTRY_CD(centry), 0,
4923*9093SRamana.Srikanth@Sun.COM BLK_TO_FBA_NUM(CENTRY_BLK(centry)), 0, 0);
49247836SJohn.Forte@Sun.COM
49257836SJohn.Forte@Sun.COM /* only clear inuse after final reference to centry */
49267836SJohn.Forte@Sun.COM
49277836SJohn.Forte@Sun.COM CLEAR_CENTRY_INUSE(centry);
49287836SJohn.Forte@Sun.COM }
49297836SJohn.Forte@Sun.COM
49307836SJohn.Forte@Sun.COM
49317836SJohn.Forte@Sun.COM /*
49327836SJohn.Forte@Sun.COM * lookup to centry info associated with safestore resource
49337836SJohn.Forte@Sun.COM * return pointer to the centry info structure
49347836SJohn.Forte@Sun.COM */
49357836SJohn.Forte@Sun.COM ss_centry_info_t *
49367836SJohn.Forte@Sun.COM sdbc_get_cinfo_byres(ss_resource_t *res)
49377836SJohn.Forte@Sun.COM {
49387836SJohn.Forte@Sun.COM ss_centry_info_t *cinfo;
49397836SJohn.Forte@Sun.COM ss_centry_info_t *cend;
49407836SJohn.Forte@Sun.COM int found = 0;
49417836SJohn.Forte@Sun.COM
49427836SJohn.Forte@Sun.COM ASSERT(res != NULL);
49437836SJohn.Forte@Sun.COM
49447836SJohn.Forte@Sun.COM if (res == NULL)
49457836SJohn.Forte@Sun.COM return (NULL);
49467836SJohn.Forte@Sun.COM
49477836SJohn.Forte@Sun.COM cinfo = _sdbc_gl_centry_info;
4948*9093SRamana.Srikanth@Sun.COM cend = _sdbc_gl_centry_info +
4949*9093SRamana.Srikanth@Sun.COM (_sdbc_gl_centry_info_size / sizeof (ss_centry_info_t)) - 1;
49507836SJohn.Forte@Sun.COM
49517836SJohn.Forte@Sun.COM for (; cinfo <= cend; ++cinfo)
49527836SJohn.Forte@Sun.COM if (cinfo->sc_res == res) {
49537836SJohn.Forte@Sun.COM ++found;
49547836SJohn.Forte@Sun.COM break;
49557836SJohn.Forte@Sun.COM }
49567836SJohn.Forte@Sun.COM
49577836SJohn.Forte@Sun.COM if (!found)
49587836SJohn.Forte@Sun.COM cinfo = NULL; /* bad */
49597836SJohn.Forte@Sun.COM
49607836SJohn.Forte@Sun.COM return (cinfo);
49617836SJohn.Forte@Sun.COM }
49627836SJohn.Forte@Sun.COM
49637836SJohn.Forte@Sun.COM /*
49647836SJohn.Forte@Sun.COM * _sd_alloc_write - Allocate a write block (for remote mirroring)
49657836SJohn.Forte@Sun.COM * and set centry->cc_write
49667836SJohn.Forte@Sun.COM *
49677836SJohn.Forte@Sun.COM * ARGUMENTS:
49687836SJohn.Forte@Sun.COM * centry - Head of Cache chain
49697836SJohn.Forte@Sun.COM * stall - pointer to stall count (no blocks avail)
49707836SJohn.Forte@Sun.COM *
49717836SJohn.Forte@Sun.COM * RETURNS:
49727836SJohn.Forte@Sun.COM * 0 - and sets cc_write for all entries when write contl block obtained.
49737836SJohn.Forte@Sun.COM * -1 - if a write control block could not be obtained.
49747836SJohn.Forte@Sun.COM */
49757836SJohn.Forte@Sun.COM
49767836SJohn.Forte@Sun.COM int
49777836SJohn.Forte@Sun.COM _sd_alloc_write(_sd_cctl_t *centry, int *stall)
49787836SJohn.Forte@Sun.COM {
49797836SJohn.Forte@Sun.COM
49807836SJohn.Forte@Sun.COM ss_resourcelist_t *reslist;
49817836SJohn.Forte@Sun.COM ss_resourcelist_t *savereslist;
49827836SJohn.Forte@Sun.COM ss_resource_t *res;
49837836SJohn.Forte@Sun.COM _sd_cctl_t *ce;
49847836SJohn.Forte@Sun.COM int err;
49857836SJohn.Forte@Sun.COM int need;
49867836SJohn.Forte@Sun.COM
49877836SJohn.Forte@Sun.COM
49887836SJohn.Forte@Sun.COM need = 0;
49897836SJohn.Forte@Sun.COM
49907836SJohn.Forte@Sun.COM for (ce = centry; ce; ce = ce->cc_chain) {
49917836SJohn.Forte@Sun.COM if (!(ce->cc_write))
49927836SJohn.Forte@Sun.COM need++;
49937836SJohn.Forte@Sun.COM }
49947836SJohn.Forte@Sun.COM
49957836SJohn.Forte@Sun.COM if (!need)
49967836SJohn.Forte@Sun.COM return (0);
49977836SJohn.Forte@Sun.COM
49987836SJohn.Forte@Sun.COM if ((SSOP_ALLOCRESOURCE(sdbc_safestore, need, stall, &reslist))
4999*9093SRamana.Srikanth@Sun.COM == SS_OK) {
50007836SJohn.Forte@Sun.COM savereslist = reslist;
50017836SJohn.Forte@Sun.COM for (ce = centry; ce; ce = ce->cc_chain) {
50027836SJohn.Forte@Sun.COM if (ce->cc_write)
50037836SJohn.Forte@Sun.COM continue;
50047836SJohn.Forte@Sun.COM err = SSOP_GETRESOURCE(sdbc_safestore, &reslist, &res);
50057836SJohn.Forte@Sun.COM if (err == SS_OK)
50067836SJohn.Forte@Sun.COM ce->cc_write = sdbc_get_cinfo_byres(res);
50077836SJohn.Forte@Sun.COM
50087836SJohn.Forte@Sun.COM ASSERT(err == SS_OK); /* panic if DEBUG on */
50097836SJohn.Forte@Sun.COM ASSERT(ce->cc_write != NULL);
50107836SJohn.Forte@Sun.COM
50117836SJohn.Forte@Sun.COM /*
50127836SJohn.Forte@Sun.COM * this is bad and should not happen.
50137836SJohn.Forte@Sun.COM * we use the saved reslist to cleanup
50147836SJohn.Forte@Sun.COM * and return.
50157836SJohn.Forte@Sun.COM */
50167836SJohn.Forte@Sun.COM if ((err != SS_OK) || !ce->cc_write) {
50177836SJohn.Forte@Sun.COM
5018*9093SRamana.Srikanth@Sun.COM cmn_err(CE_WARN, "!_sd_alloc_write: "
50197836SJohn.Forte@Sun.COM "bad resource list 0x%p"
50207836SJohn.Forte@Sun.COM "changing to forced write thru mode",
50217836SJohn.Forte@Sun.COM (void *)savereslist);
50227836SJohn.Forte@Sun.COM
50237836SJohn.Forte@Sun.COM (void) _sd_set_node_hint(NSC_FORCED_WRTHRU);
50247836SJohn.Forte@Sun.COM
50257836SJohn.Forte@Sun.COM while (SSOP_GETRESOURCE(sdbc_safestore,
5026*9093SRamana.Srikanth@Sun.COM &savereslist, &res) == SS_OK) {
50277836SJohn.Forte@Sun.COM
50287836SJohn.Forte@Sun.COM SSOP_DEALLOCRESOURCE(sdbc_safestore,
5029*9093SRamana.Srikanth@Sun.COM res);
50307836SJohn.Forte@Sun.COM }
50317836SJohn.Forte@Sun.COM
50327836SJohn.Forte@Sun.COM return (-1);
50337836SJohn.Forte@Sun.COM
50347836SJohn.Forte@Sun.COM }
50357836SJohn.Forte@Sun.COM
50367836SJohn.Forte@Sun.COM }
50377836SJohn.Forte@Sun.COM return (0);
50387836SJohn.Forte@Sun.COM }
50397836SJohn.Forte@Sun.COM
50407836SJohn.Forte@Sun.COM /* no safestore resources available. do sync write */
50417836SJohn.Forte@Sun.COM _sd_unblock(&_sd_flush_cv);
50427836SJohn.Forte@Sun.COM return (-1);
50437836SJohn.Forte@Sun.COM }
50447836SJohn.Forte@Sun.COM
50457836SJohn.Forte@Sun.COM /*
50467836SJohn.Forte@Sun.COM * _sd_read - Interface call to do read.
50477836SJohn.Forte@Sun.COM *
50487836SJohn.Forte@Sun.COM * ARGUMENTS:
50497836SJohn.Forte@Sun.COM * handle - handle allocated earlier on.
50507836SJohn.Forte@Sun.COM * fba_pos - disk block number to read from.
50517836SJohn.Forte@Sun.COM * fba_len - length in fbas.
50527836SJohn.Forte@Sun.COM * flag - flag: (NSC_NOBLOCK for async io)
50537836SJohn.Forte@Sun.COM *
50547836SJohn.Forte@Sun.COM * RETURNS:
50557836SJohn.Forte@Sun.COM * errno if return > 0
50567836SJohn.Forte@Sun.COM * NSC_DONE or NSC_PENDING otherwise.
50577836SJohn.Forte@Sun.COM *
50587836SJohn.Forte@Sun.COM * USAGE:
50597836SJohn.Forte@Sun.COM * This routine checks if the request is valid and calls the underlying
50607836SJohn.Forte@Sun.COM * doread routine (also called by alloc_buf)
50617836SJohn.Forte@Sun.COM */
50627836SJohn.Forte@Sun.COM
50637836SJohn.Forte@Sun.COM int
50647836SJohn.Forte@Sun.COM _sd_read(_sd_buf_handle_t *handle, nsc_off_t fba_pos, nsc_size_t fba_len,
50657836SJohn.Forte@Sun.COM int flag)
50667836SJohn.Forte@Sun.COM {
50677836SJohn.Forte@Sun.COM sdbc_cblk_fba_t st_cblk_len; /* FBA len of starting cache block */
50687836SJohn.Forte@Sun.COM sdbc_cblk_fba_t end_cblk_len; /* FBA len of ending cache block */
50697836SJohn.Forte@Sun.COM sdbc_cblk_fba_t st_cblk_off; /* FBA offset into starting cblock */
50707836SJohn.Forte@Sun.COM _sd_cctl_t *cc_ent = NULL;
50717836SJohn.Forte@Sun.COM nsc_size_t fba_orig_len = fba_len;
50727836SJohn.Forte@Sun.COM int ret;
50737836SJohn.Forte@Sun.COM int cd = HANDLE_CD(handle);
50747836SJohn.Forte@Sun.COM
50757836SJohn.Forte@Sun.COM if (_sdbc_shutdown_in_progress || (handle->bh_flag & NSC_ABUF)) {
50767836SJohn.Forte@Sun.COM ret = EIO;
50777836SJohn.Forte@Sun.COM goto out;
50787836SJohn.Forte@Sun.COM }
50797836SJohn.Forte@Sun.COM
50807836SJohn.Forte@Sun.COM
50817836SJohn.Forte@Sun.COM #if !defined(_SD_NOCHECKS)
50827836SJohn.Forte@Sun.COM if (!_SD_HANDLE_ACTIVE(handle)) {
5083*9093SRamana.Srikanth@Sun.COM cmn_err(CE_WARN, "!sdbc(_sd_read) handle %p not active",
50847836SJohn.Forte@Sun.COM (void *)handle);
50857836SJohn.Forte@Sun.COM ret = EINVAL;
50867836SJohn.Forte@Sun.COM goto out;
50877836SJohn.Forte@Sun.COM }
50887836SJohn.Forte@Sun.COM ASSERT_HANDLE_LIMITS(handle, fba_pos, fba_len);
50897836SJohn.Forte@Sun.COM #endif
50907836SJohn.Forte@Sun.COM if (fba_len == 0) {
50917836SJohn.Forte@Sun.COM ret = NSC_DONE;
50927836SJohn.Forte@Sun.COM goto out;
50937836SJohn.Forte@Sun.COM }
50947836SJohn.Forte@Sun.COM
50957836SJohn.Forte@Sun.COM KSTAT_RUNQ_ENTER(cd);
50967836SJohn.Forte@Sun.COM
50977836SJohn.Forte@Sun.COM st_cblk_off = BLK_FBA_OFF(fba_pos);
50987836SJohn.Forte@Sun.COM st_cblk_len = BLK_FBAS - st_cblk_off;
50997836SJohn.Forte@Sun.COM if ((nsc_size_t)st_cblk_len >= fba_len) {
51007836SJohn.Forte@Sun.COM end_cblk_len = 0;
51017836SJohn.Forte@Sun.COM st_cblk_len = (sdbc_cblk_fba_t)fba_len;
51027836SJohn.Forte@Sun.COM } else {
51037836SJohn.Forte@Sun.COM end_cblk_len = BLK_FBA_OFF(fba_pos + fba_len);
51047836SJohn.Forte@Sun.COM }
51057836SJohn.Forte@Sun.COM
51067836SJohn.Forte@Sun.COM cc_ent = handle->bh_centry;
51077836SJohn.Forte@Sun.COM while (CENTRY_BLK(cc_ent) != FBA_TO_BLK_NUM(fba_pos))
51087836SJohn.Forte@Sun.COM cc_ent = cc_ent->cc_chain;
51097836SJohn.Forte@Sun.COM
51107836SJohn.Forte@Sun.COM if (!SDBC_VALID_BITS(st_cblk_off, st_cblk_len, cc_ent))
51117836SJohn.Forte@Sun.COM goto need_io;
51127836SJohn.Forte@Sun.COM DATA_LOG(SDF_RD, cc_ent, st_cblk_off, st_cblk_len);
51137836SJohn.Forte@Sun.COM
5114*9093SRamana.Srikanth@Sun.COM DTRACE_PROBE4(_sd_read_data1, uint64_t,
5115*9093SRamana.Srikanth@Sun.COM (uint64_t)(BLK_TO_FBA_NUM(CENTRY_BLK(cc_ent)) + st_cblk_off),
5116*9093SRamana.Srikanth@Sun.COM uint64_t, (uint64_t)st_cblk_len, char *,
5117*9093SRamana.Srikanth@Sun.COM *(int64_t *)(cc_ent->cc_data + FBA_SIZE(st_cblk_off)),
5118*9093SRamana.Srikanth@Sun.COM char *, *(int64_t *)(cc_ent->cc_data +
5119*9093SRamana.Srikanth@Sun.COM FBA_SIZE(st_cblk_off + st_cblk_len) - 8));
51207836SJohn.Forte@Sun.COM
51217836SJohn.Forte@Sun.COM fba_pos += st_cblk_len;
51227836SJohn.Forte@Sun.COM fba_len -= st_cblk_len;
51237836SJohn.Forte@Sun.COM cc_ent = cc_ent->cc_chain;
51247836SJohn.Forte@Sun.COM
51257836SJohn.Forte@Sun.COM while (fba_len > (nsc_size_t)end_cblk_len) {
51267836SJohn.Forte@Sun.COM if (!FULLY_VALID(cc_ent))
51277836SJohn.Forte@Sun.COM goto need_io;
51287836SJohn.Forte@Sun.COM DATA_LOG(SDF_RD, cc_ent, 0, BLK_FBAS);
51297836SJohn.Forte@Sun.COM
5130*9093SRamana.Srikanth@Sun.COM DTRACE_PROBE4(_sd_read_data2, uint64_t,
5131*9093SRamana.Srikanth@Sun.COM (uint64_t)BLK_TO_FBA_NUM(CENTRY_BLK(cc_ent)),
5132*9093SRamana.Srikanth@Sun.COM uint64_t, (uint64_t)BLK_FBAS,
5133*9093SRamana.Srikanth@Sun.COM char *, *(int64_t *)(cc_ent->cc_data),
5134*9093SRamana.Srikanth@Sun.COM char *, *(int64_t *)(cc_ent->cc_data +
5135*9093SRamana.Srikanth@Sun.COM FBA_SIZE(BLK_FBAS) - 8));
51367836SJohn.Forte@Sun.COM
51377836SJohn.Forte@Sun.COM fba_pos += BLK_FBAS;
51387836SJohn.Forte@Sun.COM fba_len -= BLK_FBAS;
51397836SJohn.Forte@Sun.COM cc_ent = cc_ent->cc_chain;
51407836SJohn.Forte@Sun.COM }
51417836SJohn.Forte@Sun.COM if (fba_len) {
51427836SJohn.Forte@Sun.COM if (!SDBC_VALID_BITS(0, end_cblk_len, cc_ent))
51437836SJohn.Forte@Sun.COM goto need_io;
51447836SJohn.Forte@Sun.COM DATA_LOG(SDF_RD, cc_ent, 0, end_cblk_len);
51457836SJohn.Forte@Sun.COM
5146*9093SRamana.Srikanth@Sun.COM DTRACE_PROBE4(_sd_read_data3, uint64_t,
5147*9093SRamana.Srikanth@Sun.COM (uint64_t)BLK_TO_FBA_NUM(CENTRY_BLK(cc_ent)),
5148*9093SRamana.Srikanth@Sun.COM uint64_t, (uint64_t)end_cblk_len,
5149*9093SRamana.Srikanth@Sun.COM char *, *(int64_t *)(cc_ent->cc_data),
5150*9093SRamana.Srikanth@Sun.COM char *, *(int64_t *)(cc_ent->cc_data +
5151*9093SRamana.Srikanth@Sun.COM FBA_SIZE(end_cblk_len) - 8));
51527836SJohn.Forte@Sun.COM }
51537836SJohn.Forte@Sun.COM
51547836SJohn.Forte@Sun.COM CACHE_FBA_READ(handle->bh_cd, fba_orig_len);
51557836SJohn.Forte@Sun.COM CACHE_READ_HIT;
51567836SJohn.Forte@Sun.COM
51577836SJohn.Forte@Sun.COM FBA_READ_IO_KSTATS(handle->bh_cd, FBA_SIZE(fba_orig_len));
51587836SJohn.Forte@Sun.COM
51597836SJohn.Forte@Sun.COM ret = NSC_HIT;
51607836SJohn.Forte@Sun.COM goto stats_exit;
51617836SJohn.Forte@Sun.COM need_io:
51627836SJohn.Forte@Sun.COM _SD_DISCONNECT_CALLBACK(handle);
51637836SJohn.Forte@Sun.COM
51647836SJohn.Forte@Sun.COM ret = _sd_doread(handle, cc_ent, fba_pos, fba_len, flag);
51657836SJohn.Forte@Sun.COM
51667836SJohn.Forte@Sun.COM stats_exit:
51677836SJohn.Forte@Sun.COM KSTAT_RUNQ_EXIT(cd);
51687836SJohn.Forte@Sun.COM out:
51697836SJohn.Forte@Sun.COM return (ret);
51707836SJohn.Forte@Sun.COM }
51717836SJohn.Forte@Sun.COM
51727836SJohn.Forte@Sun.COM
51737836SJohn.Forte@Sun.COM /*
51747836SJohn.Forte@Sun.COM * sdbc_doread_prefetch - read ahead one cache block
51757836SJohn.Forte@Sun.COM *
51767836SJohn.Forte@Sun.COM * ARGUMENTS:
51777836SJohn.Forte@Sun.COM * cc_ent - cache entry
51787836SJohn.Forte@Sun.COM * fba_pos - disk block number to read from
51797836SJohn.Forte@Sun.COM * fba_len - length in fbas.
51807836SJohn.Forte@Sun.COM *
51817836SJohn.Forte@Sun.COM * RETURNS:
51827836SJohn.Forte@Sun.COM * number of fbas, if any, that are to be read beyond (fba_pos + fba_len)
51837836SJohn.Forte@Sun.COM *
51847836SJohn.Forte@Sun.COM * USAGE:
51857836SJohn.Forte@Sun.COM * if readahead is to be done allocate a cache block and place
51867836SJohn.Forte@Sun.COM * on the cc_chain of cc_ent
51877836SJohn.Forte@Sun.COM */
51887836SJohn.Forte@Sun.COM static int
51897836SJohn.Forte@Sun.COM sdbc_doread_prefetch(_sd_cctl_t *cc_ent, nsc_off_t fba_pos, nsc_size_t fba_len)
51907836SJohn.Forte@Sun.COM {
51917836SJohn.Forte@Sun.COM nsc_off_t st_cblk = FBA_TO_BLK_NUM(fba_pos);
51927836SJohn.Forte@Sun.COM nsc_off_t next_cblk = FBA_TO_BLK_NUM(fba_pos + BLK_FBAS);
51937836SJohn.Forte@Sun.COM nsc_size_t filesize;
51947836SJohn.Forte@Sun.COM int fba_count = 0; /* number of fbas to prefetch */
51957836SJohn.Forte@Sun.COM _sd_cctl_t *cc_ra; /* the read ahead cache entry */
51967836SJohn.Forte@Sun.COM int cd = CENTRY_CD(cc_ent);
51977836SJohn.Forte@Sun.COM nsc_size_t vol_fill;
51987836SJohn.Forte@Sun.COM
51997836SJohn.Forte@Sun.COM filesize = _sd_cache_files[cd].cd_info->sh_filesize;
52007836SJohn.Forte@Sun.COM vol_fill = filesize - (fba_pos + fba_len);
52017836SJohn.Forte@Sun.COM
52027836SJohn.Forte@Sun.COM /* readahead only for small reads */
52037836SJohn.Forte@Sun.COM if ((fba_len <= FBA_LEN(CACHE_BLOCK_SIZE)) && (fba_pos != 0) &&
52047836SJohn.Forte@Sun.COM (vol_fill > 0)) {
52057836SJohn.Forte@Sun.COM
52067836SJohn.Forte@Sun.COM /*
52077836SJohn.Forte@Sun.COM * if prev block is in cache and next block is not,
52087836SJohn.Forte@Sun.COM * then read ahead one block
52097836SJohn.Forte@Sun.COM */
52107836SJohn.Forte@Sun.COM if (_sd_hash_search(cd, st_cblk - 1, _sd_htable)) {
52117836SJohn.Forte@Sun.COM if (!_sd_hash_search(cd, next_cblk, _sd_htable)) {
52127836SJohn.Forte@Sun.COM
5213*9093SRamana.Srikanth@Sun.COM cc_ra = sdbc_centry_alloc_blks
5214*9093SRamana.Srikanth@Sun.COM (cd, next_cblk, 1, ALLOC_NOWAIT);
52157836SJohn.Forte@Sun.COM if (cc_ra) {
52167836SJohn.Forte@Sun.COM /* if in cache don't readahead */
5217*9093SRamana.Srikanth@Sun.COM if (cc_ra->cc_aging_dm &
5218*9093SRamana.Srikanth@Sun.COM HASH_ENTRY_DM) {
5219*9093SRamana.Srikanth@Sun.COM ++sdbc_ra_hash;
5220*9093SRamana.Srikanth@Sun.COM _sd_centry_release(cc_ra);
5221*9093SRamana.Srikanth@Sun.COM } else {
5222*9093SRamana.Srikanth@Sun.COM cc_ent->cc_chain = cc_ra;
5223*9093SRamana.Srikanth@Sun.COM cc_ra->cc_chain = 0;
5224*9093SRamana.Srikanth@Sun.COM fba_count =
5225*9093SRamana.Srikanth@Sun.COM (vol_fill >
5226*9093SRamana.Srikanth@Sun.COM (nsc_size_t)BLK_FBAS) ?
5227*9093SRamana.Srikanth@Sun.COM BLK_FBAS : (int)vol_fill;
5228*9093SRamana.Srikanth@Sun.COM /*
5229*9093SRamana.Srikanth@Sun.COM * indicate implicit prefetch
5230*9093SRamana.Srikanth@Sun.COM * and mark for release in
5231*9093SRamana.Srikanth@Sun.COM * _sd_read_complete()
5232*9093SRamana.Srikanth@Sun.COM */
5233*9093SRamana.Srikanth@Sun.COM cc_ra->cc_aging_dm |=
5234*9093SRamana.Srikanth@Sun.COM (PREFETCH_BUF_I |
5235*9093SRamana.Srikanth@Sun.COM PREFETCH_BUF_IR);
5236*9093SRamana.Srikanth@Sun.COM }
5237*9093SRamana.Srikanth@Sun.COM } else {
52387836SJohn.Forte@Sun.COM ++sdbc_ra_none;
5239*9093SRamana.Srikanth@Sun.COM }
52407836SJohn.Forte@Sun.COM }
52417836SJohn.Forte@Sun.COM }
52427836SJohn.Forte@Sun.COM
52437836SJohn.Forte@Sun.COM }
52447836SJohn.Forte@Sun.COM
52457836SJohn.Forte@Sun.COM return (fba_count);
52467836SJohn.Forte@Sun.COM }
52477836SJohn.Forte@Sun.COM
52487836SJohn.Forte@Sun.COM /*
52497836SJohn.Forte@Sun.COM * _sd_doread - Check if blocks in cache. If not completely true, do io.
52507836SJohn.Forte@Sun.COM *
52517836SJohn.Forte@Sun.COM * ARGUMENTS:
52527836SJohn.Forte@Sun.COM * handle - handle allocated earlier on.
52537836SJohn.Forte@Sun.COM * fba_pos - disk block number to read from.
52547836SJohn.Forte@Sun.COM * fba_len - length in fbas.
52557836SJohn.Forte@Sun.COM * flag - flag: (NSC_NOBLOCK for async io)
52567836SJohn.Forte@Sun.COM *
52577836SJohn.Forte@Sun.COM * RETURNS:
52587836SJohn.Forte@Sun.COM * errno if return > 0
52597836SJohn.Forte@Sun.COM * NSC_DONE(from disk), or NSC_PENDING otherwise.
52607836SJohn.Forte@Sun.COM *
52617836SJohn.Forte@Sun.COM * Comments:
52627836SJohn.Forte@Sun.COM * It initiates an io and either blocks waiting for the completion
52637836SJohn.Forte@Sun.COM * or return NSC_PENDING, depending on whether the flag bit
52647836SJohn.Forte@Sun.COM * NSC_NOBLOCK is reset or set.
52657836SJohn.Forte@Sun.COM *
52667836SJohn.Forte@Sun.COM */
52677836SJohn.Forte@Sun.COM
52687836SJohn.Forte@Sun.COM
52697836SJohn.Forte@Sun.COM static int
52707836SJohn.Forte@Sun.COM _sd_doread(_sd_buf_handle_t *handle, _sd_cctl_t *cc_ent, nsc_off_t fba_pos,
52717836SJohn.Forte@Sun.COM nsc_size_t fba_len, int flag)
52727836SJohn.Forte@Sun.COM {
52737836SJohn.Forte@Sun.COM int cd, err;
52747836SJohn.Forte@Sun.COM nsc_size_t fba_orig_len; /* length in FBA's of the original request */
52757836SJohn.Forte@Sun.COM nsc_size_t file_len; /* length in bytes of io to be done */
52767836SJohn.Forte@Sun.COM sdbc_cblk_fba_t st_cblk_len; /* FBA len of starting cache block */
52777836SJohn.Forte@Sun.COM sdbc_cblk_fba_t end_cblk_len; /* FBA len of ending cache block */
52787836SJohn.Forte@Sun.COM sdbc_cblk_fba_t st_cblk_off; /* FBA offset into starting cblock */
52797836SJohn.Forte@Sun.COM int num_bdl;
52807836SJohn.Forte@Sun.COM _sd_cctl_t *cc_temp;
52817836SJohn.Forte@Sun.COM struct buf *bp;
52827836SJohn.Forte@Sun.COM unsigned int want_bits;
52837836SJohn.Forte@Sun.COM void (*fn)(blind_t, nsc_off_t, nsc_size_t, int);
52847836SJohn.Forte@Sun.COM sdbc_cblk_fba_t end_cblk_fill; /* FBA's to fill to end of last block */
52857836SJohn.Forte@Sun.COM nsc_size_t vol_end_fill; /* # of FBA's to fill to end of the volume */
52867836SJohn.Forte@Sun.COM
52877836SJohn.Forte@Sun.COM cd = HANDLE_CD(handle);
52887836SJohn.Forte@Sun.COM SDTRACE(ST_ENTER|SDF_READ, cd, fba_len, fba_pos, flag, 0);
52897836SJohn.Forte@Sun.COM
52907836SJohn.Forte@Sun.COM ASSERT(cd >= 0);
52917836SJohn.Forte@Sun.COM if (_sd_cache_files[cd].cd_info->sh_failed) {
52927836SJohn.Forte@Sun.COM SDTRACE(ST_EXIT|SDF_READ, cd, fba_len, fba_pos, flag, EIO);
52937836SJohn.Forte@Sun.COM return (EIO);
52947836SJohn.Forte@Sun.COM }
52957836SJohn.Forte@Sun.COM
52967836SJohn.Forte@Sun.COM /*
52977836SJohn.Forte@Sun.COM * adjust the position and length so that the entire cache
52987836SJohn.Forte@Sun.COM * block is read in
52997836SJohn.Forte@Sun.COM */
53007836SJohn.Forte@Sun.COM
53017836SJohn.Forte@Sun.COM /* first, adjust to beginning of cache block */
53027836SJohn.Forte@Sun.COM
53037836SJohn.Forte@Sun.COM fba_len += BLK_FBA_OFF(fba_pos); /* add start offset to length */
53047836SJohn.Forte@Sun.COM fba_pos &= ~BLK_FBA_MASK; /* move position back to start of block */
53057836SJohn.Forte@Sun.COM
53067836SJohn.Forte@Sun.COM /* compute fill to end of cache block */
53077836SJohn.Forte@Sun.COM end_cblk_fill = (BLK_FBAS - 1) - ((fba_len - 1) % BLK_FBAS);
53087836SJohn.Forte@Sun.COM vol_end_fill = _sd_cache_files[(cd)].cd_info->sh_filesize -
5309*9093SRamana.Srikanth@Sun.COM (fba_pos + fba_len);
53107836SJohn.Forte@Sun.COM
53117836SJohn.Forte@Sun.COM /* fill to lesser of cache block or end of volume */
53127836SJohn.Forte@Sun.COM fba_len += ((nsc_size_t)end_cblk_fill < vol_end_fill) ? end_cblk_fill :
53137836SJohn.Forte@Sun.COM vol_end_fill;
53147836SJohn.Forte@Sun.COM
5315*9093SRamana.Srikanth@Sun.COM DTRACE_PROBE2(_sd_doread_rfill, nsc_off_t, fba_pos,
5316*9093SRamana.Srikanth@Sun.COM nsc_size_t, fba_len);
53177836SJohn.Forte@Sun.COM
53187836SJohn.Forte@Sun.COM
53197836SJohn.Forte@Sun.COM /* for small reads do 1-block readahead if previous block is in cache */
53207836SJohn.Forte@Sun.COM if (sdbc_prefetch1)
53217836SJohn.Forte@Sun.COM fba_len += sdbc_doread_prefetch(cc_ent, fba_pos, fba_len);
53227836SJohn.Forte@Sun.COM
53237836SJohn.Forte@Sun.COM fba_orig_len = fba_len;
53247836SJohn.Forte@Sun.COM st_cblk_off = BLK_FBA_OFF(fba_pos);
53257836SJohn.Forte@Sun.COM st_cblk_len = BLK_FBAS - st_cblk_off;
53267836SJohn.Forte@Sun.COM if ((nsc_size_t)st_cblk_len >= fba_len) {
53277836SJohn.Forte@Sun.COM end_cblk_len = 0;
53287836SJohn.Forte@Sun.COM st_cblk_len = (sdbc_cblk_fba_t)fba_len;
53297836SJohn.Forte@Sun.COM } else {
53307836SJohn.Forte@Sun.COM end_cblk_len = BLK_FBA_OFF(fba_pos + fba_len);
53317836SJohn.Forte@Sun.COM }
53327836SJohn.Forte@Sun.COM
53337836SJohn.Forte@Sun.COM cc_temp = cc_ent;
53347836SJohn.Forte@Sun.COM num_bdl = 0;
53357836SJohn.Forte@Sun.COM while (cc_temp) {
53367836SJohn.Forte@Sun.COM num_bdl += (SDBC_LOOKUP_IOCOUNT(CENTRY_DIRTY(cc_temp)));
53377836SJohn.Forte@Sun.COM cc_temp = cc_temp->cc_chain;
53387836SJohn.Forte@Sun.COM }
53397836SJohn.Forte@Sun.COM bp = sd_alloc_iob(_sd_cache_files[cd].cd_crdev,
5340*9093SRamana.Srikanth@Sun.COM fba_pos, num_bdl, B_READ);
53417836SJohn.Forte@Sun.COM if (bp == NULL) {
53427836SJohn.Forte@Sun.COM SDTRACE(ST_EXIT|SDF_READ, cd, fba_len, fba_pos, flag, E2BIG);
53437836SJohn.Forte@Sun.COM return (E2BIG);
53447836SJohn.Forte@Sun.COM }
53457836SJohn.Forte@Sun.COM
53467836SJohn.Forte@Sun.COM want_bits = SDBC_GET_BITS(st_cblk_off, st_cblk_len);
53477836SJohn.Forte@Sun.COM if (want_bits & CENTRY_DIRTY(cc_ent))
53487836SJohn.Forte@Sun.COM _sd_ccent_rd(cc_ent, want_bits, bp);
53497836SJohn.Forte@Sun.COM else {
53507836SJohn.Forte@Sun.COM sd_add_fba(bp, &cc_ent->cc_addr, st_cblk_off, st_cblk_len);
53517836SJohn.Forte@Sun.COM }
53527836SJohn.Forte@Sun.COM file_len = FBA_SIZE(st_cblk_len);
53537836SJohn.Forte@Sun.COM cc_ent = cc_ent->cc_chain;
53547836SJohn.Forte@Sun.COM fba_len -= st_cblk_len;
53557836SJohn.Forte@Sun.COM
53567836SJohn.Forte@Sun.COM while (fba_len > (nsc_size_t)end_cblk_len) {
53577836SJohn.Forte@Sun.COM if (CENTRY_DIRTY(cc_ent))
53587836SJohn.Forte@Sun.COM _sd_ccent_rd(cc_ent, (uint_t)BLK_FBA_BITS, bp);
53597836SJohn.Forte@Sun.COM else {
53607836SJohn.Forte@Sun.COM sd_add_fba(bp, &cc_ent->cc_addr, 0, BLK_FBAS);
53617836SJohn.Forte@Sun.COM }
53627836SJohn.Forte@Sun.COM file_len += CACHE_BLOCK_SIZE;
53637836SJohn.Forte@Sun.COM cc_ent = cc_ent->cc_chain;
53647836SJohn.Forte@Sun.COM fba_len -= BLK_FBAS;
53657836SJohn.Forte@Sun.COM }
53667836SJohn.Forte@Sun.COM
53677836SJohn.Forte@Sun.COM if (fba_len) {
53687836SJohn.Forte@Sun.COM want_bits = SDBC_GET_BITS(0, end_cblk_len);
53697836SJohn.Forte@Sun.COM if (want_bits & CENTRY_DIRTY(cc_ent))
53707836SJohn.Forte@Sun.COM _sd_ccent_rd(cc_ent, want_bits, bp);
53717836SJohn.Forte@Sun.COM else {
53727836SJohn.Forte@Sun.COM sd_add_fba(bp, &cc_ent->cc_addr, 0, end_cblk_len);
53737836SJohn.Forte@Sun.COM }
53747836SJohn.Forte@Sun.COM file_len += FBA_SIZE(end_cblk_len);
53757836SJohn.Forte@Sun.COM }
53767836SJohn.Forte@Sun.COM
53777836SJohn.Forte@Sun.COM CACHE_READ_MISS;
53787836SJohn.Forte@Sun.COM FBA_READ_IO_KSTATS(cd, file_len);
53797836SJohn.Forte@Sun.COM
53807836SJohn.Forte@Sun.COM DISK_FBA_READ(cd, FBA_NUM(file_len));
53817836SJohn.Forte@Sun.COM
53827836SJohn.Forte@Sun.COM fn = (handle->bh_flag & NSC_NOBLOCK) ? _sd_async_read_ea : NULL;
53837836SJohn.Forte@Sun.COM err = sd_start_io(bp, _sd_cache_files[cd].cd_strategy, fn, handle);
53847836SJohn.Forte@Sun.COM
53857836SJohn.Forte@Sun.COM if (err != NSC_PENDING) {
53867836SJohn.Forte@Sun.COM _sd_read_complete(handle, fba_pos, fba_orig_len, err);
53877836SJohn.Forte@Sun.COM }
53887836SJohn.Forte@Sun.COM
53897836SJohn.Forte@Sun.COM SDTRACE(ST_EXIT|SDF_READ, cd, fba_orig_len, fba_pos, flag, err);
53907836SJohn.Forte@Sun.COM
53917836SJohn.Forte@Sun.COM return (err);
53927836SJohn.Forte@Sun.COM }
53937836SJohn.Forte@Sun.COM
53947836SJohn.Forte@Sun.COM
53957836SJohn.Forte@Sun.COM
53967836SJohn.Forte@Sun.COM /*
53977836SJohn.Forte@Sun.COM * _sd_read_complete - Do whatever is necessary after a read io is done.
53987836SJohn.Forte@Sun.COM *
53997836SJohn.Forte@Sun.COM * ARGUMENTS:
54007836SJohn.Forte@Sun.COM * handle - handle allocated earlier on.
54017836SJohn.Forte@Sun.COM * fba_pos - disk block number to read from.
54027836SJohn.Forte@Sun.COM * fba_len - length in fbas.
54037836SJohn.Forte@Sun.COM * error - error from io if any.
54047836SJohn.Forte@Sun.COM *
54057836SJohn.Forte@Sun.COM * RETURNS:
54067836SJohn.Forte@Sun.COM * NONE.
54077836SJohn.Forte@Sun.COM *
54087836SJohn.Forte@Sun.COM * Comments:
54097836SJohn.Forte@Sun.COM * This routine marks the cache blocks valid if the io completed
54107836SJohn.Forte@Sun.COM * sucessfully. Called from the async end action as well as after
54117836SJohn.Forte@Sun.COM * a synchrnous read completes.
54127836SJohn.Forte@Sun.COM */
54137836SJohn.Forte@Sun.COM
54147836SJohn.Forte@Sun.COM void
54157836SJohn.Forte@Sun.COM _sd_read_complete(_sd_buf_handle_t *handle, nsc_off_t fba_pos,
54167836SJohn.Forte@Sun.COM nsc_size_t fba_len, int error)
54177836SJohn.Forte@Sun.COM {
54187836SJohn.Forte@Sun.COM sdbc_cblk_fba_t st_cblk_len; /* FBA len of starting cache block */
54197836SJohn.Forte@Sun.COM sdbc_cblk_fba_t end_cblk_len; /* FBA len of ending cache block */
54207836SJohn.Forte@Sun.COM sdbc_cblk_fba_t st_cblk_off; /* FBA offset into starting cblock */
54217836SJohn.Forte@Sun.COM nsc_size_t cur_fba_len; /* length in FBA's */
54227836SJohn.Forte@Sun.COM _sd_cctl_t *cc_iocent;
54237836SJohn.Forte@Sun.COM _sd_cctl_t *first_iocent; /* first buffer when processing prefetch */
54247836SJohn.Forte@Sun.COM
54257836SJohn.Forte@Sun.COM cc_iocent = handle->bh_centry;
54267836SJohn.Forte@Sun.COM
54277836SJohn.Forte@Sun.COM if ((handle->bh_error = error) == 0) {
54287836SJohn.Forte@Sun.COM while (CENTRY_BLK(cc_iocent) != FBA_TO_BLK_NUM(fba_pos))
54297836SJohn.Forte@Sun.COM cc_iocent = cc_iocent->cc_chain;
54307836SJohn.Forte@Sun.COM
54317836SJohn.Forte@Sun.COM cur_fba_len = fba_len;
54327836SJohn.Forte@Sun.COM st_cblk_off = BLK_FBA_OFF(fba_pos);
54337836SJohn.Forte@Sun.COM st_cblk_len = BLK_FBAS - st_cblk_off;
54347836SJohn.Forte@Sun.COM if ((nsc_size_t)st_cblk_len >= fba_len) {
54357836SJohn.Forte@Sun.COM end_cblk_len = 0;
54367836SJohn.Forte@Sun.COM st_cblk_len = (sdbc_cblk_fba_t)fba_len;
54377836SJohn.Forte@Sun.COM } else {
54387836SJohn.Forte@Sun.COM end_cblk_len = BLK_FBA_OFF(fba_pos + fba_len);
54397836SJohn.Forte@Sun.COM }
54407836SJohn.Forte@Sun.COM
54417836SJohn.Forte@Sun.COM SDBC_SET_VALID_BITS(st_cblk_off, st_cblk_len, cc_iocent);
54427836SJohn.Forte@Sun.COM DATA_LOG(SDF_RDIO, cc_iocent, st_cblk_off, st_cblk_len);
54437836SJohn.Forte@Sun.COM
5444*9093SRamana.Srikanth@Sun.COM DTRACE_PROBE4(_sd_read_complete_data1, uint64_t, (uint64_t)
5445*9093SRamana.Srikanth@Sun.COM BLK_TO_FBA_NUM(CENTRY_BLK(cc_iocent)) + st_cblk_off,
5446*9093SRamana.Srikanth@Sun.COM int, st_cblk_len, char *,
5447*9093SRamana.Srikanth@Sun.COM *(int64_t *)(cc_iocent->cc_data + FBA_SIZE(st_cblk_off)),
5448*9093SRamana.Srikanth@Sun.COM char *, *(int64_t *)(cc_iocent->cc_data +
5449*9093SRamana.Srikanth@Sun.COM FBA_SIZE(st_cblk_off + st_cblk_len) - 8));
54507836SJohn.Forte@Sun.COM
54517836SJohn.Forte@Sun.COM
54527836SJohn.Forte@Sun.COM first_iocent = cc_iocent;
54537836SJohn.Forte@Sun.COM cc_iocent = cc_iocent->cc_chain;
54547836SJohn.Forte@Sun.COM cur_fba_len -= st_cblk_len;
54557836SJohn.Forte@Sun.COM
54567836SJohn.Forte@Sun.COM while (cur_fba_len > (nsc_size_t)end_cblk_len) {
54577836SJohn.Forte@Sun.COM SET_FULLY_VALID(cc_iocent);
54587836SJohn.Forte@Sun.COM DATA_LOG(SDF_RDIO, cc_iocent, 0, BLK_FBAS);
54597836SJohn.Forte@Sun.COM
5460*9093SRamana.Srikanth@Sun.COM DTRACE_PROBE4(_sd_read_complete_data2, uint64_t,
5461*9093SRamana.Srikanth@Sun.COM (uint64_t)BLK_TO_FBA_NUM(CENTRY_BLK(cc_iocent)),
5462*9093SRamana.Srikanth@Sun.COM int, BLK_FBAS, char *,
5463*9093SRamana.Srikanth@Sun.COM *(int64_t *)(cc_iocent->cc_data), char *,
5464*9093SRamana.Srikanth@Sun.COM *(int64_t *)(cc_iocent->cc_data +
5465*9093SRamana.Srikanth@Sun.COM FBA_SIZE(BLK_FBAS) - 8));
54667836SJohn.Forte@Sun.COM
54677836SJohn.Forte@Sun.COM /*
54687836SJohn.Forte@Sun.COM * 4755485 release implicit prefetch buffers
54697836SJohn.Forte@Sun.COM *
54707836SJohn.Forte@Sun.COM * the cc_chain of the first buffer must NULL'd
54717836SJohn.Forte@Sun.COM * else _sd_free_buf() will do a double free when
54727836SJohn.Forte@Sun.COM * it traverses the chain.
54737836SJohn.Forte@Sun.COM *
54747836SJohn.Forte@Sun.COM * if a buffer has been marked PREFETCH_BUF_IR then
54757836SJohn.Forte@Sun.COM * it is guaranteed that
54767836SJohn.Forte@Sun.COM * 1. it is the second in a chain of two.
54777836SJohn.Forte@Sun.COM * 2. cur_fba_len is BLK_FBAS.
54787836SJohn.Forte@Sun.COM * 3. end_cblk_len is zero.
54797836SJohn.Forte@Sun.COM *
54807836SJohn.Forte@Sun.COM * because of 1 (and 2) above, we can safely exit the
54817836SJohn.Forte@Sun.COM * while loop via the break statement without
54827836SJohn.Forte@Sun.COM * executing the last two statements. the break
54837836SJohn.Forte@Sun.COM * statement is necessary because it would be unsafe
54847836SJohn.Forte@Sun.COM * to access cc_iocent which could be reallocated
54857836SJohn.Forte@Sun.COM * immediately after the _sd_centry_release().
54867836SJohn.Forte@Sun.COM */
54877836SJohn.Forte@Sun.COM if (cc_iocent->cc_aging_dm & PREFETCH_BUF_IR) {
54887836SJohn.Forte@Sun.COM cc_iocent->cc_aging_dm &= ~(PREFETCH_BUF_IR);
54897836SJohn.Forte@Sun.COM _sd_centry_release(cc_iocent);
54907836SJohn.Forte@Sun.COM first_iocent->cc_chain = NULL;
54917836SJohn.Forte@Sun.COM break;
54927836SJohn.Forte@Sun.COM }
54937836SJohn.Forte@Sun.COM
54947836SJohn.Forte@Sun.COM cc_iocent = cc_iocent->cc_chain;
54957836SJohn.Forte@Sun.COM cur_fba_len -= BLK_FBAS;
54967836SJohn.Forte@Sun.COM }
54977836SJohn.Forte@Sun.COM if (end_cblk_len) {
54987836SJohn.Forte@Sun.COM SDBC_SET_VALID_BITS(0, end_cblk_len, cc_iocent);
54997836SJohn.Forte@Sun.COM DATA_LOG(SDF_RDIO, cc_iocent, 0, end_cblk_len);
55007836SJohn.Forte@Sun.COM
5501*9093SRamana.Srikanth@Sun.COM DTRACE_PROBE4(_sd_read_complete_data3, uint64_t,
5502*9093SRamana.Srikanth@Sun.COM (uint64_t)BLK_TO_FBA_NUM(CENTRY_BLK(cc_iocent)),
5503*9093SRamana.Srikanth@Sun.COM int, end_cblk_len, char *,
5504*9093SRamana.Srikanth@Sun.COM *(int64_t *)(cc_iocent->cc_data), char *,
5505*9093SRamana.Srikanth@Sun.COM *(int64_t *)(cc_iocent->cc_data +
5506*9093SRamana.Srikanth@Sun.COM FBA_SIZE(end_cblk_len) - 8));
55077836SJohn.Forte@Sun.COM }
55087836SJohn.Forte@Sun.COM }
55097836SJohn.Forte@Sun.COM
55107836SJohn.Forte@Sun.COM }
55117836SJohn.Forte@Sun.COM
55127836SJohn.Forte@Sun.COM
55137836SJohn.Forte@Sun.COM /*
55147836SJohn.Forte@Sun.COM * _sd_async_read_ea - End action for async reads.
55157836SJohn.Forte@Sun.COM *
55167836SJohn.Forte@Sun.COM * ARGUMENTS:
55177836SJohn.Forte@Sun.COM * xhandle - handle allocated earlier on (cast to blind_t).
55187836SJohn.Forte@Sun.COM * fba_pos - disk block number read from.
55197836SJohn.Forte@Sun.COM * fba_len - length in fbas.
55207836SJohn.Forte@Sun.COM * error - error from io if any.
55217836SJohn.Forte@Sun.COM *
55227836SJohn.Forte@Sun.COM * RETURNS:
55237836SJohn.Forte@Sun.COM * NONE.
55247836SJohn.Forte@Sun.COM *
55257836SJohn.Forte@Sun.COM * Comments:
55267836SJohn.Forte@Sun.COM * This routine is called at interrupt level when the io is done.
55277836SJohn.Forte@Sun.COM * This is called only when read is asynchronous (NSC_NOBLOCK)
55287836SJohn.Forte@Sun.COM */
55297836SJohn.Forte@Sun.COM
55307836SJohn.Forte@Sun.COM static void
55317836SJohn.Forte@Sun.COM _sd_async_read_ea(blind_t xhandle, nsc_off_t fba_pos, nsc_size_t fba_len,
55327836SJohn.Forte@Sun.COM int error)
55337836SJohn.Forte@Sun.COM {
55347836SJohn.Forte@Sun.COM _sd_buf_handle_t *handle = xhandle;
55357836SJohn.Forte@Sun.COM int cd;
55367836SJohn.Forte@Sun.COM
55377836SJohn.Forte@Sun.COM if (error) {
55387836SJohn.Forte@Sun.COM cd = HANDLE_CD(handle);
55397836SJohn.Forte@Sun.COM ASSERT(cd >= 0);
55407836SJohn.Forte@Sun.COM _sd_cache_files[cd].cd_info->sh_failed = 1;
55417836SJohn.Forte@Sun.COM }
55427836SJohn.Forte@Sun.COM SDTRACE(ST_ENTER|SDF_READ_EA, HANDLE_CD(handle),
5543*9093SRamana.Srikanth@Sun.COM handle->bh_fba_len, handle->bh_fba_pos, 0, error);
55447836SJohn.Forte@Sun.COM
55457836SJohn.Forte@Sun.COM _sd_read_complete(handle, fba_pos, fba_len, error);
55467836SJohn.Forte@Sun.COM
55477836SJohn.Forte@Sun.COM #if defined(_SD_DEBUG_PATTERN)
55487836SJohn.Forte@Sun.COM check_buf_consistency(handle, "rd");
55497836SJohn.Forte@Sun.COM #endif
55507836SJohn.Forte@Sun.COM
55517836SJohn.Forte@Sun.COM SDTRACE(ST_EXIT|SDF_READ_EA, HANDLE_CD(handle),
5552*9093SRamana.Srikanth@Sun.COM handle->bh_fba_len, handle->bh_fba_pos, 0, 0);
55537836SJohn.Forte@Sun.COM _SD_READ_CALLBACK(handle);
55547836SJohn.Forte@Sun.COM }
55557836SJohn.Forte@Sun.COM
55567836SJohn.Forte@Sun.COM
55577836SJohn.Forte@Sun.COM /*
55587836SJohn.Forte@Sun.COM * _sd_async_write_ea - End action for async writes.
55597836SJohn.Forte@Sun.COM *
55607836SJohn.Forte@Sun.COM * ARGUMENTS:
55617836SJohn.Forte@Sun.COM * xhandle - handle allocated earlier on. (cast to blind_t)
55627836SJohn.Forte@Sun.COM * fba_pos - disk block number written to.
55637836SJohn.Forte@Sun.COM * fba_len - length in fbas.
55647836SJohn.Forte@Sun.COM * error - error from io if any.
55657836SJohn.Forte@Sun.COM *
55667836SJohn.Forte@Sun.COM * RETURNS:
55677836SJohn.Forte@Sun.COM * NONE.
55687836SJohn.Forte@Sun.COM *
55697836SJohn.Forte@Sun.COM * Comments:
55707836SJohn.Forte@Sun.COM * This routine is called at interrupt level when the write io is done.
55717836SJohn.Forte@Sun.COM * This is called only when we are in write-through mode and the write
55727836SJohn.Forte@Sun.COM * call indicated asynchronous callback. (NSC_NOBLOCK)
55737836SJohn.Forte@Sun.COM */
55747836SJohn.Forte@Sun.COM
55757836SJohn.Forte@Sun.COM /* ARGSUSED */
55767836SJohn.Forte@Sun.COM
55777836SJohn.Forte@Sun.COM static void
55787836SJohn.Forte@Sun.COM _sd_async_write_ea(blind_t xhandle, nsc_off_t fba_pos, nsc_size_t fba_len,
55797836SJohn.Forte@Sun.COM int error)
55807836SJohn.Forte@Sun.COM {
55817836SJohn.Forte@Sun.COM _sd_buf_handle_t *handle = xhandle;
55827836SJohn.Forte@Sun.COM handle->bh_error = error;
55837836SJohn.Forte@Sun.COM
55847836SJohn.Forte@Sun.COM if (error)
55857836SJohn.Forte@Sun.COM _sd_cache_files[HANDLE_CD(handle)].cd_info->sh_failed = 1;
55867836SJohn.Forte@Sun.COM
55877836SJohn.Forte@Sun.COM _SD_WRITE_CALLBACK(handle);
55887836SJohn.Forte@Sun.COM }
55897836SJohn.Forte@Sun.COM
55907836SJohn.Forte@Sun.COM /*
55917836SJohn.Forte@Sun.COM * update_dirty - set dirty bits in cache block which is already dirty
55927836SJohn.Forte@Sun.COM * cc_inuse is held, need cc_lock to avoid race with _sd_process_pending
55937836SJohn.Forte@Sun.COM * must check for I/O in-progress and set PEND_DIRTY.
55947836SJohn.Forte@Sun.COM * return previous dirty bits
55957836SJohn.Forte@Sun.COM * [if set _sd_process_pending will re-issue]
55967836SJohn.Forte@Sun.COM */
55977836SJohn.Forte@Sun.COM static _sd_bitmap_t
55987836SJohn.Forte@Sun.COM update_dirty(_sd_cctl_t *cc_ent, sdbc_cblk_fba_t st_off, sdbc_cblk_fba_t st_len)
55997836SJohn.Forte@Sun.COM {
56007836SJohn.Forte@Sun.COM _sd_bitmap_t old;
56017836SJohn.Forte@Sun.COM
56027836SJohn.Forte@Sun.COM /* was FAST */
56037836SJohn.Forte@Sun.COM mutex_enter(&cc_ent->cc_lock);
56047836SJohn.Forte@Sun.COM old = CENTRY_DIRTY(cc_ent);
56057836SJohn.Forte@Sun.COM if (old) {
56067836SJohn.Forte@Sun.COM /*
56077836SJohn.Forte@Sun.COM * If we are writing to an FBA that is still marked dirty,
56087836SJohn.Forte@Sun.COM * record a write cancellation.
56097836SJohn.Forte@Sun.COM */
56107836SJohn.Forte@Sun.COM if (old & SDBC_GET_BITS(st_off, st_len)) {
56117836SJohn.Forte@Sun.COM CACHE_WRITE_CANCELLATION(CENTRY_CD(cc_ent));
56127836SJohn.Forte@Sun.COM }
56137836SJohn.Forte@Sun.COM
56147836SJohn.Forte@Sun.COM /* This is a write to a block that was already dirty */
56157836SJohn.Forte@Sun.COM SDBC_SET_DIRTY(st_off, st_len, cc_ent);
56167836SJohn.Forte@Sun.COM sd_serialize();
56177836SJohn.Forte@Sun.COM if (CENTRY_IO_INPROGRESS(cc_ent))
56187836SJohn.Forte@Sun.COM cc_ent->cc_flag |= CC_PEND_DIRTY;
56197836SJohn.Forte@Sun.COM }
56207836SJohn.Forte@Sun.COM /* was FAST */
56217836SJohn.Forte@Sun.COM mutex_exit(&cc_ent->cc_lock);
56227836SJohn.Forte@Sun.COM return (old);
56237836SJohn.Forte@Sun.COM }
56247836SJohn.Forte@Sun.COM
56257836SJohn.Forte@Sun.COM /*
56267836SJohn.Forte@Sun.COM * _sd_write - Interface call to commit part of handle.
56277836SJohn.Forte@Sun.COM *
56287836SJohn.Forte@Sun.COM * ARGUMENTS:
56297836SJohn.Forte@Sun.COM * handle - handle allocated earlier o.
56307836SJohn.Forte@Sun.COM * fba_pos - disk block number to write to.
56317836SJohn.Forte@Sun.COM * fba_len - length in fbas.
56327836SJohn.Forte@Sun.COM * flag - (NSC_NOBLOCK | NSC_WRTHRU)
56337836SJohn.Forte@Sun.COM *
56347836SJohn.Forte@Sun.COM * RETURNS:
56357836SJohn.Forte@Sun.COM * errno if return > 0
56367836SJohn.Forte@Sun.COM * NSC_HIT (in cache), NSC_DONE (to disk) or NSC_PENDING otherwise.
56377836SJohn.Forte@Sun.COM *
56387836SJohn.Forte@Sun.COM * Comments:
56397836SJohn.Forte@Sun.COM * This routine checks validity of the handle and then calls the
56407836SJohn.Forte@Sun.COM * sync-write function if this write is determined to be write-through.
56417836SJohn.Forte@Sun.COM * Else, it reflects the data to the write blocks on the mirror node,
56427836SJohn.Forte@Sun.COM * (allocated in alloc_buf). If the cache block is not dirty, it is
56437836SJohn.Forte@Sun.COM * marked dirty and queued up for io processing later on.
56447836SJohn.Forte@Sun.COM * If parts are already dirty but io is not in progress yet, it is
56457836SJohn.Forte@Sun.COM * marked dirty and left alone (it is already in the queue)
56467836SJohn.Forte@Sun.COM * If parts are already dirty but io is in progress, it is marked
56477836SJohn.Forte@Sun.COM * dirty and also a flag is set indicating that this buffer should
56487836SJohn.Forte@Sun.COM * be reprocessed after the io-end-action.
56497836SJohn.Forte@Sun.COM * Attempt is made to coalesce multiple writes into a single list
56507836SJohn.Forte@Sun.COM * for io processing later on.
56517836SJohn.Forte@Sun.COM *
56527836SJohn.Forte@Sun.COM * Issuing of writes may be delayed until the handle is released;
56537836SJohn.Forte@Sun.COM * _sd_queue_write() sets NSC_QUEUE, indicating that dirty bits
56547836SJohn.Forte@Sun.COM * and reflection to mirror have already been done, just queue I/O.
56557836SJohn.Forte@Sun.COM */
56567836SJohn.Forte@Sun.COM
56577836SJohn.Forte@Sun.COM
56587836SJohn.Forte@Sun.COM
56597836SJohn.Forte@Sun.COM int
56607836SJohn.Forte@Sun.COM _sd_write(_sd_buf_handle_t *handle, nsc_off_t fba_pos, nsc_size_t fba_len,
56617836SJohn.Forte@Sun.COM int flag)
56627836SJohn.Forte@Sun.COM {
56637836SJohn.Forte@Sun.COM int cd = HANDLE_CD(handle);
56647836SJohn.Forte@Sun.COM int num_queued, ret, queue_only, store_only;
56657836SJohn.Forte@Sun.COM sdbc_cblk_fba_t st_cblk_len; /* FBA len of starting cache block */
56667836SJohn.Forte@Sun.COM sdbc_cblk_fba_t end_cblk_len; /* FBA len of ending cache block */
56677836SJohn.Forte@Sun.COM sdbc_cblk_fba_t st_cblk_off; /* FBA offset into starting cblock */
56687836SJohn.Forte@Sun.COM nsc_size_t cur_fba_len; /* position in disk blocks */
56697836SJohn.Forte@Sun.COM _sd_cctl_t *cc_ent = NULL;
56707836SJohn.Forte@Sun.COM _sd_cctl_t *cur_chain = NULL, *dirty_next = NULL;
56717836SJohn.Forte@Sun.COM
56727836SJohn.Forte@Sun.COM
56737836SJohn.Forte@Sun.COM if (_sdbc_shutdown_in_progress) {
56747836SJohn.Forte@Sun.COM ret = EIO;
56757836SJohn.Forte@Sun.COM goto out;
56767836SJohn.Forte@Sun.COM }
56777836SJohn.Forte@Sun.COM
56787836SJohn.Forte@Sun.COM
56797836SJohn.Forte@Sun.COM if (!_SD_HANDLE_ACTIVE(handle)) {
56807836SJohn.Forte@Sun.COM SDALERT(SDF_WRITE,
5681*9093SRamana.Srikanth@Sun.COM SDT_INV_CD, 0, SDT_INV_BL, handle->bh_flag, 0);
56827836SJohn.Forte@Sun.COM ret = EINVAL;
56837836SJohn.Forte@Sun.COM goto out;
56847836SJohn.Forte@Sun.COM }
56857836SJohn.Forte@Sun.COM #if !defined(_SD_NOCHECKS)
56867836SJohn.Forte@Sun.COM ASSERT_HANDLE_LIMITS(handle, fba_pos, fba_len);
56877836SJohn.Forte@Sun.COM if ((handle->bh_flag & NSC_WRBUF) == 0) {
56887836SJohn.Forte@Sun.COM ret = EINVAL;
56897836SJohn.Forte@Sun.COM goto out;
56907836SJohn.Forte@Sun.COM }
56917836SJohn.Forte@Sun.COM #endif
56927836SJohn.Forte@Sun.COM if (fba_len == 0) {
56937836SJohn.Forte@Sun.COM ret = NSC_DONE;
56947836SJohn.Forte@Sun.COM goto out;
56957836SJohn.Forte@Sun.COM }
56967836SJohn.Forte@Sun.COM
56977836SJohn.Forte@Sun.COM /*
56987836SJohn.Forte@Sun.COM * store_only: don't queue this I/O yet
56997836SJohn.Forte@Sun.COM * queue_only: queue I/O to disk, don't store in mirror node
57007836SJohn.Forte@Sun.COM */
57017836SJohn.Forte@Sun.COM if (flag & NSC_QUEUE)
57027836SJohn.Forte@Sun.COM queue_only = 1, store_only = 0;
57037836SJohn.Forte@Sun.COM else
57047836SJohn.Forte@Sun.COM if (_SD_DELAY_QUEUE && (fba_len != handle->bh_fba_len))
57057836SJohn.Forte@Sun.COM queue_only = 0, store_only = 1;
57067836SJohn.Forte@Sun.COM else
57077836SJohn.Forte@Sun.COM queue_only = store_only = 0;
57087836SJohn.Forte@Sun.COM
57097836SJohn.Forte@Sun.COM if (!queue_only && _SD_FORCE_DISCONNECT(fba_len))
57107836SJohn.Forte@Sun.COM _SD_DISCONNECT_CALLBACK(handle);
57117836SJohn.Forte@Sun.COM
57127836SJohn.Forte@Sun.COM if (_sd_cache_files[cd].cd_info->sh_failed) {
57137836SJohn.Forte@Sun.COM ret = EIO;
57147836SJohn.Forte@Sun.COM goto out;
57157836SJohn.Forte@Sun.COM }
57167836SJohn.Forte@Sun.COM
57177836SJohn.Forte@Sun.COM KSTAT_RUNQ_ENTER(cd);
57187836SJohn.Forte@Sun.COM
57197836SJohn.Forte@Sun.COM SDTRACE(ST_ENTER|SDF_WRITE, cd, fba_len, fba_pos, flag, 0);
57207836SJohn.Forte@Sun.COM
57217836SJohn.Forte@Sun.COM #if defined(_SD_DEBUG_PATTERN)
57227836SJohn.Forte@Sun.COM check_buf_consistency(handle, "wr");
57237836SJohn.Forte@Sun.COM #endif
57247836SJohn.Forte@Sun.COM
57257836SJohn.Forte@Sun.COM cc_ent = handle->bh_centry;
57267836SJohn.Forte@Sun.COM
57277836SJohn.Forte@Sun.COM while (CENTRY_BLK(cc_ent) != FBA_TO_BLK_NUM(fba_pos))
57287836SJohn.Forte@Sun.COM cc_ent = cc_ent->cc_chain;
57297836SJohn.Forte@Sun.COM
57307836SJohn.Forte@Sun.COM if (((handle->bh_flag | flag) & _SD_WRTHRU_MASK) ||
57317836SJohn.Forte@Sun.COM (!queue_only && _sd_remote_store(cc_ent, fba_pos, fba_len))) {
57327836SJohn.Forte@Sun.COM flag |= NSC_WRTHRU;
57337836SJohn.Forte@Sun.COM
57347836SJohn.Forte@Sun.COM ret = _sd_sync_write(handle, fba_pos, fba_len, flag);
57357836SJohn.Forte@Sun.COM goto stats_exit;
57367836SJohn.Forte@Sun.COM }
57377836SJohn.Forte@Sun.COM
57387836SJohn.Forte@Sun.COM if (store_only) /* enqueue in _sd_free_buf() */
57397836SJohn.Forte@Sun.COM handle->bh_flag |= NSC_QUEUE;
57407836SJohn.Forte@Sun.COM cur_fba_len = fba_len;
57417836SJohn.Forte@Sun.COM st_cblk_off = BLK_FBA_OFF(fba_pos);
57427836SJohn.Forte@Sun.COM st_cblk_len = BLK_FBAS - st_cblk_off;
57437836SJohn.Forte@Sun.COM if ((nsc_size_t)st_cblk_len >= fba_len) {
57447836SJohn.Forte@Sun.COM end_cblk_len = 0;
57457836SJohn.Forte@Sun.COM st_cblk_len = (sdbc_cblk_fba_t)fba_len;
57467836SJohn.Forte@Sun.COM } else {
57477836SJohn.Forte@Sun.COM end_cblk_len = BLK_FBA_OFF(fba_pos + fba_len);
57487836SJohn.Forte@Sun.COM }
57497836SJohn.Forte@Sun.COM
57507836SJohn.Forte@Sun.COM if (CENTRY_DIRTY(cc_ent) && update_dirty(cc_ent, st_cblk_off,
57517836SJohn.Forte@Sun.COM st_cblk_len))
57527836SJohn.Forte@Sun.COM goto loop1;
57537836SJohn.Forte@Sun.COM if (store_only) {
57547836SJohn.Forte@Sun.COM SDBC_SET_TOFLUSH(st_cblk_off, st_cblk_len, cc_ent);
57557836SJohn.Forte@Sun.COM goto loop1;
57567836SJohn.Forte@Sun.COM }
57577836SJohn.Forte@Sun.COM SDBC_SET_DIRTY(st_cblk_off, st_cblk_len, cc_ent);
57587836SJohn.Forte@Sun.COM cur_chain = dirty_next = cc_ent;
57597836SJohn.Forte@Sun.COM num_queued = 1;
57607836SJohn.Forte@Sun.COM
57617836SJohn.Forte@Sun.COM loop1:
57627836SJohn.Forte@Sun.COM DATA_LOG(SDF_WR, cc_ent, st_cblk_off, st_cblk_len);
57637836SJohn.Forte@Sun.COM
5764*9093SRamana.Srikanth@Sun.COM DTRACE_PROBE4(_sd_write_data1, uint64_t, (uint64_t)
5765*9093SRamana.Srikanth@Sun.COM (BLK_TO_FBA_NUM(CENTRY_BLK(cc_ent)) + st_cblk_off),
5766*9093SRamana.Srikanth@Sun.COM int, st_cblk_len, char *,
5767*9093SRamana.Srikanth@Sun.COM *(int64_t *)(cc_ent->cc_data + FBA_SIZE(st_cblk_off)),
5768*9093SRamana.Srikanth@Sun.COM char *, *(int64_t *)(cc_ent->cc_data +
5769*9093SRamana.Srikanth@Sun.COM FBA_SIZE(st_cblk_off+ st_cblk_len) - 8));
57707836SJohn.Forte@Sun.COM
57717836SJohn.Forte@Sun.COM cur_fba_len -= st_cblk_len;
57727836SJohn.Forte@Sun.COM cc_ent = cc_ent->cc_chain;
57737836SJohn.Forte@Sun.COM
57747836SJohn.Forte@Sun.COM while (cur_fba_len > (nsc_size_t)end_cblk_len) {
57757836SJohn.Forte@Sun.COM if (CENTRY_DIRTY(cc_ent) && update_dirty(cc_ent, 0, BLK_FBAS)) {
57767836SJohn.Forte@Sun.COM if (cur_chain) {
57777836SJohn.Forte@Sun.COM _sd_enqueue_dirty(cd, cur_chain, dirty_next,
5778*9093SRamana.Srikanth@Sun.COM num_queued);
57797836SJohn.Forte@Sun.COM cur_chain = dirty_next = NULL;
57807836SJohn.Forte@Sun.COM }
57817836SJohn.Forte@Sun.COM goto loop2;
57827836SJohn.Forte@Sun.COM }
57837836SJohn.Forte@Sun.COM if (store_only) {
57847836SJohn.Forte@Sun.COM SDBC_SET_TOFLUSH(0, BLK_FBAS, cc_ent);
57857836SJohn.Forte@Sun.COM goto loop2;
57867836SJohn.Forte@Sun.COM }
57877836SJohn.Forte@Sun.COM SDBC_SET_DIRTY(0, BLK_FBAS, cc_ent);
57887836SJohn.Forte@Sun.COM if (dirty_next) {
57897836SJohn.Forte@Sun.COM dirty_next->cc_dirty_next = cc_ent;
57907836SJohn.Forte@Sun.COM dirty_next = cc_ent;
57917836SJohn.Forte@Sun.COM num_queued++;
57927836SJohn.Forte@Sun.COM } else {
57937836SJohn.Forte@Sun.COM cur_chain = dirty_next = cc_ent;
57947836SJohn.Forte@Sun.COM num_queued = 1;
57957836SJohn.Forte@Sun.COM }
57967836SJohn.Forte@Sun.COM loop2:
57977836SJohn.Forte@Sun.COM DATA_LOG(SDF_WR, cc_ent, 0, BLK_FBAS);
57987836SJohn.Forte@Sun.COM
5799*9093SRamana.Srikanth@Sun.COM DTRACE_PROBE4(_sd_write_data2, uint64_t,
5800*9093SRamana.Srikanth@Sun.COM (uint64_t)(BLK_TO_FBA_NUM(CENTRY_BLK(cc_ent))),
5801*9093SRamana.Srikanth@Sun.COM int, BLK_FBAS, char *, *(int64_t *)(cc_ent->cc_data),
5802*9093SRamana.Srikanth@Sun.COM char *, *(int64_t *)(cc_ent->cc_data +
5803*9093SRamana.Srikanth@Sun.COM FBA_SIZE(BLK_FBAS) - 8));
58047836SJohn.Forte@Sun.COM
58057836SJohn.Forte@Sun.COM cc_ent = cc_ent->cc_chain;
58067836SJohn.Forte@Sun.COM cur_fba_len -= BLK_FBAS;
58077836SJohn.Forte@Sun.COM }
58087836SJohn.Forte@Sun.COM
58097836SJohn.Forte@Sun.COM #if defined(_SD_DEBUG)
58107836SJohn.Forte@Sun.COM if (cur_fba_len != end_cblk_len)
5811*9093SRamana.Srikanth@Sun.COM cmn_err(CE_WARN, "!fba_len %" NSC_SZFMT " end_cblk_len %d in "
58127836SJohn.Forte@Sun.COM "_sd_write", cur_fba_len, end_cblk_len);
58137836SJohn.Forte@Sun.COM #endif
58147836SJohn.Forte@Sun.COM
58157836SJohn.Forte@Sun.COM if (cur_fba_len) {
58167836SJohn.Forte@Sun.COM if (CENTRY_DIRTY(cc_ent) && update_dirty(cc_ent, 0,
58177836SJohn.Forte@Sun.COM end_cblk_len)) {
58187836SJohn.Forte@Sun.COM if (cur_chain) {
58197836SJohn.Forte@Sun.COM _sd_enqueue_dirty(cd, cur_chain, dirty_next,
5820*9093SRamana.Srikanth@Sun.COM num_queued);
58217836SJohn.Forte@Sun.COM cur_chain = dirty_next = NULL;
58227836SJohn.Forte@Sun.COM }
58237836SJohn.Forte@Sun.COM goto loop3;
58247836SJohn.Forte@Sun.COM }
58257836SJohn.Forte@Sun.COM if (store_only) {
58267836SJohn.Forte@Sun.COM SDBC_SET_TOFLUSH(0, end_cblk_len, cc_ent);
58277836SJohn.Forte@Sun.COM goto loop3;
58287836SJohn.Forte@Sun.COM }
58297836SJohn.Forte@Sun.COM SDBC_SET_DIRTY(0, end_cblk_len, cc_ent);
58307836SJohn.Forte@Sun.COM if (dirty_next) {
58317836SJohn.Forte@Sun.COM dirty_next->cc_dirty_next = cc_ent;
58327836SJohn.Forte@Sun.COM dirty_next = cc_ent;
58337836SJohn.Forte@Sun.COM num_queued++;
58347836SJohn.Forte@Sun.COM } else {
58357836SJohn.Forte@Sun.COM cur_chain = dirty_next = cc_ent;
58367836SJohn.Forte@Sun.COM num_queued = 1;
58377836SJohn.Forte@Sun.COM }
58387836SJohn.Forte@Sun.COM }
58397836SJohn.Forte@Sun.COM loop3:
58407836SJohn.Forte@Sun.COM if (cur_fba_len) {
58417836SJohn.Forte@Sun.COM DATA_LOG(SDF_WR, cc_ent, 0, end_cblk_len);
58427836SJohn.Forte@Sun.COM
5843*9093SRamana.Srikanth@Sun.COM DTRACE_PROBE4(_sd_write_data3, uint64_t,
5844*9093SRamana.Srikanth@Sun.COM (uint64_t)(BLK_TO_FBA_NUM(CENTRY_BLK(cc_ent))),
5845*9093SRamana.Srikanth@Sun.COM int, end_cblk_len, char *, *(int64_t *)(cc_ent->cc_data),
5846*9093SRamana.Srikanth@Sun.COM char *, *(int64_t *)(cc_ent->cc_data +
5847*9093SRamana.Srikanth@Sun.COM FBA_SIZE(end_cblk_len) - 8));
58487836SJohn.Forte@Sun.COM
58497836SJohn.Forte@Sun.COM }
58507836SJohn.Forte@Sun.COM
58517836SJohn.Forte@Sun.COM if (!store_only && cur_chain) {
58527836SJohn.Forte@Sun.COM _sd_enqueue_dirty(cd, cur_chain, dirty_next, num_queued);
58537836SJohn.Forte@Sun.COM }
58547836SJohn.Forte@Sun.COM
58557836SJohn.Forte@Sun.COM if (!queue_only) {
58567836SJohn.Forte@Sun.COM CACHE_FBA_WRITE(cd, fba_len);
58577836SJohn.Forte@Sun.COM CACHE_WRITE_HIT;
58587836SJohn.Forte@Sun.COM
58597836SJohn.Forte@Sun.COM FBA_WRITE_IO_KSTATS(cd, FBA_SIZE(fba_len));
58607836SJohn.Forte@Sun.COM }
58617836SJohn.Forte@Sun.COM
58627836SJohn.Forte@Sun.COM ret = NSC_HIT;
58637836SJohn.Forte@Sun.COM
58647836SJohn.Forte@Sun.COM stats_exit:
58657836SJohn.Forte@Sun.COM SDTRACE(ST_EXIT|SDF_WRITE, cd, fba_len, fba_pos, flag, ret);
58667836SJohn.Forte@Sun.COM KSTAT_RUNQ_EXIT(cd);
58677836SJohn.Forte@Sun.COM out:
58687836SJohn.Forte@Sun.COM return (ret);
58697836SJohn.Forte@Sun.COM }
58707836SJohn.Forte@Sun.COM
58717836SJohn.Forte@Sun.COM
58727836SJohn.Forte@Sun.COM /*
58737836SJohn.Forte@Sun.COM * _sd_queue_write(handle, fba_pos, fba_len): Queues delayed writes for
58747836SJohn.Forte@Sun.COM * flushing
58757836SJohn.Forte@Sun.COM *
58767836SJohn.Forte@Sun.COM * ARGUMENTS: handle - handle allocated with NSC_WRBUF
58777836SJohn.Forte@Sun.COM * fba_pos - starting fba pos from _sd_alloc_buf()
58787836SJohn.Forte@Sun.COM * fba_len - fba len from _sd_alloc_buf()
58797836SJohn.Forte@Sun.COM *
58807836SJohn.Forte@Sun.COM * USAGE : Called if _SD_DELAY_QUEUE is set. Finds all blocks in the
58817836SJohn.Forte@Sun.COM * handle marked for flushing and queues them to be written in
58827836SJohn.Forte@Sun.COM * optimized (i.e. sequential) order
58837836SJohn.Forte@Sun.COM */
58847836SJohn.Forte@Sun.COM static void
58857836SJohn.Forte@Sun.COM _sd_queue_write(_sd_buf_handle_t *handle, nsc_off_t fba_pos, nsc_size_t fba_len)
58867836SJohn.Forte@Sun.COM {
58877836SJohn.Forte@Sun.COM nsc_off_t fba_end;
58887836SJohn.Forte@Sun.COM sdbc_cblk_fba_t sblk, len, dirty;
58897836SJohn.Forte@Sun.COM _sd_cctl_t *cc_ent;
58907836SJohn.Forte@Sun.COM nsc_off_t flush_pos;
58917836SJohn.Forte@Sun.COM int flush_pos_valid = 0;
58927836SJohn.Forte@Sun.COM nsc_size_t flush_len = 0;
58937836SJohn.Forte@Sun.COM
58947836SJohn.Forte@Sun.COM cc_ent = handle->bh_centry;
58957836SJohn.Forte@Sun.COM fba_end = fba_pos + fba_len;
58967836SJohn.Forte@Sun.COM fba_pos = BLK_TO_FBA_NUM(CENTRY_BLK(cc_ent)); /* 1st block */
58977836SJohn.Forte@Sun.COM while (fba_pos < fba_end) {
58987836SJohn.Forte@Sun.COM dirty = cc_ent->cc_toflush;
58997836SJohn.Forte@Sun.COM cc_ent->cc_toflush = 0;
59007836SJohn.Forte@Sun.COM /*
59017836SJohn.Forte@Sun.COM * Full block
59027836SJohn.Forte@Sun.COM */
59037836SJohn.Forte@Sun.COM if (_SD_BMAP_ISFULL(dirty)) {
59047836SJohn.Forte@Sun.COM if (flush_pos_valid == 0) {
59057836SJohn.Forte@Sun.COM flush_pos_valid = 1;
59067836SJohn.Forte@Sun.COM flush_pos = fba_pos;
59077836SJohn.Forte@Sun.COM }
59087836SJohn.Forte@Sun.COM flush_len += BLK_FBAS;
59097836SJohn.Forte@Sun.COM }
59107836SJohn.Forte@Sun.COM /*
59117836SJohn.Forte@Sun.COM * Partial block
59127836SJohn.Forte@Sun.COM */
59137836SJohn.Forte@Sun.COM else while (dirty) {
59147836SJohn.Forte@Sun.COM sblk = SDBC_LOOKUP_STPOS(dirty);
59157836SJohn.Forte@Sun.COM len = SDBC_LOOKUP_LEN(dirty);
59167836SJohn.Forte@Sun.COM SDBC_LOOKUP_MODIFY(dirty);
59177836SJohn.Forte@Sun.COM
59187836SJohn.Forte@Sun.COM if (sblk && flush_pos_valid) {
59197836SJohn.Forte@Sun.COM (void) _sd_write(handle, flush_pos, flush_len,
5920*9093SRamana.Srikanth@Sun.COM NSC_QUEUE);
59217836SJohn.Forte@Sun.COM flush_pos_valid = 0;
59227836SJohn.Forte@Sun.COM flush_len = 0;
59237836SJohn.Forte@Sun.COM }
59247836SJohn.Forte@Sun.COM if (flush_pos_valid == 0) {
59257836SJohn.Forte@Sun.COM flush_pos_valid = 1;
59267836SJohn.Forte@Sun.COM flush_pos = fba_pos + sblk;
59277836SJohn.Forte@Sun.COM }
59287836SJohn.Forte@Sun.COM flush_len += len;
59297836SJohn.Forte@Sun.COM }
59307836SJohn.Forte@Sun.COM fba_pos += BLK_FBAS;
59317836SJohn.Forte@Sun.COM cc_ent = cc_ent->cc_chain;
59327836SJohn.Forte@Sun.COM /*
59337836SJohn.Forte@Sun.COM * If we find a gap, write out what we've got
59347836SJohn.Forte@Sun.COM */
59357836SJohn.Forte@Sun.COM if (flush_pos_valid && (flush_pos + flush_len) != fba_pos) {
59367836SJohn.Forte@Sun.COM (void) _sd_write(handle, flush_pos, flush_len,
59377836SJohn.Forte@Sun.COM NSC_QUEUE);
59387836SJohn.Forte@Sun.COM flush_pos_valid = 0;
59397836SJohn.Forte@Sun.COM flush_len = 0;
59407836SJohn.Forte@Sun.COM }
59417836SJohn.Forte@Sun.COM }
59427836SJohn.Forte@Sun.COM if (flush_pos_valid)
59437836SJohn.Forte@Sun.COM (void) _sd_write(handle, flush_pos, flush_len, NSC_QUEUE);
59447836SJohn.Forte@Sun.COM }
59457836SJohn.Forte@Sun.COM
59467836SJohn.Forte@Sun.COM
59477836SJohn.Forte@Sun.COM static int
59487836SJohn.Forte@Sun.COM _sd_remote_store(_sd_cctl_t *cc_ent, nsc_off_t fba_pos, nsc_size_t fba_len)
59497836SJohn.Forte@Sun.COM {
59507836SJohn.Forte@Sun.COM sdbc_cblk_fba_t st_cblk_len; /* FBA len of starting cache block */
59517836SJohn.Forte@Sun.COM sdbc_cblk_fba_t end_cblk_len; /* FBA len of ending cache block */
59527836SJohn.Forte@Sun.COM sdbc_cblk_fba_t st_cblk_off; /* FBA offset into starting cblock */
59537836SJohn.Forte@Sun.COM ss_resource_t *ss_res;
59547836SJohn.Forte@Sun.COM
59557836SJohn.Forte@Sun.COM if (_sd_nodes_configured <= 2 && _sd_is_mirror_down())
59567836SJohn.Forte@Sun.COM return (0);
59577836SJohn.Forte@Sun.COM st_cblk_off = BLK_FBA_OFF(fba_pos);
59587836SJohn.Forte@Sun.COM st_cblk_len = BLK_FBAS - st_cblk_off;
59597836SJohn.Forte@Sun.COM if ((nsc_size_t)st_cblk_len >= fba_len) {
59607836SJohn.Forte@Sun.COM end_cblk_len = 0;
59617836SJohn.Forte@Sun.COM st_cblk_len = (sdbc_cblk_fba_t)fba_len;
59627836SJohn.Forte@Sun.COM } else {
59637836SJohn.Forte@Sun.COM end_cblk_len = BLK_FBA_OFF(fba_pos + fba_len);
59647836SJohn.Forte@Sun.COM }
59657836SJohn.Forte@Sun.COM
59667836SJohn.Forte@Sun.COM fba_len -= st_cblk_len;
59677836SJohn.Forte@Sun.COM
59687836SJohn.Forte@Sun.COM ss_res = cc_ent->cc_write->sc_res;
59697836SJohn.Forte@Sun.COM if (SSOP_WRITE_CBLOCK(sdbc_safestore, ss_res,
5970*9093SRamana.Srikanth@Sun.COM cc_ent->cc_data + FBA_SIZE(st_cblk_off), FBA_SIZE(st_cblk_len),
5971*9093SRamana.Srikanth@Sun.COM FBA_SIZE(st_cblk_off))) {
59727836SJohn.Forte@Sun.COM
59737836SJohn.Forte@Sun.COM cmn_err(CE_WARN,
5974*9093SRamana.Srikanth@Sun.COM "!sdbc(_sd_write) safe store failed. Going synchronous");
59757836SJohn.Forte@Sun.COM SDTRACE(SDF_REFLECT, CENTRY_CD(cc_ent), fba_len,
5976*9093SRamana.Srikanth@Sun.COM fba_pos, 0, -1);
59777836SJohn.Forte@Sun.COM return (-1);
59787836SJohn.Forte@Sun.COM }
59797836SJohn.Forte@Sun.COM
59807836SJohn.Forte@Sun.COM cc_ent = cc_ent->cc_chain;
59817836SJohn.Forte@Sun.COM while (fba_len > (nsc_size_t)end_cblk_len) {
59827836SJohn.Forte@Sun.COM fba_len -= BLK_FBAS;
59837836SJohn.Forte@Sun.COM
5984*9093SRamana.Srikanth@Sun.COM if (SSOP_WRITE_CBLOCK(sdbc_safestore, ss_res, cc_ent->cc_data,
5985*9093SRamana.Srikanth@Sun.COM CACHE_BLOCK_SIZE, 0)) {
5986*9093SRamana.Srikanth@Sun.COM
5987*9093SRamana.Srikanth@Sun.COM cmn_err(CE_WARN, "!sdbc(_sd_write) safe store failed. "
59887836SJohn.Forte@Sun.COM "Going synchronous");
59897836SJohn.Forte@Sun.COM SDTRACE(SDF_REFLECT, CENTRY_CD(cc_ent), fba_len,
5990*9093SRamana.Srikanth@Sun.COM fba_pos, 0, -1);
59917836SJohn.Forte@Sun.COM return (-1);
59927836SJohn.Forte@Sun.COM }
59937836SJohn.Forte@Sun.COM
59947836SJohn.Forte@Sun.COM cc_ent = cc_ent->cc_chain;
59957836SJohn.Forte@Sun.COM } /* end while */
59967836SJohn.Forte@Sun.COM
59977836SJohn.Forte@Sun.COM if (fba_len) {
59987836SJohn.Forte@Sun.COM if (SSOP_WRITE_CBLOCK(sdbc_safestore, ss_res,
5999*9093SRamana.Srikanth@Sun.COM cc_ent->cc_data, FBA_SIZE(end_cblk_len), 0)) {
6000*9093SRamana.Srikanth@Sun.COM
6001*9093SRamana.Srikanth@Sun.COM cmn_err(CE_WARN, "!sdbc(_sd_write) nvmem dma failed. "
60027836SJohn.Forte@Sun.COM "Going synchronous");
60037836SJohn.Forte@Sun.COM SDTRACE(SDF_REFLECT, CENTRY_CD(cc_ent), fba_len,
6004*9093SRamana.Srikanth@Sun.COM fba_pos, 0, -1);
60057836SJohn.Forte@Sun.COM return (-1);
60067836SJohn.Forte@Sun.COM }
60077836SJohn.Forte@Sun.COM }
60087836SJohn.Forte@Sun.COM return (0);
60097836SJohn.Forte@Sun.COM }
60107836SJohn.Forte@Sun.COM
60117836SJohn.Forte@Sun.COM
60127836SJohn.Forte@Sun.COM /*
60137836SJohn.Forte@Sun.COM * _sd_sync_write2 - Write-through function.
60147836SJohn.Forte@Sun.COM *
60157836SJohn.Forte@Sun.COM * ARGUMENTS:
60167836SJohn.Forte@Sun.COM * wr_handle - handle into which to write the data.
60177836SJohn.Forte@Sun.COM * wr_st_pos - starting FBA position in wr_handle.
60187836SJohn.Forte@Sun.COM * fba_len - length in fbas.
60197836SJohn.Forte@Sun.COM * flag - NSC_NOBLOCK for async io.
60207836SJohn.Forte@Sun.COM * rd_handle - handle from which to read the data, or NULL.
60217836SJohn.Forte@Sun.COM * rd_st_pos - starting FBA position in rd_handle.
60227836SJohn.Forte@Sun.COM *
60237836SJohn.Forte@Sun.COM * RETURNS:
60247836SJohn.Forte@Sun.COM * errno if return > 0
60257836SJohn.Forte@Sun.COM * NSC_DONE or NSC_PENDING otherwise.
60267836SJohn.Forte@Sun.COM *
60277836SJohn.Forte@Sun.COM * Comments:
60287836SJohn.Forte@Sun.COM * This routine initiates io of the indicated portion. It returns
60297836SJohn.Forte@Sun.COM * synchronously after io is completed if NSC_NOBLOCK is not set.
60307836SJohn.Forte@Sun.COM * Else NSC_PENDING is returned with a subsequent write callback on
60317836SJohn.Forte@Sun.COM * io completion.
60327836SJohn.Forte@Sun.COM *
60337836SJohn.Forte@Sun.COM * See _sd_copy_direct() for usage when
60347836SJohn.Forte@Sun.COM * (wr_handle != rd_handle && rd_handle != NULL)
60357836SJohn.Forte@Sun.COM */
60367836SJohn.Forte@Sun.COM
60377836SJohn.Forte@Sun.COM static int
60387836SJohn.Forte@Sun.COM _sd_sync_write2(_sd_buf_handle_t *wr_handle, nsc_off_t wr_st_pos,
60397836SJohn.Forte@Sun.COM nsc_size_t fba_len, int flag, _sd_buf_handle_t *rd_handle,
60407836SJohn.Forte@Sun.COM nsc_off_t rd_st_pos)
60417836SJohn.Forte@Sun.COM {
60427836SJohn.Forte@Sun.COM void (*fn)(blind_t, nsc_off_t, nsc_size_t, int);
60437836SJohn.Forte@Sun.COM _sd_cctl_t *wr_ent, *rd_ent;
60447836SJohn.Forte@Sun.COM nsc_size_t this_len;
60457836SJohn.Forte@Sun.COM nsc_off_t rd_pos, wr_pos;
60467836SJohn.Forte@Sun.COM nsc_size_t log_bytes;
60477836SJohn.Forte@Sun.COM int cd = HANDLE_CD(wr_handle);
60487836SJohn.Forte@Sun.COM int err;
60497836SJohn.Forte@Sun.COM uint_t dirty;
60507836SJohn.Forte@Sun.COM struct buf *bp;
60517836SJohn.Forte@Sun.COM
60527836SJohn.Forte@Sun.COM LINTUSED(flag);
60537836SJohn.Forte@Sun.COM
60547836SJohn.Forte@Sun.COM _SD_DISCONNECT_CALLBACK(wr_handle);
60557836SJohn.Forte@Sun.COM
60567836SJohn.Forte@Sun.COM if (rd_handle == NULL) {
60577836SJohn.Forte@Sun.COM rd_handle = wr_handle;
60587836SJohn.Forte@Sun.COM rd_st_pos = wr_st_pos;
60597836SJohn.Forte@Sun.COM }
60607836SJohn.Forte@Sun.COM
60617836SJohn.Forte@Sun.COM wr_ent = wr_handle->bh_centry;
60627836SJohn.Forte@Sun.COM while (CENTRY_BLK(wr_ent) != FBA_TO_BLK_NUM(wr_st_pos))
60637836SJohn.Forte@Sun.COM wr_ent = wr_ent->cc_chain;
60647836SJohn.Forte@Sun.COM
60657836SJohn.Forte@Sun.COM rd_ent = rd_handle->bh_centry;
60667836SJohn.Forte@Sun.COM while (CENTRY_BLK(rd_ent) != FBA_TO_BLK_NUM(rd_st_pos))
60677836SJohn.Forte@Sun.COM rd_ent = rd_ent->cc_chain;
60687836SJohn.Forte@Sun.COM
60697836SJohn.Forte@Sun.COM bp = sd_alloc_iob(_sd_cache_files[cd].cd_crdev,
60707836SJohn.Forte@Sun.COM wr_st_pos, FBA_TO_BLK_LEN(fba_len) + 2, B_WRITE);
60717836SJohn.Forte@Sun.COM
60727836SJohn.Forte@Sun.COM if (bp == NULL)
60737836SJohn.Forte@Sun.COM return (E2BIG);
60747836SJohn.Forte@Sun.COM
60757836SJohn.Forte@Sun.COM wr_pos = BLK_FBA_OFF(wr_st_pos);
60767836SJohn.Forte@Sun.COM rd_pos = BLK_FBA_OFF(rd_st_pos);
60777836SJohn.Forte@Sun.COM log_bytes = 0;
60787836SJohn.Forte@Sun.COM
60797836SJohn.Forte@Sun.COM do {
60807836SJohn.Forte@Sun.COM this_len = min((BLK_FBAS - rd_pos), (BLK_FBAS - wr_pos));
60817836SJohn.Forte@Sun.COM
60827836SJohn.Forte@Sun.COM if (this_len > fba_len)
60837836SJohn.Forte@Sun.COM this_len = fba_len;
60847836SJohn.Forte@Sun.COM
60857836SJohn.Forte@Sun.COM /*
60867836SJohn.Forte@Sun.COM * clear dirty bits in the write handle.
60877836SJohn.Forte@Sun.COM */
60887836SJohn.Forte@Sun.COM
60897836SJohn.Forte@Sun.COM if (CENTRY_DIRTY(wr_ent)) {
60907836SJohn.Forte@Sun.COM mutex_enter(&wr_ent->cc_lock);
60917836SJohn.Forte@Sun.COM
60927836SJohn.Forte@Sun.COM if (CENTRY_DIRTY(wr_ent)) {
60937836SJohn.Forte@Sun.COM if (this_len == (nsc_size_t)BLK_FBAS ||
60947836SJohn.Forte@Sun.COM rd_handle != wr_handle) {
60957836SJohn.Forte@Sun.COM /*
60967836SJohn.Forte@Sun.COM * optimization for when we have a
60977836SJohn.Forte@Sun.COM * full cache block, or are doing
60987836SJohn.Forte@Sun.COM * copy_direct (see below).
60997836SJohn.Forte@Sun.COM */
61007836SJohn.Forte@Sun.COM
61017836SJohn.Forte@Sun.COM wr_ent->cc_write->sc_dirty = 0;
61027836SJohn.Forte@Sun.COM } else {
61037836SJohn.Forte@Sun.COM dirty = wr_ent->cc_write->sc_dirty;
61047836SJohn.Forte@Sun.COM dirty &= ~(SDBC_GET_BITS(
61057836SJohn.Forte@Sun.COM wr_pos, this_len));
61067836SJohn.Forte@Sun.COM wr_ent->cc_write->sc_dirty = dirty;
61077836SJohn.Forte@Sun.COM }
61087836SJohn.Forte@Sun.COM
61097836SJohn.Forte@Sun.COM SSOP_SETCENTRY(sdbc_safestore,
6110*9093SRamana.Srikanth@Sun.COM wr_ent->cc_write);
61117836SJohn.Forte@Sun.COM }
61127836SJohn.Forte@Sun.COM
61137836SJohn.Forte@Sun.COM mutex_exit(&wr_ent->cc_lock);
61147836SJohn.Forte@Sun.COM }
61157836SJohn.Forte@Sun.COM
61167836SJohn.Forte@Sun.COM /*
61177836SJohn.Forte@Sun.COM * update valid bits in the write handle.
61187836SJohn.Forte@Sun.COM */
61197836SJohn.Forte@Sun.COM
61207836SJohn.Forte@Sun.COM if (rd_handle == wr_handle) {
61217836SJohn.Forte@Sun.COM if (this_len == (nsc_size_t)BLK_FBAS) {
61227836SJohn.Forte@Sun.COM SET_FULLY_VALID(wr_ent);
61237836SJohn.Forte@Sun.COM } else {
61247836SJohn.Forte@Sun.COM SDBC_SET_VALID_BITS(wr_pos, this_len, wr_ent);
61257836SJohn.Forte@Sun.COM }
61267836SJohn.Forte@Sun.COM } else {
61277836SJohn.Forte@Sun.COM /*
61287836SJohn.Forte@Sun.COM * doing copy_direct, so mark the write handle
61297836SJohn.Forte@Sun.COM * as invalid since the data is on disk, but not
61307836SJohn.Forte@Sun.COM * in cache.
61317836SJohn.Forte@Sun.COM */
61327836SJohn.Forte@Sun.COM wr_ent->cc_valid = 0;
61337836SJohn.Forte@Sun.COM }
61347836SJohn.Forte@Sun.COM
61357836SJohn.Forte@Sun.COM DATA_LOG(SDF_WRSYNC, rd_ent, rd_pos, this_len);
61367836SJohn.Forte@Sun.COM
6137*9093SRamana.Srikanth@Sun.COM DTRACE_PROBE4(_sd_sync_write2_data, uint64_t,
6138*9093SRamana.Srikanth@Sun.COM (uint64_t)BLK_TO_FBA_NUM(CENTRY_BLK(rd_ent)) + rd_pos,
6139*9093SRamana.Srikanth@Sun.COM uint64_t, (uint64_t)this_len, char *,
6140*9093SRamana.Srikanth@Sun.COM *(int64_t *)(rd_ent->cc_data + FBA_SIZE(rd_pos)),
6141*9093SRamana.Srikanth@Sun.COM char *, *(int64_t *)(rd_ent->cc_data +
6142*9093SRamana.Srikanth@Sun.COM FBA_SIZE(rd_pos + this_len) - 8));
61437836SJohn.Forte@Sun.COM
61447836SJohn.Forte@Sun.COM sd_add_fba(bp, &rd_ent->cc_addr, rd_pos, this_len);
61457836SJohn.Forte@Sun.COM
61467836SJohn.Forte@Sun.COM log_bytes += FBA_SIZE(this_len);
61477836SJohn.Forte@Sun.COM fba_len -= this_len;
61487836SJohn.Forte@Sun.COM
61497836SJohn.Forte@Sun.COM wr_pos += this_len;
61507836SJohn.Forte@Sun.COM if (wr_pos >= (nsc_size_t)BLK_FBAS) {
61517836SJohn.Forte@Sun.COM wr_ent = wr_ent->cc_chain;
61527836SJohn.Forte@Sun.COM wr_pos = 0;
61537836SJohn.Forte@Sun.COM }
61547836SJohn.Forte@Sun.COM
61557836SJohn.Forte@Sun.COM rd_pos += this_len;
61567836SJohn.Forte@Sun.COM if (rd_pos >= (nsc_size_t)BLK_FBAS) {
61577836SJohn.Forte@Sun.COM rd_ent = rd_ent->cc_chain;
61587836SJohn.Forte@Sun.COM rd_pos = 0;
61597836SJohn.Forte@Sun.COM }
61607836SJohn.Forte@Sun.COM
61617836SJohn.Forte@Sun.COM } while (fba_len > 0);
61627836SJohn.Forte@Sun.COM
61637836SJohn.Forte@Sun.COM DISK_FBA_WRITE(cd, FBA_NUM(log_bytes));
61647836SJohn.Forte@Sun.COM CACHE_WRITE_MISS;
61657836SJohn.Forte@Sun.COM
61667836SJohn.Forte@Sun.COM FBA_WRITE_IO_KSTATS(cd, log_bytes);
61677836SJohn.Forte@Sun.COM
61687836SJohn.Forte@Sun.COM fn = (wr_handle->bh_flag & NSC_NOBLOCK) ? _sd_async_write_ea : NULL;
61697836SJohn.Forte@Sun.COM
61707836SJohn.Forte@Sun.COM err = sd_start_io(bp, _sd_cache_files[cd].cd_strategy, fn, wr_handle);
61717836SJohn.Forte@Sun.COM
61727836SJohn.Forte@Sun.COM if (err != NSC_PENDING) {
61737836SJohn.Forte@Sun.COM DATA_LOG_CHAIN(SDF_WRSYEA, wr_handle->bh_centry,
61747836SJohn.Forte@Sun.COM wr_st_pos, FBA_NUM(log_bytes));
61757836SJohn.Forte@Sun.COM }
61767836SJohn.Forte@Sun.COM
61777836SJohn.Forte@Sun.COM return (err);
61787836SJohn.Forte@Sun.COM }
61797836SJohn.Forte@Sun.COM
61807836SJohn.Forte@Sun.COM
61817836SJohn.Forte@Sun.COM static int
61827836SJohn.Forte@Sun.COM _sd_sync_write(_sd_buf_handle_t *handle, nsc_off_t fba_pos, nsc_size_t fba_len,
61837836SJohn.Forte@Sun.COM int flag)
61847836SJohn.Forte@Sun.COM {
61857836SJohn.Forte@Sun.COM return (_sd_sync_write2(handle, fba_pos, fba_len, flag, NULL, 0));
61867836SJohn.Forte@Sun.COM }
61877836SJohn.Forte@Sun.COM
61887836SJohn.Forte@Sun.COM
61897836SJohn.Forte@Sun.COM /*
61907836SJohn.Forte@Sun.COM * _sd_zero - Interface call to zero out a portion of cache blocks.
61917836SJohn.Forte@Sun.COM *
61927836SJohn.Forte@Sun.COM * ARGUMENTS:
61937836SJohn.Forte@Sun.COM * handle - handle allocated earlier on.
61947836SJohn.Forte@Sun.COM * fba_pos - disk block number to zero from.
61957836SJohn.Forte@Sun.COM * fba_len - length in fbas.
61967836SJohn.Forte@Sun.COM * flag - NSC_NOBLOCK for async io.
61977836SJohn.Forte@Sun.COM *
61987836SJohn.Forte@Sun.COM * RETURNS:
61997836SJohn.Forte@Sun.COM * errno if return > 0
62007836SJohn.Forte@Sun.COM * NSC_DONE or NSC_PENDING otherwise.
62017836SJohn.Forte@Sun.COM *
62027836SJohn.Forte@Sun.COM * Comments:
62037836SJohn.Forte@Sun.COM * This routine zeroes out the indicated portion of the cache blocks
62047836SJohn.Forte@Sun.COM * and commits the data to disk.
62057836SJohn.Forte@Sun.COM * (See write for more details on the commit)
62067836SJohn.Forte@Sun.COM */
62077836SJohn.Forte@Sun.COM
62087836SJohn.Forte@Sun.COM
62097836SJohn.Forte@Sun.COM int
62107836SJohn.Forte@Sun.COM _sd_zero(_sd_buf_handle_t *handle, nsc_off_t fba_pos, nsc_size_t fba_len,
62117836SJohn.Forte@Sun.COM int flag)
62127836SJohn.Forte@Sun.COM {
62137836SJohn.Forte@Sun.COM int cd;
62147836SJohn.Forte@Sun.COM sdbc_cblk_fba_t st_cblk_len; /* FBA len of starting cache block */
62157836SJohn.Forte@Sun.COM sdbc_cblk_fba_t end_cblk_len; /* FBA len of ending cache block */
62167836SJohn.Forte@Sun.COM sdbc_cblk_fba_t st_cblk_off; /* FBA offset into starting cblock */
62177836SJohn.Forte@Sun.COM nsc_size_t cur_fba_len; /* position in disk blocks */
62187836SJohn.Forte@Sun.COM int ret;
62197836SJohn.Forte@Sun.COM _sd_cctl_t *cc_ent;
62207836SJohn.Forte@Sun.COM
62217836SJohn.Forte@Sun.COM if (_sdbc_shutdown_in_progress) {
62227836SJohn.Forte@Sun.COM DTRACE_PROBE(shutdown);
62237836SJohn.Forte@Sun.COM return (EIO);
62247836SJohn.Forte@Sun.COM }
62257836SJohn.Forte@Sun.COM
62267836SJohn.Forte@Sun.COM if (!_SD_HANDLE_ACTIVE(handle)) {
6227*9093SRamana.Srikanth@Sun.COM cmn_err(CE_WARN, "!sdbc(_sd_zero) handle %p not active",
62287836SJohn.Forte@Sun.COM (void *)handle);
62297836SJohn.Forte@Sun.COM
62307836SJohn.Forte@Sun.COM DTRACE_PROBE1(handle_active, int, handle->bh_flag);
62317836SJohn.Forte@Sun.COM
62327836SJohn.Forte@Sun.COM return (EINVAL);
62337836SJohn.Forte@Sun.COM }
62347836SJohn.Forte@Sun.COM ASSERT_HANDLE_LIMITS(handle, fba_pos, fba_len);
62357836SJohn.Forte@Sun.COM if ((handle->bh_flag & NSC_WRBUF) == 0) {
62367836SJohn.Forte@Sun.COM DTRACE_PROBE1(handle_write, int, handle->bh_flag);
62377836SJohn.Forte@Sun.COM return (EINVAL);
62387836SJohn.Forte@Sun.COM }
62397836SJohn.Forte@Sun.COM
62407836SJohn.Forte@Sun.COM if (fba_len == 0) {
62417836SJohn.Forte@Sun.COM DTRACE_PROBE(zero_len);
62427836SJohn.Forte@Sun.COM return (NSC_DONE);
62437836SJohn.Forte@Sun.COM }
62447836SJohn.Forte@Sun.COM
62457836SJohn.Forte@Sun.COM if (_SD_FORCE_DISCONNECT(fba_len))
62467836SJohn.Forte@Sun.COM _SD_DISCONNECT_CALLBACK(handle);
62477836SJohn.Forte@Sun.COM
62487836SJohn.Forte@Sun.COM cd = HANDLE_CD(handle);
62497836SJohn.Forte@Sun.COM SDTRACE(ST_ENTER|SDF_ZERO, cd, fba_len, fba_pos, flag, 0);
62507836SJohn.Forte@Sun.COM
62517836SJohn.Forte@Sun.COM cc_ent = handle->bh_centry;
62527836SJohn.Forte@Sun.COM while (CENTRY_BLK(cc_ent) != FBA_TO_BLK_NUM(fba_pos))
62537836SJohn.Forte@Sun.COM cc_ent = cc_ent->cc_chain;
62547836SJohn.Forte@Sun.COM cur_fba_len = fba_len;
62557836SJohn.Forte@Sun.COM st_cblk_off = BLK_FBA_OFF(fba_pos);
62567836SJohn.Forte@Sun.COM st_cblk_len = BLK_FBAS - st_cblk_off;
62577836SJohn.Forte@Sun.COM if ((nsc_size_t)st_cblk_len >= fba_len) {
62587836SJohn.Forte@Sun.COM end_cblk_len = 0;
62597836SJohn.Forte@Sun.COM st_cblk_len = (sdbc_cblk_fba_t)fba_len;
62607836SJohn.Forte@Sun.COM } else {
62617836SJohn.Forte@Sun.COM end_cblk_len = BLK_FBA_OFF(fba_pos + fba_len);
62627836SJohn.Forte@Sun.COM }
62637836SJohn.Forte@Sun.COM
62647836SJohn.Forte@Sun.COM cur_fba_len -= st_cblk_len;
62657836SJohn.Forte@Sun.COM bzero(cc_ent->cc_data + FBA_SIZE(st_cblk_off), FBA_SIZE(st_cblk_len));
62667836SJohn.Forte@Sun.COM
62677836SJohn.Forte@Sun.COM cc_ent = cc_ent->cc_chain;
62687836SJohn.Forte@Sun.COM while (cur_fba_len > (nsc_size_t)end_cblk_len) {
62697836SJohn.Forte@Sun.COM cur_fba_len -= BLK_FBAS;
62707836SJohn.Forte@Sun.COM bzero(cc_ent->cc_data, CACHE_BLOCK_SIZE);
62717836SJohn.Forte@Sun.COM cc_ent = cc_ent->cc_chain;
62727836SJohn.Forte@Sun.COM }
62737836SJohn.Forte@Sun.COM if (cur_fba_len) {
62747836SJohn.Forte@Sun.COM bzero(cc_ent->cc_data, FBA_SIZE(cur_fba_len));
62757836SJohn.Forte@Sun.COM }
62767836SJohn.Forte@Sun.COM
62777836SJohn.Forte@Sun.COM ret = _sd_write(handle, fba_pos, fba_len, flag);
62787836SJohn.Forte@Sun.COM SDTRACE(ST_EXIT|SDF_ZERO, cd, fba_len, fba_pos, flag, ret);
62797836SJohn.Forte@Sun.COM
62807836SJohn.Forte@Sun.COM return (ret);
62817836SJohn.Forte@Sun.COM }
62827836SJohn.Forte@Sun.COM
62837836SJohn.Forte@Sun.COM
62847836SJohn.Forte@Sun.COM /*
62857836SJohn.Forte@Sun.COM * _sd_copy - Copies portions of 2 handles.
62867836SJohn.Forte@Sun.COM *
62877836SJohn.Forte@Sun.COM * ARGUMENTS:
62887836SJohn.Forte@Sun.COM * handle1 - handle allocated earlier on.
62897836SJohn.Forte@Sun.COM * handle2 - handle allocated earlier on.
62907836SJohn.Forte@Sun.COM * fba_pos1 - disk block number to read from.
62917836SJohn.Forte@Sun.COM * fba_pos2 - disk block number to write to.
62927836SJohn.Forte@Sun.COM * fba_len - length in fbas.
62937836SJohn.Forte@Sun.COM *
62947836SJohn.Forte@Sun.COM * RETURNS:
62957836SJohn.Forte@Sun.COM * errno if return > 0
62967836SJohn.Forte@Sun.COM * NSC_DONE otherwise.
62977836SJohn.Forte@Sun.COM *
62987836SJohn.Forte@Sun.COM * Comments:
62997836SJohn.Forte@Sun.COM * This routine copies the 2 handles.
63007836SJohn.Forte@Sun.COM * WARNING: this could put the cache blocks in the destination handle
63017836SJohn.Forte@Sun.COM * in an inconsistent state. (the blocks could be valid in cache,
63027836SJohn.Forte@Sun.COM * but the copy makes the cache different from disk)
63037836SJohn.Forte@Sun.COM *
63047836SJohn.Forte@Sun.COM */
63057836SJohn.Forte@Sun.COM
63067836SJohn.Forte@Sun.COM
63077836SJohn.Forte@Sun.COM int
63087836SJohn.Forte@Sun.COM _sd_copy(_sd_buf_handle_t *handle1, _sd_buf_handle_t *handle2,
63097836SJohn.Forte@Sun.COM nsc_off_t fba_pos1, nsc_off_t fba_pos2, nsc_size_t fba_len)
63107836SJohn.Forte@Sun.COM {
63117836SJohn.Forte@Sun.COM sdbc_cblk_fba_t st_cblk_len; /* FBA len of starting cache block */
63127836SJohn.Forte@Sun.COM sdbc_cblk_fba_t end_cblk_len; /* FBA len of ending cache block */
63137836SJohn.Forte@Sun.COM sdbc_cblk_fba_t st_cblk_off; /* FBA offset into starting cblock */
63147836SJohn.Forte@Sun.COM nsc_off_t off1, off2; /* offsets in FBA's into the disk */
63157836SJohn.Forte@Sun.COM nsc_size_t cur_fba_len; /* position in disk blocks */
63167836SJohn.Forte@Sun.COM _sd_cctl_t *cc_ent1, *cc_ent2;
63177836SJohn.Forte@Sun.COM
63187836SJohn.Forte@Sun.COM if (_sdbc_shutdown_in_progress) {
63197836SJohn.Forte@Sun.COM DTRACE_PROBE(shutdown);
63207836SJohn.Forte@Sun.COM return (EIO);
63217836SJohn.Forte@Sun.COM }
63227836SJohn.Forte@Sun.COM if (!_SD_HANDLE_ACTIVE(handle1) || !_SD_HANDLE_ACTIVE(handle2)) {
6323*9093SRamana.Srikanth@Sun.COM cmn_err(CE_WARN, "!sdbc(_sd_copy) handle %p or %p not active",
63247836SJohn.Forte@Sun.COM (void *)handle1, (void *)handle2);
63257836SJohn.Forte@Sun.COM
6326*9093SRamana.Srikanth@Sun.COM DTRACE_PROBE2(handle_active1, int, handle1->bh_flag,
6327*9093SRamana.Srikanth@Sun.COM int, handle2->bh_flag);
63287836SJohn.Forte@Sun.COM
63297836SJohn.Forte@Sun.COM return (EINVAL);
63307836SJohn.Forte@Sun.COM }
63317836SJohn.Forte@Sun.COM ASSERT_HANDLE_LIMITS(handle1, fba_pos1, fba_len);
63327836SJohn.Forte@Sun.COM ASSERT_HANDLE_LIMITS(handle2, fba_pos2, fba_len);
63337836SJohn.Forte@Sun.COM
63347836SJohn.Forte@Sun.COM cc_ent1 = handle1->bh_centry;
63357836SJohn.Forte@Sun.COM while (CENTRY_BLK(cc_ent1) != FBA_TO_BLK_NUM(fba_pos1))
63367836SJohn.Forte@Sun.COM cc_ent1 = cc_ent1->cc_chain;
63377836SJohn.Forte@Sun.COM
63387836SJohn.Forte@Sun.COM cc_ent2 = handle2->bh_centry;
63397836SJohn.Forte@Sun.COM while (CENTRY_BLK(cc_ent2) != FBA_TO_BLK_NUM(fba_pos2))
63407836SJohn.Forte@Sun.COM cc_ent2 = cc_ent2->cc_chain;
63417836SJohn.Forte@Sun.COM
63427836SJohn.Forte@Sun.COM if (BLK_FBA_OFF(fba_pos1) != BLK_FBA_OFF(fba_pos2)) {
63437836SJohn.Forte@Sun.COM /* Different offsets, do it slowly (per fba) */
63447836SJohn.Forte@Sun.COM
63457836SJohn.Forte@Sun.COM while (fba_len) {
63467836SJohn.Forte@Sun.COM off1 = FBA_SIZE(BLK_FBA_OFF(fba_pos1));
63477836SJohn.Forte@Sun.COM off2 = FBA_SIZE(BLK_FBA_OFF(fba_pos2));
63487836SJohn.Forte@Sun.COM
63497836SJohn.Forte@Sun.COM bcopy(cc_ent1->cc_data+off1, cc_ent2->cc_data+off2,
6350*9093SRamana.Srikanth@Sun.COM FBA_SIZE(1));
63517836SJohn.Forte@Sun.COM
63527836SJohn.Forte@Sun.COM fba_pos1++;
63537836SJohn.Forte@Sun.COM fba_pos2++;
63547836SJohn.Forte@Sun.COM fba_len--;
63557836SJohn.Forte@Sun.COM
63567836SJohn.Forte@Sun.COM if (FBA_TO_BLK_NUM(fba_pos1) != CENTRY_BLK(cc_ent1))
63577836SJohn.Forte@Sun.COM cc_ent1 = cc_ent1->cc_chain;
63587836SJohn.Forte@Sun.COM if (FBA_TO_BLK_NUM(fba_pos2) != CENTRY_BLK(cc_ent2))
63597836SJohn.Forte@Sun.COM cc_ent2 = cc_ent2->cc_chain;
63607836SJohn.Forte@Sun.COM }
63617836SJohn.Forte@Sun.COM
63627836SJohn.Forte@Sun.COM DTRACE_PROBE(_sd_copy_end);
63637836SJohn.Forte@Sun.COM return (NSC_DONE);
63647836SJohn.Forte@Sun.COM }
63657836SJohn.Forte@Sun.COM cur_fba_len = fba_len;
63667836SJohn.Forte@Sun.COM st_cblk_off = BLK_FBA_OFF(fba_pos1);
63677836SJohn.Forte@Sun.COM st_cblk_len = BLK_FBAS - st_cblk_off;
63687836SJohn.Forte@Sun.COM if ((nsc_size_t)st_cblk_len >= fba_len) {
63697836SJohn.Forte@Sun.COM end_cblk_len = 0;
63707836SJohn.Forte@Sun.COM st_cblk_len = (sdbc_cblk_fba_t)fba_len;
63717836SJohn.Forte@Sun.COM } else {
63727836SJohn.Forte@Sun.COM end_cblk_len = BLK_FBA_OFF(fba_pos1 + fba_len);
63737836SJohn.Forte@Sun.COM }
63747836SJohn.Forte@Sun.COM
63757836SJohn.Forte@Sun.COM bcopy(cc_ent1->cc_data + FBA_SIZE(st_cblk_off),
63767836SJohn.Forte@Sun.COM cc_ent2->cc_data + FBA_SIZE(st_cblk_off), FBA_SIZE(st_cblk_len));
63777836SJohn.Forte@Sun.COM cur_fba_len -= st_cblk_len;
63787836SJohn.Forte@Sun.COM cc_ent1 = cc_ent1->cc_chain;
63797836SJohn.Forte@Sun.COM cc_ent2 = cc_ent2->cc_chain;
63807836SJohn.Forte@Sun.COM
63817836SJohn.Forte@Sun.COM while (cur_fba_len > (nsc_size_t)end_cblk_len) {
63827836SJohn.Forte@Sun.COM bcopy(cc_ent1->cc_data, cc_ent2->cc_data, CACHE_BLOCK_SIZE);
63837836SJohn.Forte@Sun.COM cc_ent1 = cc_ent1->cc_chain;
63847836SJohn.Forte@Sun.COM cc_ent2 = cc_ent2->cc_chain;
63857836SJohn.Forte@Sun.COM cur_fba_len -= BLK_FBAS;
63867836SJohn.Forte@Sun.COM }
63877836SJohn.Forte@Sun.COM if (cur_fba_len) {
63887836SJohn.Forte@Sun.COM bcopy(cc_ent1->cc_data, cc_ent2->cc_data,
63897836SJohn.Forte@Sun.COM FBA_SIZE(end_cblk_len));
63907836SJohn.Forte@Sun.COM }
63917836SJohn.Forte@Sun.COM
63927836SJohn.Forte@Sun.COM return (NSC_DONE);
63937836SJohn.Forte@Sun.COM }
63947836SJohn.Forte@Sun.COM
63957836SJohn.Forte@Sun.COM
63967836SJohn.Forte@Sun.COM /*
63977836SJohn.Forte@Sun.COM * _sd_copy_direct - Copies data from one handle direct to another disk.
63987836SJohn.Forte@Sun.COM *
63997836SJohn.Forte@Sun.COM * ARGUMENTS:
64007836SJohn.Forte@Sun.COM * handle1 - handle to read from
64017836SJohn.Forte@Sun.COM * handle2 - handle to write to
64027836SJohn.Forte@Sun.COM * fba_pos1 - disk block number to read from.
64037836SJohn.Forte@Sun.COM * fba_pos2 - disk block number to write to.
64047836SJohn.Forte@Sun.COM * fba_len - length in fbas.
64057836SJohn.Forte@Sun.COM *
64067836SJohn.Forte@Sun.COM * RETURNS:
64077836SJohn.Forte@Sun.COM * errno if return > 0
64087836SJohn.Forte@Sun.COM * NSC_DONE otherwise.
64097836SJohn.Forte@Sun.COM *
64107836SJohn.Forte@Sun.COM * Comments:
64117836SJohn.Forte@Sun.COM * This routine copies data from handle1 directly (sync write)
64127836SJohn.Forte@Sun.COM * onto the disk pointed to by handle2. The handle2 is then
64137836SJohn.Forte@Sun.COM * invalidated since the data it contains is now stale compared to
64147836SJohn.Forte@Sun.COM * the disk.
64157836SJohn.Forte@Sun.COM */
64167836SJohn.Forte@Sun.COM
64177836SJohn.Forte@Sun.COM static int
64187836SJohn.Forte@Sun.COM _sd_copy_direct(_sd_buf_handle_t *handle1, _sd_buf_handle_t *handle2,
64197836SJohn.Forte@Sun.COM nsc_off_t fba_pos1, nsc_off_t fba_pos2, nsc_size_t fba_len)
64207836SJohn.Forte@Sun.COM {
64217836SJohn.Forte@Sun.COM int rc;
64227836SJohn.Forte@Sun.COM
64237836SJohn.Forte@Sun.COM if (_sdbc_shutdown_in_progress) {
64247836SJohn.Forte@Sun.COM DTRACE_PROBE(shutdown);
64257836SJohn.Forte@Sun.COM return (EIO);
64267836SJohn.Forte@Sun.COM }
64277836SJohn.Forte@Sun.COM
64287836SJohn.Forte@Sun.COM if (!_SD_HANDLE_ACTIVE(handle1) || !_SD_HANDLE_ACTIVE(handle2)) {
64297836SJohn.Forte@Sun.COM cmn_err(CE_WARN,
6430*9093SRamana.Srikanth@Sun.COM "!sdbc(_sd_copy_direct) handle %p or %p not active",
64317836SJohn.Forte@Sun.COM (void *)handle1, (void *)handle2);
64327836SJohn.Forte@Sun.COM
6433*9093SRamana.Srikanth@Sun.COM DTRACE_PROBE2(handle_active2, int, handle1->bh_flag,
6434*9093SRamana.Srikanth@Sun.COM int, handle2->bh_flag);
64357836SJohn.Forte@Sun.COM
64367836SJohn.Forte@Sun.COM return (EINVAL);
64377836SJohn.Forte@Sun.COM }
64387836SJohn.Forte@Sun.COM
64397836SJohn.Forte@Sun.COM ASSERT_HANDLE_LIMITS(handle1, fba_pos1, fba_len);
64407836SJohn.Forte@Sun.COM ASSERT_HANDLE_LIMITS(handle2, fba_pos2, fba_len);
64417836SJohn.Forte@Sun.COM
64427836SJohn.Forte@Sun.COM if ((handle2->bh_flag & NSC_WRITE) == 0) {
64437836SJohn.Forte@Sun.COM cmn_err(CE_WARN,
6444*9093SRamana.Srikanth@Sun.COM "!sdbc(_sd_copy_direct) handle2 %p is not writeable",
64457836SJohn.Forte@Sun.COM (void *)handle2);
64467836SJohn.Forte@Sun.COM DTRACE_PROBE1(handle2_write, int, handle2->bh_flag);
64477836SJohn.Forte@Sun.COM return (EINVAL);
64487836SJohn.Forte@Sun.COM }
64497836SJohn.Forte@Sun.COM
64507836SJohn.Forte@Sun.COM rc = _sd_sync_write2(handle2, fba_pos2, fba_len, 0, handle1, fba_pos1);
64517836SJohn.Forte@Sun.COM
64527836SJohn.Forte@Sun.COM return (rc);
64537836SJohn.Forte@Sun.COM }
64547836SJohn.Forte@Sun.COM
64557836SJohn.Forte@Sun.COM
64567836SJohn.Forte@Sun.COM /*
64577836SJohn.Forte@Sun.COM * _sd_enqueue_dirty - Enqueue a list of dirty buffers.
64587836SJohn.Forte@Sun.COM *
64597836SJohn.Forte@Sun.COM * ARGUMENTS:
64607836SJohn.Forte@Sun.COM * cd - cache descriptor.
64617836SJohn.Forte@Sun.COM * chain - pointer to list.
64627836SJohn.Forte@Sun.COM * cc_last - last entry in the chain.
64637836SJohn.Forte@Sun.COM * numq - number of entries in the list.
64647836SJohn.Forte@Sun.COM *
64657836SJohn.Forte@Sun.COM * RETURNS:
64667836SJohn.Forte@Sun.COM * NONE.
64677836SJohn.Forte@Sun.COM *
64687836SJohn.Forte@Sun.COM * Comments:
64697836SJohn.Forte@Sun.COM * This routine queues up the dirty blocks for io processing.
64707836SJohn.Forte@Sun.COM * It uses the cc_last to try to coalesce multiple lists into a
64717836SJohn.Forte@Sun.COM * single list, if consecutive writes are sequential in nature.
64727836SJohn.Forte@Sun.COM */
64737836SJohn.Forte@Sun.COM
64747836SJohn.Forte@Sun.COM void
64757836SJohn.Forte@Sun.COM _sd_enqueue_dirty(int cd, _sd_cctl_t *chain, _sd_cctl_t *cc_last, int numq)
64767836SJohn.Forte@Sun.COM {
64777836SJohn.Forte@Sun.COM _sd_cd_info_t *cdi;
64787836SJohn.Forte@Sun.COM _sd_cctl_t *last_ent;
64797836SJohn.Forte@Sun.COM int start_write = 0, maxq = SGIO_MAX;
64807836SJohn.Forte@Sun.COM
64817836SJohn.Forte@Sun.COM ASSERT(cd >= 0);
64827836SJohn.Forte@Sun.COM cdi = &(_sd_cache_files[cd]);
64837836SJohn.Forte@Sun.COM #if defined(_SD_DEBUG)
64847836SJohn.Forte@Sun.COM if (chain->cc_dirty_link)
6485*9093SRamana.Srikanth@Sun.COM cmn_err(CE_WARN, "!dirty_link set in enq %x fl %x",
6486*9093SRamana.Srikanth@Sun.COM chain->cc_dirty_link, chain->cc_flag);
64877836SJohn.Forte@Sun.COM #endif
64887836SJohn.Forte@Sun.COM
64897836SJohn.Forte@Sun.COM /* was FAST */
64907836SJohn.Forte@Sun.COM mutex_enter(&(cdi->cd_lock));
64917836SJohn.Forte@Sun.COM cdi->cd_info->sh_numdirty += numq;
64927836SJohn.Forte@Sun.COM if (cc_last == NULL)
64937836SJohn.Forte@Sun.COM numq = 0;
64947836SJohn.Forte@Sun.COM
64957836SJohn.Forte@Sun.COM if (cdi->cd_dirty_head == NULL) {
64967836SJohn.Forte@Sun.COM cdi->cd_dirty_head = cdi->cd_dirty_tail = chain;
64977836SJohn.Forte@Sun.COM cdi->cd_last_ent = cc_last;
64987836SJohn.Forte@Sun.COM cdi->cd_lastchain_ptr = chain;
64997836SJohn.Forte@Sun.COM cdi->cd_lastchain = numq;
65007836SJohn.Forte@Sun.COM } else {
65017836SJohn.Forte@Sun.COM if ((cc_last) && (last_ent = cdi->cd_last_ent) &&
65027836SJohn.Forte@Sun.COM (CENTRY_BLK(chain) == (CENTRY_BLK(last_ent)+1)) &&
65037836SJohn.Forte@Sun.COM (SDBC_DIRTY_NEIGHBORS(last_ent, chain)) &&
65047836SJohn.Forte@Sun.COM (cdi->cd_lastchain + numq < maxq)) {
65057836SJohn.Forte@Sun.COM cdi->cd_last_ent->cc_dirty_next = chain;
65067836SJohn.Forte@Sun.COM cdi->cd_last_ent = cc_last;
65077836SJohn.Forte@Sun.COM cdi->cd_lastchain += numq;
65087836SJohn.Forte@Sun.COM } else {
65097836SJohn.Forte@Sun.COM cdi->cd_dirty_tail->cc_dirty_link = chain;
65107836SJohn.Forte@Sun.COM cdi->cd_dirty_tail = chain;
65117836SJohn.Forte@Sun.COM cdi->cd_last_ent = cc_last;
65127836SJohn.Forte@Sun.COM cdi->cd_lastchain_ptr = chain;
65137836SJohn.Forte@Sun.COM cdi->cd_lastchain = numq;
65147836SJohn.Forte@Sun.COM start_write = 1;
65157836SJohn.Forte@Sun.COM }
65167836SJohn.Forte@Sun.COM }
65177836SJohn.Forte@Sun.COM /* was FAST */
65187836SJohn.Forte@Sun.COM mutex_exit(&(cdi->cd_lock));
65197836SJohn.Forte@Sun.COM if (start_write)
65207836SJohn.Forte@Sun.COM (void) _SD_CD_WRITER(cd);
65217836SJohn.Forte@Sun.COM }
65227836SJohn.Forte@Sun.COM
65237836SJohn.Forte@Sun.COM /*
65247836SJohn.Forte@Sun.COM * _sd_enqueue_dirty_chain - Enqueue a chain of a list of dirty buffers.
65257836SJohn.Forte@Sun.COM *
65267836SJohn.Forte@Sun.COM * ARGUMENTS:
65277836SJohn.Forte@Sun.COM * cd - cache descriptor.
65287836SJohn.Forte@Sun.COM * chain_first - first list in this chain.
65297836SJohn.Forte@Sun.COM * chain_last - last list in this chain.
65307836SJohn.Forte@Sun.COM * numq - number of entries being queue (total of all lists)
65317836SJohn.Forte@Sun.COM *
65327836SJohn.Forte@Sun.COM * RETURNS:
65337836SJohn.Forte@Sun.COM * NONE.
65347836SJohn.Forte@Sun.COM *
65357836SJohn.Forte@Sun.COM * Comments:
65367836SJohn.Forte@Sun.COM * This routine is called from the processing after io completions.
65377836SJohn.Forte@Sun.COM * If the buffers are still dirty, they are queued up in one shot.
65387836SJohn.Forte@Sun.COM */
65397836SJohn.Forte@Sun.COM
65407836SJohn.Forte@Sun.COM void
65417836SJohn.Forte@Sun.COM _sd_enqueue_dirty_chain(int cd,
65427836SJohn.Forte@Sun.COM _sd_cctl_t *chain_first,
65437836SJohn.Forte@Sun.COM _sd_cctl_t *chain_last,
65447836SJohn.Forte@Sun.COM int numq)
65457836SJohn.Forte@Sun.COM {
65467836SJohn.Forte@Sun.COM _sd_cd_info_t *cdi;
65477836SJohn.Forte@Sun.COM
65487836SJohn.Forte@Sun.COM ASSERT(cd >= 0);
65497836SJohn.Forte@Sun.COM cdi = &(_sd_cache_files[cd]);
65507836SJohn.Forte@Sun.COM if (chain_last->cc_dirty_link)
65517836SJohn.Forte@Sun.COM cmn_err(CE_PANIC,
6552*9093SRamana.Srikanth@Sun.COM "!_sd_enqueue_dirty_chain: chain_last %p dirty_link %p",
6553*9093SRamana.Srikanth@Sun.COM (void *)chain_last, (void *)chain_last->cc_dirty_link);
65547836SJohn.Forte@Sun.COM /* was FAST */
65557836SJohn.Forte@Sun.COM mutex_enter(&(cdi->cd_lock));
65567836SJohn.Forte@Sun.COM cdi->cd_last_ent = NULL;
65577836SJohn.Forte@Sun.COM cdi->cd_lastchain_ptr = NULL;
65587836SJohn.Forte@Sun.COM cdi->cd_lastchain = 0;
65597836SJohn.Forte@Sun.COM
65607836SJohn.Forte@Sun.COM cdi->cd_info->sh_numdirty += numq;
65617836SJohn.Forte@Sun.COM if (cdi->cd_dirty_head == NULL) {
65627836SJohn.Forte@Sun.COM cdi->cd_dirty_head = chain_first;
65637836SJohn.Forte@Sun.COM cdi->cd_dirty_tail = chain_last;
65647836SJohn.Forte@Sun.COM } else {
65657836SJohn.Forte@Sun.COM cdi->cd_dirty_tail->cc_dirty_link = chain_first;
65667836SJohn.Forte@Sun.COM cdi->cd_dirty_tail = chain_last;
65677836SJohn.Forte@Sun.COM }
65687836SJohn.Forte@Sun.COM /* was FAST */
65697836SJohn.Forte@Sun.COM mutex_exit(&(cdi->cd_lock));
65707836SJohn.Forte@Sun.COM }
65717836SJohn.Forte@Sun.COM
65727836SJohn.Forte@Sun.COM
65737836SJohn.Forte@Sun.COM #ifndef _MULTI_DATAMODEL
65747836SJohn.Forte@Sun.COM /* ARGSUSED */
65757836SJohn.Forte@Sun.COM #endif
65767836SJohn.Forte@Sun.COM static int
65777836SJohn.Forte@Sun.COM convert_stats(_sd_stats32_t *uptr)
65787836SJohn.Forte@Sun.COM /*
65797836SJohn.Forte@Sun.COM * Convert the 64 bit statistic structure to 32bit version.
65807836SJohn.Forte@Sun.COM * Possibly losing information when cache is > 4gb. Ha!
65817836SJohn.Forte@Sun.COM *
65827836SJohn.Forte@Sun.COM * NOTE: this code isn't really MT ready since the copied to struct
65837836SJohn.Forte@Sun.COM * is static. However the race is pretty benign and isn't a whole
65847836SJohn.Forte@Sun.COM * lot worse than the vanilla version which copies data to user
65857836SJohn.Forte@Sun.COM * space from kernel structures that can be changing under it too.
65867836SJohn.Forte@Sun.COM * We can't use a local stack structure since the data size is
65877836SJohn.Forte@Sun.COM * 70k or so and kernel stacks are tiny (8k).
65887836SJohn.Forte@Sun.COM */
65897836SJohn.Forte@Sun.COM {
65907836SJohn.Forte@Sun.COM #ifndef _MULTI_DATAMODEL
65917836SJohn.Forte@Sun.COM return (SDBC_EMODELCONVERT);
65927836SJohn.Forte@Sun.COM #else
65937836SJohn.Forte@Sun.COM int rc = 0;
65947836SJohn.Forte@Sun.COM
65957836SJohn.Forte@Sun.COM /*
65967836SJohn.Forte@Sun.COM * This could be done in less code with bcopy type operations
65977836SJohn.Forte@Sun.COM * but this is simpler to follow and easier to change if
65987836SJohn.Forte@Sun.COM * the structures change.
65997836SJohn.Forte@Sun.COM */
66007836SJohn.Forte@Sun.COM
66017836SJohn.Forte@Sun.COM _sd_cache_stats32->net_dirty = _sd_cache_stats->net_dirty;
66027836SJohn.Forte@Sun.COM _sd_cache_stats32->net_pending = _sd_cache_stats->net_pending;
66037836SJohn.Forte@Sun.COM _sd_cache_stats32->net_free = _sd_cache_stats->net_free;
66047836SJohn.Forte@Sun.COM _sd_cache_stats32->st_count = _sd_cache_stats->st_count;
66057836SJohn.Forte@Sun.COM _sd_cache_stats32->st_loc_count = _sd_cache_stats->st_loc_count;
66067836SJohn.Forte@Sun.COM _sd_cache_stats32->st_rdhits = _sd_cache_stats->st_rdhits;
66077836SJohn.Forte@Sun.COM _sd_cache_stats32->st_rdmiss = _sd_cache_stats->st_rdmiss;
66087836SJohn.Forte@Sun.COM _sd_cache_stats32->st_wrhits = _sd_cache_stats->st_wrhits;
66097836SJohn.Forte@Sun.COM _sd_cache_stats32->st_wrmiss = _sd_cache_stats->st_wrmiss;
66107836SJohn.Forte@Sun.COM _sd_cache_stats32->st_blksize = _sd_cache_stats->st_blksize;
66117836SJohn.Forte@Sun.COM
66127836SJohn.Forte@Sun.COM _sd_cache_stats32->st_lru_blocks = _sd_cache_stats->st_lru_blocks;
66137836SJohn.Forte@Sun.COM _sd_cache_stats32->st_lru_noreq = _sd_cache_stats->st_lru_noreq;
66147836SJohn.Forte@Sun.COM _sd_cache_stats32->st_lru_req = _sd_cache_stats->st_lru_req;
66157836SJohn.Forte@Sun.COM
66167836SJohn.Forte@Sun.COM _sd_cache_stats32->st_wlru_inq = _sd_cache_stats->st_wlru_inq;
66177836SJohn.Forte@Sun.COM
66187836SJohn.Forte@Sun.COM _sd_cache_stats32->st_cachesize = _sd_cache_stats->st_cachesize;
66197836SJohn.Forte@Sun.COM _sd_cache_stats32->st_numblocks = _sd_cache_stats->st_numblocks;
66207836SJohn.Forte@Sun.COM _sd_cache_stats32->st_wrcancelns = _sd_cache_stats->st_wrcancelns;
66217836SJohn.Forte@Sun.COM _sd_cache_stats32->st_destaged = _sd_cache_stats->st_destaged;
66227836SJohn.Forte@Sun.COM
66237836SJohn.Forte@Sun.COM /*
66247836SJohn.Forte@Sun.COM * bcopy the shared stats which has nothing that needs conversion
66257836SJohn.Forte@Sun.COM * in them
66267836SJohn.Forte@Sun.COM */
66277836SJohn.Forte@Sun.COM
66287836SJohn.Forte@Sun.COM bcopy(_sd_cache_stats->st_shared, _sd_cache_stats32->st_shared,
66297836SJohn.Forte@Sun.COM sizeof (_sd_shared_t) * sdbc_max_devs);
66307836SJohn.Forte@Sun.COM
66317836SJohn.Forte@Sun.COM if (copyout(_sd_cache_stats32, uptr, sizeof (_sd_stats32_t) +
66327836SJohn.Forte@Sun.COM (sdbc_max_devs - 1) * sizeof (_sd_shared_t)))
66337836SJohn.Forte@Sun.COM rc = EFAULT;
66347836SJohn.Forte@Sun.COM
66357836SJohn.Forte@Sun.COM return (rc);
66367836SJohn.Forte@Sun.COM #endif /* _MULTI_DATAMODEL */
66377836SJohn.Forte@Sun.COM }
66387836SJohn.Forte@Sun.COM
66397836SJohn.Forte@Sun.COM
66407836SJohn.Forte@Sun.COM int
66417836SJohn.Forte@Sun.COM _sd_get_stats(_sd_stats_t *uptr, int convert_32)
66427836SJohn.Forte@Sun.COM {
66437836SJohn.Forte@Sun.COM int rc = 0;
66447836SJohn.Forte@Sun.COM
66457836SJohn.Forte@Sun.COM if (_sd_cache_stats == NULL) {
66467836SJohn.Forte@Sun.COM static _sd_stats_t dummy;
66477836SJohn.Forte@Sun.COM #ifdef _MULTI_DATAMODEL
66487836SJohn.Forte@Sun.COM static _sd_stats32_t dummy32;
66497836SJohn.Forte@Sun.COM #endif
66507836SJohn.Forte@Sun.COM
66517836SJohn.Forte@Sun.COM if (convert_32) {
66527836SJohn.Forte@Sun.COM #ifdef _MULTI_DATAMODEL
66537836SJohn.Forte@Sun.COM if (copyout(&dummy32, uptr, sizeof (_sd_stats32_t)))
66547836SJohn.Forte@Sun.COM rc = EFAULT;
66557836SJohn.Forte@Sun.COM #else
66567836SJohn.Forte@Sun.COM rc = SDBC_EMODELCONVERT;
66577836SJohn.Forte@Sun.COM #endif
66587836SJohn.Forte@Sun.COM } else if (copyout(&dummy, uptr, sizeof (_sd_stats_t)))
66597836SJohn.Forte@Sun.COM rc = EFAULT;
66607836SJohn.Forte@Sun.COM return (rc);
66617836SJohn.Forte@Sun.COM }
66627836SJohn.Forte@Sun.COM
66637836SJohn.Forte@Sun.COM _sd_cache_stats->st_lru_blocks = _sd_lru_q.sq_inq;
66647836SJohn.Forte@Sun.COM _sd_cache_stats->st_lru_noreq = _sd_lru_q.sq_noreq_stat;
66657836SJohn.Forte@Sun.COM _sd_cache_stats->st_lru_req = _sd_lru_q.sq_req_stat;
66667836SJohn.Forte@Sun.COM
66677836SJohn.Forte@Sun.COM if (sdbc_safestore) {
66687836SJohn.Forte@Sun.COM ssioc_stats_t ss_stats;
66697836SJohn.Forte@Sun.COM
66707836SJohn.Forte@Sun.COM if (SSOP_CTL(sdbc_safestore, SSIOC_STATS,
6671*9093SRamana.Srikanth@Sun.COM (uintptr_t)&ss_stats) == 0)
66727836SJohn.Forte@Sun.COM _sd_cache_stats->st_wlru_inq = ss_stats.wq_inq;
66737836SJohn.Forte@Sun.COM else
66747836SJohn.Forte@Sun.COM _sd_cache_stats->st_wlru_inq = 0;
66757836SJohn.Forte@Sun.COM }
66767836SJohn.Forte@Sun.COM
66777836SJohn.Forte@Sun.COM if (convert_32)
66787836SJohn.Forte@Sun.COM rc = convert_stats((_sd_stats32_t *)uptr);
66797836SJohn.Forte@Sun.COM else if (copyout(_sd_cache_stats, uptr,
66807836SJohn.Forte@Sun.COM sizeof (_sd_stats_t) + (sdbc_max_devs - 1) * sizeof (_sd_shared_t)))
66817836SJohn.Forte@Sun.COM rc = EFAULT;
66827836SJohn.Forte@Sun.COM
66837836SJohn.Forte@Sun.COM return (rc);
66847836SJohn.Forte@Sun.COM }
66857836SJohn.Forte@Sun.COM
66867836SJohn.Forte@Sun.COM
66877836SJohn.Forte@Sun.COM int
66887836SJohn.Forte@Sun.COM _sd_set_hint(int cd, uint_t hint)
66897836SJohn.Forte@Sun.COM {
66907836SJohn.Forte@Sun.COM int ret = 0;
66917836SJohn.Forte@Sun.COM if (FILE_OPENED(cd)) {
66927836SJohn.Forte@Sun.COM SDTRACE(ST_ENTER|SDF_HINT, cd, 1, SDT_INV_BL, hint, 0);
66937836SJohn.Forte@Sun.COM _sd_cache_files[cd].cd_hint |= (hint & _SD_HINT_MASK);
66947836SJohn.Forte@Sun.COM SDTRACE(ST_EXIT|SDF_HINT, cd, 1, SDT_INV_BL, hint, ret);
66957836SJohn.Forte@Sun.COM } else
66967836SJohn.Forte@Sun.COM ret = EINVAL;
66977836SJohn.Forte@Sun.COM
66987836SJohn.Forte@Sun.COM return (ret);
66997836SJohn.Forte@Sun.COM }
67007836SJohn.Forte@Sun.COM
67017836SJohn.Forte@Sun.COM
67027836SJohn.Forte@Sun.COM
67037836SJohn.Forte@Sun.COM int
67047836SJohn.Forte@Sun.COM _sd_clear_hint(int cd, uint_t hint)
67057836SJohn.Forte@Sun.COM {
67067836SJohn.Forte@Sun.COM int ret = 0;
67077836SJohn.Forte@Sun.COM if (FILE_OPENED(cd)) {
67087836SJohn.Forte@Sun.COM SDTRACE(ST_ENTER|SDF_HINT, cd, 2, SDT_INV_BL, hint, 0);
67097836SJohn.Forte@Sun.COM _sd_cache_files[cd].cd_hint &= ~(hint & _SD_HINT_MASK);
67107836SJohn.Forte@Sun.COM SDTRACE(ST_EXIT|SDF_HINT, cd, 2, SDT_INV_BL, hint, ret);
67117836SJohn.Forte@Sun.COM } else
67127836SJohn.Forte@Sun.COM ret = EINVAL;
67137836SJohn.Forte@Sun.COM
67147836SJohn.Forte@Sun.COM return (ret);
67157836SJohn.Forte@Sun.COM }
67167836SJohn.Forte@Sun.COM
67177836SJohn.Forte@Sun.COM
67187836SJohn.Forte@Sun.COM int
67197836SJohn.Forte@Sun.COM _sd_get_cd_hint(int cd, uint_t *hint)
67207836SJohn.Forte@Sun.COM {
67217836SJohn.Forte@Sun.COM *hint = 0;
67227836SJohn.Forte@Sun.COM if (FILE_OPENED(cd)) {
67237836SJohn.Forte@Sun.COM *hint = _sd_cache_files[cd].cd_hint;
67247836SJohn.Forte@Sun.COM return (0);
67257836SJohn.Forte@Sun.COM } else
67267836SJohn.Forte@Sun.COM return (EINVAL);
67277836SJohn.Forte@Sun.COM }
67287836SJohn.Forte@Sun.COM
67297836SJohn.Forte@Sun.COM static int
67307836SJohn.Forte@Sun.COM _sd_node_hint_caller(blind_t hint, int hint_action)
67317836SJohn.Forte@Sun.COM {
67327836SJohn.Forte@Sun.COM int rc;
67337836SJohn.Forte@Sun.COM
67347836SJohn.Forte@Sun.COM switch (hint_action) {
67357836SJohn.Forte@Sun.COM case NSC_GET_NODE_HINT:
67367836SJohn.Forte@Sun.COM rc = _sd_get_node_hint((uint_t *)hint);
67377836SJohn.Forte@Sun.COM break;
67387836SJohn.Forte@Sun.COM case NSC_SET_NODE_HINT:
67397836SJohn.Forte@Sun.COM rc = _sd_set_node_hint((uint_t)(unsigned long)hint);
67407836SJohn.Forte@Sun.COM break;
67417836SJohn.Forte@Sun.COM case NSC_CLEAR_NODE_HINT:
67427836SJohn.Forte@Sun.COM rc = _sd_clear_node_hint((uint_t)(unsigned long)hint);
67437836SJohn.Forte@Sun.COM break;
67447836SJohn.Forte@Sun.COM default:
67457836SJohn.Forte@Sun.COM rc = EINVAL;
67467836SJohn.Forte@Sun.COM break;
67477836SJohn.Forte@Sun.COM }
67487836SJohn.Forte@Sun.COM
67497836SJohn.Forte@Sun.COM return (rc);
67507836SJohn.Forte@Sun.COM }
67517836SJohn.Forte@Sun.COM
67527836SJohn.Forte@Sun.COM int
67537836SJohn.Forte@Sun.COM _sd_set_node_hint(uint_t hint)
67547836SJohn.Forte@Sun.COM {
67557836SJohn.Forte@Sun.COM SDTRACE(ST_ENTER|SDF_HINT, SDT_INV_CD, 3, SDT_INV_BL, hint, 0);
67567836SJohn.Forte@Sun.COM if ((_sd_node_hint & NSC_NO_FORCED_WRTHRU) &&
67577836SJohn.Forte@Sun.COM (hint & NSC_FORCED_WRTHRU))
67587836SJohn.Forte@Sun.COM return (EINVAL);
67597836SJohn.Forte@Sun.COM _sd_node_hint |= (hint & _SD_HINT_MASK);
67607836SJohn.Forte@Sun.COM SDTRACE(ST_EXIT|SDF_HINT, SDT_INV_CD, 3, SDT_INV_BL, hint, 0);
67617836SJohn.Forte@Sun.COM return (0);
67627836SJohn.Forte@Sun.COM }
67637836SJohn.Forte@Sun.COM
67647836SJohn.Forte@Sun.COM
67657836SJohn.Forte@Sun.COM int
67667836SJohn.Forte@Sun.COM _sd_clear_node_hint(uint_t hint)
67677836SJohn.Forte@Sun.COM {
67687836SJohn.Forte@Sun.COM SDTRACE(ST_ENTER|SDF_HINT, SDT_INV_CD, 4, SDT_INV_BL, hint, 0);
67697836SJohn.Forte@Sun.COM _sd_node_hint &= ~(hint & _SD_HINT_MASK);
67707836SJohn.Forte@Sun.COM SDTRACE(ST_EXIT|SDF_HINT, SDT_INV_CD, 4, SDT_INV_BL, hint, 0);
67717836SJohn.Forte@Sun.COM return (0);
67727836SJohn.Forte@Sun.COM }
67737836SJohn.Forte@Sun.COM
67747836SJohn.Forte@Sun.COM
67757836SJohn.Forte@Sun.COM int
67767836SJohn.Forte@Sun.COM _sd_get_node_hint(uint_t *hint)
67777836SJohn.Forte@Sun.COM {
67787836SJohn.Forte@Sun.COM *hint = _sd_node_hint;
67797836SJohn.Forte@Sun.COM return (0);
67807836SJohn.Forte@Sun.COM }
67817836SJohn.Forte@Sun.COM
67827836SJohn.Forte@Sun.COM
67837836SJohn.Forte@Sun.COM int
67847836SJohn.Forte@Sun.COM _sd_get_partsize(blind_t xcd, nsc_size_t *ptr)
67857836SJohn.Forte@Sun.COM {
67867836SJohn.Forte@Sun.COM int cd = (int)(unsigned long)xcd;
67877836SJohn.Forte@Sun.COM
67887836SJohn.Forte@Sun.COM if (FILE_OPENED(cd)) {
67897836SJohn.Forte@Sun.COM *ptr = _sd_cache_files[cd].cd_info->sh_filesize;
67907836SJohn.Forte@Sun.COM return (0);
67917836SJohn.Forte@Sun.COM } else
67927836SJohn.Forte@Sun.COM return (EINVAL);
67937836SJohn.Forte@Sun.COM }
67947836SJohn.Forte@Sun.COM
67957836SJohn.Forte@Sun.COM
67967836SJohn.Forte@Sun.COM int
67977836SJohn.Forte@Sun.COM _sd_get_maxfbas(blind_t xcd, int flag, nsc_size_t *ptr)
67987836SJohn.Forte@Sun.COM {
67997836SJohn.Forte@Sun.COM int cd = (int)(unsigned long)xcd;
68007836SJohn.Forte@Sun.COM
68017836SJohn.Forte@Sun.COM if (!FILE_OPENED(cd))
68027836SJohn.Forte@Sun.COM return (EINVAL);
68037836SJohn.Forte@Sun.COM
68047836SJohn.Forte@Sun.COM if (flag & NSC_CACHEBLK)
68057836SJohn.Forte@Sun.COM *ptr = BLK_FBAS;
68067836SJohn.Forte@Sun.COM else
68077836SJohn.Forte@Sun.COM *ptr = sdbc_max_fbas;
68087836SJohn.Forte@Sun.COM
68097836SJohn.Forte@Sun.COM return (0);
68107836SJohn.Forte@Sun.COM }
68117836SJohn.Forte@Sun.COM
68127836SJohn.Forte@Sun.COM
68137836SJohn.Forte@Sun.COM int
68147836SJohn.Forte@Sun.COM _sd_control(blind_t xcd, int cmd, void *ptr, int len)
68157836SJohn.Forte@Sun.COM {
68167836SJohn.Forte@Sun.COM _sd_cd_info_t *cdi;
68177836SJohn.Forte@Sun.COM int cd = (int)(unsigned long)xcd;
68187836SJohn.Forte@Sun.COM
68197836SJohn.Forte@Sun.COM cdi = &(_sd_cache_files[cd]);
68207836SJohn.Forte@Sun.COM return (nsc_control(cdi->cd_rawfd, cmd, ptr, len));
68217836SJohn.Forte@Sun.COM }
68227836SJohn.Forte@Sun.COM
68237836SJohn.Forte@Sun.COM
68247836SJohn.Forte@Sun.COM int
68257836SJohn.Forte@Sun.COM _sd_discard_pinned(blind_t xcd, nsc_off_t fba_pos, nsc_size_t fba_len)
68267836SJohn.Forte@Sun.COM {
68277836SJohn.Forte@Sun.COM int cd = (int)(unsigned long)xcd;
68287836SJohn.Forte@Sun.COM _sd_cctl_t *cc_ent, **cc_lst, **cc_tmp, *nxt;
68297836SJohn.Forte@Sun.COM ss_centry_info_t *wctl;
68307836SJohn.Forte@Sun.COM int found = 0;
68317836SJohn.Forte@Sun.COM nsc_off_t cblk;
68327836SJohn.Forte@Sun.COM _sd_cd_info_t *cdi = &_sd_cache_files[cd];
68337836SJohn.Forte@Sun.COM int rc;
68347836SJohn.Forte@Sun.COM
68357836SJohn.Forte@Sun.COM if ((!FILE_OPENED(cd)) || (!cdi->cd_info->sh_failed)) {
68367836SJohn.Forte@Sun.COM
68377836SJohn.Forte@Sun.COM return (EINVAL);
68387836SJohn.Forte@Sun.COM }
68397836SJohn.Forte@Sun.COM
68407836SJohn.Forte@Sun.COM for (cblk = FBA_TO_BLK_NUM(fba_pos);
6841*9093SRamana.Srikanth@Sun.COM cblk < FBA_TO_BLK_LEN(fba_pos + fba_len); cblk++) {
68427836SJohn.Forte@Sun.COM if (cc_ent =
68437836SJohn.Forte@Sun.COM (_sd_cctl_t *)_sd_hash_search(cd, cblk, _sd_htable)) {
68447836SJohn.Forte@Sun.COM if (!CENTRY_PINNED(cc_ent))
68457836SJohn.Forte@Sun.COM continue;
68467836SJohn.Forte@Sun.COM
68477836SJohn.Forte@Sun.COM /*
68487836SJohn.Forte@Sun.COM * remove cc_ent from failed links
68497836SJohn.Forte@Sun.COM * cc_lst - pointer to "cc_dirty_link" pointer
68507836SJohn.Forte@Sun.COM * starts at &cd_failed_head.
68517836SJohn.Forte@Sun.COM * cc_tmp - pointer to "cc_dirty_next"
68527836SJohn.Forte@Sun.COM * except when equal to cc_lst.
68537836SJohn.Forte@Sun.COM */
68547836SJohn.Forte@Sun.COM mutex_enter(&cdi->cd_lock);
68557836SJohn.Forte@Sun.COM cc_tmp = cc_lst = &(cdi->cd_fail_head);
68567836SJohn.Forte@Sun.COM while (*cc_tmp != cc_ent) {
68577836SJohn.Forte@Sun.COM cc_tmp = &((*cc_tmp)->cc_dirty_next);
68587836SJohn.Forte@Sun.COM if (!*cc_tmp)
68597836SJohn.Forte@Sun.COM cc_lst = &((*cc_lst)->cc_dirty_link),
6860*9093SRamana.Srikanth@Sun.COM cc_tmp = cc_lst;
68617836SJohn.Forte@Sun.COM }
68627836SJohn.Forte@Sun.COM if (*cc_tmp) {
68637836SJohn.Forte@Sun.COM found++;
68647836SJohn.Forte@Sun.COM if (cc_lst != cc_tmp) /* break chain */
68657836SJohn.Forte@Sun.COM *cc_tmp = NULL;
68667836SJohn.Forte@Sun.COM nxt = cc_ent->cc_dirty_next;
68677836SJohn.Forte@Sun.COM if (nxt) {
68687836SJohn.Forte@Sun.COM nxt->cc_dirty_link =
6869*9093SRamana.Srikanth@Sun.COM (*cc_lst)->cc_dirty_link;
68707836SJohn.Forte@Sun.COM *cc_lst = nxt;
68717836SJohn.Forte@Sun.COM } else {
68727836SJohn.Forte@Sun.COM *cc_lst = (*cc_lst)->cc_dirty_link;
68737836SJohn.Forte@Sun.COM }
68747836SJohn.Forte@Sun.COM cdi->cd_info->sh_numfail--;
68757836SJohn.Forte@Sun.COM nsc_unpinned_data(cdi->cd_iodev,
6876*9093SRamana.Srikanth@Sun.COM BLK_TO_FBA_NUM(CENTRY_BLK(cc_ent)),
6877*9093SRamana.Srikanth@Sun.COM BLK_FBAS);
68787836SJohn.Forte@Sun.COM }
68797836SJohn.Forte@Sun.COM mutex_exit(&cdi->cd_lock);
68807836SJohn.Forte@Sun.COM
68817836SJohn.Forte@Sun.COM /* clear dirty bits */
68827836SJohn.Forte@Sun.COM /* was FAST */
68837836SJohn.Forte@Sun.COM mutex_enter(&cc_ent->cc_lock);
68847836SJohn.Forte@Sun.COM cc_ent->cc_valid = cc_ent->cc_dirty = 0;
68857836SJohn.Forte@Sun.COM cc_ent->cc_flag &= ~(CC_QHEAD|CC_PEND_DIRTY|CC_PINNED);
68867836SJohn.Forte@Sun.COM cc_ent->cc_dirty_link = NULL;
68877836SJohn.Forte@Sun.COM wctl = cc_ent->cc_write;
68887836SJohn.Forte@Sun.COM cc_ent->cc_write = NULL;
68897836SJohn.Forte@Sun.COM /* was FAST */
68907836SJohn.Forte@Sun.COM mutex_exit(&cc_ent->cc_lock);
68917836SJohn.Forte@Sun.COM
68927836SJohn.Forte@Sun.COM /* release cache block to head of LRU */
68937836SJohn.Forte@Sun.COM if (wctl) {
68947836SJohn.Forte@Sun.COM wctl->sc_flag = 0;
68957836SJohn.Forte@Sun.COM wctl->sc_dirty = 0;
68967836SJohn.Forte@Sun.COM SSOP_SETCENTRY(sdbc_safestore, wctl);
68977836SJohn.Forte@Sun.COM SSOP_DEALLOCRESOURCE(sdbc_safestore,
6898*9093SRamana.Srikanth@Sun.COM wctl->sc_res);
68997836SJohn.Forte@Sun.COM }
69007836SJohn.Forte@Sun.COM
69017836SJohn.Forte@Sun.COM if (!sdbc_use_dmchain)
69027836SJohn.Forte@Sun.COM _sd_requeue_head(cc_ent);
69037836SJohn.Forte@Sun.COM }
69047836SJohn.Forte@Sun.COM }
69057836SJohn.Forte@Sun.COM
69067836SJohn.Forte@Sun.COM rc = found ? NSC_DONE : EINVAL;
69077836SJohn.Forte@Sun.COM
69087836SJohn.Forte@Sun.COM return (rc);
69097836SJohn.Forte@Sun.COM }
69107836SJohn.Forte@Sun.COM
69117836SJohn.Forte@Sun.COM
69127836SJohn.Forte@Sun.COM /*
69137836SJohn.Forte@Sun.COM * Handle allocation
69147836SJohn.Forte@Sun.COM */
69157836SJohn.Forte@Sun.COM
69167836SJohn.Forte@Sun.COM _sd_buf_hlist_t _sd_handle_list;
69177836SJohn.Forte@Sun.COM
69187836SJohn.Forte@Sun.COM /*
69197836SJohn.Forte@Sun.COM * _sdbc_handles_unload - cache is being unloaded.
69207836SJohn.Forte@Sun.COM */
69217836SJohn.Forte@Sun.COM void
69227836SJohn.Forte@Sun.COM _sdbc_handles_unload(void)
69237836SJohn.Forte@Sun.COM {
69247836SJohn.Forte@Sun.COM mutex_destroy(&_sd_handle_list.hl_lock);
69257836SJohn.Forte@Sun.COM
69267836SJohn.Forte@Sun.COM }
69277836SJohn.Forte@Sun.COM
69287836SJohn.Forte@Sun.COM /*
69297836SJohn.Forte@Sun.COM * _sdbc_handles_load - cache is being unloaded.
69307836SJohn.Forte@Sun.COM */
69317836SJohn.Forte@Sun.COM int
69327836SJohn.Forte@Sun.COM _sdbc_handles_load(void)
69337836SJohn.Forte@Sun.COM {
69347836SJohn.Forte@Sun.COM mutex_init(&_sd_handle_list.hl_lock, NULL, MUTEX_DRIVER, NULL);
69357836SJohn.Forte@Sun.COM
69367836SJohn.Forte@Sun.COM return (0);
69377836SJohn.Forte@Sun.COM }
69387836SJohn.Forte@Sun.COM
69397836SJohn.Forte@Sun.COM int
69407836SJohn.Forte@Sun.COM _sdbc_handles_configure()
69417836SJohn.Forte@Sun.COM {
69427836SJohn.Forte@Sun.COM _sd_handle_list.hl_count = 0;
69437836SJohn.Forte@Sun.COM
69447836SJohn.Forte@Sun.COM _sd_handle_list.hl_top.bh_next = &_sd_handle_list.hl_top;
69457836SJohn.Forte@Sun.COM _sd_handle_list.hl_top.bh_prev = &_sd_handle_list.hl_top;
69467836SJohn.Forte@Sun.COM
69477836SJohn.Forte@Sun.COM return (0);
69487836SJohn.Forte@Sun.COM }
69497836SJohn.Forte@Sun.COM
69507836SJohn.Forte@Sun.COM
69517836SJohn.Forte@Sun.COM
69527836SJohn.Forte@Sun.COM /*
69537836SJohn.Forte@Sun.COM * _sdbc_handles_deconfigure - cache is being deconfigured
69547836SJohn.Forte@Sun.COM */
69557836SJohn.Forte@Sun.COM void
69567836SJohn.Forte@Sun.COM _sdbc_handles_deconfigure(void)
69577836SJohn.Forte@Sun.COM {
69587836SJohn.Forte@Sun.COM _sd_handle_list.hl_count = 0;
69597836SJohn.Forte@Sun.COM }
69607836SJohn.Forte@Sun.COM
69617836SJohn.Forte@Sun.COM
69627836SJohn.Forte@Sun.COM _sd_buf_handle_t *
69637836SJohn.Forte@Sun.COM _sd_alloc_handle(sdbc_callback_fn_t d_cb, sdbc_callback_fn_t r_cb,
69647836SJohn.Forte@Sun.COM sdbc_callback_fn_t w_cb)
69657836SJohn.Forte@Sun.COM {
69667836SJohn.Forte@Sun.COM _sd_buf_handle_t *handle;
69677836SJohn.Forte@Sun.COM
69687836SJohn.Forte@Sun.COM handle = (_sd_buf_handle_t *)kmem_zalloc(sizeof (_sd_buf_handle_t),
6969*9093SRamana.Srikanth@Sun.COM KM_SLEEP);
69707836SJohn.Forte@Sun.COM /* maintain list and count for debugging */
69717836SJohn.Forte@Sun.COM mutex_enter(&_sd_handle_list.hl_lock);
69727836SJohn.Forte@Sun.COM
69737836SJohn.Forte@Sun.COM handle->bh_prev = &_sd_handle_list.hl_top;
69747836SJohn.Forte@Sun.COM handle->bh_next = _sd_handle_list.hl_top.bh_next;
69757836SJohn.Forte@Sun.COM _sd_handle_list.hl_top.bh_next->bh_prev = handle;
69767836SJohn.Forte@Sun.COM _sd_handle_list.hl_top.bh_next = handle;
69777836SJohn.Forte@Sun.COM
69787836SJohn.Forte@Sun.COM ++_sd_handle_list.hl_count;
69797836SJohn.Forte@Sun.COM mutex_exit(&_sd_handle_list.hl_lock);
69807836SJohn.Forte@Sun.COM #if !defined(_SD_NOCHECKS)
69817836SJohn.Forte@Sun.COM ASSERT(!(handle->bh_flag & (NSC_HALLOCATED | NSC_HACTIVE)));
69827836SJohn.Forte@Sun.COM #endif
69837836SJohn.Forte@Sun.COM handle->bh_disconnect_cb = d_cb;
69847836SJohn.Forte@Sun.COM handle->bh_read_cb = r_cb;
69857836SJohn.Forte@Sun.COM handle->bh_write_cb = w_cb;
69867836SJohn.Forte@Sun.COM handle->bh_flag |= NSC_HALLOCATED;
69877836SJohn.Forte@Sun.COM handle->bh_alloc_thread = nsc_threadp();
69887836SJohn.Forte@Sun.COM
69897836SJohn.Forte@Sun.COM return (handle);
69907836SJohn.Forte@Sun.COM }
69917836SJohn.Forte@Sun.COM
69927836SJohn.Forte@Sun.COM int
69937836SJohn.Forte@Sun.COM _sd_free_handle(_sd_buf_handle_t *handle)
69947836SJohn.Forte@Sun.COM {
69957836SJohn.Forte@Sun.COM
69967836SJohn.Forte@Sun.COM if ((handle->bh_flag & NSC_HALLOCATED) == 0) {
6997*9093SRamana.Srikanth@Sun.COM cmn_err(CE_WARN, "!sdbc(_sd_free_handle) handle %p not valid",
69987836SJohn.Forte@Sun.COM (void *)handle);
69997836SJohn.Forte@Sun.COM
70007836SJohn.Forte@Sun.COM DTRACE_PROBE(_sd_free_handle_end);
70017836SJohn.Forte@Sun.COM
70027836SJohn.Forte@Sun.COM return (EINVAL);
70037836SJohn.Forte@Sun.COM }
70047836SJohn.Forte@Sun.COM if (_SD_HANDLE_ACTIVE(handle)) {
70057836SJohn.Forte@Sun.COM cmn_err(CE_WARN,
7006*9093SRamana.Srikanth@Sun.COM "!sdbc(_sd_free_handle) attempt to free active handle %p",
70077836SJohn.Forte@Sun.COM (void *)handle);
70087836SJohn.Forte@Sun.COM
70097836SJohn.Forte@Sun.COM DTRACE_PROBE1(free_handle_active, int, handle->bh_flag);
70107836SJohn.Forte@Sun.COM
70117836SJohn.Forte@Sun.COM return (EINVAL);
70127836SJohn.Forte@Sun.COM }
70137836SJohn.Forte@Sun.COM
70147836SJohn.Forte@Sun.COM
70157836SJohn.Forte@Sun.COM /* remove from queue before free */
70167836SJohn.Forte@Sun.COM mutex_enter(&_sd_handle_list.hl_lock);
70177836SJohn.Forte@Sun.COM handle->bh_prev->bh_next = handle->bh_next;
70187836SJohn.Forte@Sun.COM handle->bh_next->bh_prev = handle->bh_prev;
70197836SJohn.Forte@Sun.COM --_sd_handle_list.hl_count;
70207836SJohn.Forte@Sun.COM mutex_exit(&_sd_handle_list.hl_lock);
70217836SJohn.Forte@Sun.COM
70227836SJohn.Forte@Sun.COM kmem_free(handle, sizeof (_sd_buf_handle_t));
70237836SJohn.Forte@Sun.COM
70247836SJohn.Forte@Sun.COM return (0);
70257836SJohn.Forte@Sun.COM }
70267836SJohn.Forte@Sun.COM
70277836SJohn.Forte@Sun.COM
70287836SJohn.Forte@Sun.COM
70297836SJohn.Forte@Sun.COM
70307836SJohn.Forte@Sun.COM #if !defined (_SD_8K_BLKSIZE)
70317836SJohn.Forte@Sun.COM #define _SD_MAX_MAP 0x100
70327836SJohn.Forte@Sun.COM #else /* !(_SD_8K_BLKSIZE) */
70337836SJohn.Forte@Sun.COM #define _SD_MAX_MAP 0x10000
70347836SJohn.Forte@Sun.COM #endif /* !(_SD_8K_BLKSIZE) */
70357836SJohn.Forte@Sun.COM
70367836SJohn.Forte@Sun.COM char _sd_contig_bmap[_SD_MAX_MAP];
70377836SJohn.Forte@Sun.COM _sd_map_info_t _sd_lookup_map[_SD_MAX_MAP];
70387836SJohn.Forte@Sun.COM
70397836SJohn.Forte@Sun.COM void
70407836SJohn.Forte@Sun.COM _sd_init_contig_bmap(void)
70417836SJohn.Forte@Sun.COM {
70427836SJohn.Forte@Sun.COM int i, j;
70437836SJohn.Forte@Sun.COM
70447836SJohn.Forte@Sun.COM for (i = 1; i < _SD_MAX_MAP; i = ((i << 1) | 1))
70457836SJohn.Forte@Sun.COM for (j = i; j < _SD_MAX_MAP; j <<= 1)
70467836SJohn.Forte@Sun.COM _sd_contig_bmap[j] = 1;
70477836SJohn.Forte@Sun.COM }
70487836SJohn.Forte@Sun.COM
70497836SJohn.Forte@Sun.COM
70507836SJohn.Forte@Sun.COM
70517836SJohn.Forte@Sun.COM
70527836SJohn.Forte@Sun.COM void
70537836SJohn.Forte@Sun.COM _sd_init_lookup_map(void)
70547836SJohn.Forte@Sun.COM {
70557836SJohn.Forte@Sun.COM unsigned int i, j, k;
70567836SJohn.Forte@Sun.COM int stpos, len;
70577836SJohn.Forte@Sun.COM _sd_bitmap_t mask;
70587836SJohn.Forte@Sun.COM
70597836SJohn.Forte@Sun.COM for (i = 0; i < _SD_MAX_MAP; i++) {
70607836SJohn.Forte@Sun.COM for (j = i, k = 0; j && ((j & 1) == 0); j >>= 1, k++)
70617836SJohn.Forte@Sun.COM ;
70627836SJohn.Forte@Sun.COM stpos = k;
70637836SJohn.Forte@Sun.COM _sd_lookup_map[i].mi_stpos = (unsigned char)k;
70647836SJohn.Forte@Sun.COM
70657836SJohn.Forte@Sun.COM for (k = 0; j & 1; j >>= 1, k++)
70667836SJohn.Forte@Sun.COM ;
70677836SJohn.Forte@Sun.COM len = k;
70687836SJohn.Forte@Sun.COM _sd_lookup_map[i].mi_len = (unsigned char)k;
70697836SJohn.Forte@Sun.COM
70707836SJohn.Forte@Sun.COM _sd_lookup_map[i].mi_mask = SDBC_GET_BITS(stpos, len);
70717836SJohn.Forte@Sun.COM }
70727836SJohn.Forte@Sun.COM for (i = 0; i < _SD_MAX_MAP; i++) {
70737836SJohn.Forte@Sun.COM mask = (_sd_bitmap_t)i;
70747836SJohn.Forte@Sun.COM for (j = 0; mask; j++)
70757836SJohn.Forte@Sun.COM SDBC_LOOKUP_MODIFY(mask);
70767836SJohn.Forte@Sun.COM
70777836SJohn.Forte@Sun.COM _sd_lookup_map[i].mi_dirty_count = (unsigned char)j;
70787836SJohn.Forte@Sun.COM }
70797836SJohn.Forte@Sun.COM for (i = 0; i < _SD_MAX_MAP; i++) {
70807836SJohn.Forte@Sun.COM _sd_lookup_map[i].mi_io_count = SDBC_LOOKUP_DTCOUNT(i);
70817836SJohn.Forte@Sun.COM mask = ~i;
70827836SJohn.Forte@Sun.COM _sd_lookup_map[i].mi_io_count += SDBC_LOOKUP_DTCOUNT(mask);
70837836SJohn.Forte@Sun.COM }
70847836SJohn.Forte@Sun.COM }
70857836SJohn.Forte@Sun.COM
70867836SJohn.Forte@Sun.COM
70877836SJohn.Forte@Sun.COM nsc_def_t _sd_sdbc_def[] = {
70887836SJohn.Forte@Sun.COM "Open", (uintptr_t)_sd_open_io, 0,
70897836SJohn.Forte@Sun.COM "Close", (uintptr_t)_sd_close_io, 0,
70907836SJohn.Forte@Sun.COM "Attach", (uintptr_t)_sdbc_io_attach_cd, 0,
70917836SJohn.Forte@Sun.COM "Detach", (uintptr_t)_sdbc_io_detach_cd, 0,
70927836SJohn.Forte@Sun.COM "AllocBuf", (uintptr_t)_sd_alloc_buf, 0,
70937836SJohn.Forte@Sun.COM "FreeBuf", (uintptr_t)_sd_free_buf, 0,
70947836SJohn.Forte@Sun.COM "Read", (uintptr_t)_sd_read, 0,
70957836SJohn.Forte@Sun.COM "Write", (uintptr_t)_sd_write, 0,
70967836SJohn.Forte@Sun.COM "Zero", (uintptr_t)_sd_zero, 0,
70977836SJohn.Forte@Sun.COM "Copy", (uintptr_t)_sd_copy, 0,
70987836SJohn.Forte@Sun.COM "CopyDirect", (uintptr_t)_sd_copy_direct, 0,
70997836SJohn.Forte@Sun.COM "Uncommit", (uintptr_t)_sd_uncommit, 0,
71007836SJohn.Forte@Sun.COM "AllocHandle", (uintptr_t)_sd_alloc_handle, 0,
71017836SJohn.Forte@Sun.COM "FreeHandle", (uintptr_t)_sd_free_handle, 0,
71027836SJohn.Forte@Sun.COM "Discard", (uintptr_t)_sd_discard_pinned, 0,
71037836SJohn.Forte@Sun.COM "Sizes", (uintptr_t)_sd_cache_sizes, 0,
71047836SJohn.Forte@Sun.COM "GetPinned", (uintptr_t)_sd_get_pinned, 0,
71057836SJohn.Forte@Sun.COM "NodeHints", (uintptr_t)_sd_node_hint_caller, 0,
71067836SJohn.Forte@Sun.COM "PartSize", (uintptr_t)_sd_get_partsize, 0,
71077836SJohn.Forte@Sun.COM "MaxFbas", (uintptr_t)_sd_get_maxfbas, 0,
71087836SJohn.Forte@Sun.COM "Control", (uintptr_t)_sd_control, 0,
71097836SJohn.Forte@Sun.COM "Provide", NSC_CACHE, 0,
71107836SJohn.Forte@Sun.COM 0, 0, 0
71117836SJohn.Forte@Sun.COM };
71127836SJohn.Forte@Sun.COM
71137836SJohn.Forte@Sun.COM /*
71147836SJohn.Forte@Sun.COM * do the SD_GET_CD_CLUSTER_DATA ioctl (get the global filename data)
71157836SJohn.Forte@Sun.COM */
71167836SJohn.Forte@Sun.COM /* ARGSUSED */
71177836SJohn.Forte@Sun.COM int
71187836SJohn.Forte@Sun.COM sd_get_file_info_data(char *uaddrp)
71197836SJohn.Forte@Sun.COM {
71207836SJohn.Forte@Sun.COM return (ENOTTY);
71217836SJohn.Forte@Sun.COM }
71227836SJohn.Forte@Sun.COM
71237836SJohn.Forte@Sun.COM /*
71247836SJohn.Forte@Sun.COM * do the SD_GET_CD_CLUSTER_SIZE ioctl (get size of global filename area)
71257836SJohn.Forte@Sun.COM */
71267836SJohn.Forte@Sun.COM int
71277836SJohn.Forte@Sun.COM sd_get_file_info_size(void *uaddrp)
71287836SJohn.Forte@Sun.COM {
71297836SJohn.Forte@Sun.COM if (copyout(&_sdbc_gl_file_info_size, uaddrp,
7130*9093SRamana.Srikanth@Sun.COM sizeof (_sdbc_gl_file_info_size))) {
71317836SJohn.Forte@Sun.COM return (EFAULT);
71327836SJohn.Forte@Sun.COM }
71337836SJohn.Forte@Sun.COM
71347836SJohn.Forte@Sun.COM return (0);
71357836SJohn.Forte@Sun.COM }
71367836SJohn.Forte@Sun.COM
71377836SJohn.Forte@Sun.COM
71387836SJohn.Forte@Sun.COM /*
71397836SJohn.Forte@Sun.COM * SD_GET_GLMUL_SIZES ioctl
71407836SJohn.Forte@Sun.COM * get sizes of the global info regions (for this node only)
71417836SJohn.Forte@Sun.COM */
71427836SJohn.Forte@Sun.COM /* ARGSUSED */
71437836SJohn.Forte@Sun.COM int
71447836SJohn.Forte@Sun.COM sd_get_glmul_sizes(int *uaddrp)
71457836SJohn.Forte@Sun.COM {
71467836SJohn.Forte@Sun.COM return (ENOTTY);
71477836SJohn.Forte@Sun.COM }
71487836SJohn.Forte@Sun.COM
71497836SJohn.Forte@Sun.COM /*
71507836SJohn.Forte@Sun.COM * SD_GET_GLMUL_INFO ioctl
71517836SJohn.Forte@Sun.COM * get the global metadata for write blocks (for this node only)
71527836SJohn.Forte@Sun.COM */
71537836SJohn.Forte@Sun.COM /* ARGSUSED */
71547836SJohn.Forte@Sun.COM int
71557836SJohn.Forte@Sun.COM sd_get_glmul_info(char *uaddrp)
71567836SJohn.Forte@Sun.COM {
71577836SJohn.Forte@Sun.COM
71587836SJohn.Forte@Sun.COM return (ENOTTY);
71597836SJohn.Forte@Sun.COM }
71607836SJohn.Forte@Sun.COM
71617836SJohn.Forte@Sun.COM int
71627836SJohn.Forte@Sun.COM sdbc_global_stats_update(kstat_t *ksp, int rw)
71637836SJohn.Forte@Sun.COM {
71647836SJohn.Forte@Sun.COM sdbc_global_stats_t *sdbc_gstats;
71657836SJohn.Forte@Sun.COM _sd_stats_t *gstats_vars;
71667836SJohn.Forte@Sun.COM uint_t hint;
71677836SJohn.Forte@Sun.COM
71687836SJohn.Forte@Sun.COM sdbc_gstats = (sdbc_global_stats_t *)(ksp->ks_data);
71697836SJohn.Forte@Sun.COM
71707836SJohn.Forte@Sun.COM gstats_vars = _sd_cache_stats;
71717836SJohn.Forte@Sun.COM
71727836SJohn.Forte@Sun.COM if (rw == KSTAT_WRITE) {
71737836SJohn.Forte@Sun.COM return (EACCES);
71747836SJohn.Forte@Sun.COM }
71757836SJohn.Forte@Sun.COM
71767836SJohn.Forte@Sun.COM /* default to READ */
71777836SJohn.Forte@Sun.COM sdbc_gstats->ci_sdbc_count.value.ul = gstats_vars->st_count;
71787836SJohn.Forte@Sun.COM sdbc_gstats->ci_sdbc_loc_count.value.ul = gstats_vars->st_loc_count;
71797836SJohn.Forte@Sun.COM sdbc_gstats->ci_sdbc_rdhits.value.ul = (ulong_t)gstats_vars->st_rdhits;
71807836SJohn.Forte@Sun.COM sdbc_gstats->ci_sdbc_rdmiss.value.ul = (ulong_t)gstats_vars->st_rdmiss;
71817836SJohn.Forte@Sun.COM sdbc_gstats->ci_sdbc_wrhits.value.ul = (ulong_t)gstats_vars->st_wrhits;
71827836SJohn.Forte@Sun.COM sdbc_gstats->ci_sdbc_wrmiss.value.ul = (ulong_t)gstats_vars->st_wrmiss;
71837836SJohn.Forte@Sun.COM
71847836SJohn.Forte@Sun.COM sdbc_gstats->ci_sdbc_blksize.value.ul =
71857836SJohn.Forte@Sun.COM (ulong_t)gstats_vars->st_blksize;
71867836SJohn.Forte@Sun.COM sdbc_gstats->ci_sdbc_lru_blocks.value.ul = (ulong_t)_sd_lru_q.sq_inq;
71877836SJohn.Forte@Sun.COM #ifdef DEBUG
71887836SJohn.Forte@Sun.COM sdbc_gstats->ci_sdbc_lru_noreq.value.ul =
71897836SJohn.Forte@Sun.COM (ulong_t)_sd_lru_q.sq_noreq_stat;
71907836SJohn.Forte@Sun.COM sdbc_gstats->ci_sdbc_lru_req.value.ul = (ulong_t)_sd_lru_q.sq_req_stat;
71917836SJohn.Forte@Sun.COM #endif
71927836SJohn.Forte@Sun.COM sdbc_gstats->ci_sdbc_wlru_inq.value.ul =
71937836SJohn.Forte@Sun.COM (ulong_t)gstats_vars->st_wlru_inq;
71947836SJohn.Forte@Sun.COM sdbc_gstats->ci_sdbc_cachesize.value.ul =
71957836SJohn.Forte@Sun.COM (ulong_t)gstats_vars->st_cachesize;
71967836SJohn.Forte@Sun.COM sdbc_gstats->ci_sdbc_numblocks.value.ul =
71977836SJohn.Forte@Sun.COM (ulong_t)gstats_vars->st_numblocks;
71987836SJohn.Forte@Sun.COM sdbc_gstats->ci_sdbc_wrcancelns.value.ul =
71997836SJohn.Forte@Sun.COM (ulong_t)gstats_vars->st_wrcancelns;
72007836SJohn.Forte@Sun.COM sdbc_gstats->ci_sdbc_destaged.value.ul =
72017836SJohn.Forte@Sun.COM (ulong_t)gstats_vars->st_destaged;
72027836SJohn.Forte@Sun.COM sdbc_gstats->ci_sdbc_num_shared.value.ul = (ulong_t)sdbc_max_devs;
72037836SJohn.Forte@Sun.COM (void) _sd_get_node_hint(&hint);
72047836SJohn.Forte@Sun.COM sdbc_gstats->ci_sdbc_nodehints.value.ul = (ulong_t)hint;
72057836SJohn.Forte@Sun.COM
72067836SJohn.Forte@Sun.COM
72077836SJohn.Forte@Sun.COM return (0);
72087836SJohn.Forte@Sun.COM }
72097836SJohn.Forte@Sun.COM
72107836SJohn.Forte@Sun.COM int
72117836SJohn.Forte@Sun.COM sdbc_cd_stats_update(kstat_t *ksp, int rw)
72127836SJohn.Forte@Sun.COM {
72137836SJohn.Forte@Sun.COM sdbc_cd_stats_t *sdbc_shstats;
72147836SJohn.Forte@Sun.COM _sd_shared_t *shstats_vars;
72157836SJohn.Forte@Sun.COM int name_len;
72167836SJohn.Forte@Sun.COM uint_t hint;
72177836SJohn.Forte@Sun.COM
72187836SJohn.Forte@Sun.COM sdbc_shstats = (sdbc_cd_stats_t *)(ksp->ks_data);
72197836SJohn.Forte@Sun.COM
72207836SJohn.Forte@Sun.COM shstats_vars = (_sd_shared_t *)(ksp->ks_private);
72217836SJohn.Forte@Sun.COM
72227836SJohn.Forte@Sun.COM if (rw == KSTAT_WRITE) {
72237836SJohn.Forte@Sun.COM return (EACCES);
72247836SJohn.Forte@Sun.COM }
72257836SJohn.Forte@Sun.COM
72267836SJohn.Forte@Sun.COM /* copy tail of filename to kstat. leave 1 byte for null char */
72277836SJohn.Forte@Sun.COM if (shstats_vars->sh_filename != NULL) {
72287836SJohn.Forte@Sun.COM name_len = (int)strlen(shstats_vars->sh_filename);
72297836SJohn.Forte@Sun.COM name_len -= (KSTAT_DATA_CHAR_LEN - 1);
72307836SJohn.Forte@Sun.COM
72317836SJohn.Forte@Sun.COM if (name_len < 0) {
72327836SJohn.Forte@Sun.COM name_len = 0;
72337836SJohn.Forte@Sun.COM }
72347836SJohn.Forte@Sun.COM
72357836SJohn.Forte@Sun.COM (void) strlcpy(sdbc_shstats->ci_sdbc_vol_name.value.c,
72367836SJohn.Forte@Sun.COM shstats_vars->sh_filename + name_len, KSTAT_DATA_CHAR_LEN);
72377836SJohn.Forte@Sun.COM } else {
7238*9093SRamana.Srikanth@Sun.COM cmn_err(CE_WARN, "!Kstat error: no volume name associated "
72397836SJohn.Forte@Sun.COM "with cache descriptor");
72407836SJohn.Forte@Sun.COM }
72417836SJohn.Forte@Sun.COM
72427836SJohn.Forte@Sun.COM sdbc_shstats->ci_sdbc_failed.value.ul =
72437836SJohn.Forte@Sun.COM (ulong_t)shstats_vars->sh_failed;
72447836SJohn.Forte@Sun.COM sdbc_shstats->ci_sdbc_cd.value.ul = (ulong_t)shstats_vars->sh_cd;
72457836SJohn.Forte@Sun.COM sdbc_shstats->ci_sdbc_cache_read.value.ul =
72467836SJohn.Forte@Sun.COM (ulong_t)shstats_vars->sh_cache_read;
72477836SJohn.Forte@Sun.COM sdbc_shstats->ci_sdbc_cache_write.value.ul =
72487836SJohn.Forte@Sun.COM (ulong_t)shstats_vars->sh_cache_write;
72497836SJohn.Forte@Sun.COM sdbc_shstats->ci_sdbc_disk_read.value.ul =
72507836SJohn.Forte@Sun.COM (ulong_t)shstats_vars->sh_disk_read;
72517836SJohn.Forte@Sun.COM sdbc_shstats->ci_sdbc_disk_write.value.ul =
72527836SJohn.Forte@Sun.COM (ulong_t)shstats_vars->sh_disk_write;
72537836SJohn.Forte@Sun.COM #ifdef NSC_MULTI_TERABYTE
72547836SJohn.Forte@Sun.COM sdbc_shstats->ci_sdbc_filesize.value.ui64 =
72557836SJohn.Forte@Sun.COM (uint64_t)shstats_vars->sh_filesize;
72567836SJohn.Forte@Sun.COM #else
72577836SJohn.Forte@Sun.COM sdbc_shstats->ci_sdbc_filesize.value.ul =
72587836SJohn.Forte@Sun.COM (ulong_t)shstats_vars->sh_filesize;
72597836SJohn.Forte@Sun.COM #endif
72607836SJohn.Forte@Sun.COM sdbc_shstats->ci_sdbc_numdirty.value.ul =
72617836SJohn.Forte@Sun.COM (ulong_t)shstats_vars->sh_numdirty;
72627836SJohn.Forte@Sun.COM sdbc_shstats->ci_sdbc_numio.value.ul = (ulong_t)shstats_vars->sh_numio;
72637836SJohn.Forte@Sun.COM sdbc_shstats->ci_sdbc_numfail.value.ul =
72647836SJohn.Forte@Sun.COM (ulong_t)shstats_vars->sh_numfail;
72657836SJohn.Forte@Sun.COM sdbc_shstats->ci_sdbc_destaged.value.ul =
72667836SJohn.Forte@Sun.COM (ulong_t)shstats_vars->sh_destaged;
72677836SJohn.Forte@Sun.COM sdbc_shstats->ci_sdbc_wrcancelns.value.ul =
72687836SJohn.Forte@Sun.COM (ulong_t)shstats_vars->sh_wrcancelns;
72697836SJohn.Forte@Sun.COM (void) _sd_get_cd_hint(shstats_vars->sh_cd, &hint);
72707836SJohn.Forte@Sun.COM sdbc_shstats->ci_sdbc_cdhints.value.ul = (ulong_t)hint;
72717836SJohn.Forte@Sun.COM
72727836SJohn.Forte@Sun.COM
72737836SJohn.Forte@Sun.COM return (0);
72747836SJohn.Forte@Sun.COM }
72757836SJohn.Forte@Sun.COM
72767836SJohn.Forte@Sun.COM
72777836SJohn.Forte@Sun.COM /*
72787836SJohn.Forte@Sun.COM * cd_kstat_add
72797836SJohn.Forte@Sun.COM *
72807836SJohn.Forte@Sun.COM * Installs all kstats and associated infrastructure (mutex, buffer),
72817836SJohn.Forte@Sun.COM * associated with a particular cache descriptor. This function is called
72827836SJohn.Forte@Sun.COM * when the cache descriptor is opened in _sd_open().
72837836SJohn.Forte@Sun.COM * "cd" -- cache descriptor number whose kstats we wish to add
72847836SJohn.Forte@Sun.COM * returns: 0 on success, -1 on failure
72857836SJohn.Forte@Sun.COM */
72867836SJohn.Forte@Sun.COM static int
72877836SJohn.Forte@Sun.COM cd_kstat_add(int cd)
72887836SJohn.Forte@Sun.COM {
72897836SJohn.Forte@Sun.COM char name[KSTAT_STRLEN];
72907836SJohn.Forte@Sun.COM
72917836SJohn.Forte@Sun.COM if (cd < 0 || cd >= sdbc_max_devs) {
7292*9093SRamana.Srikanth@Sun.COM cmn_err(CE_WARN, "!invalid cache descriptor: %d", cd);
72937836SJohn.Forte@Sun.COM return (-1);
72947836SJohn.Forte@Sun.COM }
72957836SJohn.Forte@Sun.COM
72967836SJohn.Forte@Sun.COM /* create a regular kstat for this cache descriptor */
72977836SJohn.Forte@Sun.COM if (!sdbc_cd_kstats) {
7298*9093SRamana.Srikanth@Sun.COM cmn_err(CE_WARN, "!sdbc_cd_kstats not allocated");
72997836SJohn.Forte@Sun.COM return (-1);
73007836SJohn.Forte@Sun.COM }
73017836SJohn.Forte@Sun.COM
73027836SJohn.Forte@Sun.COM (void) snprintf(name, KSTAT_STRLEN, "%s%d", SDBC_KSTAT_CDSTATS, cd);
73037836SJohn.Forte@Sun.COM
73047836SJohn.Forte@Sun.COM sdbc_cd_kstats[cd] = kstat_create(SDBC_KSTAT_MODULE,
73057836SJohn.Forte@Sun.COM cd, name, SDBC_KSTAT_CLASS, KSTAT_TYPE_NAMED,
73067836SJohn.Forte@Sun.COM sizeof (sdbc_cd_stats)/sizeof (kstat_named_t),
73077836SJohn.Forte@Sun.COM KSTAT_FLAG_VIRTUAL|KSTAT_FLAG_WRITABLE);
73087836SJohn.Forte@Sun.COM
73097836SJohn.Forte@Sun.COM if (sdbc_cd_kstats[cd] != NULL) {
73107836SJohn.Forte@Sun.COM sdbc_cd_kstats[cd]->ks_data = &sdbc_cd_stats;
73117836SJohn.Forte@Sun.COM sdbc_cd_kstats[cd]->ks_update = sdbc_cd_stats_update;
73127836SJohn.Forte@Sun.COM sdbc_cd_kstats[cd]->ks_private =
73137836SJohn.Forte@Sun.COM &_sd_cache_stats->st_shared[cd];
73147836SJohn.Forte@Sun.COM kstat_install(sdbc_cd_kstats[cd]);
73157836SJohn.Forte@Sun.COM } else {
7316*9093SRamana.Srikanth@Sun.COM cmn_err(CE_WARN, "!cdstats %d kstat allocation failed", cd);
73177836SJohn.Forte@Sun.COM }
73187836SJohn.Forte@Sun.COM
73197836SJohn.Forte@Sun.COM /* create an I/O kstat for this cache descriptor */
73207836SJohn.Forte@Sun.COM if (!sdbc_cd_io_kstats) {
7321*9093SRamana.Srikanth@Sun.COM cmn_err(CE_WARN, "!sdbc_cd_io_kstats not allocated");
73227836SJohn.Forte@Sun.COM return (-1);
73237836SJohn.Forte@Sun.COM }
73247836SJohn.Forte@Sun.COM
73257836SJohn.Forte@Sun.COM (void) snprintf(name, KSTAT_STRLEN, "%s%d", SDBC_IOKSTAT_CDSTATS, cd);
73267836SJohn.Forte@Sun.COM
73277836SJohn.Forte@Sun.COM sdbc_cd_io_kstats[cd] = kstat_create(
73287836SJohn.Forte@Sun.COM SDBC_KSTAT_MODULE, cd, name, "disk", KSTAT_TYPE_IO, 1, 0);
73297836SJohn.Forte@Sun.COM
73307836SJohn.Forte@Sun.COM if (sdbc_cd_io_kstats[cd]) {
73317836SJohn.Forte@Sun.COM if (!sdbc_cd_io_kstats_mutexes) {
7332*9093SRamana.Srikanth@Sun.COM cmn_err(CE_WARN, "!sdbc_cd_io_kstats_mutexes not "
73337836SJohn.Forte@Sun.COM "allocated");
73347836SJohn.Forte@Sun.COM return (-1);
73357836SJohn.Forte@Sun.COM }
73367836SJohn.Forte@Sun.COM
73377836SJohn.Forte@Sun.COM mutex_init(&sdbc_cd_io_kstats_mutexes[cd], NULL,
73387836SJohn.Forte@Sun.COM MUTEX_DRIVER, NULL);
73397836SJohn.Forte@Sun.COM
73407836SJohn.Forte@Sun.COM sdbc_cd_io_kstats[cd]->ks_lock = &sdbc_cd_io_kstats_mutexes[cd];
73417836SJohn.Forte@Sun.COM
73427836SJohn.Forte@Sun.COM kstat_install(sdbc_cd_io_kstats[cd]);
73437836SJohn.Forte@Sun.COM
73447836SJohn.Forte@Sun.COM } else {
7345*9093SRamana.Srikanth@Sun.COM cmn_err(CE_WARN, "!sdbc cd %d io kstat allocation failed", cd);
73467836SJohn.Forte@Sun.COM }
73477836SJohn.Forte@Sun.COM
73487836SJohn.Forte@Sun.COM return (0);
73497836SJohn.Forte@Sun.COM }
73507836SJohn.Forte@Sun.COM
73517836SJohn.Forte@Sun.COM /*
73527836SJohn.Forte@Sun.COM * cd_kstat_remove
73537836SJohn.Forte@Sun.COM *
73547836SJohn.Forte@Sun.COM * Uninstalls all kstats and associated infrastructure (mutex, buffer),
73557836SJohn.Forte@Sun.COM * associated with a particular cache descriptor. This function is called
73567836SJohn.Forte@Sun.COM * when the cache descriptor is closed in _sd_close().
73577836SJohn.Forte@Sun.COM * "cd" -- cache descriptor number whose kstats we wish to remove
73587836SJohn.Forte@Sun.COM * returns: 0 on success, -1 on failure
73597836SJohn.Forte@Sun.COM */
73607836SJohn.Forte@Sun.COM static int
73617836SJohn.Forte@Sun.COM cd_kstat_remove(int cd)
73627836SJohn.Forte@Sun.COM {
73637836SJohn.Forte@Sun.COM if (cd < 0 || cd >= sdbc_max_devs) {
7364*9093SRamana.Srikanth@Sun.COM cmn_err(CE_WARN, "!invalid cache descriptor: %d", cd);
73657836SJohn.Forte@Sun.COM return (-1);
73667836SJohn.Forte@Sun.COM }
73677836SJohn.Forte@Sun.COM
73687836SJohn.Forte@Sun.COM /* delete the regular kstat corresponding to this cache descriptor */
73697836SJohn.Forte@Sun.COM if (sdbc_cd_kstats && sdbc_cd_kstats[cd]) {
73707836SJohn.Forte@Sun.COM kstat_delete(sdbc_cd_kstats[cd]);
73717836SJohn.Forte@Sun.COM sdbc_cd_kstats[cd] = NULL;
73727836SJohn.Forte@Sun.COM }
73737836SJohn.Forte@Sun.COM
73747836SJohn.Forte@Sun.COM /* delete the I/O kstat corresponding to this cache descriptor */
73757836SJohn.Forte@Sun.COM if (sdbc_cd_io_kstats && sdbc_cd_io_kstats[cd]) {
73767836SJohn.Forte@Sun.COM kstat_delete(sdbc_cd_io_kstats[cd]);
73777836SJohn.Forte@Sun.COM sdbc_cd_io_kstats[cd] = NULL;
73787836SJohn.Forte@Sun.COM
73797836SJohn.Forte@Sun.COM if (sdbc_cd_io_kstats_mutexes) {
73807836SJohn.Forte@Sun.COM /* destroy the mutex associated with this I/O kstat */
73817836SJohn.Forte@Sun.COM mutex_destroy(&sdbc_cd_io_kstats_mutexes[cd]);
73827836SJohn.Forte@Sun.COM }
73837836SJohn.Forte@Sun.COM }
73847836SJohn.Forte@Sun.COM
73857836SJohn.Forte@Sun.COM return (0);
73867836SJohn.Forte@Sun.COM }
73877836SJohn.Forte@Sun.COM
73887836SJohn.Forte@Sun.COM #ifdef DEBUG
73897836SJohn.Forte@Sun.COM /*
73907836SJohn.Forte@Sun.COM * kstat update
73917836SJohn.Forte@Sun.COM */
73927836SJohn.Forte@Sun.COM int
73937836SJohn.Forte@Sun.COM sdbc_dynmem_kstat_update_dm(kstat_t *ksp, int rw)
73947836SJohn.Forte@Sun.COM {
73957836SJohn.Forte@Sun.COM sdbc_dynmem_dm_t *sdbc_dynmem;
73967836SJohn.Forte@Sun.COM _dm_process_vars_t *process_vars;
73977836SJohn.Forte@Sun.COM _dm_process_vars_t local_dm_process_vars;
73987836SJohn.Forte@Sun.COM
73997836SJohn.Forte@Sun.COM simplect_dm++;
74007836SJohn.Forte@Sun.COM
74017836SJohn.Forte@Sun.COM sdbc_dynmem = (sdbc_dynmem_dm_t *)(ksp->ks_data);
74027836SJohn.Forte@Sun.COM
74037836SJohn.Forte@Sun.COM /* global dynmem_processing_dm */
74047836SJohn.Forte@Sun.COM process_vars = (_dm_process_vars_t *)(ksp->ks_private);
74057836SJohn.Forte@Sun.COM
74067836SJohn.Forte@Sun.COM if (rw == KSTAT_WRITE) {
74077836SJohn.Forte@Sun.COM simplect_dm = sdbc_dynmem->ci_sdbc_simplect.value.ul;
74087836SJohn.Forte@Sun.COM local_dm_process_vars.monitor_dynmem_process =
74097836SJohn.Forte@Sun.COM sdbc_dynmem->ci_sdbc_monitor_dynmem.value.ul;
74107836SJohn.Forte@Sun.COM local_dm_process_vars.max_dyn_list =
74117836SJohn.Forte@Sun.COM sdbc_dynmem->ci_sdbc_max_dyn_list.value.ul;
74127836SJohn.Forte@Sun.COM local_dm_process_vars.cache_aging_ct1 =
74137836SJohn.Forte@Sun.COM sdbc_dynmem->ci_sdbc_cache_aging_ct1.value.ul;
74147836SJohn.Forte@Sun.COM local_dm_process_vars.cache_aging_ct2 =
74157836SJohn.Forte@Sun.COM sdbc_dynmem->ci_sdbc_cache_aging_ct2.value.ul;
74167836SJohn.Forte@Sun.COM local_dm_process_vars.cache_aging_ct3 =
74177836SJohn.Forte@Sun.COM sdbc_dynmem->ci_sdbc_cache_aging_ct3.value.ul;
74187836SJohn.Forte@Sun.COM local_dm_process_vars.cache_aging_sec1 =
74197836SJohn.Forte@Sun.COM sdbc_dynmem->ci_sdbc_cache_aging_sec1.value.ul;
74207836SJohn.Forte@Sun.COM local_dm_process_vars.cache_aging_sec2 =
74217836SJohn.Forte@Sun.COM sdbc_dynmem->ci_sdbc_cache_aging_sec2.value.ul;
74227836SJohn.Forte@Sun.COM local_dm_process_vars.cache_aging_sec3 =
74237836SJohn.Forte@Sun.COM sdbc_dynmem->ci_sdbc_cache_aging_sec3.value.ul;
74247836SJohn.Forte@Sun.COM local_dm_process_vars.cache_aging_pcnt1 =
74257836SJohn.Forte@Sun.COM sdbc_dynmem->ci_sdbc_cache_aging_pcnt1.value.ul;
74267836SJohn.Forte@Sun.COM local_dm_process_vars.cache_aging_pcnt2 =
74277836SJohn.Forte@Sun.COM sdbc_dynmem->ci_sdbc_cache_aging_pcnt2.value.ul;
74287836SJohn.Forte@Sun.COM local_dm_process_vars.max_holds_pcnt =
74297836SJohn.Forte@Sun.COM sdbc_dynmem->ci_sdbc_max_holds_pcnt.value.ul;
74307836SJohn.Forte@Sun.COM local_dm_process_vars.process_directive =
74317836SJohn.Forte@Sun.COM sdbc_dynmem->ci_sdbc_process_directive.value.ul;
74327836SJohn.Forte@Sun.COM (void) sdbc_edit_xfer_process_vars_dm(&local_dm_process_vars);
74337836SJohn.Forte@Sun.COM
74347836SJohn.Forte@Sun.COM if (process_vars->process_directive & WAKE_DEALLOC_THREAD_DM) {
74357836SJohn.Forte@Sun.COM process_vars->process_directive &=
74367836SJohn.Forte@Sun.COM ~WAKE_DEALLOC_THREAD_DM;
74377836SJohn.Forte@Sun.COM mutex_enter(&dynmem_processing_dm.thread_dm_lock);
74387836SJohn.Forte@Sun.COM cv_broadcast(&dynmem_processing_dm.thread_dm_cv);
74397836SJohn.Forte@Sun.COM mutex_exit(&dynmem_processing_dm.thread_dm_lock);
74407836SJohn.Forte@Sun.COM }
74417836SJohn.Forte@Sun.COM
74427836SJohn.Forte@Sun.COM return (0);
74437836SJohn.Forte@Sun.COM }
74447836SJohn.Forte@Sun.COM
74457836SJohn.Forte@Sun.COM /* default to READ */
74467836SJohn.Forte@Sun.COM sdbc_dynmem->ci_sdbc_simplect.value.ul = simplect_dm;
74477836SJohn.Forte@Sun.COM sdbc_dynmem->ci_sdbc_monitor_dynmem.value.ul =
74487836SJohn.Forte@Sun.COM process_vars->monitor_dynmem_process;
74497836SJohn.Forte@Sun.COM sdbc_dynmem->ci_sdbc_max_dyn_list.value.ul =
74507836SJohn.Forte@Sun.COM process_vars->max_dyn_list;
74517836SJohn.Forte@Sun.COM sdbc_dynmem->ci_sdbc_cache_aging_ct1.value.ul =
74527836SJohn.Forte@Sun.COM process_vars->cache_aging_ct1;
74537836SJohn.Forte@Sun.COM sdbc_dynmem->ci_sdbc_cache_aging_ct2.value.ul =
74547836SJohn.Forte@Sun.COM process_vars->cache_aging_ct2;
74557836SJohn.Forte@Sun.COM sdbc_dynmem->ci_sdbc_cache_aging_ct3.value.ul =
74567836SJohn.Forte@Sun.COM process_vars->cache_aging_ct3;
74577836SJohn.Forte@Sun.COM sdbc_dynmem->ci_sdbc_cache_aging_sec1.value.ul =
74587836SJohn.Forte@Sun.COM process_vars->cache_aging_sec1;
74597836SJohn.Forte@Sun.COM sdbc_dynmem->ci_sdbc_cache_aging_sec2.value.ul =
74607836SJohn.Forte@Sun.COM process_vars->cache_aging_sec2;
74617836SJohn.Forte@Sun.COM sdbc_dynmem->ci_sdbc_cache_aging_sec3.value.ul =
74627836SJohn.Forte@Sun.COM process_vars->cache_aging_sec3;
74637836SJohn.Forte@Sun.COM sdbc_dynmem->ci_sdbc_cache_aging_pcnt1.value.ul =
74647836SJohn.Forte@Sun.COM process_vars->cache_aging_pcnt1;
74657836SJohn.Forte@Sun.COM sdbc_dynmem->ci_sdbc_cache_aging_pcnt2.value.ul =
74667836SJohn.Forte@Sun.COM process_vars->cache_aging_pcnt2;
74677836SJohn.Forte@Sun.COM sdbc_dynmem->ci_sdbc_max_holds_pcnt.value.ul =
74687836SJohn.Forte@Sun.COM process_vars->max_holds_pcnt;
74697836SJohn.Forte@Sun.COM sdbc_dynmem->ci_sdbc_process_directive.value.ul =
74707836SJohn.Forte@Sun.COM process_vars->process_directive;
74717836SJohn.Forte@Sun.COM
74727836SJohn.Forte@Sun.COM sdbc_dynmem->ci_sdbc_alloc_ct.value.ul = process_vars->alloc_ct;
74737836SJohn.Forte@Sun.COM sdbc_dynmem->ci_sdbc_dealloc_ct.value.ul = process_vars->dealloc_ct;
74747836SJohn.Forte@Sun.COM sdbc_dynmem->ci_sdbc_history.value.ul = process_vars->history;
74757836SJohn.Forte@Sun.COM sdbc_dynmem->ci_sdbc_nodatas.value.ul = process_vars->nodatas;
74767836SJohn.Forte@Sun.COM sdbc_dynmem->ci_sdbc_candidates.value.ul = process_vars->candidates;
74777836SJohn.Forte@Sun.COM sdbc_dynmem->ci_sdbc_deallocs.value.ul = process_vars->deallocs;
74787836SJohn.Forte@Sun.COM sdbc_dynmem->ci_sdbc_hosts.value.ul = process_vars->hosts;
74797836SJohn.Forte@Sun.COM sdbc_dynmem->ci_sdbc_pests.value.ul = process_vars->pests;
74807836SJohn.Forte@Sun.COM sdbc_dynmem->ci_sdbc_metas.value.ul = process_vars->metas;
74817836SJohn.Forte@Sun.COM sdbc_dynmem->ci_sdbc_holds.value.ul = process_vars->holds;
74827836SJohn.Forte@Sun.COM sdbc_dynmem->ci_sdbc_others.value.ul = process_vars->others;
74837836SJohn.Forte@Sun.COM sdbc_dynmem->ci_sdbc_notavail.value.ul = process_vars->notavail;
74847836SJohn.Forte@Sun.COM
74857836SJohn.Forte@Sun.COM return (0);
74867836SJohn.Forte@Sun.COM }
74877836SJohn.Forte@Sun.COM #endif
7488