summaryrefslogtreecommitdiff
path: root/usr/src/uts/common/os/devctl.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/uts/common/os/devctl.c')
-rw-r--r--usr/src/uts/common/os/devctl.c447
1 files changed, 326 insertions, 121 deletions
diff --git a/usr/src/uts/common/os/devctl.c b/usr/src/uts/common/os/devctl.c
index 57a7c05ac8..90354cde34 100644
--- a/usr/src/uts/common/os/devctl.c
+++ b/usr/src/uts/common/os/devctl.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -51,7 +50,6 @@
#include <sys/fs/snode.h>
#include <sys/fs/dv_node.h>
#include <sys/kobj.h>
-
#include <sys/devctl_impl.h>
@@ -65,6 +63,8 @@ int devid_discovery_secs = 0;
int devid_cache_read_disable = 0;
int devid_cache_write_disable = 0;
+int sdev_cache_read_disable = 0;
+int sdev_cache_write_disable = 0;
int kfio_report_error = 0; /* kernel file i/o operations */
int devid_report_error = 0; /* devid cache operations */
@@ -78,13 +78,46 @@ static kmutex_t devid_discovery_mutex;
static kcondvar_t devid_discovery_cv;
static clock_t devid_last_discovery = 0;
+
+static int devid_nvp2nvl(nvfd_t *, nvlist_t **);
+static nvp_list_t *devid_nvl2nvp(nvlist_t *, char *);
+static void devid_nvp_free(nvp_list_t *);
+
+static int sdev_nvp2nvl(nvfd_t *, nvlist_t **);
+static nvp_list_t *sdev_nvl2nvp(nvlist_t *, char *);
+static void sdev_nvp_free(nvp_list_t *);
+
/*
- * Descriptor for /etc/devices/devid_cache
+ * Descriptors for the /etc/devices cache files
*/
-nvfd_t devid_cache_fd = {
+static nvfd_t devid_cache_fd = {
"/etc/devices/devid_cache",
+ devid_nvp2nvl, /* nvf_nvp2nvl */
+ devid_nvl2nvp, /* nvf_nvl2nvp */
+ devid_nvp_free, /* nvf_nvp_free */
+ NULL, /* nvf_write_complete */
+ 0, NULL, NULL, 0
+
};
-static nvfd_t *dcfd = &devid_cache_fd;
+static nvfd_t sdev_cache_fd = {
+ "/etc/devices/devname_cache",
+ sdev_nvp2nvl, /* nvf_nvp2nvl */
+ sdev_nvl2nvp, /* nvf_nvl2nvp */
+ sdev_nvp_free, /* nvf_nvp_free */
+ NULL, /* nvf_write_complete */
+ 0, NULL, NULL, 0
+};
+
+static nvfd_t *dcfd = &devid_cache_fd;
+nvfd_t *sdevfd = &sdev_cache_fd;
+
+static nvfd_t *cachefds[] = {
+ &devid_cache_fd,
+ &sdev_cache_fd
+};
+
+#define NCACHEFDS ((sizeof (cachefds)) / (sizeof (nvfd_t *)))
+
extern int modrootloaded;
@@ -122,6 +155,11 @@ i_ddi_devices_init(void)
dcfd->nvf_tail = NULL;
rw_init(&dcfd->nvf_lock, NULL, RW_DRIVER, NULL);
+ sdevfd->nvf_flags = 0;
+ sdevfd->nvf_list = NULL;
+ sdevfd->nvf_tail = NULL;
+ rw_init(&sdevfd->nvf_lock, NULL, RW_DRIVER, NULL);
+
mutex_init(&devid_discovery_mutex, NULL, MUTEX_DEFAULT, NULL);
cv_init(&devid_discovery_cv, NULL, CV_DRIVER, NULL);
}
@@ -546,44 +584,63 @@ e_fwrite_nvlist(nvfd_t *nvfd, nvlist_t *nvl)
}
static void
-nvp_free(nvp_list_t *np)
+devid_nvp_free(nvp_list_t *np)
+{
+ nvp_devid_t *dp = NVP2DEVID(np);
+
+ if (dp->nvp_devpath)
+ kmem_free(dp->nvp_devpath, strlen(dp->nvp_devpath)+1);
+ if (dp->nvp_devid)
+ kmem_free(dp->nvp_devid, ddi_devid_sizeof(dp->nvp_devid));
+
+ kmem_free(dp, sizeof (nvp_devid_t));
+}
+
+static void
+sdev_nvp_free(nvp_list_t *np)
{
- if (np->nvp_devpath)
- kmem_free(np->nvp_devpath, strlen(np->nvp_devpath)+1);
- if (np->nvp_devid)
- kmem_free(np->nvp_devid, ddi_devid_sizeof(np->nvp_devid));
+ nvp_devname_t *dp = NVP2DEVNAME(np);
+ int i;
+ char **p;
+
+ if (dp->nvp_npaths > 0) {
+ p = dp->nvp_paths;
+ for (i = 0; i < dp->nvp_npaths; i++, p++) {
+ kmem_free(*p, strlen(*p)+1);
+ }
+ kmem_free(dp->nvp_paths,
+ dp->nvp_npaths * sizeof (char *));
+ kmem_free(dp->nvp_expirecnts,
+ dp->nvp_npaths * sizeof (int));
+ }
- kmem_free(np, sizeof (nvp_list_t));
+ kmem_free(dp, sizeof (nvp_devname_t));
}
static void
-nvp_list_free(nvp_list_t *nvp)
+nvp_list_free(nvfd_t *nvf, nvp_list_t *nvp)
{
nvp_list_t *np;
nvp_list_t *next;
for (np = nvp; np; np = next) {
next = np->nvp_next;
- nvp_free(np);
+ (nvf->nvf_nvp_free)(np);
}
}
+
/*
- * Free the devid-related information in an nvp element
- * If no more data is stored in the nvp element, free
- * it and unlink it from the list
- *
- * Since at present there is no further use of nvp's,
- * there's nothing to check.
+ * Free an nvp element in a list
*/
-static nvp_list_t *
-nfd_devid_free_and_unlink(nvfd_t *nvf, nvp_list_t *np)
+void
+nfd_nvp_free_and_unlink(nvfd_t *nvf, nvp_list_t *np)
{
nvp_list_t *pv, *next;
pv = np->nvp_prev;
next = np->nvp_next;
- nvp_free(np);
+ (nvf->nvf_nvp_free)(np);
/* remove element at head */
if (pv == NULL) {
@@ -602,12 +659,10 @@ nfd_devid_free_and_unlink(nvfd_t *nvf, nvp_list_t *np)
pv->nvp_next = next;
next->nvp_prev = pv;
}
-
- return (next);
}
-static void
-nfd_devid_link(nvfd_t *nvf, nvp_list_t *np)
+void
+nfd_nvp_link(nvfd_t *nvf, nvp_list_t *np)
{
if (nvf->nvf_list == NULL) {
nvf->nvf_list = np;
@@ -622,16 +677,17 @@ nfd_devid_link(nvfd_t *nvf, nvp_list_t *np)
/*
* Convert a device path/nvlist pair to an nvp_list_t
* Used to parse the nvlist format when reading
+ * /etc/devices/devid_cache
*/
static nvp_list_t *
-nvlist_to_nvp(nvlist_t *nvl, char *name)
+devid_nvl2nvp(nvlist_t *nvl, char *name)
{
- nvp_list_t *np;
+ nvp_devid_t *np;
ddi_devid_t devidp;
int rval;
uint_t n;
- np = kmem_zalloc(sizeof (nvp_list_t), KM_SLEEP);
+ np = kmem_zalloc(sizeof (nvp_devid_t), KM_SLEEP);
np->nvp_devpath = i_ddi_strdup(name, KM_SLEEP);
NVP_DEVID_DEBUG_PATH((np->nvp_devpath));
@@ -654,18 +710,70 @@ nvlist_to_nvp(nvlist_t *nvl, char *name)
}
}
- return (np);
+ return (NVPLIST(np));
}
/*
+ * Convert a device path/nvlist pair to an nvp_list_t
+ * Used to parse the nvlist format when reading
+ * /etc/devices/devname_cache
+ */
+static nvp_list_t *
+sdev_nvl2nvp(nvlist_t *nvl, char *name)
+{
+ nvp_devname_t *np;
+ char **strs;
+ int *cnts;
+ uint_t nstrs, ncnts;
+ int rval, i;
+
+ /* name of the sublist must match what we created */
+ if (strcmp(name, DP_DEVNAME_ID) != 0) {
+ return (NULL);
+ }
+
+ np = kmem_zalloc(sizeof (nvp_devname_t), KM_SLEEP);
+
+ rval = nvlist_lookup_string_array(nvl,
+ DP_DEVNAME_NCACHE_ID, &strs, &nstrs);
+ if (rval) {
+ kmem_free(np, sizeof (nvp_devname_t));
+ return (NULL);
+ }
+
+ np->nvp_npaths = nstrs;
+ np->nvp_paths = kmem_zalloc(nstrs * sizeof (char *), KM_SLEEP);
+ for (i = 0; i < nstrs; i++) {
+ np->nvp_paths[i] = i_ddi_strdup(strs[i], KM_SLEEP);
+ }
+ np->nvp_expirecnts = kmem_zalloc(nstrs * sizeof (int), KM_SLEEP);
+ for (i = 0; i < nstrs; i++) {
+ np->nvp_expirecnts[i] = 4; /* XXX sdev_nc_expirecnt */
+ }
+
+ rval = nvlist_lookup_int32_array(nvl,
+ DP_DEVNAME_NC_EXPIRECNT_ID, &cnts, &ncnts);
+ if (rval == 0) {
+ ASSERT(ncnts == nstrs);
+ ncnts = max(ncnts, nstrs);
+ for (i = 0; i < nstrs; i++) {
+ np->nvp_expirecnts[i] = cnts[i];
+ }
+ }
+
+ return (NVPLIST(np));
+}
+
+
+/*
* Convert a list of nvp_list_t's to a single nvlist
- * Used when writing the nvlist file
+ * Used when writing the nvlist file.
*/
static int
-nvp_to_nvlist(nvfd_t *nvfd, nvlist_t **ret_nvl)
+devid_nvp2nvl(nvfd_t *nvfd, nvlist_t **ret_nvl)
{
nvlist_t *nvl, *sub_nvl;
- nvp_list_t *np;
+ nvp_devid_t *np;
int rval;
ASSERT(modrootloaded);
@@ -677,7 +785,7 @@ nvp_to_nvlist(nvfd_t *nvfd, nvlist_t **ret_nvl)
return (DDI_FAILURE);
}
- for (np = nvfd->nvf_list; np; np = np->nvp_next) {
+ for (np = NVF_DEVID_LIST(nvfd); np; np = NVP_DEVID_NEXT(np)) {
if (np->nvp_devid == NULL)
continue;
NVP_DEVID_DEBUG_PATH(np->nvp_devpath);
@@ -689,18 +797,16 @@ nvp_to_nvlist(nvfd_t *nvfd, nvlist_t **ret_nvl)
goto err;
}
- if (np->nvp_devid) {
- rval = nvlist_add_byte_array(sub_nvl, DP_DEVID_ID,
- (uchar_t *)np->nvp_devid,
- ddi_devid_sizeof(np->nvp_devid));
- if (rval == 0) {
- NVP_DEVID_DEBUG_DEVID(np->nvp_devid);
- } else {
- KFIOERR((CE_CONT,
- "%s: nvlist add error %d (devid)\n",
- nvfd->nvf_name, rval));
- goto err;
- }
+ rval = nvlist_add_byte_array(sub_nvl, DP_DEVID_ID,
+ (uchar_t *)np->nvp_devid,
+ ddi_devid_sizeof(np->nvp_devid));
+ if (rval == 0) {
+ NVP_DEVID_DEBUG_DEVID(np->nvp_devid);
+ } else {
+ KFIOERR((CE_CONT,
+ "%s: nvlist add error %d (devid)\n",
+ nvfd->nvf_name, rval));
+ goto err;
}
rval = nvlist_add_nvlist(nvl, np->nvp_devpath, sub_nvl);
@@ -723,6 +829,76 @@ err:
return (DDI_FAILURE);
}
+/*
+ * Convert a list of nvp_list_t's to a single nvlist
+ * Used when writing the nvlist file.
+ */
+static int
+sdev_nvp2nvl(nvfd_t *nvfd, nvlist_t **ret_nvl)
+{
+ nvlist_t *nvl, *sub_nvl;
+ nvp_devname_t *np;
+ int rval;
+
+ ASSERT(modrootloaded);
+
+ rval = nvlist_alloc(&nvl, NV_UNIQUE_NAME, KM_SLEEP);
+ if (rval != 0) {
+ KFIOERR((CE_CONT, "%s: nvlist alloc error %d\n",
+ nvfd->nvf_name, rval));
+ return (DDI_FAILURE);
+ }
+
+ if ((np = NVF_DEVNAME_LIST(nvfd)) != NULL) {
+ ASSERT(NVP_DEVNAME_NEXT(np) == NULL);
+
+ rval = nvlist_alloc(&sub_nvl, NV_UNIQUE_NAME, KM_SLEEP);
+ if (rval != 0) {
+ KFIOERR((CE_CONT, "%s: nvlist alloc error %d\n",
+ nvfd->nvf_name, rval));
+ sub_nvl = NULL;
+ goto err;
+ }
+
+ rval = nvlist_add_string_array(sub_nvl,
+ DP_DEVNAME_NCACHE_ID, np->nvp_paths, np->nvp_npaths);
+ if (rval != 0) {
+ KFIOERR((CE_CONT,
+ "%s: nvlist add error %d (sdev)\n",
+ nvfd->nvf_name, rval));
+ goto err;
+ }
+
+ rval = nvlist_add_int32_array(sub_nvl,
+ DP_DEVNAME_NC_EXPIRECNT_ID,
+ np->nvp_expirecnts, np->nvp_npaths);
+ if (rval != 0) {
+ KFIOERR((CE_CONT,
+ "%s: nvlist add error %d (sdev)\n",
+ nvfd->nvf_name, rval));
+ goto err;
+ }
+
+ rval = nvlist_add_nvlist(nvl, DP_DEVNAME_ID, sub_nvl);
+ if (rval != 0) {
+ KFIOERR((CE_CONT, "%s: nvlist add error %d (sublist)\n",
+ nvfd->nvf_name, rval));
+ goto err;
+ }
+ nvlist_free(sub_nvl);
+ }
+
+ *ret_nvl = nvl;
+ return (DDI_SUCCESS);
+
+err:
+ if (sub_nvl)
+ nvlist_free(sub_nvl);
+ nvlist_free(nvl);
+ *ret_nvl = NULL;
+ return (DDI_FAILURE);
+}
+
/*
* Read a file in the nvlist format
@@ -769,17 +945,18 @@ fread_nvp_list(nvfd_t *nvfd)
* convert nvlist for this device to
* an nvp_list_t struct
*/
- np = nvlist_to_nvp(sublist, name);
- np->nvp_next = NULL;
- np->nvp_prev = nvp_tail;
+ np = (nvfd->nvf_nvl2nvp)(sublist, name);
+ if (np) {
+ np->nvp_next = NULL;
+ np->nvp_prev = nvp_tail;
- if (nvp_list == NULL) {
- nvp_list = np;
- } else {
- nvp_tail->nvp_next = np;
+ if (nvp_list == NULL) {
+ nvp_list = np;
+ } else {
+ nvp_tail->nvp_next = np;
+ }
+ nvp_tail = np;
}
- nvp_tail = np;
-
break;
default:
@@ -800,7 +977,7 @@ fread_nvp_list(nvfd_t *nvfd)
error:
nvlist_free(nvl);
if (nvp_list)
- nvp_list_free(nvp_list);
+ nvp_list_free(nvfd, nvp_list);
return (rval);
}
@@ -810,7 +987,7 @@ i_ddi_read_one_nvfile(nvfd_t *nvfd)
{
int rval;
- KFDEBUG((CE_CONT, "Reading %s\n", nvfd->nvf_name));
+ KFDEBUG((CE_CONT, "reading %s\n", nvfd->nvf_name));
rval = fread_nvp_list(nvfd);
if (rval) {
@@ -836,39 +1013,26 @@ i_ddi_read_one_nvfile(nvfd_t *nvfd)
return (rval);
}
+/* for information possibly required to mount root */
void
i_ddi_read_devices_files(void)
{
- nvfd_t nvfd;
- int rval;
-
mdi_read_devices_files();
- if (devid_cache_read_disable)
- return;
-
- nvfd.nvf_name = dcfd->nvf_name;
- nvfd.nvf_flags = 0;
- nvfd.nvf_list = NULL;
- nvfd.nvf_tail = NULL;
- rw_init(&nvfd.nvf_lock, NULL, RW_DRIVER, NULL);
-
- rval = i_ddi_read_one_nvfile(&nvfd);
-
- rw_enter(&dcfd->nvf_lock, RW_WRITER);
-
- if (rval == 0) {
- if (dcfd->nvf_list != NULL) {
- nvp_list_free(dcfd->nvf_list);
- }
- dcfd->nvf_list = nvfd.nvf_list;
- dcfd->nvf_tail = nvfd.nvf_tail;
+ if (devid_cache_read_disable == 0) {
+ ASSERT(dcfd->nvf_list == NULL);
+ (void) i_ddi_read_one_nvfile(dcfd);
}
- dcfd->nvf_flags = nvfd.nvf_flags;
-
- rw_exit(&dcfd->nvf_lock);
+}
- rw_destroy(&nvfd.nvf_lock);
+/* may be done after root is mounted */
+void
+i_ddi_read_devname_file(void)
+{
+ if (sdev_cache_read_disable == 0) {
+ ASSERT(sdevfd->nvf_list == NULL);
+ (void) i_ddi_read_one_nvfile(sdevfd);
+ }
}
static int
@@ -1003,8 +1167,8 @@ e_ddi_devid_discovery(ddi_devid_t devid)
int
e_devid_cache_register(dev_info_t *dip, ddi_devid_t devid)
{
- nvp_list_t *np;
- nvp_list_t *new_nvp;
+ nvp_devid_t *np;
+ nvp_devid_t *new_nvp;
ddi_devid_t new_devid;
int new_devid_size;
char *path, *fullpath;
@@ -1022,14 +1186,14 @@ e_devid_cache_register(dev_info_t *dip, ddi_devid_t devid)
DEVID_LOG_REG(("register", devid, path));
- new_nvp = kmem_zalloc(sizeof (nvp_list_t), KM_SLEEP);
+ new_nvp = kmem_zalloc(sizeof (nvp_devid_t), KM_SLEEP);
new_devid_size = ddi_devid_sizeof(devid);
new_devid = kmem_alloc(new_devid_size, KM_SLEEP);
(void) bcopy(devid, new_devid, new_devid_size);
rw_enter(&dcfd->nvf_lock, RW_WRITER);
- for (np = dcfd->nvf_list; np != NULL; np = np->nvp_next) {
+ for (np = NVF_DEVID_LIST(dcfd); np; np = NVP_DEVID_NEXT(np)) {
if (strcmp(path, np->nvp_devpath) == 0) {
DEVID_DEBUG2((CE_CONT,
"register: %s path match\n", path));
@@ -1041,7 +1205,7 @@ e_devid_cache_register(dev_info_t *dip, ddi_devid_t devid)
np->nvp_dip = dip;
NVF_MARK_DIRTY(dcfd);
rw_exit(&dcfd->nvf_lock);
- kmem_free(new_nvp, sizeof (nvp_list_t));
+ kmem_free(new_nvp, sizeof (nvp_devid_t));
kmem_free(path, pathlen);
goto exit;
}
@@ -1063,8 +1227,7 @@ e_devid_cache_register(dev_info_t *dip, ddi_devid_t devid)
* may map to multiple paths but one path
* should only map to one devid.
*/
- (void) nfd_devid_free_and_unlink(
- dcfd, np);
+ nfd_nvp_free_and_unlink(dcfd, NVPLIST(np));
np = NULL;
break;
} else {
@@ -1074,7 +1237,7 @@ e_devid_cache_register(dev_info_t *dip, ddi_devid_t devid)
NVP_DEVID_DIP | NVP_DEVID_REGISTERED;
np->nvp_dip = dip;
rw_exit(&dcfd->nvf_lock);
- kmem_free(new_nvp, sizeof (nvp_list_t));
+ kmem_free(new_nvp, sizeof (nvp_devid_t));
kmem_free(path, pathlen);
kmem_free(new_devid, new_devid_size);
return (DDI_SUCCESS);
@@ -1093,7 +1256,7 @@ e_devid_cache_register(dev_info_t *dip, ddi_devid_t devid)
new_nvp->nvp_devid = new_devid;
NVF_MARK_DIRTY(dcfd);
- nfd_devid_link(dcfd, new_nvp);
+ nfd_nvp_link(dcfd, NVPLIST(new_nvp));
rw_exit(&dcfd->nvf_lock);
@@ -1101,7 +1264,8 @@ exit:
if (free_devid)
kmem_free(free_devid, ddi_devid_sizeof(free_devid));
- wake_nvpflush_daemon(dcfd);
+ if (!devid_cache_write_disable)
+ wake_nvpflush_daemon();
return (DDI_SUCCESS);
}
@@ -1115,11 +1279,11 @@ exit:
void
e_devid_cache_unregister(dev_info_t *dip)
{
- nvp_list_t *np;
+ nvp_devid_t *np;
rw_enter(&dcfd->nvf_lock, RW_WRITER);
- for (np = dcfd->nvf_list; np != NULL; np = np->nvp_next) {
+ for (np = NVF_DEVID_LIST(dcfd); np; np = NVP_DEVID_NEXT(np)) {
if (np->nvp_devid == NULL)
continue;
if ((np->nvp_flags & NVP_DEVID_DIP) && np->nvp_dip == dip) {
@@ -1138,26 +1302,26 @@ e_devid_cache_unregister(dev_info_t *dip)
void
e_devid_cache_cleanup(void)
{
- nvp_list_t *np, *next;
+ nvp_devid_t *np, *next;
rw_enter(&dcfd->nvf_lock, RW_WRITER);
- for (np = dcfd->nvf_list; np != NULL; np = next) {
- next = np->nvp_next;
+ for (np = NVF_DEVID_LIST(dcfd); np; np = next) {
+ next = NVP_DEVID_NEXT(np);
if (np->nvp_devid == NULL)
continue;
if ((np->nvp_flags & NVP_DEVID_REGISTERED) == 0) {
DEVID_LOG_REMOVE((CE_CONT,
"cleanup: %s\n", np->nvp_devpath));
NVF_MARK_DIRTY(dcfd);
- next = nfd_devid_free_and_unlink(dcfd, np);
+ nfd_nvp_free_and_unlink(dcfd, NVPLIST(np));
}
}
rw_exit(&dcfd->nvf_lock);
if (NVF_IS_DIRTY(dcfd))
- wake_nvpflush_daemon(dcfd);
+ wake_nvpflush_daemon();
}
@@ -1229,7 +1393,7 @@ static int
e_devid_cache_devi_path_lists(ddi_devid_t devid, int retmax,
int *retndevis, dev_info_t **retdevis, int *retnpaths, char **retpaths)
{
- nvp_list_t *np;
+ nvp_devid_t *np;
int ndevis, npaths;
dev_info_t *dip, *pdip;
int circ;
@@ -1238,7 +1402,7 @@ e_devid_cache_devi_path_lists(ddi_devid_t devid, int retmax,
ndevis = 0;
npaths = 0;
- for (np = dcfd->nvf_list; np != NULL; np = np->nvp_next) {
+ for (np = NVF_DEVID_LIST(dcfd); np; np = NVP_DEVID_NEXT(np)) {
if (np->nvp_devid == NULL)
continue;
if (ddi_devid_valid(np->nvp_devid) != DDI_SUCCESS) {
@@ -1514,6 +1678,25 @@ static clock_t nvpticks;
static void nvpflush_daemon(void);
+void
+nvf_register_write_complete(nvfd_t *fd, void (*f)(nvfd_t *))
+{
+ fd->nvf_write_complete = f;
+}
+
+void
+nvf_unregister_write_complete(nvfd_t *fd)
+{
+ fd->nvf_write_complete = NULL;
+}
+
+static void
+nvf_write_complete(nvfd_t *fd)
+{
+ if (fd->nvf_write_complete) {
+ (*(fd->nvf_write_complete))(fd);
+ }
+}
void
i_ddi_start_flush_daemon(void)
@@ -1523,8 +1706,9 @@ i_ddi_start_flush_daemon(void)
mutex_init(&nvpflush_lock, NULL, MUTEX_DRIVER, NULL);
cv_init(&nvpflush_cv, NULL, CV_DRIVER, NULL);
- if (NVF_IS_DIRTY(dcfd)) {
- wake_nvpflush_daemon(dcfd);
+ if ((NVF_IS_DIRTY(dcfd) && !devid_cache_write_disable) ||
+ (NVF_IS_DIRTY(sdevfd) && !sdevfd && sdev_cache_write_disable)) {
+ wake_nvpflush_daemon();
}
}
@@ -1542,6 +1726,7 @@ nvpflush_timeout(void *arg)
nvpflush_id = timeout(nvpflush_timeout, NULL, nticks);
} else {
do_nvpflush = 1;
+ NVPDAEMON_DEBUG((CE_CONT, "signal nvpdaemon\n"));
cv_signal(&nvpflush_cv);
nvpflush_id = 0;
nvpflush_timer_busy = 0;
@@ -1549,17 +1734,16 @@ nvpflush_timeout(void *arg)
}
}
-static void
-wake_nvpflush_daemon(nvfd_t *nvfp)
+void
+wake_nvpflush_daemon()
{
clock_t nticks;
/*
- * If root is readonly or the system isn't up yet
+ * If the system isn't up yet
* don't even think about starting a flush.
*/
- if (devid_cache_write_disable ||
- !i_ddi_io_initialized() || NVF_IS_READONLY(nvfp))
+ if (!i_ddi_io_initialized())
return;
mutex_enter(&nvpflush_lock);
@@ -1603,7 +1787,7 @@ nvpflush_one(nvfd_t *nvfd)
rw_exit(&nvfd->nvf_lock);
return (DDI_FAILURE);
}
- if (nvp_to_nvlist(nvfd, &nvl) != DDI_SUCCESS) {
+ if (((nvfd->nvf_nvp2nvl)(nvfd, &nvl)) != DDI_SUCCESS) {
KFIOERR((CE_CONT, "nvpflush: "
"%s nvlist construction failed\n", nvfd->nvf_name));
rw_exit(&nvfd->nvf_lock);
@@ -1654,12 +1838,14 @@ nvpflush_one(nvfd_t *nvfd)
return (rval);
}
+
static void
nvpflush_daemon(void)
{
callb_cpr_t cprinfo;
clock_t clk;
int rval;
+ int i;
ASSERT(modrootloaded);
@@ -1701,21 +1887,40 @@ nvpflush_daemon(void)
* Try flushing what's dirty, reschedule if there's
* a failure or data gets marked as dirty again.
*/
- NVPDAEMON_DEBUG((CE_CONT, "nvpdaemon: flush\n"));
- rval = nvpflush_one(dcfd);
+ for (i = 0; i < NCACHEFDS; i++) {
+ rw_enter(&cachefds[i]->nvf_lock, RW_READER);
+ if (NVF_IS_DIRTY(cachefds[i])) {
+ NVPDAEMON_DEBUG((CE_CONT,
+ "nvpdaemon: flush %s\n",
+ cachefds[i]->nvf_name));
+ rw_exit(&cachefds[i]->nvf_lock);
+ rval = nvpflush_one(cachefds[i]);
+ rw_enter(&cachefds[i]->nvf_lock, RW_READER);
+ if (rval != DDI_SUCCESS ||
+ NVF_IS_DIRTY(cachefds[i])) {
+ rw_exit(&cachefds[i]->nvf_lock);
+ NVPDAEMON_DEBUG((CE_CONT,
+ "nvpdaemon: %s dirty again\n",
+ cachefds[i]->nvf_name));
+ wake_nvpflush_daemon();
+ } else {
+ rw_exit(&cachefds[i]->nvf_lock);
+ nvf_write_complete(cachefds[i]);
+ }
+ } else {
+ NVPDAEMON_DEBUG((CE_CONT,
+ "nvpdaemon: not dirty %s\n",
+ cachefds[i]->nvf_name));
+ rw_exit(&cachefds[i]->nvf_lock);
+ }
+ }
- rw_enter(&dcfd->nvf_lock, RW_READER);
- if (rval != DDI_SUCCESS || NVF_IS_DIRTY(dcfd)) {
- rw_exit(&dcfd->nvf_lock);
- NVPDAEMON_DEBUG((CE_CONT, "nvpdaemon: dirty again\n"));
- wake_nvpflush_daemon(dcfd);
- } else
- rw_exit(&dcfd->nvf_lock);
mutex_enter(&nvpflush_lock);
nvpbusy = 0;
}
}
+
void
i_ddi_clean_devices_files(void)
{