facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai/*
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * CDDL HEADER START
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai *
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * The contents of this file are subject to the terms of the
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * Common Development and Distribution License (the "License").
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * You may not use this file except in compliance with the License.
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai *
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * or http://www.opensolaris.org/os/licensing.
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * See the License for the specific language governing permissions
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * and limitations under the License.
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai *
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * When distributing Covered Code, include this CDDL HEADER in each
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * If applicable, add the following below this CDDL HEADER, with the
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * fields enclosed by brackets "[]" replaced with your own identifying
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * information: Portions Copyright [yyyy] [name of copyright owner]
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai *
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * CDDL HEADER END
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai/*
89dfdb3f985a88e7d40543a4bf41dc09d44b9fdeSrikanth, Ramana * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * Use is subject to license terms.
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai/*
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * negative cache handling for the /dev fs
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai#include <sys/types.h>
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai#include <sys/param.h>
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai#include <sys/t_lock.h>
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai#include <sys/systm.h>
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai#include <sys/sysmacros.h>
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai#include <sys/user.h>
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai#include <sys/time.h>
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai#include <sys/vfs.h>
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai#include <sys/vnode.h>
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai#include <sys/file.h>
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai#include <sys/fcntl.h>
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai#include <sys/flock.h>
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai#include <sys/kmem.h>
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai#include <sys/uio.h>
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai#include <sys/errno.h>
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai#include <sys/stat.h>
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai#include <sys/cred.h>
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai#include <sys/cmn_err.h>
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai#include <sys/debug.h>
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai#include <sys/mode.h>
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai#include <sys/policy.h>
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai#include <fs/fs_subr.h>
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai#include <sys/mount.h>
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai#include <sys/fs/snode.h>
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai#include <sys/fs/dv_node.h>
3c5e027b0f15017d4b6afff01915ea70ae476223Eric Taylor#include <sys/fs/sdev_impl.h>
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai#include <sys/sunndi.h>
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai#include <sys/sunmdi.h>
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai#include <sys/ddi.h>
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai#include <sys/modctl.h>
83c4dfe9546fd839e7a52bca7e9920da918f916ejg#include <sys/devcache.h>
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai/*
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * ncache is a negative cache of failed lookups. An entry
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * is added after an attempt to configure a device by that
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * name failed. An accumulation of these entries over time
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * gives us a set of device name for which implicit reconfiguration
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * does not need to be attempted. If a name is created matching
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * an entry in ncache, that entry is removed, with the
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * persistent store updated.
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai *
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * Implicit reconfig is initiated for any name during lookup that
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * can't be resolved from the backing store and that isn't
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * present in the negative cache. This functionality is
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * enabled during system startup once communication with devfsadm
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * can be achieved. Since readdir is more general, implicit
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * reconfig initiated by reading a directory isn't enabled until
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * the system is more fully booted, at the time of the multi-user
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * milestone, corresponding to init state 2.
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai *
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * A maximum is imposed on the number of entries in the cache
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * to limit some script going wild and as a defense against attack.
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * The default limit is 64 and can be adjusted via sdev_nc_max_entries.
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai *
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * Each entry also has a expiration count. When looked up a name in
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * the cache is set to the default. Subsequent boots will decrement
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * the count if a name isn't referenced. This permits a once-only
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * entry to eventually be removed over time.
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai *
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * sdev_reconfig_delay implements a "debounce" of the timing beyond
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * system available indication, providing what the filesystem considers
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * to be the system-is-fully-booted state. This is provided to adjust
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * the timing if some application startup is performing a readdir
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * in /dev that initiates a troublesome implicit reconfig on every boot.
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai *
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * sdev_nc_disable_reset can be used to disable clearing the negative cache
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * on reconfig boot. The default is to clear the cache on reconfig boot.
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * sdev_nc_disable can be used to disable the negative cache itself.
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai *
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * sdev_reconfig_disable can be used to disable implicit reconfig.
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * The default is that implicit reconfig is enabled.
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai/* tunables and defaults */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai#define SDEV_NC_EXPIRECNT 4
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai#define SDEV_NC_MAX_ENTRIES 64
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai#define SEV_RECONFIG_DELAY 6 /* seconds */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
83c4dfe9546fd839e7a52bca7e9920da918f916ejg/* tunables */
83c4dfe9546fd839e7a52bca7e9920da918f916ejgint sdev_nc_expirecnt = SDEV_NC_EXPIRECNT;
83c4dfe9546fd839e7a52bca7e9920da918f916ejgint sdev_nc_max_entries = SDEV_NC_MAX_ENTRIES;
83c4dfe9546fd839e7a52bca7e9920da918f916ejgint sdev_reconfig_delay = SEV_RECONFIG_DELAY;
83c4dfe9546fd839e7a52bca7e9920da918f916ejgint sdev_reconfig_verbose = 0;
83c4dfe9546fd839e7a52bca7e9920da918f916ejgint sdev_reconfig_disable = 0;
83c4dfe9546fd839e7a52bca7e9920da918f916ejgint sdev_nc_disable = 0;
83c4dfe9546fd839e7a52bca7e9920da918f916ejgint sdev_nc_disable_reset = 0;
83c4dfe9546fd839e7a52bca7e9920da918f916ejgint sdev_nc_verbose = 0;
83c4dfe9546fd839e7a52bca7e9920da918f916ejgint sdev_cache_read_disable = 0;
83c4dfe9546fd839e7a52bca7e9920da918f916ejgint sdev_cache_write_disable = 0;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai/* globals */
83c4dfe9546fd839e7a52bca7e9920da918f916ejgint sdev_boot_state = SDEV_BOOT_STATE_INITIAL;
83c4dfe9546fd839e7a52bca7e9920da918f916ejgint sdev_reconfig_boot = 0;
83c4dfe9546fd839e7a52bca7e9920da918f916ejgsdev_nc_list_t *sdev_ncache;
83c4dfe9546fd839e7a52bca7e9920da918f916ejgstatic nvf_handle_t sdevfd_handle;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai/* static prototypes */
83c4dfe9546fd839e7a52bca7e9920da918f916ejgstatic void sdev_ncache_write_complete(nvf_handle_t);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaistatic void sdev_ncache_write(void);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaistatic void sdev_ncache_process_store(void);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaistatic sdev_nc_list_t *sdev_nc_newlist(void);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaistatic void sdev_nc_free_unlinked_node(sdev_nc_node_t *);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaistatic sdev_nc_node_t *sdev_nc_findpath(sdev_nc_list_t *, char *);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaistatic void sdev_nc_insertnode(sdev_nc_list_t *, sdev_nc_node_t *);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaistatic void sdev_nc_free_bootonly(void);
83c4dfe9546fd839e7a52bca7e9920da918f916ejgstatic int sdev_ncache_unpack_nvlist(nvf_handle_t, nvlist_t *, char *);
83c4dfe9546fd839e7a52bca7e9920da918f916ejgstatic int sdev_ncache_pack_list(nvf_handle_t, nvlist_t **);
83c4dfe9546fd839e7a52bca7e9920da918f916ejgstatic void sdev_ncache_list_free(nvf_handle_t);
83c4dfe9546fd839e7a52bca7e9920da918f916ejgstatic void sdev_nvp_free(nvp_devname_t *);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
83c4dfe9546fd839e7a52bca7e9920da918f916ejg/*
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * Registration for /etc/devices/devname_cache
83c4dfe9546fd839e7a52bca7e9920da918f916ejg */
83c4dfe9546fd839e7a52bca7e9920da918f916ejgstatic nvf_ops_t sdev_cache_ops = {
83c4dfe9546fd839e7a52bca7e9920da918f916ejg "/etc/devices/devname_cache", /* path to cache */
83c4dfe9546fd839e7a52bca7e9920da918f916ejg sdev_ncache_unpack_nvlist, /* read: unpack nvlist */
83c4dfe9546fd839e7a52bca7e9920da918f916ejg sdev_ncache_pack_list, /* write: pack list */
83c4dfe9546fd839e7a52bca7e9920da918f916ejg sdev_ncache_list_free, /* free data list */
83c4dfe9546fd839e7a52bca7e9920da918f916ejg sdev_ncache_write_complete /* write complete callback */
83c4dfe9546fd839e7a52bca7e9920da918f916ejg};
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai/*
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * called once at filesystem initialization
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaivoid
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaisdev_ncache_init(void)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai{
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai sdev_ncache = sdev_nc_newlist();
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai}
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai/*
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * called at mount of the global instance
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * currently the global instance is never unmounted
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaivoid
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaisdev_ncache_setup(void)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai{
83c4dfe9546fd839e7a52bca7e9920da918f916ejg sdevfd_handle = nvf_register_file(&sdev_cache_ops);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg ASSERT(sdevfd_handle);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
83c4dfe9546fd839e7a52bca7e9920da918f916ejg list_create(nvf_list(sdevfd_handle), sizeof (nvp_devname_t),
83c4dfe9546fd839e7a52bca7e9920da918f916ejg offsetof(nvp_devname_t, nvp_link));
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
83c4dfe9546fd839e7a52bca7e9920da918f916ejg rw_enter(nvf_lock(sdevfd_handle), RW_WRITER);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg if (!sdev_cache_read_disable) {
83c4dfe9546fd839e7a52bca7e9920da918f916ejg (void) nvf_read_file(sdevfd_handle);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai sdev_ncache_process_store();
83c4dfe9546fd839e7a52bca7e9920da918f916ejg rw_exit(nvf_lock(sdevfd_handle));
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai sdev_devstate_change();
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai}
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaistatic void
83c4dfe9546fd839e7a52bca7e9920da918f916ejgsdev_nvp_free(nvp_devname_t *dp)
83c4dfe9546fd839e7a52bca7e9920da918f916ejg{
83c4dfe9546fd839e7a52bca7e9920da918f916ejg int i;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg char **p;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejg if (dp->nvp_npaths > 0) {
83c4dfe9546fd839e7a52bca7e9920da918f916ejg p = dp->nvp_paths;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg for (i = 0; i < dp->nvp_npaths; i++, p++) {
83c4dfe9546fd839e7a52bca7e9920da918f916ejg kmem_free(*p, strlen(*p)+1);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg }
83c4dfe9546fd839e7a52bca7e9920da918f916ejg kmem_free(dp->nvp_paths,
3c5e027b0f15017d4b6afff01915ea70ae476223Eric Taylor dp->nvp_npaths * sizeof (char *));
83c4dfe9546fd839e7a52bca7e9920da918f916ejg kmem_free(dp->nvp_expirecnts,
3c5e027b0f15017d4b6afff01915ea70ae476223Eric Taylor dp->nvp_npaths * sizeof (int));
83c4dfe9546fd839e7a52bca7e9920da918f916ejg }
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejg kmem_free(dp, sizeof (nvp_devname_t));
83c4dfe9546fd839e7a52bca7e9920da918f916ejg}
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejgstatic void
83c4dfe9546fd839e7a52bca7e9920da918f916ejgsdev_ncache_list_free(nvf_handle_t fd)
83c4dfe9546fd839e7a52bca7e9920da918f916ejg{
83c4dfe9546fd839e7a52bca7e9920da918f916ejg list_t *listp;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg nvp_devname_t *dp;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejg ASSERT(fd == sdevfd_handle);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg ASSERT(RW_WRITE_HELD(nvf_lock(fd)));
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejg listp = nvf_list(fd);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg if ((dp = list_head(listp)) != NULL) {
83c4dfe9546fd839e7a52bca7e9920da918f916ejg list_remove(listp, dp);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg sdev_nvp_free(dp);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg }
83c4dfe9546fd839e7a52bca7e9920da918f916ejg}
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejg/*
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * Unpack a device path/nvlist pair to internal data list format.
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * Used to decode the nvlist format into the internal representation
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * when reading /etc/devices/devname_cache.
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * Note that the expiration counts are optional, for compatibility
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * with earlier instances of the cache. If not present, the
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * expire counts are initialized to defaults.
83c4dfe9546fd839e7a52bca7e9920da918f916ejg */
83c4dfe9546fd839e7a52bca7e9920da918f916ejgstatic int
83c4dfe9546fd839e7a52bca7e9920da918f916ejgsdev_ncache_unpack_nvlist(nvf_handle_t fd, nvlist_t *nvl, char *name)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai{
83c4dfe9546fd839e7a52bca7e9920da918f916ejg nvp_devname_t *np;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg char **strs;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg int *cnts;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg uint_t nstrs, ncnts;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg int rval, i;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejg ASSERT(fd == sdevfd_handle);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg ASSERT(RW_WRITE_HELD(nvf_lock(fd)));
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejg /* name of the sublist must match what we created */
83c4dfe9546fd839e7a52bca7e9920da918f916ejg if (strcmp(name, DP_DEVNAME_ID) != 0) {
83c4dfe9546fd839e7a52bca7e9920da918f916ejg return (-1);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg }
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejg np = kmem_zalloc(sizeof (nvp_devname_t), KM_SLEEP);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejg rval = nvlist_lookup_string_array(nvl,
83c4dfe9546fd839e7a52bca7e9920da918f916ejg DP_DEVNAME_NCACHE_ID, &strs, &nstrs);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg if (rval) {
83c4dfe9546fd839e7a52bca7e9920da918f916ejg kmem_free(np, sizeof (nvp_devname_t));
83c4dfe9546fd839e7a52bca7e9920da918f916ejg return (-1);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg }
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejg np->nvp_npaths = nstrs;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg np->nvp_paths = kmem_zalloc(nstrs * sizeof (char *), KM_SLEEP);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg for (i = 0; i < nstrs; i++) {
83c4dfe9546fd839e7a52bca7e9920da918f916ejg np->nvp_paths[i] = i_ddi_strdup(strs[i], KM_SLEEP);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg }
83c4dfe9546fd839e7a52bca7e9920da918f916ejg np->nvp_expirecnts = kmem_zalloc(nstrs * sizeof (int), KM_SLEEP);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg for (i = 0; i < nstrs; i++) {
83c4dfe9546fd839e7a52bca7e9920da918f916ejg np->nvp_expirecnts[i] = sdev_nc_expirecnt;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg }
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejg rval = nvlist_lookup_int32_array(nvl,
83c4dfe9546fd839e7a52bca7e9920da918f916ejg DP_DEVNAME_NC_EXPIRECNT_ID, &cnts, &ncnts);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg if (rval == 0) {
83c4dfe9546fd839e7a52bca7e9920da918f916ejg ASSERT(ncnts == nstrs);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg ncnts = min(ncnts, nstrs);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg for (i = 0; i < nstrs; i++) {
83c4dfe9546fd839e7a52bca7e9920da918f916ejg np->nvp_expirecnts[i] = cnts[i];
83c4dfe9546fd839e7a52bca7e9920da918f916ejg }
83c4dfe9546fd839e7a52bca7e9920da918f916ejg }
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejg list_insert_tail(nvf_list(sdevfd_handle), np);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejg return (0);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg}
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejg/*
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * Pack internal format cache data to a single nvlist.
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * Used when writing the nvlist file.
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * Note this is called indirectly by the nvpflush daemon.
83c4dfe9546fd839e7a52bca7e9920da918f916ejg */
83c4dfe9546fd839e7a52bca7e9920da918f916ejgstatic int
83c4dfe9546fd839e7a52bca7e9920da918f916ejgsdev_ncache_pack_list(nvf_handle_t fd, nvlist_t **ret_nvl)
83c4dfe9546fd839e7a52bca7e9920da918f916ejg{
83c4dfe9546fd839e7a52bca7e9920da918f916ejg nvlist_t *nvl, *sub_nvl;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai nvp_devname_t *np;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg int rval;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg list_t *listp;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
83c4dfe9546fd839e7a52bca7e9920da918f916ejg ASSERT(fd == sdevfd_handle);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg ASSERT(RW_WRITE_HELD(nvf_lock(fd)));
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejg rval = nvlist_alloc(&nvl, NV_UNIQUE_NAME, KM_SLEEP);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg if (rval != 0) {
83c4dfe9546fd839e7a52bca7e9920da918f916ejg nvf_error("%s: nvlist alloc error %d\n",
3c5e027b0f15017d4b6afff01915ea70ae476223Eric Taylor nvf_cache_name(fd), rval);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg return (DDI_FAILURE);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejg listp = nvf_list(sdevfd_handle);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg if ((np = list_head(listp)) != NULL) {
83c4dfe9546fd839e7a52bca7e9920da918f916ejg ASSERT(list_next(listp, np) == NULL);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejg rval = nvlist_alloc(&sub_nvl, NV_UNIQUE_NAME, KM_SLEEP);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg if (rval != 0) {
83c4dfe9546fd839e7a52bca7e9920da918f916ejg nvf_error("%s: nvlist alloc error %d\n",
3c5e027b0f15017d4b6afff01915ea70ae476223Eric Taylor nvf_cache_name(fd), rval);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg sub_nvl = NULL;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg goto err;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg }
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejg rval = nvlist_add_string_array(sub_nvl,
83c4dfe9546fd839e7a52bca7e9920da918f916ejg DP_DEVNAME_NCACHE_ID, np->nvp_paths, np->nvp_npaths);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg if (rval != 0) {
83c4dfe9546fd839e7a52bca7e9920da918f916ejg nvf_error("%s: nvlist add error %d (sdev)\n",
83c4dfe9546fd839e7a52bca7e9920da918f916ejg nvf_cache_name(fd), rval);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg goto err;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg }
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejg rval = nvlist_add_int32_array(sub_nvl,
83c4dfe9546fd839e7a52bca7e9920da918f916ejg DP_DEVNAME_NC_EXPIRECNT_ID,
83c4dfe9546fd839e7a52bca7e9920da918f916ejg np->nvp_expirecnts, np->nvp_npaths);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg if (rval != 0) {
83c4dfe9546fd839e7a52bca7e9920da918f916ejg nvf_error("%s: nvlist add error %d (sdev)\n",
83c4dfe9546fd839e7a52bca7e9920da918f916ejg nvf_cache_name(fd), rval);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg goto err;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg }
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejg rval = nvlist_add_nvlist(nvl, DP_DEVNAME_ID, sub_nvl);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg if (rval != 0) {
83c4dfe9546fd839e7a52bca7e9920da918f916ejg nvf_error("%s: nvlist add error %d (sublist)\n",
83c4dfe9546fd839e7a52bca7e9920da918f916ejg nvf_cache_name(fd), rval);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg goto err;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg }
83c4dfe9546fd839e7a52bca7e9920da918f916ejg nvlist_free(sub_nvl);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg }
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejg *ret_nvl = nvl;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg return (DDI_SUCCESS);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejgerr:
aab83bb83be7342f6cfccaed8d5fe0b2f404855dJosef 'Jeff' Sipek nvlist_free(sub_nvl);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg nvlist_free(nvl);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg *ret_nvl = NULL;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg return (DDI_FAILURE);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai}
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
83c4dfe9546fd839e7a52bca7e9920da918f916ejg/*
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * Run through the data read from the backing cache store
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * to establish the initial state of the neg. cache.
83c4dfe9546fd839e7a52bca7e9920da918f916ejg */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaistatic void
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaisdev_ncache_process_store(void)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai{
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai sdev_nc_list_t *ncl = sdev_ncache;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai nvp_devname_t *np;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai sdev_nc_node_t *lp;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai char *path;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai int i, n;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg list_t *listp;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (sdev_nc_disable)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai return;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
83c4dfe9546fd839e7a52bca7e9920da918f916ejg ASSERT(RW_WRITE_HELD(nvf_lock(sdevfd_handle)));
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejg listp = nvf_list(sdevfd_handle);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg for (np = list_head(listp); np; np = list_next(listp, np)) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai for (i = 0; i < np->nvp_npaths; i++) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai sdcmn_err5((" %s %d\n",
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai np->nvp_paths[i], np->nvp_expirecnts[i]));
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (ncl->ncl_nentries < sdev_nc_max_entries) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai path = np->nvp_paths[i];
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai n = strlen(path) + 1;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai lp = kmem_alloc(sizeof (sdev_nc_node_t),
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai KM_SLEEP);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai lp->ncn_name = kmem_alloc(n, KM_SLEEP);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai bcopy(path, lp->ncn_name, n);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai lp->ncn_flags = NCN_SRC_STORE;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai lp->ncn_expirecnt = np->nvp_expirecnts[i];
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai sdev_nc_insertnode(ncl, lp);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai } else if (sdev_nc_verbose) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai cmn_err(CE_CONT,
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai "?%s: truncating from ncache (max %d)\n",
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai np->nvp_paths[i], sdev_nc_max_entries);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai}
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
83c4dfe9546fd839e7a52bca7e9920da918f916ejg/*
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * called by nvpflush daemon to inform us that an update of
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * the cache file has been completed.
83c4dfe9546fd839e7a52bca7e9920da918f916ejg */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaistatic void
83c4dfe9546fd839e7a52bca7e9920da918f916ejgsdev_ncache_write_complete(nvf_handle_t fd)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai{
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai sdev_nc_list_t *ncl = sdev_ncache;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
83c4dfe9546fd839e7a52bca7e9920da918f916ejg ASSERT(fd == sdevfd_handle);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai mutex_enter(&ncl->ncl_mutex);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai ASSERT(ncl->ncl_flags & NCL_LIST_WRITING);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (ncl->ncl_flags & NCL_LIST_DIRTY) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai sdcmn_err5(("ncache write complete but dirty again\n"));
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai ncl->ncl_flags &= ~NCL_LIST_DIRTY;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai mutex_exit(&ncl->ncl_mutex);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai sdev_ncache_write();
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai } else {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai sdcmn_err5(("ncache write complete\n"));
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai ncl->ncl_flags &= ~NCL_LIST_WRITING;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai mutex_exit(&ncl->ncl_mutex);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg rw_enter(nvf_lock(fd), RW_WRITER);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg sdev_ncache_list_free(fd);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg rw_exit(nvf_lock(fd));
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai}
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
83c4dfe9546fd839e7a52bca7e9920da918f916ejg/*
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * Prepare to perform an update of the neg. cache backing store.
83c4dfe9546fd839e7a52bca7e9920da918f916ejg */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaistatic void
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaisdev_ncache_write(void)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai{
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai sdev_nc_list_t *ncl = sdev_ncache;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai nvp_devname_t *np;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai sdev_nc_node_t *lp;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai int n, i;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (sdev_cache_write_disable) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai mutex_enter(&ncl->ncl_mutex);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai ncl->ncl_flags &= ~NCL_LIST_WRITING;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai mutex_exit(&ncl->ncl_mutex);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai return;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai /* proper lock ordering here is essential */
83c4dfe9546fd839e7a52bca7e9920da918f916ejg rw_enter(nvf_lock(sdevfd_handle), RW_WRITER);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg sdev_ncache_list_free(sdevfd_handle);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai rw_enter(&ncl->ncl_lock, RW_READER);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai n = ncl->ncl_nentries;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai ASSERT(n <= sdev_nc_max_entries);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai np = kmem_zalloc(sizeof (nvp_devname_t), KM_SLEEP);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai np->nvp_npaths = n;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai np->nvp_paths = kmem_zalloc(n * sizeof (char *), KM_SLEEP);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai np->nvp_expirecnts = kmem_zalloc(n * sizeof (int), KM_SLEEP);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai i = 0;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai for (lp = list_head(&ncl->ncl_list); lp;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai lp = list_next(&ncl->ncl_list, lp)) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai np->nvp_paths[i] = i_ddi_strdup(lp->ncn_name, KM_SLEEP);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai np->nvp_expirecnts[i] = lp->ncn_expirecnt;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai sdcmn_err5((" %s %d\n",
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai np->nvp_paths[i], np->nvp_expirecnts[i]));
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai i++;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai rw_exit(&ncl->ncl_lock);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
83c4dfe9546fd839e7a52bca7e9920da918f916ejg nvf_mark_dirty(sdevfd_handle);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg list_insert_tail(nvf_list(sdevfd_handle), np);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg rw_exit(nvf_lock(sdevfd_handle));
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
83c4dfe9546fd839e7a52bca7e9920da918f916ejg nvf_wake_daemon();
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai}
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaistatic void
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaisdev_nc_flush_updates(void)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai{
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai sdev_nc_list_t *ncl = sdev_ncache;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (sdev_nc_disable || sdev_cache_write_disable)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai return;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai mutex_enter(&ncl->ncl_mutex);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (((ncl->ncl_flags &
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai (NCL_LIST_DIRTY | NCL_LIST_WENABLE | NCL_LIST_WRITING)) ==
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai (NCL_LIST_DIRTY | NCL_LIST_WENABLE))) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai ncl->ncl_flags &= ~NCL_LIST_DIRTY;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai ncl->ncl_flags |= NCL_LIST_WRITING;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai mutex_exit(&ncl->ncl_mutex);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai sdev_ncache_write();
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai } else {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai mutex_exit(&ncl->ncl_mutex);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai}
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaistatic void
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaisdev_nc_flush_boot_update(void)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai{
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai sdev_nc_list_t *ncl = sdev_ncache;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (sdev_nc_disable || sdev_cache_write_disable ||
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai (sdev_boot_state == SDEV_BOOT_STATE_INITIAL)) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai return;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai mutex_enter(&ncl->ncl_mutex);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (ncl->ncl_flags & NCL_LIST_WENABLE) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai mutex_exit(&ncl->ncl_mutex);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai sdev_nc_flush_updates();
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai } else {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai mutex_exit(&ncl->ncl_mutex);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai}
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaistatic void
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaisdev_state_boot_complete()
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai{
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai sdev_nc_list_t *ncl = sdev_ncache;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai sdev_nc_node_t *lp, *next;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai /*
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * Once boot is complete, decrement the expire count of each entry
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * in the cache not touched by a reference. Remove any that
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * goes to zero. This effectively removes random entries over
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * time.
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai rw_enter(&ncl->ncl_lock, RW_WRITER);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai mutex_enter(&ncl->ncl_mutex);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai for (lp = list_head(&ncl->ncl_list); lp; lp = next) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai next = list_next(&ncl->ncl_list, lp);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (sdev_nc_expirecnt > 0 && lp->ncn_expirecnt > 0) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (lp->ncn_flags & NCN_ACTIVE) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (lp->ncn_expirecnt != sdev_nc_expirecnt) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai lp->ncn_expirecnt = sdev_nc_expirecnt;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai ncl->ncl_flags |= NCL_LIST_DIRTY;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai } else {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (--lp->ncn_expirecnt == 0) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai list_remove(&ncl->ncl_list, lp);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai sdev_nc_free_unlinked_node(lp);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai ncl->ncl_nentries--;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai ncl->ncl_flags |= NCL_LIST_DIRTY;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai mutex_exit(&ncl->ncl_mutex);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai rw_exit(&ncl->ncl_lock);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai sdev_nc_flush_boot_update();
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai sdev_boot_state = SDEV_BOOT_STATE_COMPLETE;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai}
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai/*
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * Upon transition to the login state on a reconfigure boot,
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * a debounce timer is set up so that we cache all the nonsense
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * lookups we're hit with by the windowing system startup.
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai/*ARGSUSED*/
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaistatic void
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaisdev_state_timeout(void *arg)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai{
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai sdev_state_boot_complete();
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai}
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaistatic void
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaisdev_state_sysavail()
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai{
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai sdev_nc_list_t *ncl = sdev_ncache;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai clock_t nticks;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai int nsecs;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai mutex_enter(&ncl->ncl_mutex);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai ncl->ncl_flags |= NCL_LIST_WENABLE;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai mutex_exit(&ncl->ncl_mutex);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai nsecs = sdev_reconfig_delay;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (nsecs == 0) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai sdev_state_boot_complete();
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai } else {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai nticks = drv_usectohz(1000000 * nsecs);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai sdcmn_err5(("timeout initiated %ld\n", nticks));
bc1009abdd0a493796645bd983c1601396c09a5fjg (void) timeout(sdev_state_timeout, NULL, nticks);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai sdev_nc_flush_boot_update();
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai}
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai/*
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * Called to inform the filesystem of progress during boot,
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * either a notice of reconfiguration boot or an indication of
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * system boot complete. At system boot complete, set up a
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * timer at the expiration of which no further failed lookups
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * will be added to the negative cache.
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai *
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * The dev filesystem infers from reconfig boot that implicit
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * reconfig need not be invoked at all as all available devices
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * will have already been named.
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai *
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * The dev filesystem infers from "system available" that devfsadmd
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * can now be run and hence implicit reconfiguration may be initiated.
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * During early stages of system startup, implicit reconfig is
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * not done to avoid impacting boot performance.
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaivoid
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaisdev_devstate_change(void)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai{
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai int new_state;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai /*
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * Track system state and manage interesting transitions
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai new_state = SDEV_BOOT_STATE_INITIAL;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (i_ddi_reconfig())
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai new_state = SDEV_BOOT_STATE_RECONFIG;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (i_ddi_sysavail())
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai new_state = SDEV_BOOT_STATE_SYSAVAIL;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (sdev_boot_state < new_state) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai switch (new_state) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai case SDEV_BOOT_STATE_RECONFIG:
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai sdcmn_err5(("state change: reconfigure boot\n"));
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai sdev_boot_state = new_state;
89dfdb3f985a88e7d40543a4bf41dc09d44b9fdeSrikanth, Ramana /*
89dfdb3f985a88e7d40543a4bf41dc09d44b9fdeSrikanth, Ramana * The /dev filesystem fills a hot-plug .vs.
89dfdb3f985a88e7d40543a4bf41dc09d44b9fdeSrikanth, Ramana * public-namespace gap by invoking 'devfsadm' once
89dfdb3f985a88e7d40543a4bf41dc09d44b9fdeSrikanth, Ramana * as a result of the first /dev lookup failure
89dfdb3f985a88e7d40543a4bf41dc09d44b9fdeSrikanth, Ramana * (or getdents/readdir). Originally, it was thought
89dfdb3f985a88e7d40543a4bf41dc09d44b9fdeSrikanth, Ramana * that a reconfig reboot did not have a hot-plug gap,
89dfdb3f985a88e7d40543a4bf41dc09d44b9fdeSrikanth, Ramana * but this is not true - the gap is just smaller:
89dfdb3f985a88e7d40543a4bf41dc09d44b9fdeSrikanth, Ramana * it exists from the the time the smf invocation of
89dfdb3f985a88e7d40543a4bf41dc09d44b9fdeSrikanth, Ramana * devfsadm completes its forced devinfo snapshot,
89dfdb3f985a88e7d40543a4bf41dc09d44b9fdeSrikanth, Ramana * to the time when the smf devfsadmd daemon invocation
89dfdb3f985a88e7d40543a4bf41dc09d44b9fdeSrikanth, Ramana * is set up and listening for hotplug sysevents.
89dfdb3f985a88e7d40543a4bf41dc09d44b9fdeSrikanth, Ramana * Since there is still a gap with reconfig reboot,
89dfdb3f985a88e7d40543a4bf41dc09d44b9fdeSrikanth, Ramana * we no longer set 'sdev_reconfig_boot'.
89dfdb3f985a88e7d40543a4bf41dc09d44b9fdeSrikanth, Ramana */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (!sdev_nc_disable_reset)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai sdev_nc_free_bootonly();
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai break;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai case SDEV_BOOT_STATE_SYSAVAIL:
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai sdcmn_err5(("system available\n"));
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai sdev_boot_state = new_state;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai sdev_state_sysavail();
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai break;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai}
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai/*
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * Lookup: filter out entries in the negative cache
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * Return 1 if the lookup should not cause a reconfig.
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaiint
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaisdev_lookup_filter(sdev_node_t *dv, char *nm)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai{
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai int n;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai sdev_nc_list_t *ncl = sdev_ncache;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai sdev_nc_node_t *lp;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai char *path;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai int rval = 0;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai int changed = 0;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai ASSERT(i_ddi_io_initialized());
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai ASSERT(SDEVTOV(dv)->v_type == VDIR);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (sdev_nc_disable)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai return (0);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai n = strlen(dv->sdev_path) + strlen(nm) + 2;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai path = kmem_alloc(n, KM_SLEEP);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai (void) sprintf(path, "%s/%s", dv->sdev_path, nm);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai rw_enter(&ncl->ncl_lock, RW_READER);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if ((lp = sdev_nc_findpath(ncl, path)) != NULL) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai sdcmn_err5(("%s/%s: lookup by %s cached, no reconfig\n",
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai dv->sdev_name, nm, curproc->p_user.u_comm));
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (sdev_nc_verbose) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai cmn_err(CE_CONT,
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai "?%s/%s: lookup by %s cached, no reconfig\n",
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai dv->sdev_name, nm, curproc->p_user.u_comm);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai mutex_enter(&ncl->ncl_mutex);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai lp->ncn_flags |= NCN_ACTIVE;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (sdev_nc_expirecnt > 0 && lp->ncn_expirecnt > 0 &&
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai lp->ncn_expirecnt < sdev_nc_expirecnt) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai lp->ncn_expirecnt = sdev_nc_expirecnt;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai ncl->ncl_flags |= NCL_LIST_DIRTY;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai changed = 1;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai mutex_exit(&ncl->ncl_mutex);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai rval = 1;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai rw_exit(&ncl->ncl_lock);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai kmem_free(path, n);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (changed)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai sdev_nc_flush_boot_update();
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai return (rval);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai}
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaivoid
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaisdev_lookup_failed(sdev_node_t *dv, char *nm, int failed_flags)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai{
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (sdev_nc_disable)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai return;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai /*
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * If we're still in the initial boot stage, always update
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * the cache - we may not have received notice of the
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * reconfig boot state yet. On a reconfigure boot, entries
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * from the backing store are not re-persisted on update,
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * but new entries are marked as needing an update.
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * Never cache dynamic or non-global nodes.
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (SDEV_IS_GLOBAL(dv) && !SDEV_IS_DYNAMIC(dv) &&
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai !SDEV_IS_NO_NCACHE(dv) &&
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai ((failed_flags & SLF_NO_NCACHE) == 0) &&
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai ((sdev_reconfig_boot &&
3c5e027b0f15017d4b6afff01915ea70ae476223Eric Taylor (sdev_boot_state != SDEV_BOOT_STATE_COMPLETE)) ||
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai (!sdev_reconfig_boot && ((failed_flags & SLF_REBUILT))))) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai sdev_nc_addname(sdev_ncache,
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai dv, nm, NCN_SRC_CURRENT|NCN_ACTIVE);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai}
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaistatic sdev_nc_list_t *
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaisdev_nc_newlist(void)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai{
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai sdev_nc_list_t *ncl;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai ncl = kmem_zalloc(sizeof (sdev_nc_list_t), KM_SLEEP);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai rw_init(&ncl->ncl_lock, NULL, RW_DEFAULT, NULL);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai mutex_init(&ncl->ncl_mutex, NULL, MUTEX_DEFAULT, NULL);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai list_create(&ncl->ncl_list, sizeof (sdev_nc_node_t),
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai offsetof(sdev_nc_node_t, ncn_link));
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai return (ncl);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai}
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaistatic void
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaisdev_nc_free_unlinked_node(sdev_nc_node_t *lp)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai{
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai kmem_free(lp->ncn_name, strlen(lp->ncn_name) + 1);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai kmem_free(lp, sizeof (sdev_nc_node_t));
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai}
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaistatic sdev_nc_node_t *
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaisdev_nc_findpath(sdev_nc_list_t *ncl, char *path)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai{
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai sdev_nc_node_t *lp;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai ASSERT(RW_LOCK_HELD(&ncl->ncl_lock));
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai for (lp = list_head(&ncl->ncl_list); lp;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai lp = list_next(&ncl->ncl_list, lp)) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (strcmp(path, lp->ncn_name) == 0)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai return (lp);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai return (NULL);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai}
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaistatic void
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaisdev_nc_insertnode(sdev_nc_list_t *ncl, sdev_nc_node_t *new)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai{
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai sdev_nc_node_t *lp;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai rw_enter(&ncl->ncl_lock, RW_WRITER);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai lp = sdev_nc_findpath(ncl, new->ncn_name);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (lp == NULL) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (ncl->ncl_nentries == sdev_nc_max_entries) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai sdcmn_err5((
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai "%s by %s: not adding to ncache (max %d)\n",
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai new->ncn_name, curproc->p_user.u_comm,
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai ncl->ncl_nentries));
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (sdev_nc_verbose) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai cmn_err(CE_CONT, "?%s by %s: "
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai "not adding to ncache (max %d)\n",
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai new->ncn_name, curproc->p_user.u_comm,
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai ncl->ncl_nentries);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai rw_exit(&ncl->ncl_lock);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai sdev_nc_free_unlinked_node(new);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai } else {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai list_insert_tail(&ncl->ncl_list, new);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai ncl->ncl_nentries++;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai /* don't mark list dirty for nodes from store */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai mutex_enter(&ncl->ncl_mutex);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if ((new->ncn_flags & NCN_SRC_STORE) == 0) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai sdcmn_err5(("%s by %s: add to ncache\n",
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai new->ncn_name, curproc->p_user.u_comm));
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (sdev_nc_verbose) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai cmn_err(CE_CONT,
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai "?%s by %s: add to ncache\n",
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai new->ncn_name,
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai curproc->p_user.u_comm);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai ncl->ncl_flags |= NCL_LIST_DIRTY;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai mutex_exit(&ncl->ncl_mutex);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai rw_exit(&ncl->ncl_lock);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai lp = new;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai sdev_nc_flush_boot_update();
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai } else {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai mutex_enter(&ncl->ncl_mutex);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai lp->ncn_flags |= new->ncn_flags;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai mutex_exit(&ncl->ncl_mutex);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai rw_exit(&ncl->ncl_lock);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai sdev_nc_free_unlinked_node(new);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai}
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaivoid
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaisdev_nc_addname(sdev_nc_list_t *ncl, sdev_node_t *dv, char *nm, int flags)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai{
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai int n;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai sdev_nc_node_t *lp;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai ASSERT(SDEVTOV(dv)->v_type == VDIR);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai lp = kmem_zalloc(sizeof (sdev_nc_node_t), KM_SLEEP);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai n = strlen(dv->sdev_path) + strlen(nm) + 2;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai lp->ncn_name = kmem_alloc(n, KM_SLEEP);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai (void) sprintf(lp->ncn_name, "%s/%s",
3c5e027b0f15017d4b6afff01915ea70ae476223Eric Taylor dv->sdev_path, nm);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai lp->ncn_flags = flags;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai lp->ncn_expirecnt = sdev_nc_expirecnt;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai sdev_nc_insertnode(ncl, lp);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai}
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaivoid
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaisdev_nc_node_exists(sdev_node_t *dv)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai{
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai /* dynamic and non-global nodes are never cached */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (SDEV_IS_GLOBAL(dv) && !SDEV_IS_DYNAMIC(dv) &&
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai !SDEV_IS_NO_NCACHE(dv)) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai sdev_nc_path_exists(sdev_ncache, dv->sdev_path);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai}
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaivoid
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaisdev_nc_path_exists(sdev_nc_list_t *ncl, char *path)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai{
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai sdev_nc_node_t *lp;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (sdev_nc_disable)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai return;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai rw_enter(&ncl->ncl_lock, RW_READER);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if ((lp = sdev_nc_findpath(ncl, path)) == NULL) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai rw_exit(&ncl->ncl_lock);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai return;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (rw_tryupgrade(&ncl->ncl_lock) == 0) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai rw_exit(&ncl->ncl_lock);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai rw_enter(&ncl->ncl_lock, RW_WRITER);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai lp = sdev_nc_findpath(ncl, path);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (lp) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai list_remove(&ncl->ncl_list, lp);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai ncl->ncl_nentries--;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai mutex_enter(&ncl->ncl_mutex);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai ncl->ncl_flags |= NCL_LIST_DIRTY;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (ncl->ncl_flags & NCL_LIST_WENABLE) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai mutex_exit(&ncl->ncl_mutex);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai rw_exit(&ncl->ncl_lock);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai sdev_nc_flush_updates();
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai } else {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai mutex_exit(&ncl->ncl_mutex);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai rw_exit(&ncl->ncl_lock);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai sdev_nc_free_unlinked_node(lp);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai sdcmn_err5(("%s by %s: removed from ncache\n",
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai path, curproc->p_user.u_comm));
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (sdev_nc_verbose) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai cmn_err(CE_CONT, "?%s by %s: removed from ncache\n",
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai path, curproc->p_user.u_comm);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai } else
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai rw_exit(&ncl->ncl_lock);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai}
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaistatic void
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaisdev_nc_free_bootonly(void)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai{
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai sdev_nc_list_t *ncl = sdev_ncache;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai sdev_nc_node_t *lp;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai sdev_nc_node_t *next;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai rw_enter(&ncl->ncl_lock, RW_WRITER);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai for (lp = list_head(&ncl->ncl_list); lp; lp = next) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai next = list_next(&ncl->ncl_list, lp);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if ((lp->ncn_flags & NCN_SRC_CURRENT) == 0) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai sdcmn_err5(("freeing %s\n", lp->ncn_name));
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai mutex_enter(&ncl->ncl_mutex);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai ncl->ncl_flags |= NCL_LIST_DIRTY;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai mutex_exit(&ncl->ncl_mutex);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai list_remove(&ncl->ncl_list, lp);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai sdev_nc_free_unlinked_node(lp);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai ncl->ncl_nentries--;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai rw_exit(&ncl->ncl_lock);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai}