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 */
|