xref: /titanic_44/usr/src/uts/common/os/retire_store.c (revision e2dcee5754c56d91c6e1ff847db294541069ca0d)
1*25e8c5aaSvikram /*
2*25e8c5aaSvikram  * CDDL HEADER START
3*25e8c5aaSvikram  *
4*25e8c5aaSvikram  * The contents of this file are subject to the terms of the
5*25e8c5aaSvikram  * Common Development and Distribution License (the "License").
6*25e8c5aaSvikram  * You may not use this file except in compliance with the License.
7*25e8c5aaSvikram  *
8*25e8c5aaSvikram  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*25e8c5aaSvikram  * or http://www.opensolaris.org/os/licensing.
10*25e8c5aaSvikram  * See the License for the specific language governing permissions
11*25e8c5aaSvikram  * and limitations under the License.
12*25e8c5aaSvikram  *
13*25e8c5aaSvikram  * When distributing Covered Code, include this CDDL HEADER in each
14*25e8c5aaSvikram  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*25e8c5aaSvikram  * If applicable, add the following below this CDDL HEADER, with the
16*25e8c5aaSvikram  * fields enclosed by brackets "[]" replaced with your own identifying
17*25e8c5aaSvikram  * information: Portions Copyright [yyyy] [name of copyright owner]
18*25e8c5aaSvikram  *
19*25e8c5aaSvikram  * CDDL HEADER END
20*25e8c5aaSvikram  */
21*25e8c5aaSvikram /*
22*25e8c5aaSvikram  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
23*25e8c5aaSvikram  * Use is subject to license terms.
24*25e8c5aaSvikram  */
25*25e8c5aaSvikram 
26*25e8c5aaSvikram #include <sys/ddi.h>
27*25e8c5aaSvikram #include <sys/sunddi.h>
28*25e8c5aaSvikram #include <sys/sunndi.h>
29*25e8c5aaSvikram #include <sys/ddi_impldefs.h>
30*25e8c5aaSvikram #include <sys/ddi_implfuncs.h>
31*25e8c5aaSvikram #include <sys/list.h>
32*25e8c5aaSvikram #include <sys/reboot.h>
33*25e8c5aaSvikram #include <sys/sysmacros.h>
34*25e8c5aaSvikram #include <sys/console.h>
35*25e8c5aaSvikram #include <sys/devcache.h>
36*25e8c5aaSvikram 
37*25e8c5aaSvikram /*
38*25e8c5aaSvikram  * The nvpair name in the I/O retire specific sub-nvlist
39*25e8c5aaSvikram  */
40*25e8c5aaSvikram #define	RIO_STORE_VERSION_STR	"rio-store-version"
41*25e8c5aaSvikram #define	RIO_STORE_MAGIC_STR	"rio-store-magic"
42*25e8c5aaSvikram #define	RIO_STORE_FLAGS_STR	"rio-store-flags"
43*25e8c5aaSvikram 
44*25e8c5aaSvikram #define	RIO_STORE_VERSION_1	1
45*25e8c5aaSvikram #define	RIO_STORE_VERSION	RIO_STORE_VERSION_1
46*25e8c5aaSvikram 
47*25e8c5aaSvikram /*
48*25e8c5aaSvikram  * decoded retire list element
49*25e8c5aaSvikram  */
50*25e8c5aaSvikram 
51*25e8c5aaSvikram typedef enum rio_store_flags {
52*25e8c5aaSvikram 	RIO_STORE_F_INVAL = 0,
53*25e8c5aaSvikram 	RIO_STORE_F_RETIRED = 1,
54*25e8c5aaSvikram 	RIO_STORE_F_BYPASS = 2
55*25e8c5aaSvikram } rio_store_flags_t;
56*25e8c5aaSvikram 
57*25e8c5aaSvikram typedef struct rio_store {
58*25e8c5aaSvikram 	char			*rst_devpath;
59*25e8c5aaSvikram 	rio_store_flags_t	rst_flags;
60*25e8c5aaSvikram 	list_node_t		rst_next;
61*25e8c5aaSvikram } rio_store_t;
62*25e8c5aaSvikram 
63*25e8c5aaSvikram #define	RIO_STORE_MAGIC		0x601fcace	/* retire */
64*25e8c5aaSvikram 
65*25e8c5aaSvikram static int rio_store_decode(nvf_handle_t nvfh, nvlist_t *line_nvl, char *name);
66*25e8c5aaSvikram static int rio_store_encode(nvf_handle_t nvfh, nvlist_t **ret_nvl);
67*25e8c5aaSvikram static void retire_list_free(nvf_handle_t  nvfh);
68*25e8c5aaSvikram 
69*25e8c5aaSvikram 
70*25e8c5aaSvikram /*
71*25e8c5aaSvikram  * Retire I/O persistent store registration info
72*25e8c5aaSvikram  */
73*25e8c5aaSvikram static nvf_ops_t rio_store_ops = {
74*25e8c5aaSvikram 	"/etc/devices/retire_store",	/* path to store */
75*25e8c5aaSvikram 	rio_store_decode,		/* decode nvlist into retire_list */
76*25e8c5aaSvikram 	rio_store_encode,		/* encode retire_list into nvlist */
77*25e8c5aaSvikram 	retire_list_free,		/* free retire_list */
78*25e8c5aaSvikram 	NULL				/* write complete callback */
79*25e8c5aaSvikram };
80*25e8c5aaSvikram 
81*25e8c5aaSvikram static nvf_handle_t	rio_store_handle;
82*25e8c5aaSvikram static char		store_path[MAXPATHLEN];
83*25e8c5aaSvikram static int		store_debug = 0;
84*25e8c5aaSvikram static int		bypass_msg = 0;
85*25e8c5aaSvikram static int		retire_msg = 0;
86*25e8c5aaSvikram 
87*25e8c5aaSvikram #define	STORE_DEBUG	0x0001
88*25e8c5aaSvikram #define	STORE_TRACE	0x0002
89*25e8c5aaSvikram 
90*25e8c5aaSvikram #define	STORE_DBG(args)		if (store_debug & STORE_DEBUG)	cmn_err args
91*25e8c5aaSvikram #define	STORE_TRC(args)		if (store_debug & STORE_TRACE)	cmn_err args
92*25e8c5aaSvikram 
93*25e8c5aaSvikram /*
94*25e8c5aaSvikram  * We don't use the simple read disable offered by the
95*25e8c5aaSvikram  * caching framework (see devcache.c) as it will not
96*25e8c5aaSvikram  * have the desired effect of bypassing the persistent
97*25e8c5aaSvikram  * store. A simple read disable will
98*25e8c5aaSvikram  *
99*25e8c5aaSvikram  *	1. cause any additions to the cache to destroy the
100*25e8c5aaSvikram  *	   existing on-disk cache
101*25e8c5aaSvikram  *
102*25e8c5aaSvikram  *	2. prevent deletions from the existing on-disk
103*25e8c5aaSvikram  *	   cache which is needed for recovery from bad
104*25e8c5aaSvikram  *	   retire decisions.
105*25e8c5aaSvikram  *
106*25e8c5aaSvikram  * Use the following tunable instead
107*25e8c5aaSvikram  *
108*25e8c5aaSvikram  */
109*25e8c5aaSvikram int	ddi_retire_store_bypass = 0;
110*25e8c5aaSvikram 
111*25e8c5aaSvikram 
112*25e8c5aaSvikram 
113*25e8c5aaSvikram /*
114*25e8c5aaSvikram  * Initialize retire store data structures
115*25e8c5aaSvikram  */
116*25e8c5aaSvikram void
retire_store_init(void)117*25e8c5aaSvikram retire_store_init(void)
118*25e8c5aaSvikram {
119*25e8c5aaSvikram 	if (boothowto & RB_ASKNAME) {
120*25e8c5aaSvikram 
121*25e8c5aaSvikram 		printf("Retire store [%s] (/dev/null to bypass): ",
122*25e8c5aaSvikram 		    rio_store_ops.nvfr_cache_path);
123*25e8c5aaSvikram 		console_gets(store_path, sizeof (store_path) - 1);
124*25e8c5aaSvikram 		store_path[sizeof (store_path) - 1] = '\0';
125*25e8c5aaSvikram 
126*25e8c5aaSvikram 		if (strcmp(store_path, "/dev/null") == 0) {
127*25e8c5aaSvikram 			ddi_retire_store_bypass = 1;
128*25e8c5aaSvikram 		} else if (store_path[0] != '\0') {
129*25e8c5aaSvikram 			if (store_path[0] != '/') {
130*25e8c5aaSvikram 				printf("Invalid store path: %s. Using default"
131*25e8c5aaSvikram 				    "\n", store_path);
132*25e8c5aaSvikram 			} else {
133*25e8c5aaSvikram 				rio_store_ops.nvfr_cache_path = store_path;
134*25e8c5aaSvikram 			}
135*25e8c5aaSvikram 		}
136*25e8c5aaSvikram 	}
137*25e8c5aaSvikram 
138*25e8c5aaSvikram 	rio_store_handle = nvf_register_file(&rio_store_ops);
139*25e8c5aaSvikram 
140*25e8c5aaSvikram 	list_create(nvf_list(rio_store_handle), sizeof (rio_store_t),
141*25e8c5aaSvikram 	    offsetof(rio_store_t, rst_next));
142*25e8c5aaSvikram }
143*25e8c5aaSvikram 
144*25e8c5aaSvikram /*
145*25e8c5aaSvikram  * Read and populate the in-core retire store
146*25e8c5aaSvikram  */
147*25e8c5aaSvikram void
retire_store_read(void)148*25e8c5aaSvikram retire_store_read(void)
149*25e8c5aaSvikram {
150*25e8c5aaSvikram 	rw_enter(nvf_lock(rio_store_handle), RW_WRITER);
151*25e8c5aaSvikram 	ASSERT(list_head(nvf_list(rio_store_handle)) == NULL);
152*25e8c5aaSvikram 	(void) nvf_read_file(rio_store_handle);
153*25e8c5aaSvikram 	rw_exit(nvf_lock(rio_store_handle));
154*25e8c5aaSvikram 	STORE_DBG((CE_NOTE, "Read on-disk retire store"));
155*25e8c5aaSvikram }
156*25e8c5aaSvikram 
157*25e8c5aaSvikram static void
rio_store_free(rio_store_t * rsp)158*25e8c5aaSvikram rio_store_free(rio_store_t *rsp)
159*25e8c5aaSvikram {
160*25e8c5aaSvikram 	int flag_mask = RIO_STORE_F_RETIRED|RIO_STORE_F_BYPASS;
161*25e8c5aaSvikram 
162*25e8c5aaSvikram 	ASSERT(rsp);
163*25e8c5aaSvikram 	ASSERT(rsp->rst_devpath);
164*25e8c5aaSvikram 	ASSERT(rsp->rst_flags & RIO_STORE_F_RETIRED);
165*25e8c5aaSvikram 	ASSERT(!(rsp->rst_flags & ~flag_mask));
166*25e8c5aaSvikram 
167*25e8c5aaSvikram 	STORE_TRC((CE_NOTE, "store: freed path: %s", rsp->rst_devpath));
168*25e8c5aaSvikram 
169*25e8c5aaSvikram 	kmem_free(rsp->rst_devpath, strlen(rsp->rst_devpath) + 1);
170*25e8c5aaSvikram 	kmem_free(rsp, sizeof (*rsp));
171*25e8c5aaSvikram }
172*25e8c5aaSvikram 
173*25e8c5aaSvikram static void
retire_list_free(nvf_handle_t nvfh)174*25e8c5aaSvikram retire_list_free(nvf_handle_t  nvfh)
175*25e8c5aaSvikram {
176*25e8c5aaSvikram 	list_t		*listp;
177*25e8c5aaSvikram 	rio_store_t	*rsp;
178*25e8c5aaSvikram 
179*25e8c5aaSvikram 	ASSERT(nvfh == rio_store_handle);
180*25e8c5aaSvikram 	ASSERT(RW_WRITE_HELD(nvf_lock(nvfh)));
181*25e8c5aaSvikram 
182*25e8c5aaSvikram 	listp = nvf_list(nvfh);
183*25e8c5aaSvikram 	while (rsp = list_head(listp)) {
184*25e8c5aaSvikram 		list_remove(listp, rsp);
185*25e8c5aaSvikram 		rio_store_free(rsp);
186*25e8c5aaSvikram 	}
187*25e8c5aaSvikram 
188*25e8c5aaSvikram 	STORE_DBG((CE_NOTE, "store: freed retire list"));
189*25e8c5aaSvikram }
190*25e8c5aaSvikram 
191*25e8c5aaSvikram static int
rio_store_decode(nvf_handle_t nvfh,nvlist_t * line_nvl,char * name)192*25e8c5aaSvikram rio_store_decode(nvf_handle_t nvfh, nvlist_t *line_nvl, char *name)
193*25e8c5aaSvikram {
194*25e8c5aaSvikram 	rio_store_t	*rsp;
195*25e8c5aaSvikram 	int32_t		version;
196*25e8c5aaSvikram 	int32_t		magic;
197*25e8c5aaSvikram 	int32_t		flags;
198*25e8c5aaSvikram 	int		rval;
199*25e8c5aaSvikram 
200*25e8c5aaSvikram 	ASSERT(nvfh == rio_store_handle);
201*25e8c5aaSvikram 	ASSERT(RW_WRITE_HELD(nvf_lock(nvfh)));
202*25e8c5aaSvikram 	ASSERT(name);
203*25e8c5aaSvikram 
204*25e8c5aaSvikram 	version = 0;
205*25e8c5aaSvikram 	rval = nvlist_lookup_int32(line_nvl, RIO_STORE_VERSION_STR, &version);
206*25e8c5aaSvikram 	if (rval != 0 || version != RIO_STORE_VERSION) {
207*25e8c5aaSvikram 		return (EINVAL);
208*25e8c5aaSvikram 	}
209*25e8c5aaSvikram 
210*25e8c5aaSvikram 	magic = 0;
211*25e8c5aaSvikram 	rval = nvlist_lookup_int32(line_nvl, RIO_STORE_MAGIC_STR, &magic);
212*25e8c5aaSvikram 	if (rval != 0 || magic != RIO_STORE_MAGIC) {
213*25e8c5aaSvikram 		return (EINVAL);
214*25e8c5aaSvikram 	}
215*25e8c5aaSvikram 
216*25e8c5aaSvikram 	flags = 0;
217*25e8c5aaSvikram 	rval = nvlist_lookup_int32(line_nvl, RIO_STORE_FLAGS_STR, &flags);
218*25e8c5aaSvikram 	if (rval != 0 || flags != RIO_STORE_F_RETIRED) {
219*25e8c5aaSvikram 		return (EINVAL);
220*25e8c5aaSvikram 	}
221*25e8c5aaSvikram 
222*25e8c5aaSvikram 	if (ddi_retire_store_bypass) {
223*25e8c5aaSvikram 		flags |= RIO_STORE_F_BYPASS;
224*25e8c5aaSvikram 		if (!bypass_msg) {
225*25e8c5aaSvikram 			bypass_msg = 1;
226*25e8c5aaSvikram 			cmn_err(CE_WARN,
227*25e8c5aaSvikram 			    "Bypassing retire store /etc/devices/retire_store");
228*25e8c5aaSvikram 		}
229*25e8c5aaSvikram 	}
230*25e8c5aaSvikram 
231*25e8c5aaSvikram 	rsp = kmem_zalloc(sizeof (rio_store_t), KM_SLEEP);
232*25e8c5aaSvikram 	rsp->rst_devpath = i_ddi_strdup(name, KM_SLEEP);
233*25e8c5aaSvikram 	rsp->rst_flags = flags;
234*25e8c5aaSvikram 	list_insert_tail(nvf_list(nvfh), rsp);
235*25e8c5aaSvikram 
236*25e8c5aaSvikram 	STORE_TRC((CE_NOTE, "store: added to retire list: %s", name));
237*25e8c5aaSvikram 	if (!retire_msg) {
238*25e8c5aaSvikram 		retire_msg = 1;
239*25e8c5aaSvikram 		cmn_err(CE_NOTE, "One or more I/O devices have been retired");
240*25e8c5aaSvikram 	}
241*25e8c5aaSvikram 
242*25e8c5aaSvikram 	return (0);
243*25e8c5aaSvikram }
244*25e8c5aaSvikram 
245*25e8c5aaSvikram static int
rio_store_encode(nvf_handle_t nvfh,nvlist_t ** ret_nvl)246*25e8c5aaSvikram rio_store_encode(nvf_handle_t nvfh, nvlist_t **ret_nvl)
247*25e8c5aaSvikram {
248*25e8c5aaSvikram 	nvlist_t	*nvl;
249*25e8c5aaSvikram 	nvlist_t	*line_nvl;
250*25e8c5aaSvikram 	list_t		*listp;
251*25e8c5aaSvikram 	rio_store_t	*rsp;
252*25e8c5aaSvikram 	int		rval;
253*25e8c5aaSvikram 
254*25e8c5aaSvikram 	ASSERT(nvfh == rio_store_handle);
255*25e8c5aaSvikram 	ASSERT(RW_WRITE_HELD(nvf_lock(nvfh)));
256*25e8c5aaSvikram 
257*25e8c5aaSvikram 	*ret_nvl = NULL;
258*25e8c5aaSvikram 
259*25e8c5aaSvikram 	nvl = NULL;
260*25e8c5aaSvikram 	rval = nvlist_alloc(&nvl, NV_UNIQUE_NAME, KM_SLEEP);
261*25e8c5aaSvikram 	if (rval != 0) {
262*25e8c5aaSvikram 		return (DDI_FAILURE);
263*25e8c5aaSvikram 	}
264*25e8c5aaSvikram 
265*25e8c5aaSvikram 	listp = nvf_list(nvfh);
266*25e8c5aaSvikram 	for (rsp = list_head(listp); rsp; rsp = list_next(listp, rsp)) {
267*25e8c5aaSvikram 		int flag_mask = RIO_STORE_F_RETIRED|RIO_STORE_F_BYPASS;
268*25e8c5aaSvikram 		int flags;
269*25e8c5aaSvikram 		ASSERT(rsp->rst_devpath);
270*25e8c5aaSvikram 		ASSERT(!(rsp->rst_flags & ~flag_mask));
271*25e8c5aaSvikram 
272*25e8c5aaSvikram 		line_nvl = NULL;
273*25e8c5aaSvikram 		rval = nvlist_alloc(&line_nvl, NV_UNIQUE_NAME, KM_SLEEP);
274*25e8c5aaSvikram 		if (rval != 0) {
275*25e8c5aaSvikram 			line_nvl = NULL;
276*25e8c5aaSvikram 			goto error;
277*25e8c5aaSvikram 		}
278*25e8c5aaSvikram 
279*25e8c5aaSvikram 		rval = nvlist_add_int32(line_nvl, RIO_STORE_VERSION_STR,
280*25e8c5aaSvikram 			RIO_STORE_VERSION);
281*25e8c5aaSvikram 		if (rval != 0) {
282*25e8c5aaSvikram 			goto error;
283*25e8c5aaSvikram 		}
284*25e8c5aaSvikram 		rval = nvlist_add_int32(line_nvl, RIO_STORE_MAGIC_STR,
285*25e8c5aaSvikram 			RIO_STORE_MAGIC);
286*25e8c5aaSvikram 		if (rval != 0) {
287*25e8c5aaSvikram 			goto error;
288*25e8c5aaSvikram 		}
289*25e8c5aaSvikram 
290*25e8c5aaSvikram 		/* don't save the bypass flag */
291*25e8c5aaSvikram 		flags = RIO_STORE_F_RETIRED;
292*25e8c5aaSvikram 		rval = nvlist_add_int32(line_nvl, RIO_STORE_FLAGS_STR,
293*25e8c5aaSvikram 			flags);
294*25e8c5aaSvikram 		if (rval != 0) {
295*25e8c5aaSvikram 			goto error;
296*25e8c5aaSvikram 		}
297*25e8c5aaSvikram 
298*25e8c5aaSvikram 		rval = nvlist_add_nvlist(nvl, rsp->rst_devpath, line_nvl);
299*25e8c5aaSvikram 		if (rval != 0) {
300*25e8c5aaSvikram 			goto error;
301*25e8c5aaSvikram 		}
302*25e8c5aaSvikram 		nvlist_free(line_nvl);
303*25e8c5aaSvikram 		line_nvl = NULL;
304*25e8c5aaSvikram 	}
305*25e8c5aaSvikram 
306*25e8c5aaSvikram 	*ret_nvl = nvl;
307*25e8c5aaSvikram 	STORE_DBG((CE_NOTE, "packed retire list into nvlist"));
308*25e8c5aaSvikram 	return (DDI_SUCCESS);
309*25e8c5aaSvikram 
310*25e8c5aaSvikram error:
311*25e8c5aaSvikram 	nvlist_free(line_nvl);
312*25e8c5aaSvikram 	ASSERT(nvl);
313*25e8c5aaSvikram 	nvlist_free(nvl);
314*25e8c5aaSvikram 	return (DDI_FAILURE);
315*25e8c5aaSvikram }
316*25e8c5aaSvikram 
317*25e8c5aaSvikram int
e_ddi_retire_persist(char * devpath)318*25e8c5aaSvikram e_ddi_retire_persist(char *devpath)
319*25e8c5aaSvikram {
320*25e8c5aaSvikram 	rio_store_t	*rsp;
321*25e8c5aaSvikram 	rio_store_t	*new_rsp;
322*25e8c5aaSvikram 	list_t		*listp;
323*25e8c5aaSvikram 	char		*new_path;
324*25e8c5aaSvikram 
325*25e8c5aaSvikram 	STORE_DBG((CE_NOTE, "e_ddi_retire_persist: entered: %s", devpath));
326*25e8c5aaSvikram 
327*25e8c5aaSvikram 	new_rsp = kmem_zalloc(sizeof (*new_rsp), KM_SLEEP);
328*25e8c5aaSvikram 	new_rsp->rst_devpath = new_path = i_ddi_strdup(devpath, KM_SLEEP);
329*25e8c5aaSvikram 	new_rsp->rst_flags = RIO_STORE_F_RETIRED;
330*25e8c5aaSvikram 
331*25e8c5aaSvikram 	rw_enter(nvf_lock(rio_store_handle), RW_WRITER);
332*25e8c5aaSvikram 
333*25e8c5aaSvikram 	listp = nvf_list(rio_store_handle);
334*25e8c5aaSvikram 	for (rsp = list_head(listp); rsp; rsp = list_next(listp, rsp)) {
335*25e8c5aaSvikram 		int flag_mask = RIO_STORE_F_RETIRED|RIO_STORE_F_BYPASS;
336*25e8c5aaSvikram 		ASSERT(!(rsp->rst_flags & ~flag_mask));
337*25e8c5aaSvikram 
338*25e8c5aaSvikram 		/* already there */
339*25e8c5aaSvikram 		if (strcmp(devpath, rsp->rst_devpath) == 0) {
340*25e8c5aaSvikram 			/* explicit retire, clear bypass flag (if any) */
341*25e8c5aaSvikram 			rsp->rst_flags &= ~RIO_STORE_F_BYPASS;
342*25e8c5aaSvikram 			ASSERT(rsp->rst_flags == RIO_STORE_F_RETIRED);
343*25e8c5aaSvikram 			rw_exit(nvf_lock(rio_store_handle));
344*25e8c5aaSvikram 			kmem_free(new_path, strlen(new_path) + 1);
345*25e8c5aaSvikram 			kmem_free(new_rsp, sizeof (*new_rsp));
346*25e8c5aaSvikram 			STORE_DBG((CE_NOTE, "store: already in. Clear bypass "
347*25e8c5aaSvikram 			    ": %s", devpath));
348*25e8c5aaSvikram 			return (0);
349*25e8c5aaSvikram 		}
350*25e8c5aaSvikram 
351*25e8c5aaSvikram 	}
352*25e8c5aaSvikram 
353*25e8c5aaSvikram 	ASSERT(rsp == NULL);
354*25e8c5aaSvikram 	list_insert_tail(listp, new_rsp);
355*25e8c5aaSvikram 
356*25e8c5aaSvikram 	nvf_mark_dirty(rio_store_handle);
357*25e8c5aaSvikram 
358*25e8c5aaSvikram 	rw_exit(nvf_lock(rio_store_handle));
359*25e8c5aaSvikram 
360*25e8c5aaSvikram 	nvf_wake_daemon();
361*25e8c5aaSvikram 
362*25e8c5aaSvikram 	STORE_DBG((CE_NOTE, "store: New, added to list, dirty: %s", devpath));
363*25e8c5aaSvikram 
364*25e8c5aaSvikram 	return (0);
365*25e8c5aaSvikram }
366*25e8c5aaSvikram 
367*25e8c5aaSvikram int
e_ddi_retire_unpersist(char * devpath)368*25e8c5aaSvikram e_ddi_retire_unpersist(char *devpath)
369*25e8c5aaSvikram {
370*25e8c5aaSvikram 	rio_store_t	*rsp;
371*25e8c5aaSvikram 	rio_store_t	*next;
372*25e8c5aaSvikram 	list_t		*listp;
373*25e8c5aaSvikram 	int		is_dirty = 0;
374*25e8c5aaSvikram 
375*25e8c5aaSvikram 	STORE_DBG((CE_NOTE, "e_ddi_retire_unpersist: entered: %s", devpath));
376*25e8c5aaSvikram 
377*25e8c5aaSvikram 	rw_enter(nvf_lock(rio_store_handle), RW_WRITER);
378*25e8c5aaSvikram 
379*25e8c5aaSvikram 	listp = nvf_list(rio_store_handle);
380*25e8c5aaSvikram 	for (rsp = list_head(listp); rsp; rsp = next) {
381*25e8c5aaSvikram 		next = list_next(listp, rsp);
382*25e8c5aaSvikram 		if (strcmp(devpath, rsp->rst_devpath) != 0)
383*25e8c5aaSvikram 			continue;
384*25e8c5aaSvikram 
385*25e8c5aaSvikram 		list_remove(listp, rsp);
386*25e8c5aaSvikram 		rio_store_free(rsp);
387*25e8c5aaSvikram 
388*25e8c5aaSvikram 		STORE_DBG((CE_NOTE, "store: found in list. Freed: %s",
389*25e8c5aaSvikram 		    devpath));
390*25e8c5aaSvikram 
391*25e8c5aaSvikram 		nvf_mark_dirty(rio_store_handle);
392*25e8c5aaSvikram 		is_dirty = 1;
393*25e8c5aaSvikram 	}
394*25e8c5aaSvikram 
395*25e8c5aaSvikram 	rw_exit(nvf_lock(rio_store_handle));
396*25e8c5aaSvikram 
397*25e8c5aaSvikram 	if (is_dirty)
398*25e8c5aaSvikram 		nvf_wake_daemon();
399*25e8c5aaSvikram 
400*25e8c5aaSvikram 	return (is_dirty);
401*25e8c5aaSvikram }
402*25e8c5aaSvikram 
403*25e8c5aaSvikram int
e_ddi_device_retired(char * devpath)404*25e8c5aaSvikram e_ddi_device_retired(char *devpath)
405*25e8c5aaSvikram {
406*25e8c5aaSvikram 	list_t		*listp;
407*25e8c5aaSvikram 	rio_store_t	*rsp;
408*25e8c5aaSvikram 	size_t		len;
409*25e8c5aaSvikram 	int		retired;
410*25e8c5aaSvikram 
411*25e8c5aaSvikram 	retired = 0;
412*25e8c5aaSvikram 
413*25e8c5aaSvikram 	rw_enter(nvf_lock(rio_store_handle), RW_READER);
414*25e8c5aaSvikram 
415*25e8c5aaSvikram 	listp = nvf_list(rio_store_handle);
416*25e8c5aaSvikram 	for (rsp = list_head(listp); rsp; rsp = list_next(listp, rsp)) {
417*25e8c5aaSvikram 		int flag_mask = RIO_STORE_F_RETIRED|RIO_STORE_F_BYPASS;
418*25e8c5aaSvikram 		ASSERT(!(rsp->rst_flags & ~flag_mask));
419*25e8c5aaSvikram 
420*25e8c5aaSvikram 		/*
421*25e8c5aaSvikram 		 * If the "bypass" flag is set, then the device
422*25e8c5aaSvikram 		 * is *not* retired for the current boot of the
423*25e8c5aaSvikram 		 * system. It indicates that the retire store
424*25e8c5aaSvikram 		 * was read but the devices in the retire store
425*25e8c5aaSvikram 		 * were not retired i.e. effectively the store
426*25e8c5aaSvikram 		 * was bypassed. For why we bother to even read
427*25e8c5aaSvikram 		 * the store when we bypass it, see the comments
428*25e8c5aaSvikram 		 * for the tunable ddi_retire_store_bypass.
429*25e8c5aaSvikram 		 */
430*25e8c5aaSvikram 		if (rsp->rst_flags & RIO_STORE_F_BYPASS) {
431*25e8c5aaSvikram 			STORE_TRC((CE_NOTE, "store: found & bypassed: %s",
432*25e8c5aaSvikram 			    rsp->rst_devpath));
433*25e8c5aaSvikram 			continue;
434*25e8c5aaSvikram 		}
435*25e8c5aaSvikram 
436*25e8c5aaSvikram 		/*
437*25e8c5aaSvikram 		 * device is retired, if it or a parent exists
438*25e8c5aaSvikram 		 * in the in-core list
439*25e8c5aaSvikram 		 */
440*25e8c5aaSvikram 		len = strlen(rsp->rst_devpath);
441*25e8c5aaSvikram 		if (strncmp(devpath, rsp->rst_devpath, len) != 0)
442*25e8c5aaSvikram 			continue;
443*25e8c5aaSvikram 		if (devpath[len] == '\0' || devpath[len] == '/') {
444*25e8c5aaSvikram 			/* exact match or a child */
445*25e8c5aaSvikram 			retired = 1;
446*25e8c5aaSvikram 			STORE_TRC((CE_NOTE, "store: found & !bypassed: %s",
447*25e8c5aaSvikram 			    devpath));
448*25e8c5aaSvikram 			break;
449*25e8c5aaSvikram 		}
450*25e8c5aaSvikram 	}
451*25e8c5aaSvikram 	rw_exit(nvf_lock(rio_store_handle));
452*25e8c5aaSvikram 
453*25e8c5aaSvikram 	return (retired);
454*25e8c5aaSvikram }
455