fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * CDDL HEADER START
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * The contents of this file are subject to the terms of the
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Common Development and Distribution License (the "License").
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * You may not use this file except in compliance with the License.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * See the License for the specific language governing permissions
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * and limitations under the License.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * When distributing Covered Code, include this CDDL HEADER in each
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * If applicable, add the following below this CDDL HEADER, with the
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * fields enclosed by brackets "[]" replaced with your own identifying
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * information: Portions Copyright [yyyy] [name of copyright owner]
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * CDDL HEADER END
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Use is subject to license terms.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * _sdbd_trace_t _sd_trace_table[-1, 0 .. sdbc_max_devs - 1]
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * allocate memory, shift pointer up by one.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte#define XMEM(x, y) (void)(x = y, y = (SDT_ANY_CD), x)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Forward declare all statics that are used before defined to enforce
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * parameter checking.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Some (if not all) of these could be removed if the code were reordered
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestatic int _sd_set_adump(int cd, int flag, _sdtr_table_t *table);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * _sdbc_tr_unload - cache is being unloaded. Release any memory/lock/sv's
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * created by _sdbc_tr_unload and null the stale pointers.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * _sdbc_tr_load - cache is being loaded. Allocate the memory/lock/sv's
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * which need to be present regardless of state of cache configuration.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte mutex_init(&_sd_adump_lk, NULL, MUTEX_DRIVER, NULL);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * this maybe ought to wait to see if traces are configured, but it
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * is only 4k
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte "sdbc(_sdbc_tr_load) cannot allocate trace table");
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return (-1);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * _sdbc_tr_configure - configure a trace area for the descriptor "cd".
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Unlike other ..._configure routines this routine is called multiple
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * times since there will be an unknown number of open descriptors. At
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * cache config time if tracing is enabled only the slot for SDT_INV_CD
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * is created.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Allocate the SD cache trace area (per device)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte cmn_err(CE_WARN, "sdbc(_sdbc_tr_configure) failed to "
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return (-1);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte lk = nsc_kmem_zalloc(sizeof (kmutex_t), KM_NOSLEEP, sdbc_local_mem);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte cmn_err(CE_WARN, "sdbc(_sdbc_tr_configure) cannot "
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return (-1);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte t->tt_lbolt = (char)_sd_cache_config.trace_lbolt;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * _sdbc_tr_deconfigure
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * free all trace memory (regions) when deconfiguring cache
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (!_sd_cache_config.trace_size || !_sd_trace_configed)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte for (i = -1, tt = &_sd_trace_table[-1]; i < sdbc_max_devs; i++, tt++) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * SDALERT(f,cd,len,fba,flg,ret) \
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * _sd_alert(f,cd,len,fba,flg,ret)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Build a ALERT trace entry and place it into the trace table.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte_sd_alert(int f, int cd, int len, nsc_off_t fba, int flg, int ret)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte "sdbc(_sd_alert) cd=%x f=%x len=%x fba=%" NSC_SZFMT
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Watch out for negative error codes or simply bogus cd's */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * no device trace buffer -- use SDT_INV_CD table?
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * no device trace buffer -- use SDT_INV_CD table?
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return; /* check per-device mask */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte t->tt_cnt++; /* overwritten entries if (tt_cnt >= tt_max) */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * On LP64 systems we will only capture the low 32 bits of the
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * time this really should be good enough for our purposes.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* wakeup trace daemon, with hint */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * SDTRACE(f,cd,len,fba,flg,ret) \
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * if (_sd_trace_mask & (f)) _sd_trace(f,cd,len,fba,flg,ret)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Build a trace entry and place it into the trace table.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte_sd_trace(int f, int cd, int len, nsc_off_t fba, int flg, int ret)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Watch out for negative error codes or simply bogus cd's */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * no device trace buffer -- use SDT_INV_CD table?
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (!(t->tt_mask & f))
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return; /* check per-device mask */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Don't overwrite if alert signaled (count lost instead)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Locking only if 'trace_good' parameter set.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte t->tt_cnt++; /* overwritten entries if (tt_cnt >= tt_max) */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * On LP64 systems we will only capture the low 32 bits of the
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * time this really should be good enough for our purposes.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * _sd_scan_alert -- search for device with trace alert
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((cd != SDT_ANY_CD) && _sd_trace_table[cd].tbl->tt_alert)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte for (cd = _last_cd + 1; cd < sdbc_max_devs; cd++)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * _sd_scan_entries -- search for next device with trace entries
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte for (cd = _last_cd + 1; cd < sdbc_max_devs; cd++)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (_sd_trace_table[cd].tbl && _sd_trace_table[cd].tbl->tt_cnt)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (_sd_trace_table[cd].tbl && _sd_trace_table[cd].tbl->tt_cnt)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * copy information about new trace records to trace daemon,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * or modify trace parameters.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Some tracing parameters can be modified
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * [Either per-device if cd specified, or the defaults if cd = SDT_ANY_CD]
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * SD_LOGSIZE: table.tt_max (size for future opens)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * SD_SET_LBOLT: table.tt_lbolt
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * SD_SET_MASK: table.tt_mask
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * SD_SET_GOOD: table.tt_good
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * if (cd >= 0) dump specific device records;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * if (cd == SDT_INV_CD) dump records which don't apply to any one device.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * if (cd == SDT_ANY_CD), then choose a device:
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * 1) most recent alert, block if (flag & SD_ALERT_WAIT)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * 2) "next" device with unprocessed records.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (uap->flag & (SD_SET_SIZE|SD_SET_MASK|SD_SET_LBOLT|SD_SET_GOOD)) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return (_sd_set_adump(uap->cd, uap->flag, uap->table));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* specific device: check if configured. dump current state. */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * SDT_ANY_CD:
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * SD_ALERT_WAIT - wait for alert
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (!cv_wait_sig(&_sd_adump_cv, &_sd_adump_lk)) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (!_sd_trace_configed || !_sd_cache_initialized) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* any device with entries */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return (0); /* no new entries */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * take a snapshot of the table state
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * copy trace log entries to daemon
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * size: entries in user-level 'buf'
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * count: how many entries to copy [force count <= size]
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * tt_max: size of kernel buffer
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * tt_cnt: written entries [lossage if tt_cnt > tt_max]
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * cnt: for wrap-around calculations
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((count = tt.tt_cnt) > tt.tt_max) { /* lost from beginning */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (copyout(&(t->tt_buf[0]), ubuf, cnt * sizeof (_sdtr_t))) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * tt_alert uses fuzzy counting.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * if multiple alerts signaled, leave it at 1.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * tt_cntout is tt_cnt after dump
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * update tt_cnt for copied entries
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte t->tt_cnt = new_cnt; /* race with new traces if not "tt_good" */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (copyout(&tt, uap->table, sizeof (tt) - sizeof (_sdtr_t))) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/* set size, mask, lbolt, or good(locks) */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte_sd_set_adump(int cd, int flag, _sdtr_table_t *table)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (copyin(table, &tt, sizeof (tt) - sizeof (_sdtr_t))) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (cd == SDT_ANY_CD) { /* modify config parameter */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* explicitly set global mask, not bitwise or */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* modify particular device parameters */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte _sd_trace_mask |= tt.tt_mask; /* or-ed with global mask */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (copyout(t, table, sizeof (*t) - sizeof (_sdtr_t))) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte#else /* ! _SD_NOTRACE */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte#endif /* ! _SD_NOTRACE */