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