Print this page
7127 remove -Wno-missing-braces from Makefile.uts
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/uts/common/os/inst_sync.c
+++ new/usr/src/uts/common/os/inst_sync.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21 /*
22 22 * Copyright (c) 1992, 2010, Oracle and/or its affiliates. All rights reserved.
23 23 */
24 24
25 25 /*
26 26 * Syscall to write out the instance number data structures to
27 27 * stable storage.
28 28 */
29 29
30 30 #include <sys/types.h>
31 31 #include <sys/errno.h>
32 32 #include <sys/t_lock.h>
33 33 #include <sys/modctl.h>
34 34 #include <sys/systm.h>
35 35 #include <sys/syscall.h>
36 36 #include <sys/vfs.h>
37 37 #include <sys/vnode.h>
38 38 #include <sys/cred.h>
39 39 #include <sys/file.h>
40 40 #include <sys/cmn_err.h>
41 41 #include <sys/kmem.h>
42 42 #include <sys/cladm.h>
43 43 #include <sys/sunddi.h>
44 44 #include <sys/dditypes.h>
45 45 #include <sys/instance.h>
46 46 #include <sys/debug.h>
47 47 #include <sys/policy.h>
48 48
49 49 /*
50 50 * Userland sees:
51 51 *
52 52 * int inst_sync(pathname, flags);
53 53 *
54 54 * Returns zero if instance number information was successfully
55 55 * written to 'pathname', -1 plus error code in errno otherwise.
56 56 *
57 57 * POC notes:
58 58 *
59 59 * - This could be done as a case of the modctl(2) system call
60 60 * though the ability to have it load and unload would disappear.
61 61 *
62 62 * - 'flags' have either of two meanings:
63 63 * INST_SYNC_IF_REQUIRED 'pathname' will be written if there
64 64 * has been a change in the kernel's
65 65 * internal view of instance number
66 66 * information
67 67 * INST_SYNC_ALWAYS 'pathname' will be written even if
68 68 * the kernel's view hasn't changed.
69 69 *
70 70 * - Maybe we should pass through two filenames - one to create,
71 71 * and the other as the 'final' target i.e. do the rename of
72 72 * /etc/instance.new -> /etc/instance in the kernel.
73 73 */
74 74
75 75 static int in_sync_sys(char *pathname, uint_t flags);
76 76
77 77 static struct sysent in_sync_sysent = {
78 78 2, /* number of arguments */
79 79 SE_ARGC | SE_32RVAL1, /* c-style calling, 32-bit return value */
80 80 in_sync_sys, /* the handler */
81 81 (krwlock_t *)0 /* rw lock allocated/used by framework */
82 82 };
83 83
84 84 static struct modlsys modlsys = {
85 85 &mod_syscallops, "instance binding syscall", &in_sync_sysent
↓ open down ↓ |
85 lines elided |
↑ open up ↑ |
86 86 };
87 87
88 88 #ifdef _SYSCALL32_IMPL
89 89 static struct modlsys modlsys32 = {
90 90 &mod_syscallops32, "32-bit instance binding syscall", &in_sync_sysent
91 91 };
92 92 #endif
93 93
94 94 static struct modlinkage modlinkage = {
95 95 MODREV_1,
96 - &modlsys,
96 + { &modlsys,
97 97 #ifdef _SYSCALL32_IMPL
98 - &modlsys32,
98 + &modlsys32,
99 99 #endif
100 - NULL
100 + NULL
101 + }
101 102 };
102 103
103 104 int
104 105 _init(void)
105 106 {
106 107 return (mod_install(&modlinkage));
107 108 }
108 109
109 110 int
110 111 _info(struct modinfo *modinfop)
111 112 {
112 113 return (mod_info(&modlinkage, modinfop));
113 114 }
114 115
115 116 int
116 117 _fini(void)
117 118 {
118 119 return (mod_remove(&modlinkage));
119 120 }
120 121
121 122 static int in_write_instance(struct vnode *vp);
122 123
123 124 static int inst_sync_disable = 0;
124 125
125 126 static int
126 127 in_sync_sys(char *pathname, uint_t flags)
127 128 {
128 129 struct vnode *vp;
129 130 int error;
130 131
131 132 /* For debugging/testing */
132 133 if (inst_sync_disable)
133 134 return (0);
134 135
135 136 /*
136 137 * We must have sufficient privilege to do this, since we lock critical
137 138 * data structures whilst we're doing it ..
138 139 */
139 140 if ((error = secpolicy_sys_devices(CRED())) != 0)
140 141 return (set_errno(error));
141 142
142 143 if (flags != INST_SYNC_ALWAYS && flags != INST_SYNC_IF_REQUIRED)
143 144 return (set_errno(EINVAL));
144 145
145 146 /*
146 147 * Only one process is allowed to get the state of the instance
147 148 * number assignments on the system at any given time.
148 149 */
149 150 e_ddi_enter_instance();
150 151
151 152 /*
152 153 * Recreate the instance file only if the device tree has changed
153 154 * or if the caller explicitly requests so.
154 155 */
155 156 if (e_ddi_instance_is_clean() && flags != INST_SYNC_ALWAYS) {
156 157 error = EALREADY;
157 158 goto end;
158 159 }
159 160
160 161 /*
161 162 * Create an instance file for writing, giving it a mode that
162 163 * will only permit reading. Note that we refuse to overwrite
163 164 * an existing file.
164 165 */
165 166 if ((error = vn_open(pathname, UIO_USERSPACE,
166 167 FCREAT, 0444, &vp, CRCREAT, 0)) != 0) {
167 168 if (error == EISDIR)
168 169 error = EACCES; /* SVID compliance? */
169 170 goto end;
170 171 }
171 172
172 173 /*
173 174 * So far so good. We're singly threaded, the vnode is beckoning
174 175 * so let's get on with it. Any error, and we just give up and
175 176 * hand the first error we get back to userland.
176 177 */
177 178 error = in_write_instance(vp);
178 179
179 180 /*
180 181 * If there was any sort of error, we deliberately go and
181 182 * remove the file we just created so that any attempts to
182 183 * use it will quickly fail.
183 184 */
184 185 if (error)
185 186 (void) vn_remove(pathname, UIO_USERSPACE, RMFILE);
186 187 else
187 188 e_ddi_instance_set_clean();
188 189 end:
189 190 e_ddi_exit_instance();
190 191 return (error ? set_errno(error) : 0);
191 192 }
192 193
193 194 /*
194 195 * At the risk of reinventing stdio ..
195 196 */
196 197 #define FBUFSIZE 512
197 198
198 199 typedef struct _File {
199 200 char *ptr;
200 201 int count;
201 202 char buf[FBUFSIZE];
202 203 vnode_t *vp;
203 204 offset_t voffset;
204 205 } File;
205 206
206 207 static int
207 208 in_write(struct vnode *vp, offset_t *vo, caddr_t buf, int count)
208 209 {
209 210 int error;
210 211 ssize_t resid;
211 212 rlim64_t rlimit = *vo + count + 1;
212 213
213 214 error = vn_rdwr(UIO_WRITE, vp, buf, count, *vo,
214 215 UIO_SYSSPACE, 0, rlimit, CRED(), &resid);
215 216
216 217 *vo += (offset_t)(count - resid);
217 218
218 219 return (error);
219 220 }
220 221
221 222 static File *
222 223 in_fvpopen(struct vnode *vp)
223 224 {
224 225 File *fp;
225 226
226 227 fp = kmem_zalloc(sizeof (File), KM_SLEEP);
227 228 fp->vp = vp;
228 229 fp->ptr = fp->buf;
229 230
230 231 return (fp);
231 232 }
232 233
233 234 static int
234 235 in_fclose(File *fp)
235 236 {
236 237 int error;
237 238
238 239 error = VOP_CLOSE(fp->vp, FCREAT, 1, (offset_t)0, CRED(), NULL);
239 240 VN_RELE(fp->vp);
240 241 kmem_free(fp, sizeof (File));
241 242 return (error);
242 243 }
243 244
244 245 static int
245 246 in_fflush(File *fp)
246 247 {
247 248 int error = 0;
248 249
249 250 if (fp->count)
250 251 error = in_write(fp->vp, &fp->voffset, fp->buf, fp->count);
251 252 if (error == 0)
252 253 error = VOP_FSYNC(fp->vp, FSYNC, CRED(), NULL);
253 254 return (error);
254 255 }
255 256
256 257 static int
257 258 in_fputs(File *fp, char *buf)
258 259 {
259 260 int error = 0;
260 261
261 262 while (*buf) {
262 263 *fp->ptr++ = *buf++;
263 264 if (++fp->count == FBUFSIZE) {
264 265 error = in_write(fp->vp, &fp->voffset, fp->buf,
265 266 fp->count);
266 267 if (error)
267 268 break;
268 269 fp->count = 0;
269 270 fp->ptr = fp->buf;
270 271 }
271 272 }
272 273
273 274 return (error);
274 275 }
275 276
276 277 /*
277 278 * External linkage
278 279 */
279 280 static File *in_fp;
280 281
281 282 /*
282 283 * XXX what is the maximum length of the name of a driver? Must be maximum
283 284 * XXX file name length (find the correct constant and substitute for this one
284 285 */
285 286 #define DRVNAMELEN (1 + 256)
286 287 static char linebuffer[MAXPATHLEN + 1 + 1 + 1 + 1 + 10 + 1 + DRVNAMELEN];
287 288
288 289 /*
289 290 * XXX Maybe we should just write 'in_fprintf' instead ..
290 291 */
291 292 static int
292 293 in_walktree(in_node_t *np, char *this)
293 294 {
294 295 char *next;
295 296 int error = 0;
296 297 in_drv_t *dp;
297 298
298 299 for (error = 0; np; np = np->in_sibling) {
299 300
300 301 if (np->in_drivers == NULL)
301 302 continue;
302 303
303 304 if (np->in_unit_addr[0] == '\0')
304 305 (void) sprintf(this, "/%s", np->in_node_name);
305 306 else
306 307 (void) sprintf(this, "/%s@%s", np->in_node_name,
307 308 np->in_unit_addr);
308 309 next = this + strlen(this);
309 310
310 311 ASSERT(np->in_drivers);
311 312
312 313 for (dp = np->in_drivers; dp; dp = dp->ind_next_drv) {
313 314 uint_t inst_val = dp->ind_instance;
314 315
315 316 /*
316 317 * Flushing IN_PROVISIONAL could result in duplicate
317 318 * instances
318 319 * Flushing IN_UNKNOWN results in instance -1
319 320 */
320 321 if (dp->ind_state != IN_PERMANENT)
321 322 continue;
322 323
323 324 (void) sprintf(next, "\" %d \"%s\"\n", inst_val,
324 325 dp->ind_driver_name);
325 326 if (error = in_fputs(in_fp, linebuffer))
326 327 return (error);
327 328 }
328 329
329 330 if (np->in_child)
330 331 if (error = in_walktree(np->in_child, next))
331 332 break;
332 333 }
333 334 return (error);
334 335 }
335 336
336 337
337 338 /*
338 339 * Walk the instance tree, writing out what we find.
339 340 *
340 341 * There's some fairly nasty sharing of buffers in this
341 342 * bit of code, so be careful out there when you're
342 343 * rewriting it ..
343 344 */
344 345 static int
345 346 in_write_instance(struct vnode *vp)
346 347 {
347 348 int error;
348 349 char *cp;
349 350
350 351 in_fp = in_fvpopen(vp);
351 352
352 353 /*
353 354 * Place a bossy comment at the beginning of the file.
354 355 */
355 356 error = in_fputs(in_fp,
356 357 "#\n#\tCaution! This file contains critical kernel state\n#\n");
357 358
358 359 if (error == 0) {
359 360 in_node_t *root = e_ddi_instance_root();
360 361 cp = linebuffer;
361 362 *cp++ = '\"';
362 363 error = in_walktree(root->in_child, cp);
363 364 }
364 365
365 366 if (error == 0) {
366 367 if ((error = in_fflush(in_fp)) == 0)
367 368 error = in_fclose(in_fp);
368 369 } else
369 370 (void) in_fclose(in_fp);
370 371
371 372 return (error);
372 373 }
↓ open down ↓ |
262 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX