Print this page
5253 kmem_alloc/kmem_zalloc won't fail with KM_SLEEP
5254 getrbuf won't fail with KM_SLEEP
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/uts/common/avs/ns/solaris/nsc_raw.c
+++ new/usr/src/uts/common/avs/ns/solaris/nsc_raw.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 #include <sys/types.h>
27 27 #include <sys/debug.h>
28 28 #include <sys/kmem.h>
29 29 #include <sys/ksynch.h>
30 30 #ifndef DS_DDICT
31 31 #include <sys/vnode.h>
32 32 #endif
33 33 #include <sys/cmn_err.h>
34 34 #include <sys/open.h>
35 35 #include <sys/file.h>
36 36 #include <sys/cred.h>
37 37 #include <sys/conf.h>
38 38 #include <sys/errno.h>
39 39 #include <sys/uio.h>
40 40 #ifndef DS_DDICT
41 41 #include <sys/pathname.h> /* for lookupname */
42 42 #endif
43 43 #include <sys/ddi.h>
44 44 #include <sys/sunddi.h>
45 45 #include <sys/sunldi.h>
46 46
47 47 #include <ns/solaris/nsc_thread.h>
48 48 #ifdef DS_DDICT
49 49 #include "../contract.h"
50 50 #endif
51 51 #include "../nsctl.h"
52 52 #include "nskernd.h"
53 53
54 54
55 55 typedef struct raw_maj {
56 56 struct raw_maj *next;
57 57 major_t major;
58 58 struct dev_ops *devops;
59 59 strategy_fn_t strategy;
60 60 int (*open)(dev_t *, int, int, cred_t *);
61 61 int (*close)(dev_t, int, int, cred_t *);
62 62 int (*ioctl)(dev_t, int, intptr_t, int, cred_t *, int *);
63 63 } raw_maj_t;
64 64
65 65 typedef struct raw_dev {
66 66 ldi_handle_t lh; /* Solaris layered driver handle */
67 67 struct vnode *vp; /* vnode of device */
68 68 uint64_t size; /* size of device in blocks */
69 69 raw_maj_t *major; /* pointer to major structure */
70 70 char *path; /* pathname -- kmem_alloc'd */
71 71 int plen; /* length of kmem_alloc for pathname */
72 72 dev_t rdev; /* device number */
73 73 char in_use; /* flag */
74 74 int partition; /* partition number */
75 75 } raw_dev_t;
76 76
77 77 static int fd_hwm = 0; /* first never used entry in _nsc_raw_files */
78 78
79 79 static raw_dev_t *_nsc_raw_files;
80 80 static raw_maj_t *_nsc_raw_majors;
81 81
82 82 kmutex_t _nsc_raw_lock;
83 83
84 84 int _nsc_raw_flags = 0; /* required by nsctl */
85 85 static int _nsc_raw_maxdevs; /* local copy */
86 86
87 87 static int _raw_strategy(struct buf *); /* forward decl */
88 88
89 89 static dev_t
90 90 ldi_get_dev_t_from_path(char *path)
91 91 {
92 92 vnode_t *vp;
93 93 dev_t rdev;
94 94
95 95 /* Validate parameters */
96 96 if (path == NULL)
97 97 return (NULL);
98 98
99 99 /* Lookup path */
100 100 vp = NULL;
101 101 if (lookupname(path, UIO_SYSSPACE, FOLLOW, NULLVPP, &vp))
102 102 return (NULL);
103 103
104 104 /* Validate resulting vnode */
105 105 if ((vp) && (vp->v_type == VCHR))
106 106 rdev = vp->v_rdev;
107 107 else
108 108 rdev = (dev_t)NULL;
109 109
110 110 /* Release vnode */
111 111 if (vp)
↓ open down ↓ |
111 lines elided |
↑ open up ↑ |
112 112 VN_RELE(vp);
113 113
114 114 return (rdev);
115 115 }
116 116
117 117 int
118 118 _nsc_init_raw(int maxdevs)
119 119 {
120 120 _nsc_raw_files =
121 121 kmem_zalloc(sizeof (*_nsc_raw_files) * maxdevs, KM_SLEEP);
122 - if (!_nsc_raw_files)
123 - return (ENOMEM);
124 122
125 123 _nsc_raw_maxdevs = maxdevs;
126 124 _nsc_raw_majors = NULL;
127 125
128 126 mutex_init(&_nsc_raw_lock, NULL, MUTEX_DRIVER, NULL);
129 127 return (0);
130 128 }
131 129
132 130
133 131 void
134 132 _nsc_deinit_raw(void)
135 133 {
136 134 raw_maj_t *maj = _nsc_raw_majors;
137 135 raw_maj_t *next;
138 136
139 137 /* Free the memory allocated for strategy pointers */
140 138 while (maj != NULL) {
141 139 next = maj->next;
142 140 kmem_free(maj, sizeof (*maj));
143 141 maj = next;
144 142 }
145 143
146 144 mutex_destroy(&_nsc_raw_lock);
147 145 kmem_free(_nsc_raw_files, sizeof (*_nsc_raw_files) * _nsc_raw_maxdevs);
148 146 _nsc_raw_files = NULL;
149 147 _nsc_raw_maxdevs = 0;
150 148 }
151 149
152 150
153 151 /* must be called with the _nsc_raw_lock held */
154 152 static raw_maj_t *
155 153 _raw_get_maj_info(major_t umaj)
156 154 {
157 155 raw_maj_t *maj = _nsc_raw_majors;
158 156
159 157 ASSERT(MUTEX_HELD(&_nsc_raw_lock));
160 158
161 159 /* Walk through the linked list */
162 160 while (maj != NULL) {
163 161 if (maj->major == umaj) {
164 162 /* Found major number */
165 163 break;
166 164 }
167 165 maj = maj->next;
168 166 }
169 167
170 168 if (maj == NULL) {
171 169 struct dev_ops *ops = NULL;
172 170 #ifdef DEBUG
173 171 const int maxtry = 5;
174 172 int try = maxtry;
175 173 #endif
176 174
177 175 /*
178 176 * The earlier ldi_open call has locked the driver
179 177 * for this major number into memory, so just index into
180 178 * the devopsp array to get the dev_ops pointer which
181 179 * must be valid.
182 180 */
183 181
184 182 ops = devopsp[umaj];
185 183
186 184 if (ops == NULL || ops->devo_cb_ops == NULL) {
187 185 cmn_err(CE_WARN,
188 186 "nskern: cannot find dev_ops for major %d", umaj);
189 187
190 188 return (NULL);
191 189 }
192 190
193 191 #ifdef DEBUG
194 192 cmn_err(CE_NOTE,
195 193 "nsc_raw: held driver (%d) after %d attempts",
196 194 umaj, (maxtry - try));
197 195 #endif /* DEBUG */
198 196
199 197 maj = kmem_zalloc(sizeof (raw_maj_t), KM_NOSLEEP);
200 198 if (!maj) {
201 199 return (NULL);
202 200 }
203 201
204 202 maj->strategy = ops->devo_cb_ops->cb_strategy;
205 203 maj->ioctl = ops->devo_cb_ops->cb_ioctl;
206 204 maj->close = ops->devo_cb_ops->cb_close;
207 205 maj->open = ops->devo_cb_ops->cb_open;
208 206 maj->major = umaj;
209 207 maj->devops = ops;
210 208
211 209 if (maj->strategy == NULL ||
212 210 maj->strategy == nodev ||
213 211 maj->strategy == nulldev) {
214 212 cmn_err(CE_WARN,
215 213 "nskern: no strategy function for "
216 214 "disk driver (major %d)",
217 215 umaj);
218 216 kmem_free(maj, sizeof (*maj));
219 217 return (NULL);
220 218 }
221 219
222 220 maj->next = _nsc_raw_majors;
223 221 _nsc_raw_majors = maj;
224 222 }
225 223
226 224 return (maj);
227 225 }
228 226
229 227
230 228 /*
231 229 * nsc_get_strategy returns the strategy function associated with
232 230 * the major number umaj. NULL is returned if no strategy is found.
233 231 */
234 232 strategy_fn_t
235 233 nsc_get_strategy(major_t umaj)
236 234 {
237 235 raw_maj_t *maj;
238 236 strategy_fn_t strategy = NULL;
239 237
240 238 mutex_enter(&_nsc_raw_lock);
241 239
242 240 for (maj = _nsc_raw_majors; maj != NULL; maj = maj->next) {
243 241 if (maj->major == umaj) {
244 242 /* Found major number */
245 243 strategy = maj->strategy;
246 244 break;
247 245 }
248 246 }
249 247
250 248 mutex_exit(&_nsc_raw_lock);
251 249
252 250 return (strategy);
253 251 }
254 252
255 253
256 254 void *
257 255 nsc_get_devops(major_t umaj)
258 256 {
259 257 raw_maj_t *maj;
260 258 void *devops = NULL;
261 259
262 260 mutex_enter(&_nsc_raw_lock);
263 261
264 262 for (maj = _nsc_raw_majors; maj != NULL; maj = maj->next) {
265 263 if (maj->major == umaj) {
266 264 devops = maj->devops;
267 265 break;
268 266 }
269 267 }
270 268
271 269 mutex_exit(&_nsc_raw_lock);
272 270
273 271 return (devops);
274 272 }
275 273
276 274
277 275 /*
278 276 * _raw_open
279 277 *
280 278 * Multiple opens, single close.
281 279 */
282 280
283 281 /* ARGSUSED */
284 282 static int
285 283 _raw_open(char *path, int flag, blind_t *cdp, void *iodev)
286 284 {
287 285 struct cred *cred;
288 286 raw_dev_t *cdi = NULL;
289 287 char *spath;
290 288 dev_t rdev;
291 289 int rc, cd, the_cd;
292 290 int plen;
293 291 ldi_ident_t li;
294 292
295 293 if (proc_nskernd == NULL) {
296 294 cmn_err(CE_WARN, "nskern: no nskernd daemon running!");
↓ open down ↓ |
163 lines elided |
↑ open up ↑ |
297 295 return (ENXIO);
298 296 }
299 297
300 298 if (_nsc_raw_maxdevs == 0) {
301 299 cmn_err(CE_WARN, "nskern: _raw_open() before _nsc_init_raw()!");
302 300 return (ENXIO);
303 301 }
304 302
305 303 plen = strlen(path) + 1;
306 304 spath = kmem_alloc(plen, KM_SLEEP);
307 - if (spath == NULL) {
308 - cmn_err(CE_WARN,
309 - "nskern: unable to alloc memory in _raw_open()");
310 - return (ENOMEM);
311 - }
312 305
313 306 (void) strcpy(spath, path);
314 307
315 308 /*
316 309 * Lookup the vnode to extract the dev_t info,
317 310 * then release the vnode.
318 311 */
319 312 if ((rdev = ldi_get_dev_t_from_path(path)) == 0) {
320 313 kmem_free(spath, plen);
321 314 return (ENXIO);
322 315 }
323 316
324 317 /*
325 318 * See if this device is already opened
326 319 */
327 320
328 321 the_cd = -1;
329 322
330 323 mutex_enter(&_nsc_raw_lock);
331 324
332 325 for (cd = 0, cdi = _nsc_raw_files; cd < fd_hwm; cd++, cdi++) {
333 326 if (rdev == cdi->rdev) {
334 327 the_cd = cd;
335 328 break;
336 329 } else if (the_cd == -1 && !cdi->in_use)
337 330 the_cd = cd;
338 331 }
339 332
340 333 if (the_cd == -1) {
341 334 if (fd_hwm < _nsc_raw_maxdevs)
342 335 the_cd = fd_hwm++;
343 336 else {
344 337 mutex_exit(&_nsc_raw_lock);
345 338 cmn_err(CE_WARN, "_raw_open: too many open devices");
346 339 kmem_free(spath, plen);
347 340 return (EIO);
348 341 }
349 342 }
350 343
351 344 cdi = &_nsc_raw_files[the_cd];
352 345 if (cdi->in_use) {
353 346 /* already set up - just return */
354 347 mutex_exit(&_nsc_raw_lock);
355 348 *cdp = (blind_t)cdi->rdev;
356 349 kmem_free(spath, plen);
357 350 return (0);
358 351 }
359 352
360 353 cdi->partition = -1;
361 354 cdi->size = (uint64_t)0;
362 355 cdi->rdev = rdev;
363 356 cdi->path = spath;
364 357 cdi->plen = plen;
365 358
366 359 cred = ddi_get_cred();
367 360
368 361 /*
369 362 * Layered driver
370 363 *
371 364 * We use xxx_open_by_dev() since this guarantees that a
372 365 * specfs vnode is created and used, not a standard filesystem
373 366 * vnode. This is necessary since in a cluster PXFS will block
374 367 * vnode operations during switchovers, so we have to use the
375 368 * underlying specfs vnode not the PXFS vnode.
376 369 *
377 370 */
378 371
379 372 if ((rc = ldi_ident_from_dev(cdi->rdev, &li)) == 0) {
380 373 rc = ldi_open_by_dev(&cdi->rdev,
381 374 OTYP_BLK, FREAD|FWRITE, cred, &cdi->lh, li);
382 375 }
383 376 if (rc != 0) {
384 377 cdi->lh = NULL;
385 378 goto failed;
386 379 }
387 380
388 381 /*
389 382 * grab the major_t related information
390 383 */
391 384
392 385 cdi->major = _raw_get_maj_info(getmajor(rdev));
393 386 if (cdi->major == NULL) {
394 387 /* Out of memory */
395 388 cmn_err(CE_WARN,
396 389 "_raw_open: cannot alloc major number structure");
397 390
398 391 rc = ENOMEM;
399 392 goto failed;
400 393 }
401 394
402 395 *cdp = (blind_t)cdi->rdev;
403 396 cdi->in_use++;
404 397
405 398 mutex_exit(&_nsc_raw_lock);
406 399
407 400 return (rc);
408 401
409 402 failed:
410 403
411 404 if (cdi->lh)
412 405 (void) ldi_close(cdi->lh, FWRITE|FREAD, cred);
413 406
414 407 bzero(cdi, sizeof (*cdi));
415 408
416 409 mutex_exit(&_nsc_raw_lock);
417 410
418 411 kmem_free(spath, plen);
419 412 return (rc);
420 413 }
421 414
422 415
423 416 static int
424 417 __raw_get_cd(dev_t fd)
425 418 {
426 419 int cd;
427 420
428 421 if (_nsc_raw_maxdevs != 0) {
429 422 for (cd = 0; cd < fd_hwm; cd++) {
430 423 if (fd == _nsc_raw_files[cd].rdev)
431 424 return (cd);
432 425 }
433 426 }
434 427
435 428 return (-1);
436 429 }
437 430
438 431
439 432 /*
440 433 * _raw_close
441 434 *
442 435 * Multiple opens, single close.
443 436 */
444 437
445 438 static int
446 439 _raw_close(dev_t fd)
447 440 {
448 441 struct cred *cred;
449 442 raw_dev_t *cdi;
450 443 int rc;
451 444 int cd;
452 445
453 446 mutex_enter(&_nsc_raw_lock);
454 447
455 448 if ((cd = __raw_get_cd(fd)) == -1 || !_nsc_raw_files[cd].in_use) {
456 449 mutex_exit(&_nsc_raw_lock);
457 450 return (EIO);
458 451 }
459 452
460 453 cdi = &_nsc_raw_files[cd];
461 454
462 455 cred = ddi_get_cred();
463 456
464 457 rc = ldi_close(cdi->lh, FREAD|FWRITE, cred);
465 458 if (rc != 0) {
466 459 mutex_exit(&_nsc_raw_lock);
467 460 return (rc);
468 461 }
469 462
470 463 kmem_free(cdi->path, cdi->plen);
471 464
472 465 bzero(cdi, sizeof (*cdi));
473 466
474 467 mutex_exit(&_nsc_raw_lock);
475 468
476 469 return (0);
477 470 }
478 471
479 472
480 473 /* ARGSUSED */
481 474 static int
482 475 _raw_uread(dev_t fd, uio_t *uiop, cred_t *crp)
483 476 {
484 477 return (physio(_raw_strategy, 0, fd, B_READ, minphys, uiop));
485 478 }
486 479
487 480
488 481 /* ARGSUSED */
489 482 static int
490 483 _raw_uwrite(dev_t fd, uio_t *uiop, cred_t *crp)
491 484 {
492 485 return (physio(_raw_strategy, 0, fd, B_WRITE, minphys, uiop));
493 486 }
494 487
495 488
496 489 static int
497 490 _raw_strategy(struct buf *bp)
498 491 {
499 492 int cd = __raw_get_cd(bp->b_edev);
500 493
501 494 if (cd == -1 || _nsc_raw_files[cd].major == NULL) {
502 495 bioerror(bp, ENXIO);
503 496 biodone(bp);
504 497 return (NULL);
505 498 }
506 499
507 500 return ((*_nsc_raw_files[cd].major->strategy)(bp));
508 501 }
509 502
510 503
511 504 static int
512 505 _raw_partsize(dev_t fd, nsc_size_t *rvalp)
513 506 {
514 507 int cd;
515 508
516 509 if ((cd = __raw_get_cd(fd)) == -1 || !_nsc_raw_files[cd].in_use)
517 510 return (EIO);
518 511
519 512 *rvalp = (nsc_size_t)_nsc_raw_files[cd].size;
520 513 return (0);
521 514 }
522 515
523 516
524 517 /*
525 518 * Return largest i/o size.
526 519 */
527 520
528 521 static nsc_size_t nsc_rawmaxfbas = 0;
529 522 /* ARGSUSED */
530 523 static int
531 524 _raw_maxfbas(dev_t dev, int flag, nsc_size_t *ptr)
532 525 {
533 526 struct buf *bp;
534 527 if (flag == NSC_CACHEBLK)
535 528 *ptr = 1;
536 529 else {
537 530 if (nsc_rawmaxfbas == 0) {
538 531 bp = getrbuf(KM_SLEEP);
539 532 bp->b_bcount = 4096 * 512;
540 533 minphys(bp);
541 534 nsc_rawmaxfbas = FBA_NUM(bp->b_bcount);
542 535 freerbuf(bp);
543 536 }
544 537 *ptr = nsc_rawmaxfbas;
545 538 }
546 539 return (0);
547 540 }
548 541
549 542
550 543 /*
551 544 * Control device or system.
552 545 */
553 546
554 547 /* ARGSUSED */
555 548 static int
556 549 _raw_control(dev_t dev, int cmd, int *ptr)
557 550 {
558 551 #ifdef DEBUG
559 552 cmn_err(CE_WARN, "unrecognised nsc_control: %x", cmd);
560 553 #endif
561 554 return (EINVAL); /* no control commands understood */
562 555 }
563 556
564 557
565 558 static int
566 559 _raw_get_bsize(dev_t dev, uint64_t *bsizep, int *partitionp)
567 560 {
568 561 #ifdef DKIOCPARTITION
569 562 struct partition64 *p64 = NULL;
570 563 #endif
571 564 struct dk_cinfo *dki_info = NULL;
572 565 struct dev_ops *ops;
573 566 struct cred *cred;
574 567 struct vtoc *vtoc = NULL;
575 568 dev_info_t *dip;
576 569 raw_dev_t *cdi;
577 570 int rc, cd;
578 571 int flags;
579 572 int rval;
580 573
581 574 *partitionp = -1;
582 575 *bsizep = 0;
583 576
584 577 if ((cd = __raw_get_cd(dev)) == -1 || !_nsc_raw_files[cd].in_use)
585 578 return (-1);
586 579
587 580 cdi = &_nsc_raw_files[cd];
588 581 ops = cdi->major->devops;
589 582
590 583 if (ops == NULL) {
591 584 return (-1);
592 585 }
593 586
594 587 rc = (*ops->devo_getinfo)(NULL, DDI_INFO_DEVT2DEVINFO,
595 588 (void *)dev, (void **)&dip);
596 589
597 590 if (rc != DDI_SUCCESS || dip == NULL) {
598 591 return (-1);
599 592 }
600 593
601 594 if (!ddi_prop_exists(DDI_DEV_T_ANY, dip,
602 595 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, DDI_KERNEL_IOCTL)) {
603 596 return (-1);
604 597 }
605 598
606 599 cred = ddi_get_cred();
607 600
608 601 flags = FKIOCTL | FREAD | FWRITE | DATAMODEL_NATIVE;
609 602
610 603 dki_info = kmem_alloc(sizeof (*dki_info), KM_SLEEP);
611 604
612 605 /* DKIOCINFO */
613 606 rc = (*cdi->major->ioctl)(dev, DKIOCINFO,
614 607 (intptr_t)dki_info, flags, cred, &rval);
615 608
616 609 if (rc != 0) {
617 610 goto out;
618 611 }
619 612
620 613 /* return partition number */
621 614 *partitionp = (int)dki_info->dki_partition;
622 615
623 616 vtoc = kmem_alloc(sizeof (*vtoc), KM_SLEEP);
624 617
625 618 /* DKIOCGVTOC */
626 619 rc = (*cdi->major->ioctl)(dev, DKIOCGVTOC,
627 620 (intptr_t)vtoc, flags, cred, &rval);
628 621
629 622 if (rc) {
630 623 /* DKIOCGVTOC failed, but there might be an EFI label */
631 624 rc = -1;
632 625
633 626 #ifdef DKIOCPARTITION
634 627 /* do we have an EFI partition table? */
635 628 p64 = kmem_alloc(sizeof (*p64), KM_SLEEP);
636 629 p64->p_partno = (uint_t)*partitionp;
637 630
638 631 /* DKIOCPARTITION */
639 632 rc = (*cdi->major->ioctl)(dev, DKIOCPARTITION,
640 633 (intptr_t)p64, flags, cred, &rval);
641 634
642 635 if (rc == 0) {
643 636 /* found EFI, return size */
644 637 *bsizep = (uint64_t)p64->p_size;
645 638 } else {
646 639 /* both DKIOCGVTOC and DKIOCPARTITION failed - error */
647 640 rc = -1;
648 641 }
649 642 #endif
650 643
651 644 goto out;
652 645 }
653 646
654 647 if ((vtoc->v_sanity != VTOC_SANE) ||
655 648 (vtoc->v_version != V_VERSION && vtoc->v_version != 0) ||
656 649 (dki_info->dki_partition > V_NUMPAR)) {
657 650 rc = -1;
658 651 goto out;
659 652 }
660 653
661 654 *bsizep = (uint64_t)vtoc->v_part[(int)dki_info->dki_partition].p_size;
662 655 rc = 0;
663 656
664 657 out:
665 658 if (dki_info) {
666 659 kmem_free(dki_info, sizeof (*dki_info));
667 660 }
668 661
669 662 if (vtoc) {
670 663 kmem_free(vtoc, sizeof (*vtoc));
671 664 }
672 665
673 666 #ifdef DKIOCPARTITION
674 667 if (p64) {
675 668 kmem_free(p64, sizeof (*p64));
676 669 }
677 670 #endif
678 671
679 672 return (rc);
680 673 }
681 674
682 675
683 676 /*
684 677 * Ugly, ugly, ugly.
685 678 *
686 679 * Some volume managers (Veritas) don't support layered ioctls
687 680 * (no FKIOCTL support, no DDI_KERNEL_IOCTL property defined) AND
688 681 * do not support the properties for bdev_Size()/bdev_size().
689 682 *
690 683 * If the underlying driver has specified DDI_KERNEL_IOCTL, then we use
691 684 * the FKIOCTL technique. Otherwise ...
692 685 *
693 686 * The only reliable way to get the partition size, is to bounce the
694 687 * command through user land (nskernd).
695 688 *
696 689 * Then, SunCluster PXFS blocks access at the vnode level to device
697 690 * nodes during failover / switchover, so a read_vtoc() function call
698 691 * from user land deadlocks. So, we end up coming back into the kernel
699 692 * to go directly to the underlying device driver - that's what
700 693 * nskern_bsize() is doing below.
701 694 *
702 695 * There has to be a better way ...
703 696 */
704 697
705 698 static int
706 699 _raw_init_dev(dev_t fd, uint64_t *sizep, int *partitionp)
707 700 {
708 701 struct nskernd *nsk;
709 702 int rc, cd;
710 703
711 704 if ((cd = __raw_get_cd(fd)) == -1 || !_nsc_raw_files[cd].in_use)
712 705 return (EIO);
713 706
714 707 /* try the in-kernel way */
715 708
716 709 rc = _raw_get_bsize(fd, sizep, partitionp);
717 710 if (rc == 0) {
718 711 return (0);
719 712 }
720 713
721 714 /* fallback to the the slow way */
722 715
723 716 nsk = kmem_zalloc(sizeof (*nsk), KM_SLEEP);
724 717 nsk->command = NSKERND_BSIZE;
725 718 nsk->data1 = (uint64_t)0;
726 719 nsk->data2 = (uint64_t)fd;
727 720 (void) strncpy(nsk->char1, _nsc_raw_files[cd].path, NSC_MAXPATH);
728 721
729 722 rc = nskernd_get(nsk);
730 723 if (rc == 0) {
731 724 *partitionp = (int)nsk->data2;
732 725 *sizep = nsk->data1;
733 726 }
734 727
735 728 kmem_free(nsk, sizeof (*nsk));
736 729 return (rc < 0 ? EIO : 0);
737 730 }
738 731
739 732
740 733 static int
741 734 _raw_attach_io(dev_t fd)
742 735 {
743 736 int cd;
744 737
745 738 if ((cd = __raw_get_cd(fd)) == -1 || !_nsc_raw_files[cd].in_use)
746 739 return (EIO);
747 740
748 741 return (_raw_init_dev(fd, &_nsc_raw_files[cd].size,
749 742 &_nsc_raw_files[cd].partition));
750 743 }
751 744
752 745
753 746 /*
754 747 * See the comment above _raw_init_dev().
755 748 */
756 749
757 750 int
758 751 nskern_bsize(struct nscioc_bsize *bsize, int *rvp)
759 752 {
760 753 struct cred *cred;
761 754 raw_dev_t *cdi;
762 755 int errno = 0;
763 756 int flag;
764 757 int cd;
765 758
766 759 *rvp = 0;
767 760
768 761 if (bsize == NULL || rvp == NULL)
769 762 return (EINVAL);
770 763
771 764 cd = __raw_get_cd(bsize->raw_fd);
772 765 if (cd == -1 || !_nsc_raw_files[cd].in_use)
773 766 return (EIO);
774 767
775 768 cdi = &_nsc_raw_files[cd];
776 769 cred = ddi_get_cred();
777 770
778 771 /*
779 772 * ddi_mmap_get_model() returns the model for this user thread
780 773 * which is what we want - get_udatamodel() is not public.
781 774 */
782 775
783 776 flag = FREAD | FWRITE | ddi_mmap_get_model();
784 777
785 778 if (bsize->efi == 0) {
786 779 /* DKIOCINFO */
787 780 errno = (*cdi->major->ioctl)(bsize->raw_fd,
788 781 DKIOCINFO, (intptr_t)bsize->dki_info, flag, cred, rvp);
789 782
790 783 if (errno) {
791 784 return (errno);
792 785 }
793 786
794 787 /* DKIOCGVTOC */
795 788 errno = (*cdi->major->ioctl)(bsize->raw_fd,
796 789 DKIOCGVTOC, (intptr_t)bsize->vtoc, flag, cred, rvp);
797 790
798 791 if (errno) {
799 792 return (errno);
800 793 }
801 794 } else {
802 795 #ifdef DKIOCPARTITION
803 796 /* do we have an EFI partition table? */
804 797 errno = (*cdi->major->ioctl)(bsize->raw_fd,
805 798 DKIOCPARTITION, (intptr_t)bsize->p64, flag, cred, rvp);
806 799
807 800 if (errno) {
808 801 return (errno);
809 802 }
810 803 #endif
811 804 }
812 805
813 806 return (0);
814 807 }
815 808
816 809
817 810 /*
818 811 * Private function for sv to use.
819 812 */
820 813 int
821 814 nskern_partition(dev_t fd, int *partitionp)
822 815 {
823 816 uint64_t size;
824 817 int cd, rc;
825 818
826 819 if ((cd = __raw_get_cd(fd)) == -1 || !_nsc_raw_files[cd].in_use)
827 820 return (EIO);
828 821
829 822 if ((*partitionp = _nsc_raw_files[cd].partition) != -1) {
830 823 return (0);
831 824 }
832 825
833 826 rc = _raw_init_dev(fd, &size, partitionp);
834 827 if (rc != 0 || *partitionp < 0) {
835 828 return (EIO);
836 829 }
837 830
838 831 return (0);
839 832 }
840 833
841 834
842 835 nsc_def_t _nsc_raw_def[] = {
843 836 "Open", (uintptr_t)_raw_open, 0,
844 837 "Close", (uintptr_t)_raw_close, 0,
845 838 "Attach", (uintptr_t)_raw_attach_io, 0,
846 839 "UserRead", (uintptr_t)_raw_uread, 0,
847 840 "UserWrite", (uintptr_t)_raw_uwrite, 0,
848 841 "PartSize", (uintptr_t)_raw_partsize, 0,
849 842 "MaxFbas", (uintptr_t)_raw_maxfbas, 0,
850 843 "Control", (uintptr_t)_raw_control, 0,
851 844 "Provide", NSC_DEVICE, 0,
852 845 0, 0, 0
853 846 };
↓ open down ↓ |
532 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX