summaryrefslogtreecommitdiff
path: root/usr/src/uts/common/sys/devctl_impl.h
blob: 7c39b18c37c9d20d00909b70f476140444df461c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
/*
 * 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.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */
/*
 * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 */

#ifndef	_SYS_DEVCTL_IMPL_H
#define	_SYS_DEVCTL_IMPL_H

#pragma ident	"%Z%%M%	%I%	%E% SMI"

#ifdef	__cplusplus
extern "C" {
#endif

/*
 * /etc/devices/devid_cache
 * Leave some padding for easy extension in the future
 */

#define	NVPF_HDR_MAGIC		0xdeb1dcac
#define	NVPF_HDR_VERSION	1
#define	NVPF_HDR_SIZE		128

typedef struct nvpacked_file_hdr {
	union {
		struct nvfp_hdr {
			uint32_t	magic;
			int32_t		version;
			int64_t		size;
			uint16_t	hdr_chksum;
			uint16_t	chksum;
		} nvpf;
		uchar_t		nvpf_pad[NVPF_HDR_SIZE];
	} un;
} nvpf_hdr_t;

#define	nvpf_magic		un.nvpf.magic
#define	nvpf_version		un.nvpf.version
#define	nvpf_size		un.nvpf.size
#define	nvpf_hdr_chksum		un.nvpf.hdr_chksum
#define	nvpf_chksum		un.nvpf.chksum

/*
 * The top-level nvpair identifiers in the
 * /etc/devices/devid_cache nvlist format
 */
#define	DP_DEVID_ID		"devid"


typedef struct nvp_list {
	char		*nvp_devpath;
	int		nvp_flags;
	dev_info_t	*nvp_dip;
	ddi_devid_t	nvp_devid;
	struct nvp_list	*nvp_next;
	struct nvp_list	*nvp_prev;
} nvp_list_t;

/*
 * nvp_flags
 */
#define	NVP_DEVID_REGISTERED	0x01	/* devid registered on this boot */
#define	NVP_DEVID_DIP		0x02	/* devinfo valid for this devid */


#ifdef	_KERNEL

/*
 * Descriptor used for kernel-level file i/o
 */
typedef struct kfile {
	struct vnode	*kf_vp;
	int		kf_vnflags;
	char		*kf_fname;
	offset_t	kf_fpos;
	int		kf_state;
} kfile_t;

/*
 * File descriptor for files in the nvlist format
 */
typedef struct nvfiledesc {
	char		*nvf_name;
	int		nvf_flags;
	nvp_list_t	*nvf_list;
	nvp_list_t	*nvf_tail;
	krwlock_t	nvf_lock;
} nvfd_t;


/*
 * Discovery refers to the heroic effort made to discover a device which
 * cannot be accessed.  Discovery involves walking the entire device tree
 * attaching all possible disk instances, to search for the device referenced
 * by a devid.  Obviously, full device discovery is something to be avoided
 * where at all possible.  Note that simply invoking devfsadm(1M) is
 * equivalent to running full discovery at the devid cache level.
 *
 * Reasons why a disk may not be accessible:
 *	disk powered off
 *	disk removed or cable disconnected
 *	disk or adapter broken
 *
 * Note that discovery is not needed and cannot succeed in any of these
 * cases.
 *
 * When discovery may succeed:
 *	Discovery will result in success when a device has been moved
 *	to a different address.  Note that it's recommended that
 *	devfsadm(1M) be invoked (no arguments required) whenever a system's
 *	h/w configuration has been updated.  Alternatively, a
 *	reconfiguration boot can be used to accomplish the same result.
 *
 * Note that discovery is not necessary to be able to correct an access
 * failure for a device which was powered off.  Assuming the cache has an
 * entry for such a device, simply powering it on should permit the system
 * to access it.  If problems persist after powering it on, invoke devfsadm(1M).
 *
 * Tunables
 *
 * devid_discovery_boot (default 1)
 *	Number of times discovery will be attempted prior to mounting root.
 *	Must be at least once to recover from corrupted or missing
 *	devid cache backing store.  Probably there's no reason to ever
 * 	set this to greater than one as a missing device will remain
 *	unavailable no matter how often the system searches for it.
 *
 * devid_discovery_postboot (default 1)
 *	Number of times discovery will be attempted after mounting root.
 *	This must be performed at least once to discover any devices
 *	needed after root is mounted which may have been powered
 *	off and moved before booting.
 *	Setting this to a larger positive number will introduce
 *	some inconsistency in system operation.  Searching for a device
 *	will take an indeterminate amount of time, sometimes slower,
 *	sometimes faster.  In addition, the system will sometimes
 *	discover a newly powered on device, sometimes it won't.
 *	Use of this option is not therefore recommended.
 *
 * devid_discovery_postboot_always (default 0)
 *	Set to 1, the system will always attempt full discovery.
 *
 * devid_discovery_secs (default 0)
 *	Set to a positive value, the system will attempt full discovery
 *	but with a minimum delay between attempts.  A device search
 *	within the period of time specified will result in failure.
 *
 * devid_cache_read_disable (default 0)
 *	Set to 1 to disable reading /etc/devices/devid_cache.
 *	Devid cache will continue to operate normally but
 *	at least one discovery attempt will be required.
 *
 * devid_cache_write_disable (default 0)
 *	Set to 1 to disable updates to /etc/devices/devid_cache.
 *	Any updates to the devid cache will not be preserved across a reboot.
 *
 * kfio_report_error (default 0)
 *	Set to 1 to enable some error messages related to low-level
 *	kernel file i/o operations.
 *
 * devid_report_error (default 0)
 *	Set to 1 to enable some error messages related to devid
 *	cache failures.
 *
 * nvpflush_delay (default 10)
 *	The number of seconds after data is marked dirty before the
 *	flush daemon is triggered to flush the data.  A longer period
 *	of time permits more data updates per write.  Note that
 *	every update resets the timer so no repository write will
 *	occur while data is being updated continuously.
 *
 * nvpdaemon_idle_time (default 60)
 *	The number of seconds the daemon will sleep idle before exiting.
 *
 */
extern int devid_discovery_boot;
extern int devid_discovery_postboot;
extern int devid_discovery_postboot_always;
extern int devid_discovery_secs;

extern int devid_cache_read_disable;
extern int devid_cache_write_disable;

/*
 * More thorough error reporting available both debug &
 * non-debug kernels, but turned off by default.
 */
extern int kfio_report_error;		/* kernel file i/o operations */
extern int devid_report_error;		/* devid cache operations */

/*
 * Suffix of temporary file for updates
 */
#define	MAX_SUFFIX_LEN		4
#define	NEW_FILENAME_SUFFIX	"new"

/*
 * nvf_flags
 */
#define	NVF_DIRTY	0x01		/* needs to be flushed */
#define	NVF_FLUSHING	0x02		/* in process of being flushed */
#define	NVF_ERROR	0x04		/* most recent flush failed */
#define	NVF_READONLY	0x10		/* file is read-only */
#define	NVF_CREATE_MSG	0x20		/* file not found on boot, emit msg */
#define	NVF_REBUILD_MSG	0x40		/* file was found corrupted, emit msg */

#define	NVF_IS_DIRTY(nvfd)	((nvfd)->nvf_flags & NVF_DIRTY)
#define	NVF_MARK_DIRTY(nvfd)	((nvfd)->nvf_flags |= NVF_DIRTY)
#define	NVF_CLEAR_DIRTY(nvfd)	((nvfd)->nvf_flags &= ~NVF_DIRTY)

#define	NVF_IS_READONLY(nvfd)	((nvfd)->nvf_flags & NVF_READONLY)
#define	NVF_MARK_READONLY(nvfd)	((nvfd)->nvf_flags |= NVF_READONLY)
#define	NVF_CLR_READONLY(nvfd)	((nvfd)->nvf_flags &= ~NVF_READONLY)

#ifdef	DEBUG

#define	NVPDAEMON_DEBUG(args)	{ if (nvpdaemon_debug) cmn_err args; }
#define	KFDEBUG(args)		{ if (kfio_debug) cmn_err args; }
#define	KFDEBUG1(args)		{ if (kfio_debug > 1) cmn_err args; }
#define	KFDEBUG2(args)		{ if (kfio_debug > 2) cmn_err args; }
#define	KFDUMP(args)		{ if (kfio_debug > 2) args; }
#define	DEVID_DEBUG(args)	{ if (devid_debug) cmn_err args; }
#define	DEVID_DEBUG1(args)	{ if (devid_debug > 1) cmn_err args; }
#define	DEVID_DEBUG2(args)	{ if (devid_debug > 2) cmn_err args; }
#define	DEVID_DUMP(args)	{ if (devid_debug > 2) args; }
#define	DEVID_LOG_REG(args)	{ if (devid_log_registers) devid_log args; }
#define	DEVID_LOG_FIND(args)	{ if (devid_log_finds) devid_log args; }
#define	DEVID_LOG_LOOKUP(args)	{ if (devid_log_lookups) cmn_err args; }
#define	DEVID_LOG_MATCH(args)	{ if (devid_log_matches) devid_log args; }
#define	DEVID_LOG_PATHS(args)	{ if (devid_log_paths) cmn_err args; }
#define	DEVID_LOG_ERR(args)	{ if (devid_log_failures) devid_log args; }
#define	DEVID_LOG_DISC(args)	{ if (devid_log_discovery) cmn_err args; }
#define	DEVID_LOG_HOLD(args)	{ if (devid_log_hold) cmn_err args; }
#define	DEVID_LOG_UNREG(args)	{ if (devid_log_unregisters) cmn_err args; }
#define	DEVID_LOG_REMOVE(args)	{ if (devid_log_removes) cmn_err args; }
#define	DEVID_LOG_STALE(args)	{ if (devid_log_stale) devid_log args; }
#define	DEVID_LOG_DETACH(args)	{ if (devid_log_detaches) cmn_err args; }


#define	NVP_DEVID_DEBUG_PATH(arg) {					\
		if (nvp_devid_debug)					\
			cmn_err(CE_CONT, "%s\n", arg);			\
	}

