Print this page
7127 remove -Wno-missing-braces from Makefile.uts
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/uts/common/io/devpool.c
+++ new/usr/src/uts/common/io/devpool.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 2008 Sun Microsystems, Inc. All rights reserved.
23 23 * Use is subject to license terms.
24 24 */
25 25
26 26
27 27 #include <sys/types.h>
28 28 #include <sys/file.h>
29 29 #include <sys/errno.h>
30 30 #include <sys/open.h>
31 31 #include <sys/cred.h>
32 32 #include <sys/conf.h>
33 33 #include <sys/modctl.h>
34 34 #include <sys/stat.h>
35 35 #include <sys/ddi.h>
36 36 #include <sys/sunddi.h>
37 37 #include <sys/policy.h>
38 38 #include <sys/pool.h>
39 39 #include <sys/pool_impl.h>
40 40
41 41 /*
42 42 * The kernel pools subsystem is accessed and manipulated through the pool
43 43 * device, which has two minor nodes /dev/pool, and /dev/poolctl. User
44 44 * processes can comminicate with pools through ioctls on these devices.
45 45 *
46 46 * The poolctl device (POOL_CTL_PARENT) can be used to modify and take
47 47 * snapshot of the current configuration. Only one process on the system
48 48 * can have it open at any given time. This device is also used to enable
49 49 * or disable pools. If pools are disabled, the pool driver can be unloaded
50 50 * and completely removed from the system.
51 51 *
52 52 * The pool "info" device (POOL_INFO_PARENT) can only be used to obtain
53 53 * snapshots of the current configuration and change/query pool bindings.
54 54 * While some reconfiguration transaction via the poolctl device is in
55 55 * progress, all processes using this "info" device will be provided with
56 56 * the snapshot taken at the beginning of that transaction.
57 57 */
58 58
59 59 #define POOL_CTL_PARENT 0
60 60 #define POOL_INFO_PARENT 1
61 61
62 62 static dev_info_t *pool_devi; /* pool device information */
63 63 static int pool_openctl; /* poolctl device is already open */
64 64
65 65 /*ARGSUSED*/
66 66 static int
67 67 pool_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result)
68 68 {
69 69 int error = DDI_FAILURE;
70 70
71 71 switch (infocmd) {
72 72 case DDI_INFO_DEVT2DEVINFO:
73 73 *result = pool_devi;
74 74 error = DDI_SUCCESS;
75 75 break;
76 76 case DDI_INFO_DEVT2INSTANCE:
77 77 /*
78 78 * All dev_t's map to the same, single instance.
79 79 */
80 80 *result = NULL;
81 81 error = DDI_SUCCESS;
82 82 break;
83 83 default:
84 84 break;
85 85 }
86 86 return (error);
87 87 }
88 88
89 89 static int
90 90 pool_detach(dev_info_t *devi, ddi_detach_cmd_t cmd)
91 91 {
92 92 int ret = DDI_SUCCESS;
93 93
94 94 switch (cmd) {
95 95 case DDI_DETACH:
96 96 pool_lock();
97 97 if (pool_state == POOL_ENABLED) {
98 98 ret = DDI_FAILURE;
99 99 pool_unlock();
100 100 break;
101 101 }
102 102 ddi_remove_minor_node(devi, NULL);
103 103 pool_devi = NULL;
104 104 pool_unlock();
105 105 break;
106 106 default:
107 107 ret = DDI_FAILURE;
108 108 }
109 109 return (ret);
110 110 }
111 111
112 112 static int
113 113 pool_attach(dev_info_t *devi, ddi_attach_cmd_t cmd)
114 114 {
115 115 switch (cmd) {
116 116 case DDI_ATTACH:
117 117 if (pool_devi != NULL)
118 118 return (DDI_FAILURE);
119 119 if (ddi_create_minor_node(devi, "poolctl", S_IFCHR,
120 120 POOL_CTL_PARENT, DDI_PSEUDO, 0) == DDI_FAILURE ||
121 121 ddi_create_minor_node(devi, "pool", S_IFCHR,
122 122 POOL_INFO_PARENT, DDI_PSEUDO, 0) == DDI_FAILURE) {
123 123 ddi_remove_minor_node(devi, NULL);
124 124 return (DDI_FAILURE);
125 125 }
126 126 pool_devi = devi;
127 127 ddi_report_dev(devi);
128 128 break;
129 129 case DDI_RESUME:
130 130 break;
131 131 default:
132 132 return (DDI_FAILURE);
133 133 }
134 134 return (DDI_SUCCESS);
135 135
136 136 }
137 137
138 138 /*
139 139 * There is only one instance of the pool control device, poolctl,
140 140 * and multiple instances of the pool info device, pool.
141 141 */
142 142 /*ARGSUSED*/
143 143 static int
144 144 pool_open(dev_t *devp, int flag, int otype, cred_t *credp)
145 145 {
146 146 minor_t minor = getminor(*devp);
147 147
148 148 if (otype != OTYP_CHR)
149 149 return (EINVAL);
150 150
151 151 switch (minor) {
152 152 case POOL_CTL_PARENT:
153 153 if (secpolicy_pool(CRED()) != 0)
154 154 return (EPERM);
155 155 if (pool_lock_intr() != 0)
156 156 return (EINTR);
157 157 if (pool_openctl == 1) {
158 158 pool_unlock();
159 159 return (EBUSY);
160 160 }
161 161 pool_openctl = 1;
162 162 pool_unlock();
163 163 break;
164 164 case POOL_INFO_PARENT:
165 165 break;
166 166 default:
167 167 return (ENXIO);
168 168 }
169 169 return (0);
170 170 }
171 171
172 172 /*ARGSUSED*/
173 173 static int
174 174 pool_close(dev_t dev, int flag, int otype, cred_t *credp)
175 175 {
176 176 if (otype != OTYP_CHR)
177 177 return (EINVAL);
178 178 if (getminor(dev) == 0) {
179 179 /*
180 180 * We could be closing the poolctl device without finishing
181 181 * the commit transaction first, so do that now.
182 182 */
183 183 pool_lock();
184 184 (void) pool_commit(0); /* cannot fail since arg is 0 */
185 185 pool_openctl = 0;
186 186 pool_unlock();
187 187 }
188 188 return (0);
189 189 }
190 190
191 191 /*
192 192 * Main pool interface.
193 193 */
194 194 /* ARGSUSED4 */
195 195 static int
196 196 pool_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *credp,
197 197 int *rvalp)
198 198 {
199 199 pool_xtransfer_t xtransfer;
200 200 pool_transfer_t transfer;
201 201 pool_destroy_t destroy;
202 202 pool_propget_t propget;
203 203 pool_propput_t propput;
204 204 pool_proprm_t proprm;
205 205 pool_status_t status;
206 206 pool_dissoc_t dissoc;
207 207 pool_create_t create;
208 208 pool_assoc_t assoc;
209 209 pool_bindq_t bindq;
210 210 pool_query_t query;
211 211 pool_bind_t bind;
212 212 #ifdef _MULTI_DATAMODEL
213 213 pool_xtransfer32_t xtransfer32;
214 214 pool_propput32_t propput32;
215 215 pool_propget32_t propget32;
216 216 pool_proprm32_t proprm32;
217 217 pool_query32_t query32;
218 218 #endif /* _MULTI_DATAMODEL */
219 219 char *kbuf = NULL;
220 220 size_t kbufsz = 0;
221 221 int snapshot = 0;
222 222 char *prop_name;
223 223 size_t size = 0;
224 224 nvlist_t *list;
225 225 nvpair_t *pair;
226 226 char *listbuf;
227 227 minor_t minor;
228 228 uint_t model;
229 229 id_t *id_buf;
230 230 int ret = 0;
231 231
232 232 model = ddi_model_convert_from(mode & FMODELS);
233 233 minor = getminor(dev);
234 234
235 235 /*
236 236 * Check basic permissions first.
237 237 */
238 238 switch (cmd) {
239 239 case POOL_STATUS:
240 240 case POOL_CREATE:
241 241 case POOL_ASSOC:
242 242 case POOL_DISSOC:
243 243 case POOL_DESTROY:
244 244 case POOL_TRANSFER:
245 245 case POOL_XTRANSFER:
246 246 case POOL_PROPPUT:
247 247 case POOL_PROPRM:
248 248 case POOL_COMMIT:
249 249 if (minor != POOL_CTL_PARENT)
250 250 return (EINVAL);
251 251 /*FALLTHROUGH*/
252 252 case POOL_BIND:
253 253 if (secpolicy_pool(CRED()) != 0)
254 254 return (EPERM);
255 255 break;
256 256 }
257 257
258 258 switch (cmd) {
259 259 case POOL_STATUS:
260 260 if (ddi_copyin((void *)arg, &status,
261 261 sizeof (pool_status_t), mode) != 0)
262 262 return (EFAULT);
263 263 if (pool_lock_intr() != 0)
264 264 return (EINTR);
265 265 ret = pool_status(status.ps_io_state);
266 266 pool_unlock();
267 267 break;
268 268 case POOL_STATUSQ:
269 269 /*
270 270 * No need to grab pool_lock() to look at the current state.
271 271 */
272 272 status.ps_io_state = pool_state;
273 273 if (ddi_copyout(&status, (void *)arg,
274 274 sizeof (pool_status_t), mode) != 0)
275 275 return (EFAULT);
276 276 break;
277 277 case POOL_QUERY:
278 278 switch (model) {
279 279 #ifdef _MULTI_DATAMODEL
280 280 case DDI_MODEL_ILP32:
281 281 if (ddi_copyin((void *)arg, &query32,
282 282 sizeof (pool_query32_t), mode) != 0)
283 283 return (EFAULT);
284 284 query.pq_io_bufsize = query32.pq_io_bufsize;
285 285 query.pq_io_buf = (char *)(uintptr_t)query32.pq_io_buf;
286 286 break;
287 287 #endif /* _MULTI_DATAMODEL */
288 288 default:
289 289 case DDI_MODEL_NONE:
290 290 if (ddi_copyin((void *)arg, &query,
291 291 sizeof (pool_query_t), mode) != 0)
292 292 return (EFAULT);
293 293 }
294 294 if (pool_lock_intr() != 0)
295 295 return (EINTR);
296 296 if (pool_state == POOL_DISABLED) {
297 297 pool_unlock();
298 298 return (ENOTACTIVE);
299 299 }
300 300 if (minor != 0 && pool_buf != NULL) {
301 301 /*
302 302 * Return last snapshot if some
303 303 * transaction is still in progress
304 304 */
305 305 if (kbufsz != 0 && pool_bufsz > kbufsz) {
306 306 pool_unlock();
307 307 return (ENOMEM);
308 308 }
309 309 kbuf = pool_buf;
310 310 kbufsz = size = pool_bufsz;
311 311 snapshot = 1;
312 312 } else if (query.pq_io_bufsize != 0) {
313 313 kbufsz = query.pq_io_bufsize;
314 314 kbuf = kmem_alloc(kbufsz, KM_NOSLEEP);
315 315 if (kbuf == NULL) {
316 316 pool_unlock();
317 317 return (ENOMEM);
318 318 }
319 319 ret = pool_pack_conf(kbuf, kbufsz, &size);
320 320 } else {
321 321 ret = pool_pack_conf(NULL, 0, &size);
322 322 }
323 323 if (ret == 0) {
324 324 switch (model) {
325 325 #ifdef _MULTI_DATAMODEL
326 326 case DDI_MODEL_ILP32:
327 327 query32.pq_io_bufsize = size;
328 328 if (ddi_copyout((caddr_t)&query32, (void *)arg,
329 329 sizeof (pool_query32_t), mode) != 0)
330 330 ret = EFAULT;
331 331 break;
332 332 #endif /* _MULTI_DATAMODEL */
333 333 default:
334 334 case DDI_MODEL_NONE:
335 335 query.pq_io_bufsize = size;
336 336 if (ddi_copyout(&query, (void *)arg,
337 337 sizeof (pool_query_t), mode) != 0)
338 338 ret = EFAULT;
339 339 }
340 340 if (ret == 0 && query.pq_io_buf != NULL &&
341 341 ddi_copyout(kbuf, query.pq_io_buf, size, mode) != 0)
342 342 ret = EFAULT;
343 343 }
344 344 pool_unlock();
345 345 if (snapshot == 0)
346 346 kmem_free(kbuf, kbufsz);
347 347 break;
348 348 case POOL_CREATE:
349 349 if (ddi_copyin((void *)arg,
350 350 &create, sizeof (pool_create_t), mode) != 0)
351 351 return (EFAULT);
352 352 if (pool_lock_intr() != 0)
353 353 return (EINTR);
354 354 ret = pool_create(create.pc_o_type,
355 355 create.pc_o_sub_type, &create.pc_i_id);
356 356 pool_unlock();
357 357 if (ret == 0 && ddi_copyout(&create, (void *)arg,
358 358 sizeof (pool_create_t), mode) != 0)
359 359 ret = EFAULT;
360 360 break;
361 361 case POOL_ASSOC:
362 362 if (ddi_copyin((void *)arg, &assoc,
363 363 sizeof (pool_assoc_t), mode) != 0)
364 364 return (EFAULT);
365 365 if (pool_lock_intr() != 0)
366 366 return (EINTR);
367 367 ret = pool_assoc(assoc.pa_o_pool_id,
368 368 assoc.pa_o_id_type, assoc.pa_o_res_id);
369 369 pool_unlock();
370 370 break;
371 371 case POOL_DISSOC:
372 372 if (ddi_copyin((void *)arg, &dissoc,
373 373 sizeof (pool_dissoc_t), mode) != 0)
374 374 return (EFAULT);
375 375 if (pool_lock_intr() != 0)
376 376 return (EINTR);
377 377 ret = pool_dissoc(dissoc.pd_o_pool_id, dissoc.pd_o_id_type);
378 378 pool_unlock();
379 379 break;
380 380 case POOL_DESTROY:
381 381 if (ddi_copyin((void *)arg, &destroy,
382 382 sizeof (pool_destroy_t), mode) != 0)
383 383 return (EFAULT);
384 384 if (pool_lock_intr() != 0)
385 385 return (EINTR);
386 386 ret = pool_destroy(destroy.pd_o_type, destroy.pd_o_sub_type,
387 387 destroy.pd_o_id);
388 388 pool_unlock();
389 389 break;
390 390 case POOL_TRANSFER:
391 391 if (ddi_copyin((void *)arg, &transfer,
392 392 sizeof (pool_transfer_t), mode) != 0)
393 393 return (EFAULT);
394 394 if (pool_lock_intr() != 0)
395 395 return (EINTR);
396 396 ret = pool_transfer(transfer.pt_o_id_type, transfer.pt_o_src_id,
397 397 transfer.pt_o_tgt_id, transfer.pt_o_qty);
398 398 pool_unlock();
399 399 break;
400 400 case POOL_XTRANSFER:
401 401 switch (model) {
402 402 #ifdef _MULTI_DATAMODEL
403 403 case DDI_MODEL_ILP32:
404 404 if (ddi_copyin((void *)arg, &xtransfer32,
405 405 sizeof (pool_xtransfer32_t), mode) != 0)
406 406 return (EFAULT);
407 407 xtransfer.px_o_id_type = xtransfer32.px_o_id_type;
408 408 xtransfer.px_o_src_id = xtransfer32.px_o_src_id;
409 409 xtransfer.px_o_tgt_id = xtransfer32.px_o_tgt_id;
410 410 xtransfer.px_o_complist_size =
411 411 xtransfer32.px_o_complist_size;
412 412 xtransfer.px_o_comp_list =
413 413 (id_t *)(uintptr_t)xtransfer32.px_o_comp_list;
414 414 break;
415 415 #endif /* _MULTI_DATAMODEL */
416 416 default:
417 417 case DDI_MODEL_NONE:
418 418 if (ddi_copyin((void *)arg, &xtransfer,
419 419 sizeof (pool_xtransfer_t), mode) != 0)
420 420 return (EFAULT);
421 421 }
422 422 /*
423 423 * Copy in IDs to transfer from the userland
424 424 */
425 425 if (xtransfer.px_o_complist_size > POOL_IDLIST_SIZE)
426 426 return (EINVAL);
427 427 id_buf = kmem_alloc(xtransfer.px_o_complist_size *
428 428 sizeof (id_t), KM_SLEEP);
429 429 if (ddi_copyin((void *)xtransfer.px_o_comp_list, id_buf,
430 430 xtransfer.px_o_complist_size * sizeof (id_t), mode) != 0) {
431 431 kmem_free(id_buf, xtransfer.px_o_complist_size *
432 432 sizeof (id_t));
433 433 return (EFAULT);
434 434 }
435 435 if (pool_lock_intr() != 0) {
436 436 kmem_free(id_buf, xtransfer.px_o_complist_size *
437 437 sizeof (id_t));
438 438 return (EINTR);
439 439 }
440 440 ret = pool_xtransfer(xtransfer.px_o_id_type,
441 441 xtransfer.px_o_src_id, xtransfer.px_o_tgt_id,
442 442 xtransfer.px_o_complist_size, id_buf);
443 443 pool_unlock();
444 444 kmem_free(id_buf, xtransfer.px_o_complist_size *
445 445 sizeof (id_t));
446 446 break;
447 447 case POOL_BIND:
448 448 if (ddi_copyin((void *)arg, &bind,
449 449 sizeof (pool_bind_t), mode) != 0)
450 450 return (EFAULT);
451 451 if (pool_lock_intr() != 0)
452 452 return (EINTR);
453 453 ret = pool_bind(bind.pb_o_pool_id, bind.pb_o_id_type,
454 454 bind.pb_o_id);
455 455 pool_unlock();
456 456 break;
457 457 case POOL_BINDQ:
458 458 if (ddi_copyin((void *)arg, &bindq,
459 459 sizeof (pool_bindq_t), mode) != 0) {
460 460 return (EFAULT);
461 461 }
462 462 if (pool_lock_intr() != 0)
463 463 return (EINTR);
464 464 if ((ret = pool_query_binding(bindq.pb_o_id_type,
465 465 bindq.pb_o_id, &bindq.pb_i_id)) == 0 &&
466 466 ddi_copyout(&bindq, (void *)arg,
467 467 sizeof (pool_bindq_t), mode) != 0)
468 468 ret = EFAULT;
469 469 pool_unlock();
470 470 break;
471 471 case POOL_PROPGET:
472 472 switch (model) {
473 473 #ifdef _MULTI_DATAMODEL
474 474 case DDI_MODEL_ILP32:
475 475 if (ddi_copyin((void *)arg, &propget32,
476 476 sizeof (pool_propget32_t), mode) != 0)
477 477 return (EFAULT);
478 478 propget.pp_o_id = propget32.pp_o_id;
479 479 propget.pp_o_id_type = propget32.pp_o_id_type;
480 480 propget.pp_o_id_subtype = propget32.pp_o_id_subtype;
481 481 propget.pp_o_prop_name =
482 482 (char *)(uintptr_t)propget32.pp_o_prop_name;
483 483 propget.pp_o_prop_name_size =
484 484 propget32.pp_o_prop_name_size;
485 485 propget.pp_i_buf =
486 486 (char *)(uintptr_t)propget32.pp_i_buf;
487 487 propget.pp_i_bufsize = propget32.pp_i_bufsize;
488 488 break;
489 489 #endif /* _MULTI_DATAMODEL */
490 490 default:
491 491 case DDI_MODEL_NONE:
492 492 if (ddi_copyin((void *)arg, &propget,
493 493 sizeof (pool_propget_t), mode) != 0)
494 494 return (EFAULT);
495 495 }
496 496 if (propget.pp_o_prop_name_size + 1 > POOL_PROPNAME_SIZE)
497 497 return (EINVAL);
498 498 prop_name = kmem_alloc(propget.pp_o_prop_name_size + 1,
499 499 KM_SLEEP);
500 500 if (ddi_copyin(propget.pp_o_prop_name, prop_name,
501 501 propget.pp_o_prop_name_size + 1, mode) != 0) {
502 502 kmem_free(prop_name, propget.pp_o_prop_name_size + 1);
503 503 return (EFAULT);
504 504 }
505 505 list = NULL;
506 506 if (pool_lock_intr() != 0) {
507 507 kmem_free(prop_name, propget.pp_o_prop_name_size + 1);
508 508 return (EINTR);
509 509 }
510 510 ret = pool_propget(prop_name, propget.pp_o_id_type,
511 511 propget.pp_o_id_subtype, propget.pp_o_id, &list);
512 512 pool_unlock();
513 513 kmem_free(prop_name, propget.pp_o_prop_name_size + 1);
514 514 if (ret != 0)
515 515 return (ret);
516 516 ret = nvlist_pack(list, &kbuf, &kbufsz, NV_ENCODE_NATIVE, 0);
517 517 if (ret != 0) {
518 518 nvlist_free(list);
519 519 return (ret);
520 520 }
521 521 switch (model) {
522 522 #ifdef _MULTI_DATAMODEL
523 523 case DDI_MODEL_ILP32:
524 524 propget32.pp_i_bufsize = kbufsz;
525 525 if (ddi_copyout((caddr_t)&propget32, (void *)arg,
526 526 sizeof (pool_propget32_t), mode) != 0)
527 527 ret = EFAULT;
528 528 break;
529 529 #endif /* _MULTI_DATAMODEL */
530 530 default:
531 531 case DDI_MODEL_NONE:
532 532 if (ddi_copyout(&propget, (void *)arg,
533 533 sizeof (pool_propget_t), mode) != 0)
534 534 ret = EFAULT;
535 535 }
536 536 if (ret == 0) {
537 537 if (propget.pp_i_buf == NULL) {
538 538 ret = 0;
539 539 } else if (propget.pp_i_bufsize >= kbufsz) {
540 540 if (ddi_copyout(kbuf, propget.pp_i_buf,
541 541 kbufsz, mode) != 0)
542 542 ret = EFAULT;
543 543 } else {
544 544 ret = ENOMEM;
545 545 }
546 546 }
547 547 kmem_free(kbuf, kbufsz);
548 548 nvlist_free(list);
549 549 break;
550 550 case POOL_PROPPUT:
551 551 switch (model) {
552 552 #ifdef _MULTI_DATAMODEL
553 553 case DDI_MODEL_ILP32:
554 554 if (ddi_copyin((void *)arg, &propput32,
555 555 sizeof (pool_propput32_t), mode) != 0)
556 556 return (EFAULT);
557 557 propput.pp_o_id_type = propput32.pp_o_id_type;
558 558 propput.pp_o_id_sub_type = propput32.pp_o_id_sub_type;
559 559 propput.pp_o_id = propput32.pp_o_id;
560 560 propput.pp_o_bufsize = propput32.pp_o_bufsize;
561 561 propput.pp_o_buf =
562 562 (char *)(uintptr_t)propput32.pp_o_buf;
563 563 break;
564 564 #endif /* _MULTI_DATAMODEL */
565 565 default:
566 566 case DDI_MODEL_NONE:
567 567 if (ddi_copyin((void *)arg, &propput,
568 568 sizeof (pool_propput_t), mode) != 0)
569 569 return (EFAULT);
570 570 }
571 571 if (propput.pp_o_bufsize > POOL_PROPBUF_SIZE)
572 572 return (EINVAL);
573 573 listbuf = kmem_alloc(propput.pp_o_bufsize, KM_SLEEP);
574 574 if (ddi_copyin(propput.pp_o_buf, listbuf,
575 575 propput.pp_o_bufsize, mode) != 0) {
576 576 kmem_free(listbuf, propput.pp_o_bufsize);
577 577 return (EFAULT);
578 578 }
579 579 if (nvlist_unpack(listbuf, propput.pp_o_bufsize,
580 580 &list, KM_SLEEP) != 0) {
581 581 kmem_free(listbuf, propput.pp_o_bufsize);
582 582 return (EFAULT);
583 583 }
584 584 if (pool_lock_intr() != 0) {
585 585 nvlist_free(list);
586 586 kmem_free(listbuf, propput.pp_o_bufsize);
587 587 return (EINTR);
588 588 }
589 589 /*
590 590 * Extract the nvpair from the list. The list may
591 591 * contain multiple properties.
592 592 */
593 593 for (pair = nvlist_next_nvpair(list, NULL); pair != NULL;
594 594 pair = nvlist_next_nvpair(list, pair)) {
595 595 if ((ret = pool_propput(propput.pp_o_id_type,
596 596 propput.pp_o_id_sub_type,
597 597 propput.pp_o_id, pair)) != 0)
598 598 break;
599 599 }
600 600 pool_unlock();
601 601 nvlist_free(list);
602 602 kmem_free(listbuf, propput.pp_o_bufsize);
603 603 break;
604 604 case POOL_PROPRM:
605 605 switch (model) {
606 606 #ifdef _MULTI_DATAMODEL
607 607 case DDI_MODEL_ILP32:
608 608 if (ddi_copyin((void *)arg, &proprm32,
609 609 sizeof (pool_proprm32_t), mode) != 0)
610 610 return (EFAULT);
611 611 proprm.pp_o_id_type = proprm32.pp_o_id_type;
612 612 proprm.pp_o_id_sub_type = proprm32.pp_o_id_sub_type;
613 613 proprm.pp_o_id = proprm32.pp_o_id;
614 614 proprm.pp_o_prop_name_size =
615 615 proprm32.pp_o_prop_name_size;
616 616 proprm.pp_o_prop_name =
617 617 (void *)(uintptr_t)proprm32.pp_o_prop_name;
618 618 break;
619 619 #endif /* _MULTI_DATAMODEL */
620 620 default:
621 621 case DDI_MODEL_NONE:
622 622 if (ddi_copyin((void *)arg, &proprm,
623 623 sizeof (pool_proprm_t), mode) != 0)
624 624 return (EFAULT);
625 625 }
626 626 if (proprm.pp_o_prop_name_size + 1 > POOL_PROPNAME_SIZE)
627 627 return (EINVAL);
628 628 prop_name = kmem_alloc(proprm.pp_o_prop_name_size + 1,
629 629 KM_SLEEP);
630 630 if (ddi_copyin(proprm.pp_o_prop_name, prop_name,
631 631 proprm.pp_o_prop_name_size + 1, mode) != 0) {
632 632 kmem_free(prop_name, proprm.pp_o_prop_name_size + 1);
633 633 return (EFAULT);
634 634 }
635 635 if (pool_lock_intr() != 0) {
636 636 kmem_free(prop_name, proprm.pp_o_prop_name_size + 1);
637 637 return (EINTR);
638 638 }
639 639 ret = pool_proprm(proprm.pp_o_id_type,
640 640 proprm.pp_o_id_sub_type, proprm.pp_o_id, prop_name);
641 641 pool_unlock();
642 642 kmem_free(prop_name, proprm.pp_o_prop_name_size + 1);
643 643 break;
644 644 case POOL_COMMIT:
645 645 if (pool_lock_intr() != 0)
646 646 return (EINTR);
647 647 ret = pool_commit((int)arg);
648 648 pool_unlock();
649 649 break;
650 650 default:
651 651 return (EINVAL);
652 652 }
653 653 return (ret);
654 654 }
655 655
656 656 static struct cb_ops pool_cb_ops = {
657 657 pool_open, /* open */
658 658 pool_close, /* close */
659 659 nodev, /* strategy */
660 660 nodev, /* print */
661 661 nodev, /* dump */
662 662 nodev, /* read */
663 663 nodev, /* write */
664 664 pool_ioctl, /* ioctl */
665 665 nodev, /* devmap */
666 666 nodev, /* mmap */
667 667 nodev, /* segmap */
668 668 nochpoll, /* poll */
669 669 nodev, /* cb_prop_op */
670 670 (struct streamtab *)0, /* streamtab */
671 671 D_NEW | D_MP /* driver compatibility flags */
672 672 };
673 673
674 674 static struct dev_ops pool_ops = {
675 675 DEVO_REV, /* devo_rev */
676 676 0, /* refcnt */
677 677 pool_info, /* info */
678 678 nulldev, /* identify */
679 679 nulldev, /* probe */
680 680 pool_attach, /* attach */
681 681 pool_detach, /* detach */
682 682 nodev, /* reset */
683 683 &pool_cb_ops, /* cb_ops */
684 684 (struct bus_ops *)NULL, /* bus_ops */
685 685 nulldev, /* power */
686 686 ddi_quiesce_not_needed, /* quiesce */
687 687 };
688 688
689 689 /*
↓ open down ↓ |
689 lines elided |
↑ open up ↑ |
690 690 * Module linkage information for the kernel
691 691 */
692 692 static struct modldrv modldrv = {
693 693 &mod_driverops, /* this one is a pseudo driver */
694 694 "pool driver",
695 695 &pool_ops
696 696 };
697 697
698 698 static struct modlinkage modlinkage = {
699 699 MODREV_1,
700 - &modldrv,
701 - NULL
700 + { &modldrv, NULL }
702 701 };
703 702
704 703 int
705 704 _init(void)
706 705 {
707 706 return (mod_install(&modlinkage));
708 707 }
709 708
710 709 int
711 710 _fini(void)
712 711 {
713 712 return (mod_remove(&modlinkage));
714 713 }
715 714
716 715 int
717 716 _info(struct modinfo *modinfop)
718 717 {
719 718 return (mod_info(&modlinkage, modinfop));
720 719 }
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX