devcache.c revision 25e8c5aa2b496d9026e958ac731a610167574f59
83c4dfe9546fd839e7a52bca7e9920da918f916ejg/*
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * CDDL HEADER START
83c4dfe9546fd839e7a52bca7e9920da918f916ejg *
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * The contents of this file are subject to the terms of the
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * Common Development and Distribution License (the "License").
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * You may not use this file except in compliance with the License.
83c4dfe9546fd839e7a52bca7e9920da918f916ejg *
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * or http://www.opensolaris.org/os/licensing.
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * See the License for the specific language governing permissions
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * and limitations under the License.
83c4dfe9546fd839e7a52bca7e9920da918f916ejg *
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * When distributing Covered Code, include this CDDL HEADER in each
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * If applicable, add the following below this CDDL HEADER, with the
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * fields enclosed by brackets "[]" replaced with your own identifying
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * information: Portions Copyright [yyyy] [name of copyright owner]
83c4dfe9546fd839e7a52bca7e9920da918f916ejg *
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * CDDL HEADER END
83c4dfe9546fd839e7a52bca7e9920da918f916ejg */
83c4dfe9546fd839e7a52bca7e9920da918f916ejg/*
25e8c5aa2b496d9026e958ac731a610167574f59vikram * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * Use is subject to license terms.
83c4dfe9546fd839e7a52bca7e9920da918f916ejg */
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejg#pragma ident "%Z%%M% %I% %E% SMI"
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejg#include <sys/note.h>
83c4dfe9546fd839e7a52bca7e9920da918f916ejg#include <sys/t_lock.h>
83c4dfe9546fd839e7a52bca7e9920da918f916ejg#include <sys/cmn_err.h>
83c4dfe9546fd839e7a52bca7e9920da918f916ejg#include <sys/instance.h>
83c4dfe9546fd839e7a52bca7e9920da918f916ejg#include <sys/conf.h>
83c4dfe9546fd839e7a52bca7e9920da918f916ejg#include <sys/stat.h>
83c4dfe9546fd839e7a52bca7e9920da918f916ejg#include <sys/ddi.h>
83c4dfe9546fd839e7a52bca7e9920da918f916ejg#include <sys/hwconf.h>
83c4dfe9546fd839e7a52bca7e9920da918f916ejg#include <sys/sunddi.h>
83c4dfe9546fd839e7a52bca7e9920da918f916ejg#include <sys/sunndi.h>
83c4dfe9546fd839e7a52bca7e9920da918f916ejg#include <sys/ddi_impldefs.h>
83c4dfe9546fd839e7a52bca7e9920da918f916ejg#include <sys/ndi_impldefs.h>
83c4dfe9546fd839e7a52bca7e9920da918f916ejg#include <sys/modctl.h>
83c4dfe9546fd839e7a52bca7e9920da918f916ejg#include <sys/dacf.h>
83c4dfe9546fd839e7a52bca7e9920da918f916ejg#include <sys/promif.h>
83c4dfe9546fd839e7a52bca7e9920da918f916ejg#include <sys/cpuvar.h>
83c4dfe9546fd839e7a52bca7e9920da918f916ejg#include <sys/pathname.h>
83c4dfe9546fd839e7a52bca7e9920da918f916ejg#include <sys/kobj.h>
83c4dfe9546fd839e7a52bca7e9920da918f916ejg#include <sys/devcache.h>
83c4dfe9546fd839e7a52bca7e9920da918f916ejg#include <sys/devcache_impl.h>
83c4dfe9546fd839e7a52bca7e9920da918f916ejg#include <sys/sysmacros.h>
83c4dfe9546fd839e7a52bca7e9920da918f916ejg#include <sys/varargs.h>
83c4dfe9546fd839e7a52bca7e9920da918f916ejg#include <sys/callb.h>
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejg/*
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * This facility provides interfaces to clients to register,
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * read and update cache data in persisted backing store files,
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * usually in /etc/devices. The data persisted through this
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * mechanism should be stateless data, functioning in the sense
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * of a cache. Writes are performed by a background daemon
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * thread, permitting a client to schedule an update without
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * blocking, then continue updating the data state in
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * parallel. The data is only locked by the daemon thread
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * to pack the data in preparation for the write.
83c4dfe9546fd839e7a52bca7e9920da918f916ejg *
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * Data persisted through this mechanism should be capable
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * of being regenerated through normal system operation,
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * for example attaching all disk devices would cause all
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * devids to be registered for those devices. By caching
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * a devid-device tuple, the system can operate in a
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * more optimal way, directly attaching the device mapped
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * to a devid, rather than burdensomely driving attach of
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * the entire device tree to discover a single device.
83c4dfe9546fd839e7a52bca7e9920da918f916ejg *
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * Note that a client should only need to include
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * <sys/devcache.h> for the supported interfaces.
83c4dfe9546fd839e7a52bca7e9920da918f916ejg *
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * The data per client is entirely within the control of
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * the client. When reading, data unpacked from the backing
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * store should be inserted in the list. The pointer to
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * the list can be retreived via nvf_list(). When writing,
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * the data on the list is to be packed and returned to the
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * nvpdaemon as an nvlist.
83c4dfe9546fd839e7a52bca7e9920da918f916ejg *
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * Obvious restrictions are imposed by the limits of the
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * nvlist format. The data cannot be read or written
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * piecemeal, and large amounts of data aren't recommended.
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * However, nvlists do allow that data be named and typed
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * and can be size-of-int invariant, and the cached data
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * can be versioned conveniently.
83c4dfe9546fd839e7a52bca7e9920da918f916ejg *
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * The registration involves two steps: a handle is
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * allocated by calling the registration function.
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * This sets up the data referenced by the handle and
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * initializes the lock. Following registration, the
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * client must initialize the data list. The list
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * interfaces require that the list element with offset
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * to the node link be provided. The format of the
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * list element is under the control of the client.
83c4dfe9546fd839e7a52bca7e9920da918f916ejg *
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * Locking: the address of the data list r/w lock provided
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * can be accessed with nvf_lock(). The lock must be held
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * as reader when traversing the list or checking state,
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * such as nvf_is_dirty(). The lock must be held as
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * writer when updating the list or marking it dirty.
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * The lock must not be held when waking the daemon.
83c4dfe9546fd839e7a52bca7e9920da918f916ejg *
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * The data r/w lock is held as writer when the pack,
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * unpack and free list handlers are called. The
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * lock should not be dropped and must be still held
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * upon return. The client should also hold the lock
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * as reader when checking if the list is dirty, and
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * as writer when marking the list dirty or initiating
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * a read.
83c4dfe9546fd839e7a52bca7e9920da918f916ejg *
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * The asynchronous nature of updates allows for the
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * possibility that the data may continue to be updated
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * once the daemon has been notified that an update is
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * desired. The data only needs to be locked against
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * updates when packing the data into the form to be
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * written. When the write of the packed data has
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * completed, the daemon will automatically reschedule
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * an update if the data was marked dirty after the
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * point at which it was packed. Before beginning an
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * update, the daemon attempts to lock the data as
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * writer; if the writer lock is already held, it
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * backs off and retries later. The model is to give
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * priority to the kernel processes generating the
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * data, and that the nature of the data is that
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * it does not change often, can be re-generated when
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * needed, so updates should not happen often and
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * can be delayed until the data stops changing.
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * The client may update the list or mark it dirty
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * any time it is able to acquire the lock as
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * writer first.
83c4dfe9546fd839e7a52bca7e9920da918f916ejg *
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * A failed write will be retried after some delay,
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * in the hope that the cause of the error will be
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * transient, for example a filesystem with no space
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * available. An update on a read-only filesystem
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * is failed silently and not retried; this would be
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * the case when booted off install media.
83c4dfe9546fd839e7a52bca7e9920da918f916ejg *
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * There is no unregister mechanism as of yet, as it
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * hasn't been needed so far.
83c4dfe9546fd839e7a52bca7e9920da918f916ejg */
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejg/*
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * Global list of files registered and updated by the nvpflush
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * daemon, protected by the nvf_cache_mutex. While an
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * update is taking place, a file is temporarily moved to
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * the dirty list to avoid locking the primary list for
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * the duration of the update.
83c4dfe9546fd839e7a52bca7e9920da918f916ejg */
83c4dfe9546fd839e7a52bca7e9920da918f916ejglist_t nvf_cache_files;
83c4dfe9546fd839e7a52bca7e9920da918f916ejglist_t nvf_dirty_files;
83c4dfe9546fd839e7a52bca7e9920da918f916ejgkmutex_t nvf_cache_mutex;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejg/*
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * Allow some delay from an update of the data before flushing
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * to permit simultaneous updates of multiple changes.
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * Changes in the data are expected to be bursty, ie
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * reconfig or hot-plug of a new adapter.
83c4dfe9546fd839e7a52bca7e9920da918f916ejg *
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * kfio_report_error (default 0)
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * Set to 1 to enable some error messages related to low-level
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * kernel file i/o operations.
83c4dfe9546fd839e7a52bca7e9920da918f916ejg *
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * nvpflush_delay (default 10)
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * The number of seconds after data is marked dirty before the
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * flush daemon is triggered to flush the data. A longer period
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * of time permits more data updates per write. Note that
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * every update resets the timer so no repository write will
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * occur while data is being updated continuously.
83c4dfe9546fd839e7a52bca7e9920da918f916ejg *
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * nvpdaemon_idle_time (default 60)
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * The number of seconds the daemon will sleep idle before exiting.
83c4dfe9546fd839e7a52bca7e9920da918f916ejg *
83c4dfe9546fd839e7a52bca7e9920da918f916ejg */
83c4dfe9546fd839e7a52bca7e9920da918f916ejg#define NVPFLUSH_DELAY 10
83c4dfe9546fd839e7a52bca7e9920da918f916ejg#define NVPDAEMON_IDLE_TIME 60
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejg#define TICKS_PER_SECOND (drv_usectohz(1000000))
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejg/*
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * Tunables
83c4dfe9546fd839e7a52bca7e9920da918f916ejg */
83c4dfe9546fd839e7a52bca7e9920da918f916ejgint kfio_report_error = 0; /* kernel file i/o operations */
83c4dfe9546fd839e7a52bca7e9920da918f916ejgint kfio_disable_read = 0; /* disable all reads */
83c4dfe9546fd839e7a52bca7e9920da918f916ejgint kfio_disable_write = 0; /* disable all writes */
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejgint nvpflush_delay = NVPFLUSH_DELAY;
83c4dfe9546fd839e7a52bca7e9920da918f916ejgint nvpdaemon_idle_time = NVPDAEMON_IDLE_TIME;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejgstatic timeout_id_t nvpflush_id = 0;
83c4dfe9546fd839e7a52bca7e9920da918f916ejgstatic int nvpflush_timer_busy = 0;
83c4dfe9546fd839e7a52bca7e9920da918f916ejgstatic int nvpflush_daemon_active = 0;
83c4dfe9546fd839e7a52bca7e9920da918f916ejgstatic kthread_t *nvpflush_thr_id = 0;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejgstatic int do_nvpflush = 0;
83c4dfe9546fd839e7a52bca7e9920da918f916ejgstatic int nvpbusy = 0;
83c4dfe9546fd839e7a52bca7e9920da918f916ejgstatic kmutex_t nvpflush_lock;
83c4dfe9546fd839e7a52bca7e9920da918f916ejgstatic kcondvar_t nvpflush_cv;
83c4dfe9546fd839e7a52bca7e9920da918f916ejgstatic kthread_id_t nvpflush_thread;
83c4dfe9546fd839e7a52bca7e9920da918f916ejgstatic clock_t nvpticks;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejgstatic void nvpflush_daemon(void);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejg#ifdef DEBUG
83c4dfe9546fd839e7a52bca7e9920da918f916ejgint nvpdaemon_debug = 0;
83c4dfe9546fd839e7a52bca7e9920da918f916ejgint kfio_debug = 0;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg#endif /* DEBUG */
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejgextern int modrootloaded;
83c4dfe9546fd839e7a52bca7e9920da918f916ejgextern void mdi_read_devices_files(void);
83c4dfe9546fd839e7a52bca7e9920da918f916ejgextern void mdi_clean_vhcache(void);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejg/*
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * Initialize the overall cache file management
83c4dfe9546fd839e7a52bca7e9920da918f916ejg */
83c4dfe9546fd839e7a52bca7e9920da918f916ejgvoid
83c4dfe9546fd839e7a52bca7e9920da918f916ejgi_ddi_devices_init(void)
83c4dfe9546fd839e7a52bca7e9920da918f916ejg{
83c4dfe9546fd839e7a52bca7e9920da918f916ejg list_create(&nvf_cache_files, sizeof (nvfd_t),
83c4dfe9546fd839e7a52bca7e9920da918f916ejg offsetof(nvfd_t, nvf_link));
83c4dfe9546fd839e7a52bca7e9920da918f916ejg list_create(&nvf_dirty_files, sizeof (nvfd_t),
83c4dfe9546fd839e7a52bca7e9920da918f916ejg offsetof(nvfd_t, nvf_link));
83c4dfe9546fd839e7a52bca7e9920da918f916ejg mutex_init(&nvf_cache_mutex, NULL, MUTEX_DEFAULT, NULL);
25e8c5aa2b496d9026e958ac731a610167574f59vikram retire_store_init();
83c4dfe9546fd839e7a52bca7e9920da918f916ejg devid_cache_init();
83c4dfe9546fd839e7a52bca7e9920da918f916ejg}
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejg/*
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * Read cache files
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * The files read here should be restricted to those
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * that may be required to mount root.
83c4dfe9546fd839e7a52bca7e9920da918f916ejg */
83c4dfe9546fd839e7a52bca7e9920da918f916ejgvoid
83c4dfe9546fd839e7a52bca7e9920da918f916ejgi_ddi_read_devices_files(void)
83c4dfe9546fd839e7a52bca7e9920da918f916ejg{
25e8c5aa2b496d9026e958ac731a610167574f59vikram /*
25e8c5aa2b496d9026e958ac731a610167574f59vikram * The retire store should be the first file read as it
25e8c5aa2b496d9026e958ac731a610167574f59vikram * may need to offline devices. kfio_disable_read is not
25e8c5aa2b496d9026e958ac731a610167574f59vikram * used for retire. For the rationale see the tunable
25e8c5aa2b496d9026e958ac731a610167574f59vikram * ddi_retire_store_bypass and comments in:
25e8c5aa2b496d9026e958ac731a610167574f59vikram * uts/common/os/retire_store.c
25e8c5aa2b496d9026e958ac731a610167574f59vikram */
25e8c5aa2b496d9026e958ac731a610167574f59vikram
25e8c5aa2b496d9026e958ac731a610167574f59vikram retire_store_read();
25e8c5aa2b496d9026e958ac731a610167574f59vikram
83c4dfe9546fd839e7a52bca7e9920da918f916ejg if (!kfio_disable_read) {
83c4dfe9546fd839e7a52bca7e9920da918f916ejg mdi_read_devices_files();
83c4dfe9546fd839e7a52bca7e9920da918f916ejg devid_cache_read();
83c4dfe9546fd839e7a52bca7e9920da918f916ejg }
83c4dfe9546fd839e7a52bca7e9920da918f916ejg}
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejgvoid
83c4dfe9546fd839e7a52bca7e9920da918f916ejgi_ddi_start_flush_daemon(void)
83c4dfe9546fd839e7a52bca7e9920da918f916ejg{
83c4dfe9546fd839e7a52bca7e9920da918f916ejg nvfd_t *nvfdp;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejg ASSERT(i_ddi_io_initialized());
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejg mutex_init(&nvpflush_lock, NULL, MUTEX_DRIVER, NULL);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg cv_init(&nvpflush_cv, NULL, CV_DRIVER, NULL);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejg mutex_enter(&nvf_cache_mutex);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg for (nvfdp = list_head(&nvf_cache_files); nvfdp;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg nvfdp = list_next(&nvf_cache_files, nvfdp)) {
83c4dfe9546fd839e7a52bca7e9920da918f916ejg if (NVF_IS_DIRTY(nvfdp)) {
83c4dfe9546fd839e7a52bca7e9920da918f916ejg nvf_wake_daemon();
83c4dfe9546fd839e7a52bca7e9920da918f916ejg break;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg }
83c4dfe9546fd839e7a52bca7e9920da918f916ejg }
83c4dfe9546fd839e7a52bca7e9920da918f916ejg mutex_exit(&nvf_cache_mutex);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg}
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejgvoid
83c4dfe9546fd839e7a52bca7e9920da918f916ejgi_ddi_clean_devices_files(void)
83c4dfe9546fd839e7a52bca7e9920da918f916ejg{
83c4dfe9546fd839e7a52bca7e9920da918f916ejg devid_cache_cleanup();
83c4dfe9546fd839e7a52bca7e9920da918f916ejg mdi_clean_vhcache();
83c4dfe9546fd839e7a52bca7e9920da918f916ejg}
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejg/*
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * Register a cache file to be managed and updated by the nvpflush daemon.
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * All operations are performed through the returned handle.
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * There is no unregister mechanism for now.
83c4dfe9546fd839e7a52bca7e9920da918f916ejg */
83c4dfe9546fd839e7a52bca7e9920da918f916ejgnvf_handle_t
83c4dfe9546fd839e7a52bca7e9920da918f916ejgnvf_register_file(nvf_ops_t *ops)
83c4dfe9546fd839e7a52bca7e9920da918f916ejg{
83c4dfe9546fd839e7a52bca7e9920da918f916ejg nvfd_t *nvfdp;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejg nvfdp = kmem_zalloc(sizeof (*nvfdp), KM_SLEEP);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejg nvfdp->nvf_ops = ops;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg nvfdp->nvf_flags = 0;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg rw_init(&nvfdp->nvf_lock, NULL, RW_DRIVER, NULL);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejg mutex_enter(&nvf_cache_mutex);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg list_insert_tail(&nvf_cache_files, nvfdp);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg mutex_exit(&nvf_cache_mutex);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejg return ((nvf_handle_t)nvfdp);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg}
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejg/*PRINTFLIKE1*/
83c4dfe9546fd839e7a52bca7e9920da918f916ejgvoid
83c4dfe9546fd839e7a52bca7e9920da918f916ejgnvf_error(const char *fmt, ...)
83c4dfe9546fd839e7a52bca7e9920da918f916ejg{
83c4dfe9546fd839e7a52bca7e9920da918f916ejg va_list ap;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejg if (kfio_report_error) {
83c4dfe9546fd839e7a52bca7e9920da918f916ejg va_start(ap, fmt);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg vcmn_err(CE_NOTE, fmt, ap);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg va_end(ap);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg }
83c4dfe9546fd839e7a52bca7e9920da918f916ejg}
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejg/*
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * Some operations clients may use to manage the data
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * to be persisted in a cache file.
83c4dfe9546fd839e7a52bca7e9920da918f916ejg */
83c4dfe9546fd839e7a52bca7e9920da918f916ejgchar *
83c4dfe9546fd839e7a52bca7e9920da918f916ejgnvf_cache_name(nvf_handle_t handle)
83c4dfe9546fd839e7a52bca7e9920da918f916ejg{
83c4dfe9546fd839e7a52bca7e9920da918f916ejg return (((nvfd_t *)handle)->nvf_cache_path);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg}
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejgkrwlock_t *
83c4dfe9546fd839e7a52bca7e9920da918f916ejgnvf_lock(nvf_handle_t handle)
83c4dfe9546fd839e7a52bca7e9920da918f916ejg{
83c4dfe9546fd839e7a52bca7e9920da918f916ejg return (&(((nvfd_t *)handle)->nvf_lock));
83c4dfe9546fd839e7a52bca7e9920da918f916ejg}
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejglist_t *
83c4dfe9546fd839e7a52bca7e9920da918f916ejgnvf_list(nvf_handle_t handle)
83c4dfe9546fd839e7a52bca7e9920da918f916ejg{
83c4dfe9546fd839e7a52bca7e9920da918f916ejg return (&(((nvfd_t *)handle)->nvf_data_list));
83c4dfe9546fd839e7a52bca7e9920da918f916ejg}
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejgvoid
83c4dfe9546fd839e7a52bca7e9920da918f916ejgnvf_mark_dirty(nvf_handle_t handle)
83c4dfe9546fd839e7a52bca7e9920da918f916ejg{
83c4dfe9546fd839e7a52bca7e9920da918f916ejg ASSERT(RW_WRITE_HELD(&(((nvfd_t *)handle)->nvf_lock)));
83c4dfe9546fd839e7a52bca7e9920da918f916ejg NVF_MARK_DIRTY((nvfd_t *)handle);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg}
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejgint
83c4dfe9546fd839e7a52bca7e9920da918f916ejgnvf_is_dirty(nvf_handle_t handle)
83c4dfe9546fd839e7a52bca7e9920da918f916ejg{
83c4dfe9546fd839e7a52bca7e9920da918f916ejg ASSERT(RW_LOCK_HELD(&(((nvfd_t *)handle)->nvf_lock)));
83c4dfe9546fd839e7a52bca7e9920da918f916ejg return (NVF_IS_DIRTY((nvfd_t *)handle));
83c4dfe9546fd839e7a52bca7e9920da918f916ejg}
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejgstatic uint16_t
83c4dfe9546fd839e7a52bca7e9920da918f916ejgnvp_cksum(uchar_t *buf, int64_t buflen)
83c4dfe9546fd839e7a52bca7e9920da918f916ejg{
83c4dfe9546fd839e7a52bca7e9920da918f916ejg uint16_t cksum = 0;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg uint16_t *p = (uint16_t *)buf;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg int64_t n;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejg if ((buflen & 0x01) != 0) {
83c4dfe9546fd839e7a52bca7e9920da918f916ejg buflen--;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg cksum = buf[buflen];
83c4dfe9546fd839e7a52bca7e9920da918f916ejg }
83c4dfe9546fd839e7a52bca7e9920da918f916ejg n = buflen / 2;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg while (n-- > 0)
83c4dfe9546fd839e7a52bca7e9920da918f916ejg cksum ^= *p++;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg return (cksum);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg}
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejgint
83c4dfe9546fd839e7a52bca7e9920da918f916ejgfread_nvlist(char *filename, nvlist_t **ret_nvlist)
83c4dfe9546fd839e7a52bca7e9920da918f916ejg{
83c4dfe9546fd839e7a52bca7e9920da918f916ejg struct _buf *file;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg nvpf_hdr_t hdr;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg char *buf;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg nvlist_t *nvl;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg int rval;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg uint_t offset;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg int n;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg char c;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg uint16_t cksum, hdrsum;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejg *ret_nvlist = NULL;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejg file = kobj_open_file(filename);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg if (file == (struct _buf *)-1) {
83c4dfe9546fd839e7a52bca7e9920da918f916ejg KFDEBUG((CE_CONT, "cannot open file: %s\n", filename));
83c4dfe9546fd839e7a52bca7e9920da918f916ejg return (ENOENT);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg }
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejg offset = 0;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg n = kobj_read_file(file, (char *)&hdr, sizeof (hdr), offset);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg if (n != sizeof (hdr)) {
83c4dfe9546fd839e7a52bca7e9920da918f916ejg kobj_close_file(file);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg if (n < 0) {
83c4dfe9546fd839e7a52bca7e9920da918f916ejg nvf_error("error reading header: %s\n", filename);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg return (EIO);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg } else if (n == 0) {
83c4dfe9546fd839e7a52bca7e9920da918f916ejg KFDEBUG((CE_CONT, "file empty: %s\n", filename));
83c4dfe9546fd839e7a52bca7e9920da918f916ejg } else {
83c4dfe9546fd839e7a52bca7e9920da918f916ejg nvf_error("header size incorrect: %s\n", filename);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg }
83c4dfe9546fd839e7a52bca7e9920da918f916ejg return (EINVAL);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg }
83c4dfe9546fd839e7a52bca7e9920da918f916ejg offset += n;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejg KFDEBUG2((CE_CONT, "nvpf_magic: 0x%x\n", hdr.nvpf_magic));
83c4dfe9546fd839e7a52bca7e9920da918f916ejg KFDEBUG2((CE_CONT, "nvpf_version: %d\n", hdr.nvpf_version));
83c4dfe9546fd839e7a52bca7e9920da918f916ejg KFDEBUG2((CE_CONT, "nvpf_size: %lld\n",
83c4dfe9546fd839e7a52bca7e9920da918f916ejg (longlong_t)hdr.nvpf_size));
83c4dfe9546fd839e7a52bca7e9920da918f916ejg KFDEBUG2((CE_CONT, "nvpf_hdr_chksum: 0x%x\n",
83c4dfe9546fd839e7a52bca7e9920da918f916ejg hdr.nvpf_hdr_chksum));
83c4dfe9546fd839e7a52bca7e9920da918f916ejg KFDEBUG2((CE_CONT, "nvpf_chksum: 0x%x\n", hdr.nvpf_chksum));
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejg cksum = hdr.nvpf_hdr_chksum;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg hdr.nvpf_hdr_chksum = 0;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg hdrsum = nvp_cksum((uchar_t *)&hdr, sizeof (hdr));
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejg if (hdr.nvpf_magic != NVPF_HDR_MAGIC ||
83c4dfe9546fd839e7a52bca7e9920da918f916ejg hdr.nvpf_version != NVPF_HDR_VERSION || hdrsum != cksum) {
83c4dfe9546fd839e7a52bca7e9920da918f916ejg kobj_close_file(file);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg if (hdrsum != cksum) {
83c4dfe9546fd839e7a52bca7e9920da918f916ejg nvf_error("%s: checksum error "
83c4dfe9546fd839e7a52bca7e9920da918f916ejg "(actual 0x%x, expected 0x%x)\n",
83c4dfe9546fd839e7a52bca7e9920da918f916ejg filename, hdrsum, cksum);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg }
83c4dfe9546fd839e7a52bca7e9920da918f916ejg nvf_error("%s: header information incorrect", filename);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg return (EINVAL);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg }
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejg ASSERT(hdr.nvpf_size >= 0);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejg buf = kmem_alloc(hdr.nvpf_size, KM_SLEEP);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg n = kobj_read_file(file, buf, hdr.nvpf_size, offset);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg if (n != hdr.nvpf_size) {
83c4dfe9546fd839e7a52bca7e9920da918f916ejg kmem_free(buf, hdr.nvpf_size);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg kobj_close_file(file);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg if (n < 0) {
83c4dfe9546fd839e7a52bca7e9920da918f916ejg nvf_error("%s: read error %d", filename, n);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg } else {
83c4dfe9546fd839e7a52bca7e9920da918f916ejg nvf_error("%s: incomplete read %d/%lld",
83c4dfe9546fd839e7a52bca7e9920da918f916ejg filename, n, (longlong_t)hdr.nvpf_size);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg }
83c4dfe9546fd839e7a52bca7e9920da918f916ejg return (EINVAL);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg }
83c4dfe9546fd839e7a52bca7e9920da918f916ejg offset += n;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejg rval = kobj_read_file(file, &c, 1, offset);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg kobj_close_file(file);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg if (rval > 0) {
83c4dfe9546fd839e7a52bca7e9920da918f916ejg nvf_error("%s is larger than %lld\n",
83c4dfe9546fd839e7a52bca7e9920da918f916ejg filename, (longlong_t)hdr.nvpf_size);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg kmem_free(buf, hdr.nvpf_size);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg return (EINVAL);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg }
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejg cksum = nvp_cksum((uchar_t *)buf, hdr.nvpf_size);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg if (hdr.nvpf_chksum != cksum) {
83c4dfe9546fd839e7a52bca7e9920da918f916ejg nvf_error("%s: checksum error (actual 0x%x, expected 0x%x)\n",
83c4dfe9546fd839e7a52bca7e9920da918f916ejg filename, hdr.nvpf_chksum, cksum);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg kmem_free(buf, hdr.nvpf_size);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg return (EINVAL);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg }
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejg nvl = NULL;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg rval = nvlist_unpack(buf, hdr.nvpf_size, &nvl, 0);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg if (rval != 0) {
83c4dfe9546fd839e7a52bca7e9920da918f916ejg nvf_error("%s: error %d unpacking nvlist\n",
83c4dfe9546fd839e7a52bca7e9920da918f916ejg filename, rval);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg kmem_free(buf, hdr.nvpf_size);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg return (EINVAL);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg }
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejg kmem_free(buf, hdr.nvpf_size);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg *ret_nvlist = nvl;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg return (0);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg}
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejgstatic int
83c4dfe9546fd839e7a52bca7e9920da918f916ejgkfcreate(char *filename, kfile_t **kfilep)
83c4dfe9546fd839e7a52bca7e9920da918f916ejg{
83c4dfe9546fd839e7a52bca7e9920da918f916ejg kfile_t *fp;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg int rval;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejg ASSERT(modrootloaded);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejg fp = kmem_alloc(sizeof (kfile_t), KM_SLEEP);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejg fp->kf_vnflags = FCREAT | FWRITE | FTRUNC;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg fp->kf_fname = filename;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg fp->kf_fpos = 0;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg fp->kf_state = 0;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejg KFDEBUG((CE_CONT, "create: %s flags 0x%x\n",
83c4dfe9546fd839e7a52bca7e9920da918f916ejg filename, fp->kf_vnflags));
83c4dfe9546fd839e7a52bca7e9920da918f916ejg rval = vn_open(filename, UIO_SYSSPACE, fp->kf_vnflags,
83c4dfe9546fd839e7a52bca7e9920da918f916ejg 0444, &fp->kf_vp, CRCREAT, 0);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg if (rval != 0) {
83c4dfe9546fd839e7a52bca7e9920da918f916ejg kmem_free(fp, sizeof (kfile_t));
83c4dfe9546fd839e7a52bca7e9920da918f916ejg KFDEBUG((CE_CONT, "%s: create error %d\n",
83c4dfe9546fd839e7a52bca7e9920da918f916ejg filename, rval));
83c4dfe9546fd839e7a52bca7e9920da918f916ejg return (rval);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg }
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejg *kfilep = fp;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg return (0);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg}
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejgstatic int
83c4dfe9546fd839e7a52bca7e9920da918f916ejgkfremove(char *filename)
83c4dfe9546fd839e7a52bca7e9920da918f916ejg{
83c4dfe9546fd839e7a52bca7e9920da918f916ejg int rval;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejg KFDEBUG((CE_CONT, "remove: %s\n", filename));
83c4dfe9546fd839e7a52bca7e9920da918f916ejg rval = vn_remove(filename, UIO_SYSSPACE, RMFILE);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg if (rval != 0) {
83c4dfe9546fd839e7a52bca7e9920da918f916ejg KFDEBUG((CE_CONT, "%s: remove error %d\n",
83c4dfe9546fd839e7a52bca7e9920da918f916ejg filename, rval));
83c4dfe9546fd839e7a52bca7e9920da918f916ejg }
83c4dfe9546fd839e7a52bca7e9920da918f916ejg return (rval);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg}
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejgstatic int
83c4dfe9546fd839e7a52bca7e9920da918f916ejgkfread(kfile_t *fp, char *buf, ssize_t bufsiz, ssize_t *ret_n)
83c4dfe9546fd839e7a52bca7e9920da918f916ejg{
83c4dfe9546fd839e7a52bca7e9920da918f916ejg ssize_t resid;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg int err;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg ssize_t n;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejg ASSERT(modrootloaded);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejg if (fp->kf_state != 0)
83c4dfe9546fd839e7a52bca7e9920da918f916ejg return (fp->kf_state);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejg err = vn_rdwr(UIO_READ, fp->kf_vp, buf, bufsiz, fp->kf_fpos,
83c4dfe9546fd839e7a52bca7e9920da918f916ejg UIO_SYSSPACE, 0, (rlim64_t)0, kcred, &resid);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg if (err != 0) {
83c4dfe9546fd839e7a52bca7e9920da918f916ejg KFDEBUG((CE_CONT, "%s: read error %d\n",
83c4dfe9546fd839e7a52bca7e9920da918f916ejg fp->kf_fname, err));
83c4dfe9546fd839e7a52bca7e9920da918f916ejg fp->kf_state = err;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg return (err);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg }
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejg ASSERT(resid >= 0 && resid <= bufsiz);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg n = bufsiz - resid;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejg KFDEBUG1((CE_CONT, "%s: read %ld bytes ok %ld bufsiz, %ld resid\n",
83c4dfe9546fd839e7a52bca7e9920da918f916ejg fp->kf_fname, n, bufsiz, resid));
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejg fp->kf_fpos += n;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg *ret_n = n;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg return (0);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg}
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejgstatic int
83c4dfe9546fd839e7a52bca7e9920da918f916ejgkfwrite(kfile_t *fp, char *buf, ssize_t bufsiz, ssize_t *ret_n)
83c4dfe9546fd839e7a52bca7e9920da918f916ejg{
83c4dfe9546fd839e7a52bca7e9920da918f916ejg rlim64_t rlimit;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg ssize_t resid;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg int err;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg ssize_t len;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg ssize_t n = 0;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejg ASSERT(modrootloaded);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejg if (fp->kf_state != 0)
83c4dfe9546fd839e7a52bca7e9920da918f916ejg return (fp->kf_state);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejg len = bufsiz;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg rlimit = bufsiz + 1;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg for (;;) {
83c4dfe9546fd839e7a52bca7e9920da918f916ejg err = vn_rdwr(UIO_WRITE, fp->kf_vp, buf, len, fp->kf_fpos,
83c4dfe9546fd839e7a52bca7e9920da918f916ejg UIO_SYSSPACE, FSYNC, rlimit, kcred, &resid);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg if (err) {
83c4dfe9546fd839e7a52bca7e9920da918f916ejg KFDEBUG((CE_CONT, "%s: write error %d\n",
83c4dfe9546fd839e7a52bca7e9920da918f916ejg fp->kf_fname, err));
83c4dfe9546fd839e7a52bca7e9920da918f916ejg fp->kf_state = err;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg return (err);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg }
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejg KFDEBUG1((CE_CONT, "%s: write %ld bytes ok %ld resid\n",
83c4dfe9546fd839e7a52bca7e9920da918f916ejg fp->kf_fname, len-resid, resid));
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejg ASSERT(resid >= 0 && resid <= len);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejg n += (len - resid);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg if (resid == 0)
83c4dfe9546fd839e7a52bca7e9920da918f916ejg break;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejg if (resid == len) {
83c4dfe9546fd839e7a52bca7e9920da918f916ejg KFDEBUG((CE_CONT, "%s: filesystem full?\n",
83c4dfe9546fd839e7a52bca7e9920da918f916ejg fp->kf_fname));
83c4dfe9546fd839e7a52bca7e9920da918f916ejg fp->kf_state = ENOSPC;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg return (ENOSPC);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg }
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejg len -= resid;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg buf += len;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg fp->kf_fpos += len;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg len = resid;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg }
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejg ASSERT(n == bufsiz);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg KFDEBUG1((CE_CONT, "%s: wrote %ld bytes ok\n", fp->kf_fname, n));
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejg *ret_n = n;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg return (0);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg}
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejgstatic int
83c4dfe9546fd839e7a52bca7e9920da918f916ejgkfclose(kfile_t *fp)
83c4dfe9546fd839e7a52bca7e9920da918f916ejg{
83c4dfe9546fd839e7a52bca7e9920da918f916ejg int rval;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejg KFDEBUG((CE_CONT, "close: %s\n", fp->kf_fname));
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejg if ((fp->kf_vnflags & FWRITE) && fp->kf_state == 0) {
83c4dfe9546fd839e7a52bca7e9920da918f916ejg rval = VOP_FSYNC(fp->kf_vp, FSYNC, kcred);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg if (rval != 0) {
83c4dfe9546fd839e7a52bca7e9920da918f916ejg nvf_error("%s: sync error %d\n",
83c4dfe9546fd839e7a52bca7e9920da918f916ejg fp->kf_fname, rval);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg }
83c4dfe9546fd839e7a52bca7e9920da918f916ejg KFDEBUG((CE_CONT, "%s: sync ok\n", fp->kf_fname));
83c4dfe9546fd839e7a52bca7e9920da918f916ejg }
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejg rval = VOP_CLOSE(fp->kf_vp, fp->kf_vnflags, 1, (offset_t)0, kcred);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg if (rval != 0) {
83c4dfe9546fd839e7a52bca7e9920da918f916ejg if (fp->kf_state == 0) {
83c4dfe9546fd839e7a52bca7e9920da918f916ejg nvf_error("%s: close error %d\n",
83c4dfe9546fd839e7a52bca7e9920da918f916ejg fp->kf_fname, rval);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg }
83c4dfe9546fd839e7a52bca7e9920da918f916ejg } else {
83c4dfe9546fd839e7a52bca7e9920da918f916ejg if (fp->kf_state == 0)
83c4dfe9546fd839e7a52bca7e9920da918f916ejg KFDEBUG((CE_CONT, "%s: close ok\n", fp->kf_fname));
83c4dfe9546fd839e7a52bca7e9920da918f916ejg }
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejg VN_RELE(fp->kf_vp);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg kmem_free(fp, sizeof (kfile_t));
83c4dfe9546fd839e7a52bca7e9920da918f916ejg return (rval);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg}
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejgstatic int
83c4dfe9546fd839e7a52bca7e9920da918f916ejgkfrename(char *oldname, char *newname)
83c4dfe9546fd839e7a52bca7e9920da918f916ejg{
83c4dfe9546fd839e7a52bca7e9920da918f916ejg int rval;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejg ASSERT(modrootloaded);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejg KFDEBUG((CE_CONT, "renaming %s to %s\n", oldname, newname));
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejg if ((rval = vn_rename(oldname, newname, UIO_SYSSPACE)) != 0) {
83c4dfe9546fd839e7a52bca7e9920da918f916ejg KFDEBUG((CE_CONT, "rename %s to %s: %d\n",
83c4dfe9546fd839e7a52bca7e9920da918f916ejg oldname, newname, rval));
83c4dfe9546fd839e7a52bca7e9920da918f916ejg }
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejg return (rval);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg}
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejgint
83c4dfe9546fd839e7a52bca7e9920da918f916ejgfwrite_nvlist(char *filename, nvlist_t *nvl)
83c4dfe9546fd839e7a52bca7e9920da918f916ejg{
83c4dfe9546fd839e7a52bca7e9920da918f916ejg char *buf;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg char *nvbuf;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg kfile_t *fp;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg char *newname;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg int len, err, err1;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg size_t buflen;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg ssize_t n;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejg ASSERT(modrootloaded);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejg nvbuf = NULL;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg err = nvlist_pack(nvl, &nvbuf, &buflen, NV_ENCODE_NATIVE, 0);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg if (err != 0) {
83c4dfe9546fd839e7a52bca7e9920da918f916ejg nvf_error("%s: error %d packing nvlist\n",
83c4dfe9546fd839e7a52bca7e9920da918f916ejg filename, err);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg return (err);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg }
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejg buf = kmem_alloc(sizeof (nvpf_hdr_t) + buflen, KM_SLEEP);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg bzero(buf, sizeof (nvpf_hdr_t));
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejg ((nvpf_hdr_t *)buf)->nvpf_magic = NVPF_HDR_MAGIC;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg ((nvpf_hdr_t *)buf)->nvpf_version = NVPF_HDR_VERSION;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg ((nvpf_hdr_t *)buf)->nvpf_size = buflen;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg ((nvpf_hdr_t *)buf)->nvpf_chksum = nvp_cksum((uchar_t *)nvbuf, buflen);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg ((nvpf_hdr_t *)buf)->nvpf_hdr_chksum =
83c4dfe9546fd839e7a52bca7e9920da918f916ejg nvp_cksum((uchar_t *)buf, sizeof (nvpf_hdr_t));
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejg bcopy(nvbuf, buf + sizeof (nvpf_hdr_t), buflen);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg kmem_free(nvbuf, buflen);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg buflen += sizeof (nvpf_hdr_t);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejg len = strlen(filename) + MAX_SUFFIX_LEN + 2;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg newname = kmem_alloc(len, KM_SLEEP);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejg (void) sprintf(newname, "%s.%s",
83c4dfe9546fd839e7a52bca7e9920da918f916ejg filename, NEW_FILENAME_SUFFIX);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejg /*
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * To make it unlikely we suffer data loss, write
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * data to the new temporary file. Once successful
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * complete the transaction by renaming the new file
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * to replace the previous.
83c4dfe9546fd839e7a52bca7e9920da918f916ejg */
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejg if ((err = kfcreate(newname, &fp)) == 0) {
83c4dfe9546fd839e7a52bca7e9920da918f916ejg err = kfwrite(fp, buf, buflen, &n);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg if (err) {
83c4dfe9546fd839e7a52bca7e9920da918f916ejg nvf_error("%s: write error - %d\n",
83c4dfe9546fd839e7a52bca7e9920da918f916ejg newname, err);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg } else {
83c4dfe9546fd839e7a52bca7e9920da918f916ejg if (n != buflen) {
83c4dfe9546fd839e7a52bca7e9920da918f916ejg nvf_error(
83c4dfe9546fd839e7a52bca7e9920da918f916ejg "%s: partial write %ld of %ld bytes\n",
83c4dfe9546fd839e7a52bca7e9920da918f916ejg newname, n, buflen);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg nvf_error("%s: filesystem may be full?\n",
83c4dfe9546fd839e7a52bca7e9920da918f916ejg newname);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg err = EIO;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg }
83c4dfe9546fd839e7a52bca7e9920da918f916ejg }
83c4dfe9546fd839e7a52bca7e9920da918f916ejg if ((err1 = kfclose(fp)) != 0) {
83c4dfe9546fd839e7a52bca7e9920da918f916ejg nvf_error("%s: close error\n", newname);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg if (err == 0)
83c4dfe9546fd839e7a52bca7e9920da918f916ejg err = err1;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg }
83c4dfe9546fd839e7a52bca7e9920da918f916ejg if (err != 0) {
83c4dfe9546fd839e7a52bca7e9920da918f916ejg if (kfremove(newname) != 0) {
83c4dfe9546fd839e7a52bca7e9920da918f916ejg nvf_error("%s: remove failed\n",
83c4dfe9546fd839e7a52bca7e9920da918f916ejg newname);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg }
83c4dfe9546fd839e7a52bca7e9920da918f916ejg }
83c4dfe9546fd839e7a52bca7e9920da918f916ejg } else {
83c4dfe9546fd839e7a52bca7e9920da918f916ejg nvf_error("%s: create failed - %d\n", filename, err);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg }
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejg if (err == 0) {
83c4dfe9546fd839e7a52bca7e9920da918f916ejg if ((err = kfrename(newname, filename)) != 0) {
83c4dfe9546fd839e7a52bca7e9920da918f916ejg nvf_error("%s: rename from %s failed\n",
83c4dfe9546fd839e7a52bca7e9920da918f916ejg newname, filename);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg }
83c4dfe9546fd839e7a52bca7e9920da918f916ejg }
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejg kmem_free(newname, len);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg kmem_free(buf, buflen);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejg return (err);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg}
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejgstatic int
83c4dfe9546fd839e7a52bca7e9920da918f916ejge_fwrite_nvlist(nvfd_t *nvfd, nvlist_t *nvl)
83c4dfe9546fd839e7a52bca7e9920da918f916ejg{
83c4dfe9546fd839e7a52bca7e9920da918f916ejg int err;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejg if ((err = fwrite_nvlist(nvfd->nvf_cache_path, nvl)) == 0)
83c4dfe9546fd839e7a52bca7e9920da918f916ejg return (DDI_SUCCESS);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg else {
83c4dfe9546fd839e7a52bca7e9920da918f916ejg if (err == EROFS)
83c4dfe9546fd839e7a52bca7e9920da918f916ejg NVF_MARK_READONLY(nvfd);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg return (DDI_FAILURE);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg }
83c4dfe9546fd839e7a52bca7e9920da918f916ejg}
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejgstatic void
83c4dfe9546fd839e7a52bca7e9920da918f916ejgnvp_list_free(nvfd_t *nvf)
83c4dfe9546fd839e7a52bca7e9920da918f916ejg{
83c4dfe9546fd839e7a52bca7e9920da918f916ejg ASSERT(RW_WRITE_HELD(&nvf->nvf_lock));
83c4dfe9546fd839e7a52bca7e9920da918f916ejg (nvf->nvf_list_free)((nvf_handle_t)nvf);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg ASSERT(RW_WRITE_HELD(&nvf->nvf_lock));
83c4dfe9546fd839e7a52bca7e9920da918f916ejg}
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejg/*
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * Read a file in the nvlist format
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * EIO - i/o error during read
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * ENOENT - file not found
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * EINVAL - file contents corrupted
83c4dfe9546fd839e7a52bca7e9920da918f916ejg */
83c4dfe9546fd839e7a52bca7e9920da918f916ejgstatic int
83c4dfe9546fd839e7a52bca7e9920da918f916ejgfread_nvp_list(nvfd_t *nvfd)
83c4dfe9546fd839e7a52bca7e9920da918f916ejg{
83c4dfe9546fd839e7a52bca7e9920da918f916ejg nvlist_t *nvl;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg nvpair_t *nvp;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg char *name;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg nvlist_t *sublist;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg int rval;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg int rv;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejg ASSERT(RW_WRITE_HELD(&(nvfd->nvf_lock)));
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejg rval = fread_nvlist(nvfd->nvf_cache_path, &nvl);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg if (rval != 0)
83c4dfe9546fd839e7a52bca7e9920da918f916ejg return (rval);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg ASSERT(nvl != NULL);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejg nvp = NULL;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg while ((nvp = nvlist_next_nvpair(nvl, nvp)) != NULL) {
83c4dfe9546fd839e7a52bca7e9920da918f916ejg name = nvpair_name(nvp);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg ASSERT(strlen(name) > 0);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejg switch (nvpair_type(nvp)) {
83c4dfe9546fd839e7a52bca7e9920da918f916ejg case DATA_TYPE_NVLIST:
83c4dfe9546fd839e7a52bca7e9920da918f916ejg rval = nvpair_value_nvlist(nvp, &sublist);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg if (rval != 0) {
83c4dfe9546fd839e7a52bca7e9920da918f916ejg nvf_error(
83c4dfe9546fd839e7a52bca7e9920da918f916ejg "nvpair_value_nvlist error %s %d\n",
83c4dfe9546fd839e7a52bca7e9920da918f916ejg name, rval);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg goto error;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg }
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejg /*
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * unpack nvlist for this device and
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * add elements to data list.
83c4dfe9546fd839e7a52bca7e9920da918f916ejg */
83c4dfe9546fd839e7a52bca7e9920da918f916ejg ASSERT(RW_WRITE_HELD(&(nvfd->nvf_lock)));
83c4dfe9546fd839e7a52bca7e9920da918f916ejg rv = (nvfd->nvf_unpack_nvlist)
83c4dfe9546fd839e7a52bca7e9920da918f916ejg ((nvf_handle_t)nvfd, sublist, name);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg ASSERT(RW_WRITE_HELD(&(nvfd->nvf_lock)));
83c4dfe9546fd839e7a52bca7e9920da918f916ejg if (rv != 0) {
83c4dfe9546fd839e7a52bca7e9920da918f916ejg nvf_error(
83c4dfe9546fd839e7a52bca7e9920da918f916ejg "%s: %s invalid list element\n",
83c4dfe9546fd839e7a52bca7e9920da918f916ejg nvfd->nvf_cache_path, name);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg rval = EINVAL;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg goto error;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg }
83c4dfe9546fd839e7a52bca7e9920da918f916ejg break;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejg default:
83c4dfe9546fd839e7a52bca7e9920da918f916ejg nvf_error("%s: %s unsupported data type %d\n",
83c4dfe9546fd839e7a52bca7e9920da918f916ejg nvfd->nvf_cache_path, name, nvpair_type(nvp));
83c4dfe9546fd839e7a52bca7e9920da918f916ejg rval = EINVAL;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg goto error;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg }
83c4dfe9546fd839e7a52bca7e9920da918f916ejg }
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejg nvlist_free(nvl);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejg return (0);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejgerror:
83c4dfe9546fd839e7a52bca7e9920da918f916ejg nvlist_free(nvl);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg nvp_list_free(nvfd);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg return (rval);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg}
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejgint
83c4dfe9546fd839e7a52bca7e9920da918f916ejgnvf_read_file(nvf_handle_t nvf_handle)
83c4dfe9546fd839e7a52bca7e9920da918f916ejg{
83c4dfe9546fd839e7a52bca7e9920da918f916ejg nvfd_t *nvfd = (nvfd_t *)nvf_handle;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg int rval;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejg ASSERT(RW_WRITE_HELD(&nvfd->nvf_lock));
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejg if (kfio_disable_read)
83c4dfe9546fd839e7a52bca7e9920da918f916ejg return (0);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejg KFDEBUG((CE_CONT, "reading %s\n", nvfd->nvf_cache_path));
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejg rval = fread_nvp_list(nvfd);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg if (rval) {
83c4dfe9546fd839e7a52bca7e9920da918f916ejg switch (rval) {
83c4dfe9546fd839e7a52bca7e9920da918f916ejg case EIO:
83c4dfe9546fd839e7a52bca7e9920da918f916ejg nvfd->nvf_flags |= NVF_F_REBUILD_MSG;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg cmn_err(CE_WARN, "%s: I/O error",
83c4dfe9546fd839e7a52bca7e9920da918f916ejg nvfd->nvf_cache_path);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg break;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg case ENOENT:
83c4dfe9546fd839e7a52bca7e9920da918f916ejg nvfd->nvf_flags |= NVF_F_CREATE_MSG;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg nvf_error("%s: not found\n",
83c4dfe9546fd839e7a52bca7e9920da918f916ejg nvfd->nvf_cache_path);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg break;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg case EINVAL:
83c4dfe9546fd839e7a52bca7e9920da918f916ejg default:
83c4dfe9546fd839e7a52bca7e9920da918f916ejg nvfd->nvf_flags |= NVF_F_REBUILD_MSG;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg cmn_err(CE_WARN, "%s: data file corrupted",
83c4dfe9546fd839e7a52bca7e9920da918f916ejg nvfd->nvf_cache_path);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg break;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg }
83c4dfe9546fd839e7a52bca7e9920da918f916ejg }
83c4dfe9546fd839e7a52bca7e9920da918f916ejg return (rval);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg}
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejgstatic void
83c4dfe9546fd839e7a52bca7e9920da918f916ejgnvf_write_is_complete(nvfd_t *fd)
83c4dfe9546fd839e7a52bca7e9920da918f916ejg{
83c4dfe9546fd839e7a52bca7e9920da918f916ejg if (fd->nvf_write_complete) {
83c4dfe9546fd839e7a52bca7e9920da918f916ejg (fd->nvf_write_complete)((nvf_handle_t)fd);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg }
83c4dfe9546fd839e7a52bca7e9920da918f916ejg}
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejg/*ARGSUSED*/
83c4dfe9546fd839e7a52bca7e9920da918f916ejgstatic void
83c4dfe9546fd839e7a52bca7e9920da918f916ejgnvpflush_timeout(void *arg)
83c4dfe9546fd839e7a52bca7e9920da918f916ejg{
83c4dfe9546fd839e7a52bca7e9920da918f916ejg clock_t nticks;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejg mutex_enter(&nvpflush_lock);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg nticks = nvpticks - ddi_get_lbolt();
83c4dfe9546fd839e7a52bca7e9920da918f916ejg if (nticks > 4) {
83c4dfe9546fd839e7a52bca7e9920da918f916ejg nvpflush_timer_busy = 1;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg mutex_exit(&nvpflush_lock);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg nvpflush_id = timeout(nvpflush_timeout, NULL, nticks);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg } else {
83c4dfe9546fd839e7a52bca7e9920da918f916ejg do_nvpflush = 1;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg NVPDAEMON_DEBUG((CE_CONT, "signal nvpdaemon\n"));
83c4dfe9546fd839e7a52bca7e9920da918f916ejg cv_signal(&nvpflush_cv);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg nvpflush_id = 0;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg nvpflush_timer_busy = 0;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg mutex_exit(&nvpflush_lock);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg }
83c4dfe9546fd839e7a52bca7e9920da918f916ejg}
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejg/*
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * After marking a list as dirty, wake the nvpflush daemon
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * to perform the update.
83c4dfe9546fd839e7a52bca7e9920da918f916ejg */
83c4dfe9546fd839e7a52bca7e9920da918f916ejgvoid
83c4dfe9546fd839e7a52bca7e9920da918f916ejgnvf_wake_daemon(void)
83c4dfe9546fd839e7a52bca7e9920da918f916ejg{
83c4dfe9546fd839e7a52bca7e9920da918f916ejg clock_t nticks;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejg /*
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * If the system isn't up yet
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * don't even think about starting a flush.
83c4dfe9546fd839e7a52bca7e9920da918f916ejg */
83c4dfe9546fd839e7a52bca7e9920da918f916ejg if (!i_ddi_io_initialized())
83c4dfe9546fd839e7a52bca7e9920da918f916ejg return;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejg mutex_enter(&nvpflush_lock);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejg if (nvpflush_daemon_active == 0) {
83c4dfe9546fd839e7a52bca7e9920da918f916ejg nvpflush_daemon_active = 1;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg mutex_exit(&nvpflush_lock);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg NVPDAEMON_DEBUG((CE_CONT, "starting nvpdaemon thread\n"));
83c4dfe9546fd839e7a52bca7e9920da918f916ejg nvpflush_thr_id = thread_create(NULL, 0,
83c4dfe9546fd839e7a52bca7e9920da918f916ejg (void (*)())nvpflush_daemon,
83c4dfe9546fd839e7a52bca7e9920da918f916ejg NULL, 0, &p0, TS_RUN, minclsyspri);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg mutex_enter(&nvpflush_lock);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg }
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejg nticks = nvpflush_delay * TICKS_PER_SECOND;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg nvpticks = ddi_get_lbolt() + nticks;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg if (nvpflush_timer_busy == 0) {
83c4dfe9546fd839e7a52bca7e9920da918f916ejg nvpflush_timer_busy = 1;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg mutex_exit(&nvpflush_lock);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg nvpflush_id = timeout(nvpflush_timeout, NULL, nticks + 4);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg } else
83c4dfe9546fd839e7a52bca7e9920da918f916ejg mutex_exit(&nvpflush_lock);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg}
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejgstatic int
83c4dfe9546fd839e7a52bca7e9920da918f916ejgnvpflush_one(nvfd_t *nvfd)
83c4dfe9546fd839e7a52bca7e9920da918f916ejg{
83c4dfe9546fd839e7a52bca7e9920da918f916ejg int rval = DDI_SUCCESS;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg nvlist_t *nvl;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejg rw_enter(&nvfd->nvf_lock, RW_READER);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejg ASSERT((nvfd->nvf_flags & NVF_F_FLUSHING) == 0);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejg if (!NVF_IS_DIRTY(nvfd) ||
83c4dfe9546fd839e7a52bca7e9920da918f916ejg NVF_IS_READONLY(nvfd) || kfio_disable_write) {
83c4dfe9546fd839e7a52bca7e9920da918f916ejg NVF_CLEAR_DIRTY(nvfd);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg rw_exit(&nvfd->nvf_lock);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg return (DDI_SUCCESS);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg }
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejg if (rw_tryupgrade(&nvfd->nvf_lock) == 0) {
83c4dfe9546fd839e7a52bca7e9920da918f916ejg nvf_error("nvpflush: "
83c4dfe9546fd839e7a52bca7e9920da918f916ejg "%s rw upgrade failed\n", nvfd->nvf_cache_path);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg rw_exit(&nvfd->nvf_lock);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg return (DDI_FAILURE);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg }
83c4dfe9546fd839e7a52bca7e9920da918f916ejg if (((nvfd->nvf_pack_list)
83c4dfe9546fd839e7a52bca7e9920da918f916ejg ((nvf_handle_t)nvfd, &nvl)) != DDI_SUCCESS) {
83c4dfe9546fd839e7a52bca7e9920da918f916ejg nvf_error("nvpflush: "
83c4dfe9546fd839e7a52bca7e9920da918f916ejg "%s nvlist construction failed\n", nvfd->nvf_cache_path);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg ASSERT(RW_WRITE_HELD(&nvfd->nvf_lock));
83c4dfe9546fd839e7a52bca7e9920da918f916ejg rw_exit(&nvfd->nvf_lock);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg return (DDI_FAILURE);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg }
83c4dfe9546fd839e7a52bca7e9920da918f916ejg ASSERT(RW_WRITE_HELD(&nvfd->nvf_lock));
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejg NVF_CLEAR_DIRTY(nvfd);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg nvfd->nvf_flags |= NVF_F_FLUSHING;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg rw_exit(&nvfd->nvf_lock);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejg rval = e_fwrite_nvlist(nvfd, nvl);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg nvlist_free(nvl);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejg rw_enter(&nvfd->nvf_lock, RW_WRITER);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg nvfd->nvf_flags &= ~NVF_F_FLUSHING;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg if (rval == DDI_FAILURE) {
83c4dfe9546fd839e7a52bca7e9920da918f916ejg if (NVF_IS_READONLY(nvfd)) {
83c4dfe9546fd839e7a52bca7e9920da918f916ejg rval = DDI_SUCCESS;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg nvfd->nvf_flags &= ~(NVF_F_ERROR | NVF_F_DIRTY);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg } else if ((nvfd->nvf_flags & NVF_F_ERROR) == 0) {
83c4dfe9546fd839e7a52bca7e9920da918f916ejg cmn_err(CE_CONT,
83c4dfe9546fd839e7a52bca7e9920da918f916ejg "%s: updated failed\n", nvfd->nvf_cache_path);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg nvfd->nvf_flags |= NVF_F_ERROR | NVF_F_DIRTY;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg }
83c4dfe9546fd839e7a52bca7e9920da918f916ejg } else {
83c4dfe9546fd839e7a52bca7e9920da918f916ejg if (nvfd->nvf_flags & NVF_F_CREATE_MSG) {
83c4dfe9546fd839e7a52bca7e9920da918f916ejg cmn_err(CE_CONT,
83c4dfe9546fd839e7a52bca7e9920da918f916ejg "!Creating %s\n", nvfd->nvf_cache_path);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg nvfd->nvf_flags &= ~NVF_F_CREATE_MSG;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg }
83c4dfe9546fd839e7a52bca7e9920da918f916ejg if (nvfd->nvf_flags & NVF_F_REBUILD_MSG) {
83c4dfe9546fd839e7a52bca7e9920da918f916ejg cmn_err(CE_CONT,
83c4dfe9546fd839e7a52bca7e9920da918f916ejg "!Rebuilding %s\n", nvfd->nvf_cache_path);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg nvfd->nvf_flags &= ~NVF_F_REBUILD_MSG;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg }
83c4dfe9546fd839e7a52bca7e9920da918f916ejg if (nvfd->nvf_flags & NVF_F_ERROR) {
83c4dfe9546fd839e7a52bca7e9920da918f916ejg cmn_err(CE_CONT,
83c4dfe9546fd839e7a52bca7e9920da918f916ejg "%s: update now ok\n", nvfd->nvf_cache_path);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg nvfd->nvf_flags &= ~NVF_F_ERROR;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg }
83c4dfe9546fd839e7a52bca7e9920da918f916ejg /*
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * The file may need to be flushed again if the cached
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * data was touched while writing the earlier contents.
83c4dfe9546fd839e7a52bca7e9920da918f916ejg */
83c4dfe9546fd839e7a52bca7e9920da918f916ejg if (NVF_IS_DIRTY(nvfd))
83c4dfe9546fd839e7a52bca7e9920da918f916ejg rval = DDI_FAILURE;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg }
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejg rw_exit(&nvfd->nvf_lock);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg return (rval);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg}
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejgstatic void
83c4dfe9546fd839e7a52bca7e9920da918f916ejgnvpflush_daemon(void)
83c4dfe9546fd839e7a52bca7e9920da918f916ejg{
83c4dfe9546fd839e7a52bca7e9920da918f916ejg callb_cpr_t cprinfo;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg nvfd_t *nvfdp, *nextfdp;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg clock_t clk;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg int rval;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg int want_wakeup;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg int is_now_clean;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejg ASSERT(modrootloaded);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejg nvpflush_thread = curthread;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg NVPDAEMON_DEBUG((CE_CONT, "nvpdaemon: init\n"));
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejg CALLB_CPR_INIT(&cprinfo, &nvpflush_lock, callb_generic_cpr, "nvp");
83c4dfe9546fd839e7a52bca7e9920da918f916ejg mutex_enter(&nvpflush_lock);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg for (;;) {
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejg CALLB_CPR_SAFE_BEGIN(&cprinfo);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg while (do_nvpflush == 0) {
83c4dfe9546fd839e7a52bca7e9920da918f916ejg clk = cv_timedwait(&nvpflush_cv, &nvpflush_lock,
83c4dfe9546fd839e7a52bca7e9920da918f916ejg ddi_get_lbolt() +
83c4dfe9546fd839e7a52bca7e9920da918f916ejg (nvpdaemon_idle_time * TICKS_PER_SECOND));
83c4dfe9546fd839e7a52bca7e9920da918f916ejg if (clk == -1 &&
83c4dfe9546fd839e7a52bca7e9920da918f916ejg do_nvpflush == 0 && nvpflush_timer_busy == 0) {
83c4dfe9546fd839e7a52bca7e9920da918f916ejg /*
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * Note that CALLB_CPR_EXIT calls mutex_exit()
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * on the lock passed in to CALLB_CPR_INIT,
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * so the lock must be held when invoking it.
83c4dfe9546fd839e7a52bca7e9920da918f916ejg */
83c4dfe9546fd839e7a52bca7e9920da918f916ejg CALLB_CPR_SAFE_END(&cprinfo, &nvpflush_lock);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg NVPDAEMON_DEBUG((CE_CONT, "nvpdaemon: exit\n"));
83c4dfe9546fd839e7a52bca7e9920da918f916ejg ASSERT(mutex_owned(&nvpflush_lock));
83c4dfe9546fd839e7a52bca7e9920da918f916ejg nvpflush_thr_id = NULL;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg nvpflush_daemon_active = 0;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg CALLB_CPR_EXIT(&cprinfo);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg thread_exit();
83c4dfe9546fd839e7a52bca7e9920da918f916ejg }
83c4dfe9546fd839e7a52bca7e9920da918f916ejg }
83c4dfe9546fd839e7a52bca7e9920da918f916ejg CALLB_CPR_SAFE_END(&cprinfo, &nvpflush_lock);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejg nvpbusy = 1;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg want_wakeup = 0;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg do_nvpflush = 0;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg mutex_exit(&nvpflush_lock);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejg /*
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * Try flushing what's dirty, reschedule if there's
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * a failure or data gets marked as dirty again.
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * First move each file marked dirty to the dirty
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * list to avoid locking the list across the write.
83c4dfe9546fd839e7a52bca7e9920da918f916ejg */
83c4dfe9546fd839e7a52bca7e9920da918f916ejg mutex_enter(&nvf_cache_mutex);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg for (nvfdp = list_head(&nvf_cache_files);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg nvfdp; nvfdp = nextfdp) {
83c4dfe9546fd839e7a52bca7e9920da918f916ejg nextfdp = list_next(&nvf_cache_files, nvfdp);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg rw_enter(&nvfdp->nvf_lock, RW_READER);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg if (NVF_IS_DIRTY(nvfdp)) {
83c4dfe9546fd839e7a52bca7e9920da918f916ejg list_remove(&nvf_cache_files, nvfdp);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg list_insert_tail(&nvf_dirty_files, nvfdp);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg rw_exit(&nvfdp->nvf_lock);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg } else {
83c4dfe9546fd839e7a52bca7e9920da918f916ejg NVPDAEMON_DEBUG((CE_CONT,
83c4dfe9546fd839e7a52bca7e9920da918f916ejg "nvpdaemon: not dirty %s\n",
83c4dfe9546fd839e7a52bca7e9920da918f916ejg nvfdp->nvf_cache_path));
83c4dfe9546fd839e7a52bca7e9920da918f916ejg rw_exit(&nvfdp->nvf_lock);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg }
83c4dfe9546fd839e7a52bca7e9920da918f916ejg }
83c4dfe9546fd839e7a52bca7e9920da918f916ejg mutex_exit(&nvf_cache_mutex);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejg /*
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * Now go through the dirty list
83c4dfe9546fd839e7a52bca7e9920da918f916ejg */
83c4dfe9546fd839e7a52bca7e9920da918f916ejg for (nvfdp = list_head(&nvf_dirty_files);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg nvfdp; nvfdp = nextfdp) {
83c4dfe9546fd839e7a52bca7e9920da918f916ejg nextfdp = list_next(&nvf_dirty_files, nvfdp);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejg is_now_clean = 0;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg rw_enter(&nvfdp->nvf_lock, RW_READER);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg if (NVF_IS_DIRTY(nvfdp)) {
83c4dfe9546fd839e7a52bca7e9920da918f916ejg NVPDAEMON_DEBUG((CE_CONT,
83c4dfe9546fd839e7a52bca7e9920da918f916ejg "nvpdaemon: flush %s\n",
83c4dfe9546fd839e7a52bca7e9920da918f916ejg nvfdp->nvf_cache_path));
83c4dfe9546fd839e7a52bca7e9920da918f916ejg rw_exit(&nvfdp->nvf_lock);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg rval = nvpflush_one(nvfdp);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg rw_enter(&nvfdp->nvf_lock, RW_READER);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg if (rval != DDI_SUCCESS ||
83c4dfe9546fd839e7a52bca7e9920da918f916ejg NVF_IS_DIRTY(nvfdp)) {
83c4dfe9546fd839e7a52bca7e9920da918f916ejg rw_exit(&nvfdp->nvf_lock);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg NVPDAEMON_DEBUG((CE_CONT,
83c4dfe9546fd839e7a52bca7e9920da918f916ejg "nvpdaemon: %s dirty again\n",
83c4dfe9546fd839e7a52bca7e9920da918f916ejg nvfdp->nvf_cache_path));
83c4dfe9546fd839e7a52bca7e9920da918f916ejg want_wakeup = 1;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg } else {
83c4dfe9546fd839e7a52bca7e9920da918f916ejg rw_exit(&nvfdp->nvf_lock);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg nvf_write_is_complete(nvfdp);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg is_now_clean = 1;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg }
83c4dfe9546fd839e7a52bca7e9920da918f916ejg } else {
83c4dfe9546fd839e7a52bca7e9920da918f916ejg NVPDAEMON_DEBUG((CE_CONT,
83c4dfe9546fd839e7a52bca7e9920da918f916ejg "nvpdaemon: not dirty %s\n",
83c4dfe9546fd839e7a52bca7e9920da918f916ejg nvfdp->nvf_cache_path));
83c4dfe9546fd839e7a52bca7e9920da918f916ejg rw_exit(&nvfdp->nvf_lock);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg is_now_clean = 1;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg }
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejg if (is_now_clean) {
83c4dfe9546fd839e7a52bca7e9920da918f916ejg mutex_enter(&nvf_cache_mutex);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg list_remove(&nvf_dirty_files, nvfdp);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg list_insert_tail(&nvf_cache_files,
83c4dfe9546fd839e7a52bca7e9920da918f916ejg nvfdp);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg mutex_exit(&nvf_cache_mutex);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg }
83c4dfe9546fd839e7a52bca7e9920da918f916ejg }
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejg if (want_wakeup)
83c4dfe9546fd839e7a52bca7e9920da918f916ejg nvf_wake_daemon();
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejg mutex_enter(&nvpflush_lock);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg nvpbusy = 0;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg }
83c4dfe9546fd839e7a52bca7e9920da918f916ejg}