#define	NVP_DEVID_DEBUG_DEVID(arg) {					\
		if (nvp_devid_debug) {					\
			char *ds = ddi_devid_str_encode(arg, NULL);	\
			cmn_err(CE_CONT, "devid: %s\n", ds);		\
			ddi_devid_str_free(ds);				\
		}							\
	}

static void devid_log(char *, ddi_devid_t, char *);

#else

#define	NVPDAEMON_DEBUG(args)
#define	KFDEBUG(args)
#define	KFDEBUG1(args)
#define	KFDEBUG2(args)
#define	KFDUMP(args)
#define	DEVID_DEBUG(args)
#define	DEVID_DEBUG1(args)
#define	DEVID_DEBUG2(args)
#define	DEVID_DUMP(args)
#define	DEVID_LOG_REG(args)
#define	DEVID_LOG_FIND(args)
#define	DEVID_LOG_LOOKUP(args)
#define	DEVID_LOG_MATCH(args)
#define	DEVID_LOG_PATHS(args)
#define	DEVID_LOG_ERR(args)
#define	DEVID_LOG_DISC(args)
#define	DEVID_LOG_HOLD(args)
#define	DEVID_LOG_UNREG(args)
#define	DEVID_LOG_REMOVE(args)
#define	DEVID_LOG_STALE(args)
#define	DEVID_LOG_DETACH(args)
#define	NVP_DEVID_DEBUG_PATH(arg)
#define	NVP_DEVID_DEBUG_DEVID(arg)

#endif	/* DEBUG */

#define	KFIOERR(args)		{ if (kfio_report_error) cmn_err args; }
#define	DEVIDERR(args)		{ if (devid_report_error) cmn_err args; }


static void wake_nvpflush_daemon(nvfd_t *);

#endif	/* _KERNEL */

#ifdef	__cplusplus
}
#endif

#endif	/* _SYS_DEVCTL_IMPL_H */