1 /*- 2 * SPDX-License-Identifier: (Beerware AND BSD-3-Clause) 3 * 4 * ---------------------------------------------------------------------------- 5 * "THE BEER-WARE LICENSE" (Revision 42): 6 * <phk@FreeBSD.ORG> wrote this file. As long as you retain this notice you 7 * can do whatever you want with this stuff. If we meet some day, and you think 8 * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp 9 * ---------------------------------------------------------------------------- 10 * 11 * $FreeBSD$ 12 * 13 */ 14 15 /*- 16 * The following functions are based in the vn(4) driver: mdstart_swap(), 17 * mdstart_vnode(), mdcreate_swap(), mdcreate_vnode() and mddestroy(), 18 * and as such under the following copyright: 19 * 20 * Copyright (c) 1988 University of Utah. 21 * Copyright (c) 1990, 1993 22 * The Regents of the University of California. All rights reserved. 23 * Copyright (c) 2013 The FreeBSD Foundation 24 * All rights reserved. 25 * 26 * This code is derived from software contributed to Berkeley by 27 * the Systems Programming Group of the University of Utah Computer 28 * Science Department. 29 * 30 * Portions of this software were developed by Konstantin Belousov 31 * under sponsorship from the FreeBSD Foundation. 32 * 33 * Redistribution and use in source and binary forms, with or without 34 * modification, are permitted provided that the following conditions 35 * are met: 36 * 1. Redistributions of source code must retain the above copyright 37 * notice, this list of conditions and the following disclaimer. 38 * 2. Redistributions in binary form must reproduce the above copyright 39 * notice, this list of conditions and the following disclaimer in the 40 * documentation and/or other materials provided with the distribution. 41 * 3. Neither the name of the University nor the names of its contributors 42 * may be used to endorse or promote products derived from this software 43 * without specific prior written permission. 44 * 45 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 46 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 47 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 48 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 49 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 50 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 51 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 52 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 53 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 54 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 55 * SUCH DAMAGE. 56 * 57 * from: Utah Hdr: vn.c 1.13 94/04/02 58 * 59 * from: @(#)vn.c 8.6 (Berkeley) 4/1/94 60 * From: src/sys/dev/vn/vn.c,v 1.122 2000/12/16 16:06:03 61 */ 62 63 #include "opt_rootdevname.h" 64 #include "opt_geom.h" 65 #include "opt_md.h" 66 67 #include <sys/param.h> 68 #include <sys/systm.h> 69 #include <sys/bio.h> 70 #include <sys/buf.h> 71 #include <sys/conf.h> 72 #include <sys/devicestat.h> 73 #include <sys/fcntl.h> 74 #include <sys/kernel.h> 75 #include <sys/kthread.h> 76 #include <sys/limits.h> 77 #include <sys/linker.h> 78 #include <sys/lock.h> 79 #include <sys/malloc.h> 80 #include <sys/mdioctl.h> 81 #include <sys/mount.h> 82 #include <sys/mutex.h> 83 #include <sys/sx.h> 84 #include <sys/namei.h> 85 #include <sys/proc.h> 86 #include <sys/queue.h> 87 #include <sys/rwlock.h> 88 #include <sys/sbuf.h> 89 #include <sys/sched.h> 90 #include <sys/sf_buf.h> 91 #include <sys/sysctl.h> 92 #include <sys/vnode.h> 93 #include <sys/disk.h> 94 95 #include <geom/geom.h> 96 #include <geom/geom_int.h> 97 98 #include <vm/vm.h> 99 #include <vm/vm_param.h> 100 #include <vm/vm_object.h> 101 #include <vm/vm_page.h> 102 #include <vm/vm_pager.h> 103 #include <vm/swap_pager.h> 104 #include <vm/uma.h> 105 106 #include <machine/bus.h> 107 108 #define MD_MODVER 1 109 110 #define MD_SHUTDOWN 0x10000 /* Tell worker thread to terminate. */ 111 #define MD_EXITING 0x20000 /* Worker thread is exiting. */ 112 113 #ifndef MD_NSECT 114 #define MD_NSECT (10000 * 2) 115 #endif 116 117 struct md_req { 118 unsigned md_unit; /* unit number */ 119 enum md_types md_type; /* type of disk */ 120 off_t md_mediasize; /* size of disk in bytes */ 121 unsigned md_sectorsize; /* sectorsize */ 122 unsigned md_options; /* options */ 123 int md_fwheads; /* firmware heads */ 124 int md_fwsectors; /* firmware sectors */ 125 char *md_file; /* pathname of file to mount */ 126 enum uio_seg md_file_seg; /* location of md_file */ 127 char *md_label; /* label of the device (userspace) */ 128 int *md_units; /* pointer to units array (kernel) */ 129 size_t md_units_nitems; /* items in md_units array */ 130 }; 131 132 static MALLOC_DEFINE(M_MD, "md_disk", "Memory Disk"); 133 static MALLOC_DEFINE(M_MDSECT, "md_sectors", "Memory Disk Sectors"); 134 135 static int md_debug; 136 SYSCTL_INT(_debug, OID_AUTO, mddebug, CTLFLAG_RW, &md_debug, 0, 137 "Enable md(4) debug messages"); 138 static int md_malloc_wait; 139 SYSCTL_INT(_vm, OID_AUTO, md_malloc_wait, CTLFLAG_RW, &md_malloc_wait, 0, 140 "Allow malloc to wait for memory allocations"); 141 142 #if defined(MD_ROOT) && !defined(MD_ROOT_FSTYPE) 143 #define MD_ROOT_FSTYPE "ufs" 144 #endif 145 146 #if defined(MD_ROOT) 147 /* 148 * Preloaded image gets put here. 149 */ 150 #if defined(MD_ROOT_SIZE) 151 /* 152 * We put the mfs_root symbol into the oldmfs section of the kernel object file. 153 * Applications that patch the object with the image can determine 154 * the size looking at the oldmfs section size within the kernel. 155 */ 156 u_char mfs_root[MD_ROOT_SIZE*1024] __attribute__ ((section ("oldmfs"))); 157 const int mfs_root_size = sizeof(mfs_root); 158 #else 159 extern volatile u_char __weak_symbol mfs_root; 160 extern volatile u_char __weak_symbol mfs_root_end; 161 __GLOBL(mfs_root); 162 __GLOBL(mfs_root_end); 163 #define mfs_root_size ((uintptr_t)(&mfs_root_end - &mfs_root)) 164 #endif 165 #endif 166 167 static g_init_t g_md_init; 168 static g_fini_t g_md_fini; 169 static g_start_t g_md_start; 170 static g_access_t g_md_access; 171 static void g_md_dumpconf(struct sbuf *sb, const char *indent, 172 struct g_geom *gp, struct g_consumer *cp __unused, struct g_provider *pp); 173 174 static struct cdev *status_dev = NULL; 175 static struct sx md_sx; 176 static struct unrhdr *md_uh; 177 178 static d_ioctl_t mdctlioctl; 179 180 static struct cdevsw mdctl_cdevsw = { 181 .d_version = D_VERSION, 182 .d_ioctl = mdctlioctl, 183 .d_name = MD_NAME, 184 }; 185 186 struct g_class g_md_class = { 187 .name = "MD", 188 .version = G_VERSION, 189 .init = g_md_init, 190 .fini = g_md_fini, 191 .start = g_md_start, 192 .access = g_md_access, 193 .dumpconf = g_md_dumpconf, 194 }; 195 196 DECLARE_GEOM_CLASS(g_md_class, g_md); 197 198 199 static LIST_HEAD(, md_s) md_softc_list = LIST_HEAD_INITIALIZER(md_softc_list); 200 201 #define NINDIR (PAGE_SIZE / sizeof(uintptr_t)) 202 #define NMASK (NINDIR-1) 203 static int nshift; 204 205 static int md_vnode_pbuf_freecnt; 206 207 struct indir { 208 uintptr_t *array; 209 u_int total; 210 u_int used; 211 u_int shift; 212 }; 213 214 struct md_s { 215 int unit; 216 LIST_ENTRY(md_s) list; 217 struct bio_queue_head bio_queue; 218 struct mtx queue_mtx; 219 struct mtx stat_mtx; 220 struct cdev *dev; 221 enum md_types type; 222 off_t mediasize; 223 unsigned sectorsize; 224 unsigned opencount; 225 unsigned fwheads; 226 unsigned fwsectors; 227 char ident[32]; 228 unsigned flags; 229 char name[20]; 230 struct proc *procp; 231 struct g_geom *gp; 232 struct g_provider *pp; 233 int (*start)(struct md_s *sc, struct bio *bp); 234 struct devstat *devstat; 235 236 /* MD_MALLOC related fields */ 237 struct indir *indir; 238 uma_zone_t uma; 239 240 /* MD_PRELOAD related fields */ 241 u_char *pl_ptr; 242 size_t pl_len; 243 244 /* MD_VNODE related fields */ 245 struct vnode *vnode; 246 char file[PATH_MAX]; 247 char label[PATH_MAX]; 248 struct ucred *cred; 249 250 /* MD_SWAP related fields */ 251 vm_object_t object; 252 }; 253 254 static struct indir * 255 new_indir(u_int shift) 256 { 257 struct indir *ip; 258 259 ip = malloc(sizeof *ip, M_MD, (md_malloc_wait ? M_WAITOK : M_NOWAIT) 260 | M_ZERO); 261 if (ip == NULL) 262 return (NULL); 263 ip->array = malloc(sizeof(uintptr_t) * NINDIR, 264 M_MDSECT, (md_malloc_wait ? M_WAITOK : M_NOWAIT) | M_ZERO); 265 if (ip->array == NULL) { 266 free(ip, M_MD); 267 return (NULL); 268 } 269 ip->total = NINDIR; 270 ip->shift = shift; 271 return (ip); 272 } 273 274 static void 275 del_indir(struct indir *ip) 276 { 277 278 free(ip->array, M_MDSECT); 279 free(ip, M_MD); 280 } 281 282 static void 283 destroy_indir(struct md_s *sc, struct indir *ip) 284 { 285 int i; 286 287 for (i = 0; i < NINDIR; i++) { 288 if (!ip->array[i]) 289 continue; 290 if (ip->shift) 291 destroy_indir(sc, (struct indir*)(ip->array[i])); 292 else if (ip->array[i] > 255) 293 uma_zfree(sc->uma, (void *)(ip->array[i])); 294 } 295 del_indir(ip); 296 } 297 298 /* 299 * This function does the math and allocates the top level "indir" structure 300 * for a device of "size" sectors. 301 */ 302 303 static struct indir * 304 dimension(off_t size) 305 { 306 off_t rcnt; 307 struct indir *ip; 308 int layer; 309 310 rcnt = size; 311 layer = 0; 312 while (rcnt > NINDIR) { 313 rcnt /= NINDIR; 314 layer++; 315 } 316 317 /* 318 * XXX: the top layer is probably not fully populated, so we allocate 319 * too much space for ip->array in here. 320 */ 321 ip = malloc(sizeof *ip, M_MD, M_WAITOK | M_ZERO); 322 ip->array = malloc(sizeof(uintptr_t) * NINDIR, 323 M_MDSECT, M_WAITOK | M_ZERO); 324 ip->total = NINDIR; 325 ip->shift = layer * nshift; 326 return (ip); 327 } 328 329 /* 330 * Read a given sector 331 */ 332 333 static uintptr_t 334 s_read(struct indir *ip, off_t offset) 335 { 336 struct indir *cip; 337 int idx; 338 uintptr_t up; 339 340 if (md_debug > 1) 341 printf("s_read(%jd)\n", (intmax_t)offset); 342 up = 0; 343 for (cip = ip; cip != NULL;) { 344 if (cip->shift) { 345 idx = (offset >> cip->shift) & NMASK; 346 up = cip->array[idx]; 347 cip = (struct indir *)up; 348 continue; 349 } 350 idx = offset & NMASK; 351 return (cip->array[idx]); 352 } 353 return (0); 354 } 355 356 /* 357 * Write a given sector, prune the tree if the value is 0 358 */ 359 360 static int 361 s_write(struct indir *ip, off_t offset, uintptr_t ptr) 362 { 363 struct indir *cip, *lip[10]; 364 int idx, li; 365 uintptr_t up; 366 367 if (md_debug > 1) 368 printf("s_write(%jd, %p)\n", (intmax_t)offset, (void *)ptr); 369 up = 0; 370 li = 0; 371 cip = ip; 372 for (;;) { 373 lip[li++] = cip; 374 if (cip->shift) { 375 idx = (offset >> cip->shift) & NMASK; 376 up = cip->array[idx]; 377 if (up != 0) { 378 cip = (struct indir *)up; 379 continue; 380 } 381 /* Allocate branch */ 382 cip->array[idx] = 383 (uintptr_t)new_indir(cip->shift - nshift); 384 if (cip->array[idx] == 0) 385 return (ENOSPC); 386 cip->used++; 387 up = cip->array[idx]; 388 cip = (struct indir *)up; 389 continue; 390 } 391 /* leafnode */ 392 idx = offset & NMASK; 393 up = cip->array[idx]; 394 if (up != 0) 395 cip->used--; 396 cip->array[idx] = ptr; 397 if (ptr != 0) 398 cip->used++; 399 break; 400 } 401 if (cip->used != 0 || li == 1) 402 return (0); 403 li--; 404 while (cip->used == 0 && cip != ip) { 405 li--; 406 idx = (offset >> lip[li]->shift) & NMASK; 407 up = lip[li]->array[idx]; 408 KASSERT(up == (uintptr_t)cip, ("md screwed up")); 409 del_indir(cip); 410 lip[li]->array[idx] = 0; 411 lip[li]->used--; 412 cip = lip[li]; 413 } 414 return (0); 415 } 416 417 418 static int 419 g_md_access(struct g_provider *pp, int r, int w, int e) 420 { 421 struct md_s *sc; 422 423 sc = pp->geom->softc; 424 if (sc == NULL) { 425 if (r <= 0 && w <= 0 && e <= 0) 426 return (0); 427 return (ENXIO); 428 } 429 r += pp->acr; 430 w += pp->acw; 431 e += pp->ace; 432 if ((sc->flags & MD_READONLY) != 0 && w > 0) 433 return (EROFS); 434 if ((pp->acr + pp->acw + pp->ace) == 0 && (r + w + e) > 0) { 435 sc->opencount = 1; 436 } else if ((pp->acr + pp->acw + pp->ace) > 0 && (r + w + e) == 0) { 437 sc->opencount = 0; 438 } 439 return (0); 440 } 441 442 static void 443 g_md_start(struct bio *bp) 444 { 445 struct md_s *sc; 446 447 sc = bp->bio_to->geom->softc; 448 if ((bp->bio_cmd == BIO_READ) || (bp->bio_cmd == BIO_WRITE)) { 449 mtx_lock(&sc->stat_mtx); 450 devstat_start_transaction_bio(sc->devstat, bp); 451 mtx_unlock(&sc->stat_mtx); 452 } 453 mtx_lock(&sc->queue_mtx); 454 bioq_disksort(&sc->bio_queue, bp); 455 mtx_unlock(&sc->queue_mtx); 456 wakeup(sc); 457 } 458 459 #define MD_MALLOC_MOVE_ZERO 1 460 #define MD_MALLOC_MOVE_FILL 2 461 #define MD_MALLOC_MOVE_READ 3 462 #define MD_MALLOC_MOVE_WRITE 4 463 #define MD_MALLOC_MOVE_CMP 5 464 465 static int 466 md_malloc_move_ma(vm_page_t **mp, int *ma_offs, unsigned sectorsize, 467 void *ptr, u_char fill, int op) 468 { 469 struct sf_buf *sf; 470 vm_page_t m, *mp1; 471 char *p, first; 472 off_t *uc; 473 unsigned n; 474 int error, i, ma_offs1, sz, first_read; 475 476 m = NULL; 477 error = 0; 478 sf = NULL; 479 /* if (op == MD_MALLOC_MOVE_CMP) { gcc */ 480 first = 0; 481 first_read = 0; 482 uc = ptr; 483 mp1 = *mp; 484 ma_offs1 = *ma_offs; 485 /* } */ 486 sched_pin(); 487 for (n = sectorsize; n != 0; n -= sz) { 488 sz = imin(PAGE_SIZE - *ma_offs, n); 489 if (m != **mp) { 490 if (sf != NULL) 491 sf_buf_free(sf); 492 m = **mp; 493 sf = sf_buf_alloc(m, SFB_CPUPRIVATE | 494 (md_malloc_wait ? 0 : SFB_NOWAIT)); 495 if (sf == NULL) { 496 error = ENOMEM; 497 break; 498 } 499 } 500 p = (char *)sf_buf_kva(sf) + *ma_offs; 501 switch (op) { 502 case MD_MALLOC_MOVE_ZERO: 503 bzero(p, sz); 504 break; 505 case MD_MALLOC_MOVE_FILL: 506 memset(p, fill, sz); 507 break; 508 case MD_MALLOC_MOVE_READ: 509 bcopy(ptr, p, sz); 510 cpu_flush_dcache(p, sz); 511 break; 512 case MD_MALLOC_MOVE_WRITE: 513 bcopy(p, ptr, sz); 514 break; 515 case MD_MALLOC_MOVE_CMP: 516 for (i = 0; i < sz; i++, p++) { 517 if (!first_read) { 518 *uc = (u_char)*p; 519 first = *p; 520 first_read = 1; 521 } else if (*p != first) { 522 error = EDOOFUS; 523 break; 524 } 525 } 526 break; 527 default: 528 KASSERT(0, ("md_malloc_move_ma unknown op %d\n", op)); 529 break; 530 } 531 if (error != 0) 532 break; 533 *ma_offs += sz; 534 *ma_offs %= PAGE_SIZE; 535 if (*ma_offs == 0) 536 (*mp)++; 537 ptr = (char *)ptr + sz; 538 } 539 540 if (sf != NULL) 541 sf_buf_free(sf); 542 sched_unpin(); 543 if (op == MD_MALLOC_MOVE_CMP && error != 0) { 544 *mp = mp1; 545 *ma_offs = ma_offs1; 546 } 547 return (error); 548 } 549 550 static int 551 md_malloc_move_vlist(bus_dma_segment_t **pvlist, int *pma_offs, 552 unsigned len, void *ptr, u_char fill, int op) 553 { 554 bus_dma_segment_t *vlist; 555 uint8_t *p, *end, first; 556 off_t *uc; 557 int ma_offs, seg_len; 558 559 vlist = *pvlist; 560 ma_offs = *pma_offs; 561 uc = ptr; 562 563 for (; len != 0; len -= seg_len) { 564 seg_len = imin(vlist->ds_len - ma_offs, len); 565 p = (uint8_t *)(uintptr_t)vlist->ds_addr + ma_offs; 566 switch (op) { 567 case MD_MALLOC_MOVE_ZERO: 568 bzero(p, seg_len); 569 break; 570 case MD_MALLOC_MOVE_FILL: 571 memset(p, fill, seg_len); 572 break; 573 case MD_MALLOC_MOVE_READ: 574 bcopy(ptr, p, seg_len); 575 cpu_flush_dcache(p, seg_len); 576 break; 577 case MD_MALLOC_MOVE_WRITE: 578 bcopy(p, ptr, seg_len); 579 break; 580 case MD_MALLOC_MOVE_CMP: 581 end = p + seg_len; 582 first = *uc = *p; 583 /* Confirm all following bytes match the first */ 584 while (++p < end) { 585 if (*p != first) 586 return (EDOOFUS); 587 } 588 break; 589 default: 590 KASSERT(0, ("md_malloc_move_vlist unknown op %d\n", op)); 591 break; 592 } 593 594 ma_offs += seg_len; 595 if (ma_offs == vlist->ds_len) { 596 ma_offs = 0; 597 vlist++; 598 } 599 ptr = (uint8_t *)ptr + seg_len; 600 } 601 *pvlist = vlist; 602 *pma_offs = ma_offs; 603 604 return (0); 605 } 606 607 static int 608 mdstart_malloc(struct md_s *sc, struct bio *bp) 609 { 610 u_char *dst; 611 vm_page_t *m; 612 bus_dma_segment_t *vlist; 613 int i, error, error1, ma_offs, notmapped; 614 off_t secno, nsec, uc; 615 uintptr_t sp, osp; 616 617 switch (bp->bio_cmd) { 618 case BIO_READ: 619 case BIO_WRITE: 620 case BIO_DELETE: 621 break; 622 default: 623 return (EOPNOTSUPP); 624 } 625 626 notmapped = (bp->bio_flags & BIO_UNMAPPED) != 0; 627 vlist = (bp->bio_flags & BIO_VLIST) != 0 ? 628 (bus_dma_segment_t *)bp->bio_data : NULL; 629 if (notmapped) { 630 m = bp->bio_ma; 631 ma_offs = bp->bio_ma_offset; 632 dst = NULL; 633 KASSERT(vlist == NULL, ("vlists cannot be unmapped")); 634 } else if (vlist != NULL) { 635 ma_offs = bp->bio_ma_offset; 636 dst = NULL; 637 } else { 638 dst = bp->bio_data; 639 } 640 641 nsec = bp->bio_length / sc->sectorsize; 642 secno = bp->bio_offset / sc->sectorsize; 643 error = 0; 644 while (nsec--) { 645 osp = s_read(sc->indir, secno); 646 if (bp->bio_cmd == BIO_DELETE) { 647 if (osp != 0) 648 error = s_write(sc->indir, secno, 0); 649 } else if (bp->bio_cmd == BIO_READ) { 650 if (osp == 0) { 651 if (notmapped) { 652 error = md_malloc_move_ma(&m, &ma_offs, 653 sc->sectorsize, NULL, 0, 654 MD_MALLOC_MOVE_ZERO); 655 } else if (vlist != NULL) { 656 error = md_malloc_move_vlist(&vlist, 657 &ma_offs, sc->sectorsize, NULL, 0, 658 MD_MALLOC_MOVE_ZERO); 659 } else 660 bzero(dst, sc->sectorsize); 661 } else if (osp <= 255) { 662 if (notmapped) { 663 error = md_malloc_move_ma(&m, &ma_offs, 664 sc->sectorsize, NULL, osp, 665 MD_MALLOC_MOVE_FILL); 666 } else if (vlist != NULL) { 667 error = md_malloc_move_vlist(&vlist, 668 &ma_offs, sc->sectorsize, NULL, osp, 669 MD_MALLOC_MOVE_FILL); 670 } else 671 memset(dst, osp, sc->sectorsize); 672 } else { 673 if (notmapped) { 674 error = md_malloc_move_ma(&m, &ma_offs, 675 sc->sectorsize, (void *)osp, 0, 676 MD_MALLOC_MOVE_READ); 677 } else if (vlist != NULL) { 678 error = md_malloc_move_vlist(&vlist, 679 &ma_offs, sc->sectorsize, 680 (void *)osp, 0, 681 MD_MALLOC_MOVE_READ); 682 } else { 683 bcopy((void *)osp, dst, sc->sectorsize); 684 cpu_flush_dcache(dst, sc->sectorsize); 685 } 686 } 687 osp = 0; 688 } else if (bp->bio_cmd == BIO_WRITE) { 689 if (sc->flags & MD_COMPRESS) { 690 if (notmapped) { 691 error1 = md_malloc_move_ma(&m, &ma_offs, 692 sc->sectorsize, &uc, 0, 693 MD_MALLOC_MOVE_CMP); 694 i = error1 == 0 ? sc->sectorsize : 0; 695 } else if (vlist != NULL) { 696 error1 = md_malloc_move_vlist(&vlist, 697 &ma_offs, sc->sectorsize, &uc, 0, 698 MD_MALLOC_MOVE_CMP); 699 i = error1 == 0 ? sc->sectorsize : 0; 700 } else { 701 uc = dst[0]; 702 for (i = 1; i < sc->sectorsize; i++) { 703 if (dst[i] != uc) 704 break; 705 } 706 } 707 } else { 708 i = 0; 709 uc = 0; 710 } 711 if (i == sc->sectorsize) { 712 if (osp != uc) 713 error = s_write(sc->indir, secno, uc); 714 } else { 715 if (osp <= 255) { 716 sp = (uintptr_t)uma_zalloc(sc->uma, 717 md_malloc_wait ? M_WAITOK : 718 M_NOWAIT); 719 if (sp == 0) { 720 error = ENOSPC; 721 break; 722 } 723 if (notmapped) { 724 error = md_malloc_move_ma(&m, 725 &ma_offs, sc->sectorsize, 726 (void *)sp, 0, 727 MD_MALLOC_MOVE_WRITE); 728 } else if (vlist != NULL) { 729 error = md_malloc_move_vlist( 730 &vlist, &ma_offs, 731 sc->sectorsize, (void *)sp, 732 0, MD_MALLOC_MOVE_WRITE); 733 } else { 734 bcopy(dst, (void *)sp, 735 sc->sectorsize); 736 } 737 error = s_write(sc->indir, secno, sp); 738 } else { 739 if (notmapped) { 740 error = md_malloc_move_ma(&m, 741 &ma_offs, sc->sectorsize, 742 (void *)osp, 0, 743 MD_MALLOC_MOVE_WRITE); 744 } else if (vlist != NULL) { 745 error = md_malloc_move_vlist( 746 &vlist, &ma_offs, 747 sc->sectorsize, (void *)osp, 748 0, MD_MALLOC_MOVE_WRITE); 749 } else { 750 bcopy(dst, (void *)osp, 751 sc->sectorsize); 752 } 753 osp = 0; 754 } 755 } 756 } else { 757 error = EOPNOTSUPP; 758 } 759 if (osp > 255) 760 uma_zfree(sc->uma, (void*)osp); 761 if (error != 0) 762 break; 763 secno++; 764 if (!notmapped && vlist == NULL) 765 dst += sc->sectorsize; 766 } 767 bp->bio_resid = 0; 768 return (error); 769 } 770 771 static void 772 mdcopyto_vlist(void *src, bus_dma_segment_t *vlist, off_t offset, off_t len) 773 { 774 off_t seg_len; 775 776 while (offset >= vlist->ds_len) { 777 offset -= vlist->ds_len; 778 vlist++; 779 } 780 781 while (len != 0) { 782 seg_len = omin(len, vlist->ds_len - offset); 783 bcopy(src, (void *)(uintptr_t)(vlist->ds_addr + offset), 784 seg_len); 785 offset = 0; 786 src = (uint8_t *)src + seg_len; 787 len -= seg_len; 788 vlist++; 789 } 790 } 791 792 static void 793 mdcopyfrom_vlist(bus_dma_segment_t *vlist, off_t offset, void *dst, off_t len) 794 { 795 off_t seg_len; 796 797 while (offset >= vlist->ds_len) { 798 offset -= vlist->ds_len; 799 vlist++; 800 } 801 802 while (len != 0) { 803 seg_len = omin(len, vlist->ds_len - offset); 804 bcopy((void *)(uintptr_t)(vlist->ds_addr + offset), dst, 805 seg_len); 806 offset = 0; 807 dst = (uint8_t *)dst + seg_len; 808 len -= seg_len; 809 vlist++; 810 } 811 } 812 813 static int 814 mdstart_preload(struct md_s *sc, struct bio *bp) 815 { 816 uint8_t *p; 817 818 p = sc->pl_ptr + bp->bio_offset; 819 switch (bp->bio_cmd) { 820 case BIO_READ: 821 if ((bp->bio_flags & BIO_VLIST) != 0) { 822 mdcopyto_vlist(p, (bus_dma_segment_t *)bp->bio_data, 823 bp->bio_ma_offset, bp->bio_length); 824 } else { 825 bcopy(p, bp->bio_data, bp->bio_length); 826 } 827 cpu_flush_dcache(bp->bio_data, bp->bio_length); 828 break; 829 case BIO_WRITE: 830 if ((bp->bio_flags & BIO_VLIST) != 0) { 831 mdcopyfrom_vlist((bus_dma_segment_t *)bp->bio_data, 832 bp->bio_ma_offset, p, bp->bio_length); 833 } else { 834 bcopy(bp->bio_data, p, bp->bio_length); 835 } 836 break; 837 } 838 bp->bio_resid = 0; 839 return (0); 840 } 841 842 static int 843 mdstart_vnode(struct md_s *sc, struct bio *bp) 844 { 845 int error; 846 struct uio auio; 847 struct iovec aiov; 848 struct iovec *piov; 849 struct mount *mp; 850 struct vnode *vp; 851 struct buf *pb; 852 bus_dma_segment_t *vlist; 853 struct thread *td; 854 off_t iolen, len, zerosize; 855 int ma_offs, npages; 856 857 switch (bp->bio_cmd) { 858 case BIO_READ: 859 auio.uio_rw = UIO_READ; 860 break; 861 case BIO_WRITE: 862 case BIO_DELETE: 863 auio.uio_rw = UIO_WRITE; 864 break; 865 case BIO_FLUSH: 866 break; 867 default: 868 return (EOPNOTSUPP); 869 } 870 871 td = curthread; 872 vp = sc->vnode; 873 pb = NULL; 874 piov = NULL; 875 ma_offs = bp->bio_ma_offset; 876 len = bp->bio_length; 877 878 /* 879 * VNODE I/O 880 * 881 * If an error occurs, we set BIO_ERROR but we do not set 882 * B_INVAL because (for a write anyway), the buffer is 883 * still valid. 884 */ 885 886 if (bp->bio_cmd == BIO_FLUSH) { 887 (void) vn_start_write(vp, &mp, V_WAIT); 888 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 889 error = VOP_FSYNC(vp, MNT_WAIT, td); 890 VOP_UNLOCK(vp, 0); 891 vn_finished_write(mp); 892 return (error); 893 } 894 895 auio.uio_offset = (vm_ooffset_t)bp->bio_offset; 896 auio.uio_resid = bp->bio_length; 897 auio.uio_segflg = UIO_SYSSPACE; 898 auio.uio_td = td; 899 900 if (bp->bio_cmd == BIO_DELETE) { 901 /* 902 * Emulate BIO_DELETE by writing zeros. 903 */ 904 zerosize = ZERO_REGION_SIZE - 905 (ZERO_REGION_SIZE % sc->sectorsize); 906 auio.uio_iovcnt = howmany(bp->bio_length, zerosize); 907 piov = malloc(sizeof(*piov) * auio.uio_iovcnt, M_MD, M_WAITOK); 908 auio.uio_iov = piov; 909 while (len > 0) { 910 piov->iov_base = __DECONST(void *, zero_region); 911 piov->iov_len = len; 912 if (len > zerosize) 913 piov->iov_len = zerosize; 914 len -= piov->iov_len; 915 piov++; 916 } 917 piov = auio.uio_iov; 918 } else if ((bp->bio_flags & BIO_VLIST) != 0) { 919 piov = malloc(sizeof(*piov) * bp->bio_ma_n, M_MD, M_WAITOK); 920 auio.uio_iov = piov; 921 vlist = (bus_dma_segment_t *)bp->bio_data; 922 while (len > 0) { 923 piov->iov_base = (void *)(uintptr_t)(vlist->ds_addr + 924 ma_offs); 925 piov->iov_len = vlist->ds_len - ma_offs; 926 if (piov->iov_len > len) 927 piov->iov_len = len; 928 len -= piov->iov_len; 929 ma_offs = 0; 930 vlist++; 931 piov++; 932 } 933 auio.uio_iovcnt = piov - auio.uio_iov; 934 piov = auio.uio_iov; 935 } else if ((bp->bio_flags & BIO_UNMAPPED) != 0) { 936 pb = getpbuf(&md_vnode_pbuf_freecnt); 937 bp->bio_resid = len; 938 unmapped_step: 939 npages = atop(min(MAXPHYS, round_page(len + (ma_offs & 940 PAGE_MASK)))); 941 iolen = min(ptoa(npages) - (ma_offs & PAGE_MASK), len); 942 KASSERT(iolen > 0, ("zero iolen")); 943 pmap_qenter((vm_offset_t)pb->b_data, 944 &bp->bio_ma[atop(ma_offs)], npages); 945 aiov.iov_base = (void *)((vm_offset_t)pb->b_data + 946 (ma_offs & PAGE_MASK)); 947 aiov.iov_len = iolen; 948 auio.uio_iov = &aiov; 949 auio.uio_iovcnt = 1; 950 auio.uio_resid = iolen; 951 } else { 952 aiov.iov_base = bp->bio_data; 953 aiov.iov_len = bp->bio_length; 954 auio.uio_iov = &aiov; 955 auio.uio_iovcnt = 1; 956 } 957 /* 958 * When reading set IO_DIRECT to try to avoid double-caching 959 * the data. When writing IO_DIRECT is not optimal. 960 */ 961 if (auio.uio_rw == UIO_READ) { 962 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 963 error = VOP_READ(vp, &auio, IO_DIRECT, sc->cred); 964 VOP_UNLOCK(vp, 0); 965 } else { 966 (void) vn_start_write(vp, &mp, V_WAIT); 967 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 968 error = VOP_WRITE(vp, &auio, sc->flags & MD_ASYNC ? 0 : IO_SYNC, 969 sc->cred); 970 VOP_UNLOCK(vp, 0); 971 vn_finished_write(mp); 972 if (error == 0) 973 sc->flags &= ~MD_VERIFY; 974 } 975 976 if (pb != NULL) { 977 pmap_qremove((vm_offset_t)pb->b_data, npages); 978 if (error == 0) { 979 len -= iolen; 980 bp->bio_resid -= iolen; 981 ma_offs += iolen; 982 if (len > 0) 983 goto unmapped_step; 984 } 985 relpbuf(pb, &md_vnode_pbuf_freecnt); 986 } 987 988 free(piov, M_MD); 989 if (pb == NULL) 990 bp->bio_resid = auio.uio_resid; 991 return (error); 992 } 993 994 static void 995 md_swap_page_free(vm_page_t m) 996 { 997 998 vm_page_xunbusy(m); 999 vm_page_lock(m); 1000 vm_page_free(m); 1001 vm_page_unlock(m); 1002 } 1003 1004 static int 1005 mdstart_swap(struct md_s *sc, struct bio *bp) 1006 { 1007 vm_page_t m; 1008 u_char *p; 1009 vm_pindex_t i, lastp; 1010 bus_dma_segment_t *vlist; 1011 int rv, ma_offs, offs, len, lastend; 1012 1013 switch (bp->bio_cmd) { 1014 case BIO_READ: 1015 case BIO_WRITE: 1016 case BIO_DELETE: 1017 break; 1018 default: 1019 return (EOPNOTSUPP); 1020 } 1021 1022 p = bp->bio_data; 1023 ma_offs = (bp->bio_flags & (BIO_UNMAPPED|BIO_VLIST)) != 0 ? 1024 bp->bio_ma_offset : 0; 1025 vlist = (bp->bio_flags & BIO_VLIST) != 0 ? 1026 (bus_dma_segment_t *)bp->bio_data : NULL; 1027 1028 /* 1029 * offs is the offset at which to start operating on the 1030 * next (ie, first) page. lastp is the last page on 1031 * which we're going to operate. lastend is the ending 1032 * position within that last page (ie, PAGE_SIZE if 1033 * we're operating on complete aligned pages). 1034 */ 1035 offs = bp->bio_offset % PAGE_SIZE; 1036 lastp = (bp->bio_offset + bp->bio_length - 1) / PAGE_SIZE; 1037 lastend = (bp->bio_offset + bp->bio_length - 1) % PAGE_SIZE + 1; 1038 1039 rv = VM_PAGER_OK; 1040 VM_OBJECT_WLOCK(sc->object); 1041 vm_object_pip_add(sc->object, 1); 1042 for (i = bp->bio_offset / PAGE_SIZE; i <= lastp; i++) { 1043 len = ((i == lastp) ? lastend : PAGE_SIZE) - offs; 1044 m = vm_page_grab(sc->object, i, VM_ALLOC_SYSTEM); 1045 if (bp->bio_cmd == BIO_READ) { 1046 if (m->valid == VM_PAGE_BITS_ALL) 1047 rv = VM_PAGER_OK; 1048 else 1049 rv = vm_pager_get_pages(sc->object, &m, 1, 1050 NULL, NULL); 1051 if (rv == VM_PAGER_ERROR) { 1052 md_swap_page_free(m); 1053 break; 1054 } else if (rv == VM_PAGER_FAIL) { 1055 /* 1056 * Pager does not have the page. Zero 1057 * the allocated page, and mark it as 1058 * valid. Do not set dirty, the page 1059 * can be recreated if thrown out. 1060 */ 1061 pmap_zero_page(m); 1062 m->valid = VM_PAGE_BITS_ALL; 1063 } 1064 if ((bp->bio_flags & BIO_UNMAPPED) != 0) { 1065 pmap_copy_pages(&m, offs, bp->bio_ma, 1066 ma_offs, len); 1067 } else if ((bp->bio_flags & BIO_VLIST) != 0) { 1068 physcopyout_vlist(VM_PAGE_TO_PHYS(m) + offs, 1069 vlist, ma_offs, len); 1070 cpu_flush_dcache(p, len); 1071 } else { 1072 physcopyout(VM_PAGE_TO_PHYS(m) + offs, p, len); 1073 cpu_flush_dcache(p, len); 1074 } 1075 } else if (bp->bio_cmd == BIO_WRITE) { 1076 if (len == PAGE_SIZE || m->valid == VM_PAGE_BITS_ALL) 1077 rv = VM_PAGER_OK; 1078 else 1079 rv = vm_pager_get_pages(sc->object, &m, 1, 1080 NULL, NULL); 1081 if (rv == VM_PAGER_ERROR) { 1082 md_swap_page_free(m); 1083 break; 1084 } else if (rv == VM_PAGER_FAIL) 1085 pmap_zero_page(m); 1086 1087 if ((bp->bio_flags & BIO_UNMAPPED) != 0) { 1088 pmap_copy_pages(bp->bio_ma, ma_offs, &m, 1089 offs, len); 1090 } else if ((bp->bio_flags & BIO_VLIST) != 0) { 1091 physcopyin_vlist(vlist, ma_offs, 1092 VM_PAGE_TO_PHYS(m) + offs, len); 1093 } else { 1094 physcopyin(p, VM_PAGE_TO_PHYS(m) + offs, len); 1095 } 1096 1097 m->valid = VM_PAGE_BITS_ALL; 1098 if (m->dirty != VM_PAGE_BITS_ALL) { 1099 vm_page_dirty(m); 1100 vm_pager_page_unswapped(m); 1101 } 1102 } else if (bp->bio_cmd == BIO_DELETE) { 1103 if (len == PAGE_SIZE || m->valid == VM_PAGE_BITS_ALL) 1104 rv = VM_PAGER_OK; 1105 else 1106 rv = vm_pager_get_pages(sc->object, &m, 1, 1107 NULL, NULL); 1108 if (rv == VM_PAGER_ERROR) { 1109 md_swap_page_free(m); 1110 break; 1111 } else if (rv == VM_PAGER_FAIL) { 1112 md_swap_page_free(m); 1113 m = NULL; 1114 } else { 1115 /* Page is valid. */ 1116 if (len != PAGE_SIZE) { 1117 pmap_zero_page_area(m, offs, len); 1118 if (m->dirty != VM_PAGE_BITS_ALL) { 1119 vm_page_dirty(m); 1120 vm_pager_page_unswapped(m); 1121 } 1122 } else { 1123 vm_pager_page_unswapped(m); 1124 md_swap_page_free(m); 1125 m = NULL; 1126 } 1127 } 1128 } 1129 if (m != NULL) { 1130 vm_page_xunbusy(m); 1131 vm_page_lock(m); 1132 if (vm_page_active(m)) 1133 vm_page_reference(m); 1134 else 1135 vm_page_activate(m); 1136 vm_page_unlock(m); 1137 } 1138 1139 /* Actions on further pages start at offset 0 */ 1140 p += PAGE_SIZE - offs; 1141 offs = 0; 1142 ma_offs += len; 1143 } 1144 vm_object_pip_wakeup(sc->object); 1145 VM_OBJECT_WUNLOCK(sc->object); 1146 return (rv != VM_PAGER_ERROR ? 0 : ENOSPC); 1147 } 1148 1149 static int 1150 mdstart_null(struct md_s *sc, struct bio *bp) 1151 { 1152 1153 switch (bp->bio_cmd) { 1154 case BIO_READ: 1155 bzero(bp->bio_data, bp->bio_length); 1156 cpu_flush_dcache(bp->bio_data, bp->bio_length); 1157 break; 1158 case BIO_WRITE: 1159 break; 1160 } 1161 bp->bio_resid = 0; 1162 return (0); 1163 } 1164 1165 static void 1166 md_kthread(void *arg) 1167 { 1168 struct md_s *sc; 1169 struct bio *bp; 1170 int error; 1171 1172 sc = arg; 1173 thread_lock(curthread); 1174 sched_prio(curthread, PRIBIO); 1175 thread_unlock(curthread); 1176 if (sc->type == MD_VNODE) 1177 curthread->td_pflags |= TDP_NORUNNINGBUF; 1178 1179 for (;;) { 1180 mtx_lock(&sc->queue_mtx); 1181 if (sc->flags & MD_SHUTDOWN) { 1182 sc->flags |= MD_EXITING; 1183 mtx_unlock(&sc->queue_mtx); 1184 kproc_exit(0); 1185 } 1186 bp = bioq_takefirst(&sc->bio_queue); 1187 if (!bp) { 1188 msleep(sc, &sc->queue_mtx, PRIBIO | PDROP, "mdwait", 0); 1189 continue; 1190 } 1191 mtx_unlock(&sc->queue_mtx); 1192 if (bp->bio_cmd == BIO_GETATTR) { 1193 int isv = ((sc->flags & MD_VERIFY) != 0); 1194 1195 if ((sc->fwsectors && sc->fwheads && 1196 (g_handleattr_int(bp, "GEOM::fwsectors", 1197 sc->fwsectors) || 1198 g_handleattr_int(bp, "GEOM::fwheads", 1199 sc->fwheads))) || 1200 g_handleattr_int(bp, "GEOM::candelete", 1)) 1201 error = -1; 1202 else if (sc->ident[0] != '\0' && 1203 g_handleattr_str(bp, "GEOM::ident", sc->ident)) 1204 error = -1; 1205 else if (g_handleattr_int(bp, "MNT::verified", isv)) 1206 error = -1; 1207 else 1208 error = EOPNOTSUPP; 1209 } else { 1210 error = sc->start(sc, bp); 1211 } 1212 1213 if (error != -1) { 1214 bp->bio_completed = bp->bio_length; 1215 if ((bp->bio_cmd == BIO_READ) || (bp->bio_cmd == BIO_WRITE)) 1216 devstat_end_transaction_bio(sc->devstat, bp); 1217 g_io_deliver(bp, error); 1218 } 1219 } 1220 } 1221 1222 static struct md_s * 1223 mdfind(int unit) 1224 { 1225 struct md_s *sc; 1226 1227 LIST_FOREACH(sc, &md_softc_list, list) { 1228 if (sc->unit == unit) 1229 break; 1230 } 1231 return (sc); 1232 } 1233 1234 static struct md_s * 1235 mdnew(int unit, int *errp, enum md_types type) 1236 { 1237 struct md_s *sc; 1238 int error; 1239 1240 *errp = 0; 1241 if (unit == -1) 1242 unit = alloc_unr(md_uh); 1243 else 1244 unit = alloc_unr_specific(md_uh, unit); 1245 1246 if (unit == -1) { 1247 *errp = EBUSY; 1248 return (NULL); 1249 } 1250 1251 sc = (struct md_s *)malloc(sizeof *sc, M_MD, M_WAITOK | M_ZERO); 1252 sc->type = type; 1253 bioq_init(&sc->bio_queue); 1254 mtx_init(&sc->queue_mtx, "md bio queue", NULL, MTX_DEF); 1255 mtx_init(&sc->stat_mtx, "md stat", NULL, MTX_DEF); 1256 sc->unit = unit; 1257 sprintf(sc->name, "md%d", unit); 1258 LIST_INSERT_HEAD(&md_softc_list, sc, list); 1259 error = kproc_create(md_kthread, sc, &sc->procp, 0, 0,"%s", sc->name); 1260 if (error == 0) 1261 return (sc); 1262 LIST_REMOVE(sc, list); 1263 mtx_destroy(&sc->stat_mtx); 1264 mtx_destroy(&sc->queue_mtx); 1265 free_unr(md_uh, sc->unit); 1266 free(sc, M_MD); 1267 *errp = error; 1268 return (NULL); 1269 } 1270 1271 static void 1272 mdinit(struct md_s *sc) 1273 { 1274 struct g_geom *gp; 1275 struct g_provider *pp; 1276 1277 g_topology_lock(); 1278 gp = g_new_geomf(&g_md_class, "md%d", sc->unit); 1279 gp->softc = sc; 1280 pp = g_new_providerf(gp, "md%d", sc->unit); 1281 pp->flags |= G_PF_DIRECT_SEND | G_PF_DIRECT_RECEIVE; 1282 pp->mediasize = sc->mediasize; 1283 pp->sectorsize = sc->sectorsize; 1284 switch (sc->type) { 1285 case MD_MALLOC: 1286 case MD_VNODE: 1287 case MD_SWAP: 1288 pp->flags |= G_PF_ACCEPT_UNMAPPED; 1289 break; 1290 case MD_PRELOAD: 1291 case MD_NULL: 1292 break; 1293 } 1294 sc->gp = gp; 1295 sc->pp = pp; 1296 g_error_provider(pp, 0); 1297 g_topology_unlock(); 1298 sc->devstat = devstat_new_entry("md", sc->unit, sc->sectorsize, 1299 DEVSTAT_ALL_SUPPORTED, DEVSTAT_TYPE_DIRECT, DEVSTAT_PRIORITY_MAX); 1300 } 1301 1302 static int 1303 mdcreate_malloc(struct md_s *sc, struct md_req *mdr) 1304 { 1305 uintptr_t sp; 1306 int error; 1307 off_t u; 1308 1309 error = 0; 1310 if (mdr->md_options & ~(MD_AUTOUNIT | MD_COMPRESS | MD_RESERVE)) 1311 return (EINVAL); 1312 if (mdr->md_sectorsize != 0 && !powerof2(mdr->md_sectorsize)) 1313 return (EINVAL); 1314 /* Compression doesn't make sense if we have reserved space */ 1315 if (mdr->md_options & MD_RESERVE) 1316 mdr->md_options &= ~MD_COMPRESS; 1317 if (mdr->md_fwsectors != 0) 1318 sc->fwsectors = mdr->md_fwsectors; 1319 if (mdr->md_fwheads != 0) 1320 sc->fwheads = mdr->md_fwheads; 1321 sc->flags = mdr->md_options & (MD_COMPRESS | MD_FORCE); 1322 sc->indir = dimension(sc->mediasize / sc->sectorsize); 1323 sc->uma = uma_zcreate(sc->name, sc->sectorsize, NULL, NULL, NULL, NULL, 1324 0x1ff, 0); 1325 if (mdr->md_options & MD_RESERVE) { 1326 off_t nsectors; 1327 1328 nsectors = sc->mediasize / sc->sectorsize; 1329 for (u = 0; u < nsectors; u++) { 1330 sp = (uintptr_t)uma_zalloc(sc->uma, (md_malloc_wait ? 1331 M_WAITOK : M_NOWAIT) | M_ZERO); 1332 if (sp != 0) 1333 error = s_write(sc->indir, u, sp); 1334 else 1335 error = ENOMEM; 1336 if (error != 0) 1337 break; 1338 } 1339 } 1340 return (error); 1341 } 1342 1343 1344 static int 1345 mdsetcred(struct md_s *sc, struct ucred *cred) 1346 { 1347 char *tmpbuf; 1348 int error = 0; 1349 1350 /* 1351 * Set credits in our softc 1352 */ 1353 1354 if (sc->cred) 1355 crfree(sc->cred); 1356 sc->cred = crhold(cred); 1357 1358 /* 1359 * Horrible kludge to establish credentials for NFS XXX. 1360 */ 1361 1362 if (sc->vnode) { 1363 struct uio auio; 1364 struct iovec aiov; 1365 1366 tmpbuf = malloc(sc->sectorsize, M_TEMP, M_WAITOK); 1367 bzero(&auio, sizeof(auio)); 1368 1369 aiov.iov_base = tmpbuf; 1370 aiov.iov_len = sc->sectorsize; 1371 auio.uio_iov = &aiov; 1372 auio.uio_iovcnt = 1; 1373 auio.uio_offset = 0; 1374 auio.uio_rw = UIO_READ; 1375 auio.uio_segflg = UIO_SYSSPACE; 1376 auio.uio_resid = aiov.iov_len; 1377 vn_lock(sc->vnode, LK_EXCLUSIVE | LK_RETRY); 1378 error = VOP_READ(sc->vnode, &auio, 0, sc->cred); 1379 VOP_UNLOCK(sc->vnode, 0); 1380 free(tmpbuf, M_TEMP); 1381 } 1382 return (error); 1383 } 1384 1385 static int 1386 mdcreate_vnode(struct md_s *sc, struct md_req *mdr, struct thread *td) 1387 { 1388 struct vattr vattr; 1389 struct nameidata nd; 1390 char *fname; 1391 int error, flags; 1392 1393 fname = mdr->md_file; 1394 if (mdr->md_file_seg == UIO_USERSPACE) { 1395 error = copyinstr(fname, sc->file, sizeof(sc->file), NULL); 1396 if (error != 0) 1397 return (error); 1398 } else 1399 strlcpy(sc->file, fname, sizeof(sc->file)); 1400 1401 /* 1402 * If the user specified that this is a read only device, don't 1403 * set the FWRITE mask before trying to open the backing store. 1404 */ 1405 flags = FREAD | ((mdr->md_options & MD_READONLY) ? 0 : FWRITE) \ 1406 | ((mdr->md_options & MD_VERIFY) ? O_VERIFY : 0); 1407 NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, sc->file, td); 1408 error = vn_open(&nd, &flags, 0, NULL); 1409 if (error != 0) 1410 return (error); 1411 NDFREE(&nd, NDF_ONLY_PNBUF); 1412 if (nd.ni_vp->v_type != VREG) { 1413 error = EINVAL; 1414 goto bad; 1415 } 1416 error = VOP_GETATTR(nd.ni_vp, &vattr, td->td_ucred); 1417 if (error != 0) 1418 goto bad; 1419 if (VOP_ISLOCKED(nd.ni_vp) != LK_EXCLUSIVE) { 1420 vn_lock(nd.ni_vp, LK_UPGRADE | LK_RETRY); 1421 if (nd.ni_vp->v_iflag & VI_DOOMED) { 1422 /* Forced unmount. */ 1423 error = EBADF; 1424 goto bad; 1425 } 1426 } 1427 nd.ni_vp->v_vflag |= VV_MD; 1428 VOP_UNLOCK(nd.ni_vp, 0); 1429 1430 if (mdr->md_fwsectors != 0) 1431 sc->fwsectors = mdr->md_fwsectors; 1432 if (mdr->md_fwheads != 0) 1433 sc->fwheads = mdr->md_fwheads; 1434 snprintf(sc->ident, sizeof(sc->ident), "MD-DEV%ju-INO%ju", 1435 (uintmax_t)vattr.va_fsid, (uintmax_t)vattr.va_fileid); 1436 sc->flags = mdr->md_options & (MD_FORCE | MD_ASYNC | MD_VERIFY); 1437 if (!(flags & FWRITE)) 1438 sc->flags |= MD_READONLY; 1439 sc->vnode = nd.ni_vp; 1440 1441 error = mdsetcred(sc, td->td_ucred); 1442 if (error != 0) { 1443 sc->vnode = NULL; 1444 vn_lock(nd.ni_vp, LK_EXCLUSIVE | LK_RETRY); 1445 nd.ni_vp->v_vflag &= ~VV_MD; 1446 goto bad; 1447 } 1448 return (0); 1449 bad: 1450 VOP_UNLOCK(nd.ni_vp, 0); 1451 (void)vn_close(nd.ni_vp, flags, td->td_ucred, td); 1452 return (error); 1453 } 1454 1455 static int 1456 mddestroy(struct md_s *sc, struct thread *td) 1457 { 1458 1459 if (sc->gp) { 1460 sc->gp->softc = NULL; 1461 g_topology_lock(); 1462 g_wither_geom(sc->gp, ENXIO); 1463 g_topology_unlock(); 1464 sc->gp = NULL; 1465 sc->pp = NULL; 1466 } 1467 if (sc->devstat) { 1468 devstat_remove_entry(sc->devstat); 1469 sc->devstat = NULL; 1470 } 1471 mtx_lock(&sc->queue_mtx); 1472 sc->flags |= MD_SHUTDOWN; 1473 wakeup(sc); 1474 while (!(sc->flags & MD_EXITING)) 1475 msleep(sc->procp, &sc->queue_mtx, PRIBIO, "mddestroy", hz / 10); 1476 mtx_unlock(&sc->queue_mtx); 1477 mtx_destroy(&sc->stat_mtx); 1478 mtx_destroy(&sc->queue_mtx); 1479 if (sc->vnode != NULL) { 1480 vn_lock(sc->vnode, LK_EXCLUSIVE | LK_RETRY); 1481 sc->vnode->v_vflag &= ~VV_MD; 1482 VOP_UNLOCK(sc->vnode, 0); 1483 (void)vn_close(sc->vnode, sc->flags & MD_READONLY ? 1484 FREAD : (FREAD|FWRITE), sc->cred, td); 1485 } 1486 if (sc->cred != NULL) 1487 crfree(sc->cred); 1488 if (sc->object != NULL) 1489 vm_object_deallocate(sc->object); 1490 if (sc->indir) 1491 destroy_indir(sc, sc->indir); 1492 if (sc->uma) 1493 uma_zdestroy(sc->uma); 1494 1495 LIST_REMOVE(sc, list); 1496 free_unr(md_uh, sc->unit); 1497 free(sc, M_MD); 1498 return (0); 1499 } 1500 1501 static int 1502 mdresize(struct md_s *sc, struct md_req *mdr) 1503 { 1504 int error, res; 1505 vm_pindex_t oldpages, newpages; 1506 1507 switch (sc->type) { 1508 case MD_VNODE: 1509 case MD_NULL: 1510 break; 1511 case MD_SWAP: 1512 if (mdr->md_mediasize <= 0 || 1513 (mdr->md_mediasize % PAGE_SIZE) != 0) 1514 return (EDOM); 1515 oldpages = OFF_TO_IDX(round_page(sc->mediasize)); 1516 newpages = OFF_TO_IDX(round_page(mdr->md_mediasize)); 1517 if (newpages < oldpages) { 1518 VM_OBJECT_WLOCK(sc->object); 1519 vm_object_page_remove(sc->object, newpages, 0, 0); 1520 swap_pager_freespace(sc->object, newpages, 1521 oldpages - newpages); 1522 swap_release_by_cred(IDX_TO_OFF(oldpages - 1523 newpages), sc->cred); 1524 sc->object->charge = IDX_TO_OFF(newpages); 1525 sc->object->size = newpages; 1526 VM_OBJECT_WUNLOCK(sc->object); 1527 } else if (newpages > oldpages) { 1528 res = swap_reserve_by_cred(IDX_TO_OFF(newpages - 1529 oldpages), sc->cred); 1530 if (!res) 1531 return (ENOMEM); 1532 if ((mdr->md_options & MD_RESERVE) || 1533 (sc->flags & MD_RESERVE)) { 1534 error = swap_pager_reserve(sc->object, 1535 oldpages, newpages - oldpages); 1536 if (error < 0) { 1537 swap_release_by_cred( 1538 IDX_TO_OFF(newpages - oldpages), 1539 sc->cred); 1540 return (EDOM); 1541 } 1542 } 1543 VM_OBJECT_WLOCK(sc->object); 1544 sc->object->charge = IDX_TO_OFF(newpages); 1545 sc->object->size = newpages; 1546 VM_OBJECT_WUNLOCK(sc->object); 1547 } 1548 break; 1549 default: 1550 return (EOPNOTSUPP); 1551 } 1552 1553 sc->mediasize = mdr->md_mediasize; 1554 g_topology_lock(); 1555 g_resize_provider(sc->pp, sc->mediasize); 1556 g_topology_unlock(); 1557 return (0); 1558 } 1559 1560 static int 1561 mdcreate_swap(struct md_s *sc, struct md_req *mdr, struct thread *td) 1562 { 1563 vm_ooffset_t npage; 1564 int error; 1565 1566 /* 1567 * Range check. Disallow negative sizes and sizes not being 1568 * multiple of page size. 1569 */ 1570 if (sc->mediasize <= 0 || (sc->mediasize % PAGE_SIZE) != 0) 1571 return (EDOM); 1572 1573 /* 1574 * Allocate an OBJT_SWAP object. 1575 * 1576 * Note the truncation. 1577 */ 1578 1579 if ((mdr->md_options & MD_VERIFY) != 0) 1580 return (EINVAL); 1581 npage = mdr->md_mediasize / PAGE_SIZE; 1582 if (mdr->md_fwsectors != 0) 1583 sc->fwsectors = mdr->md_fwsectors; 1584 if (mdr->md_fwheads != 0) 1585 sc->fwheads = mdr->md_fwheads; 1586 sc->object = vm_pager_allocate(OBJT_SWAP, NULL, PAGE_SIZE * npage, 1587 VM_PROT_DEFAULT, 0, td->td_ucred); 1588 if (sc->object == NULL) 1589 return (ENOMEM); 1590 sc->flags = mdr->md_options & (MD_FORCE | MD_RESERVE); 1591 if (mdr->md_options & MD_RESERVE) { 1592 if (swap_pager_reserve(sc->object, 0, npage) < 0) { 1593 error = EDOM; 1594 goto finish; 1595 } 1596 } 1597 error = mdsetcred(sc, td->td_ucred); 1598 finish: 1599 if (error != 0) { 1600 vm_object_deallocate(sc->object); 1601 sc->object = NULL; 1602 } 1603 return (error); 1604 } 1605 1606 static int 1607 mdcreate_null(struct md_s *sc, struct md_req *mdr, struct thread *td) 1608 { 1609 1610 /* 1611 * Range check. Disallow negative sizes and sizes not being 1612 * multiple of page size. 1613 */ 1614 if (sc->mediasize <= 0 || (sc->mediasize % PAGE_SIZE) != 0) 1615 return (EDOM); 1616 1617 return (0); 1618 } 1619 1620 static int 1621 kern_mdattach_locked(struct thread *td, struct md_req *mdr) 1622 { 1623 struct md_s *sc; 1624 unsigned sectsize; 1625 int error, i; 1626 1627 sx_assert(&md_sx, SA_XLOCKED); 1628 1629 switch (mdr->md_type) { 1630 case MD_MALLOC: 1631 case MD_PRELOAD: 1632 case MD_VNODE: 1633 case MD_SWAP: 1634 case MD_NULL: 1635 break; 1636 default: 1637 return (EINVAL); 1638 } 1639 if (mdr->md_sectorsize == 0) 1640 sectsize = DEV_BSIZE; 1641 else 1642 sectsize = mdr->md_sectorsize; 1643 if (sectsize > MAXPHYS || mdr->md_mediasize < sectsize) 1644 return (EINVAL); 1645 if (mdr->md_options & MD_AUTOUNIT) 1646 sc = mdnew(-1, &error, mdr->md_type); 1647 else { 1648 if (mdr->md_unit > INT_MAX) 1649 return (EINVAL); 1650 sc = mdnew(mdr->md_unit, &error, mdr->md_type); 1651 } 1652 if (sc == NULL) 1653 return (error); 1654 if (mdr->md_label != NULL) 1655 error = copyinstr(mdr->md_label, sc->label, 1656 sizeof(sc->label), NULL); 1657 if (error != 0) 1658 goto err_after_new; 1659 if (mdr->md_options & MD_AUTOUNIT) 1660 mdr->md_unit = sc->unit; 1661 sc->mediasize = mdr->md_mediasize; 1662 sc->sectorsize = sectsize; 1663 error = EDOOFUS; 1664 switch (sc->type) { 1665 case MD_MALLOC: 1666 sc->start = mdstart_malloc; 1667 error = mdcreate_malloc(sc, mdr); 1668 break; 1669 case MD_PRELOAD: 1670 /* 1671 * We disallow attaching preloaded memory disks via 1672 * ioctl. Preloaded memory disks are automatically 1673 * attached in g_md_init(). 1674 */ 1675 error = EOPNOTSUPP; 1676 break; 1677 case MD_VNODE: 1678 sc->start = mdstart_vnode; 1679 error = mdcreate_vnode(sc, mdr, td); 1680 break; 1681 case MD_SWAP: 1682 sc->start = mdstart_swap; 1683 error = mdcreate_swap(sc, mdr, td); 1684 break; 1685 case MD_NULL: 1686 sc->start = mdstart_null; 1687 error = mdcreate_null(sc, mdr, td); 1688 break; 1689 } 1690 err_after_new: 1691 if (error != 0) { 1692 mddestroy(sc, td); 1693 return (error); 1694 } 1695 1696 /* Prune off any residual fractional sector */ 1697 i = sc->mediasize % sc->sectorsize; 1698 sc->mediasize -= i; 1699 1700 mdinit(sc); 1701 return (0); 1702 } 1703 1704 static int 1705 kern_mdattach(struct thread *td, struct md_req *mdr) 1706 { 1707 int error; 1708 1709 sx_xlock(&md_sx); 1710 error = kern_mdattach_locked(td, mdr); 1711 sx_xunlock(&md_sx); 1712 return (error); 1713 } 1714 1715 static int 1716 kern_mddetach_locked(struct thread *td, struct md_req *mdr) 1717 { 1718 struct md_s *sc; 1719 1720 sx_assert(&md_sx, SA_XLOCKED); 1721 1722 if (mdr->md_mediasize != 0 || 1723 (mdr->md_options & ~MD_FORCE) != 0) 1724 return (EINVAL); 1725 1726 sc = mdfind(mdr->md_unit); 1727 if (sc == NULL) 1728 return (ENOENT); 1729 if (sc->opencount != 0 && !(sc->flags & MD_FORCE) && 1730 !(mdr->md_options & MD_FORCE)) 1731 return (EBUSY); 1732 return (mddestroy(sc, td)); 1733 } 1734 1735 static int 1736 kern_mddetach(struct thread *td, struct md_req *mdr) 1737 { 1738 int error; 1739 1740 sx_xlock(&md_sx); 1741 error = kern_mddetach_locked(td, mdr); 1742 sx_xunlock(&md_sx); 1743 return (error); 1744 } 1745 1746 static int 1747 kern_mdresize_locked(struct md_req *mdr) 1748 { 1749 struct md_s *sc; 1750 1751 sx_assert(&md_sx, SA_XLOCKED); 1752 1753 if ((mdr->md_options & ~(MD_FORCE | MD_RESERVE)) != 0) 1754 return (EINVAL); 1755 1756 sc = mdfind(mdr->md_unit); 1757 if (sc == NULL) 1758 return (ENOENT); 1759 if (mdr->md_mediasize < sc->sectorsize) 1760 return (EINVAL); 1761 if (mdr->md_mediasize < sc->mediasize && 1762 !(sc->flags & MD_FORCE) && 1763 !(mdr->md_options & MD_FORCE)) 1764 return (EBUSY); 1765 return (mdresize(sc, mdr)); 1766 } 1767 1768 static int 1769 kern_mdresize(struct md_req *mdr) 1770 { 1771 int error; 1772 1773 sx_xlock(&md_sx); 1774 error = kern_mdresize_locked(mdr); 1775 sx_xunlock(&md_sx); 1776 return (error); 1777 } 1778 1779 static int 1780 kern_mdquery_locked(struct md_req *mdr) 1781 { 1782 struct md_s *sc; 1783 int error; 1784 1785 sx_assert(&md_sx, SA_XLOCKED); 1786 1787 sc = mdfind(mdr->md_unit); 1788 if (sc == NULL) 1789 return (ENOENT); 1790 mdr->md_type = sc->type; 1791 mdr->md_options = sc->flags; 1792 mdr->md_mediasize = sc->mediasize; 1793 mdr->md_sectorsize = sc->sectorsize; 1794 error = 0; 1795 if (mdr->md_label != NULL) { 1796 error = copyout(sc->label, mdr->md_label, 1797 strlen(sc->label) + 1); 1798 if (error != 0) 1799 return (error); 1800 } 1801 if (sc->type == MD_VNODE || 1802 (sc->type == MD_PRELOAD && mdr->md_file != NULL)) 1803 error = copyout(sc->file, mdr->md_file, 1804 strlen(sc->file) + 1); 1805 return (error); 1806 } 1807 1808 static int 1809 kern_mdquery(struct md_req *mdr) 1810 { 1811 int error; 1812 1813 sx_xlock(&md_sx); 1814 error = kern_mdquery_locked(mdr); 1815 sx_xunlock(&md_sx); 1816 return (error); 1817 } 1818 1819 static int 1820 kern_mdlist_locked(struct md_req *mdr) 1821 { 1822 struct md_s *sc; 1823 int i; 1824 1825 sx_assert(&md_sx, SA_XLOCKED); 1826 1827 /* 1828 * Write the number of md devices to mdr->md_units[0]. 1829 * Write the unit number of the first (mdr->md_units_nitems - 2) 1830 * units to mdr->md_units[1::(mdr->md_units - 2)] and terminate the 1831 * list with -1. 1832 * 1833 * XXX: There is currently no mechanism to retrieve unit 1834 * numbers for more than (MDNPAD - 2) units. 1835 * 1836 * XXX: Due to the use of LIST_INSERT_HEAD in mdnew(), the 1837 * list of visible unit numbers not stable. 1838 */ 1839 i = 1; 1840 LIST_FOREACH(sc, &md_softc_list, list) { 1841 if (i < mdr->md_units_nitems - 1) 1842 mdr->md_units[i] = sc->unit; 1843 i++; 1844 } 1845 mdr->md_units[MIN(i, mdr->md_units_nitems - 1)] = -1; 1846 mdr->md_units[0] = i - 1; 1847 return (0); 1848 } 1849 1850 static int 1851 kern_mdlist(struct md_req *mdr) 1852 { 1853 int error; 1854 1855 sx_xlock(&md_sx); 1856 error = kern_mdlist_locked(mdr); 1857 sx_xunlock(&md_sx); 1858 return (error); 1859 } 1860 1861 static int 1862 mdctlioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags, 1863 struct thread *td) 1864 { 1865 struct md_req mdr; 1866 struct md_ioctl *mdio; 1867 int error; 1868 1869 if (md_debug) 1870 printf("mdctlioctl(%s %lx %p %x %p)\n", 1871 devtoname(dev), cmd, addr, flags, td); 1872 1873 switch (cmd) { 1874 case MDIOCATTACH: 1875 case MDIOCDETACH: 1876 case MDIOCRESIZE: 1877 case MDIOCQUERY: 1878 case MDIOCLIST: 1879 mdio = (struct md_ioctl *)addr; 1880 if (mdio->md_version != MDIOVERSION) 1881 return (EINVAL); 1882 mdr.md_unit = mdio->md_unit; 1883 mdr.md_type = mdio->md_type; 1884 mdr.md_mediasize = mdio->md_mediasize; 1885 mdr.md_sectorsize = mdio->md_sectorsize; 1886 mdr.md_options = mdio->md_options; 1887 mdr.md_fwheads = mdio->md_fwheads; 1888 mdr.md_fwsectors = mdio->md_fwsectors; 1889 mdr.md_file = mdio->md_file; 1890 /* If the file is adjacent to the md_ioctl it's in kernel. */ 1891 if ((void *)mdio->md_file == (void *)(mdio + 1)) 1892 mdr.md_file_seg = UIO_SYSSPACE; 1893 else 1894 mdr.md_file_seg = UIO_USERSPACE; 1895 mdr.md_label = mdio->md_label; 1896 mdr.md_units = &mdio->md_pad[0]; 1897 mdr.md_units_nitems = nitems(mdio->md_pad); 1898 break; 1899 } 1900 1901 error = 0; 1902 switch (cmd) { 1903 case MDIOCATTACH: 1904 error = kern_mdattach(td, &mdr); 1905 break; 1906 case MDIOCDETACH: 1907 error = kern_mddetach(td, &mdr); 1908 break; 1909 case MDIOCRESIZE: 1910 error = kern_mdresize(&mdr); 1911 break; 1912 case MDIOCQUERY: 1913 error = kern_mdquery(&mdr); 1914 break; 1915 case MDIOCLIST: 1916 error = kern_mdlist(&mdr); 1917 break; 1918 default: 1919 error = ENOIOCTL; 1920 } 1921 1922 switch (cmd) { 1923 case MDIOCATTACH: 1924 case MDIOCQUERY: 1925 mdio->md_unit = mdr.md_unit; 1926 mdio->md_type = mdr.md_type; 1927 mdio->md_mediasize = mdr.md_mediasize; 1928 mdio->md_sectorsize = mdr.md_sectorsize; 1929 mdio->md_options = mdr.md_options; 1930 mdio->md_fwheads = mdr.md_fwheads; 1931 mdio->md_fwsectors = mdr.md_fwsectors; 1932 break; 1933 } 1934 1935 return (error); 1936 } 1937 1938 static void 1939 md_preloaded(u_char *image, size_t length, const char *name) 1940 { 1941 struct md_s *sc; 1942 int error; 1943 1944 sc = mdnew(-1, &error, MD_PRELOAD); 1945 if (sc == NULL) 1946 return; 1947 sc->mediasize = length; 1948 sc->sectorsize = DEV_BSIZE; 1949 sc->pl_ptr = image; 1950 sc->pl_len = length; 1951 sc->start = mdstart_preload; 1952 if (name != NULL) 1953 strlcpy(sc->file, name, sizeof(sc->file)); 1954 #ifdef MD_ROOT 1955 if (sc->unit == 0) { 1956 #ifndef ROOTDEVNAME 1957 rootdevnames[0] = MD_ROOT_FSTYPE ":/dev/md0"; 1958 #endif 1959 #ifdef MD_ROOT_READONLY 1960 sc->flags |= MD_READONLY; 1961 #endif 1962 } 1963 #endif 1964 mdinit(sc); 1965 if (name != NULL) { 1966 printf("%s%d: Preloaded image <%s> %zd bytes at %p\n", 1967 MD_NAME, sc->unit, name, length, image); 1968 } else { 1969 printf("%s%d: Embedded image %zd bytes at %p\n", 1970 MD_NAME, sc->unit, length, image); 1971 } 1972 } 1973 1974 static void 1975 g_md_init(struct g_class *mp __unused) 1976 { 1977 caddr_t mod; 1978 u_char *ptr, *name, *type; 1979 unsigned len; 1980 int i; 1981 1982 /* figure out log2(NINDIR) */ 1983 for (i = NINDIR, nshift = -1; i; nshift++) 1984 i >>= 1; 1985 1986 mod = NULL; 1987 sx_init(&md_sx, "MD config lock"); 1988 g_topology_unlock(); 1989 md_uh = new_unrhdr(0, INT_MAX, NULL); 1990 #ifdef MD_ROOT 1991 if (mfs_root_size != 0) { 1992 sx_xlock(&md_sx); 1993 md_preloaded(__DEVOLATILE(u_char *, &mfs_root), mfs_root_size, 1994 NULL); 1995 sx_xunlock(&md_sx); 1996 } 1997 #endif 1998 /* XXX: are preload_* static or do they need Giant ? */ 1999 while ((mod = preload_search_next_name(mod)) != NULL) { 2000 name = (char *)preload_search_info(mod, MODINFO_NAME); 2001 if (name == NULL) 2002 continue; 2003 type = (char *)preload_search_info(mod, MODINFO_TYPE); 2004 if (type == NULL) 2005 continue; 2006 if (strcmp(type, "md_image") && strcmp(type, "mfs_root")) 2007 continue; 2008 ptr = preload_fetch_addr(mod); 2009 len = preload_fetch_size(mod); 2010 if (ptr != NULL && len != 0) { 2011 sx_xlock(&md_sx); 2012 md_preloaded(ptr, len, name); 2013 sx_xunlock(&md_sx); 2014 } 2015 } 2016 md_vnode_pbuf_freecnt = nswbuf / 10; 2017 status_dev = make_dev(&mdctl_cdevsw, INT_MAX, UID_ROOT, GID_WHEEL, 2018 0600, MDCTL_NAME); 2019 g_topology_lock(); 2020 } 2021 2022 static void 2023 g_md_dumpconf(struct sbuf *sb, const char *indent, struct g_geom *gp, 2024 struct g_consumer *cp __unused, struct g_provider *pp) 2025 { 2026 struct md_s *mp; 2027 char *type; 2028 2029 mp = gp->softc; 2030 if (mp == NULL) 2031 return; 2032 2033 switch (mp->type) { 2034 case MD_MALLOC: 2035 type = "malloc"; 2036 break; 2037 case MD_PRELOAD: 2038 type = "preload"; 2039 break; 2040 case MD_VNODE: 2041 type = "vnode"; 2042 break; 2043 case MD_SWAP: 2044 type = "swap"; 2045 break; 2046 case MD_NULL: 2047 type = "null"; 2048 break; 2049 default: 2050 type = "unknown"; 2051 break; 2052 } 2053 2054 if (pp != NULL) { 2055 if (indent == NULL) { 2056 sbuf_printf(sb, " u %d", mp->unit); 2057 sbuf_printf(sb, " s %ju", (uintmax_t) mp->sectorsize); 2058 sbuf_printf(sb, " f %ju", (uintmax_t) mp->fwheads); 2059 sbuf_printf(sb, " fs %ju", (uintmax_t) mp->fwsectors); 2060 sbuf_printf(sb, " l %ju", (uintmax_t) mp->mediasize); 2061 sbuf_printf(sb, " t %s", type); 2062 if ((mp->type == MD_VNODE && mp->vnode != NULL) || 2063 (mp->type == MD_PRELOAD && mp->file[0] != '\0')) 2064 sbuf_printf(sb, " file %s", mp->file); 2065 sbuf_printf(sb, " label %s", mp->label); 2066 } else { 2067 sbuf_printf(sb, "%s<unit>%d</unit>\n", indent, 2068 mp->unit); 2069 sbuf_printf(sb, "%s<sectorsize>%ju</sectorsize>\n", 2070 indent, (uintmax_t) mp->sectorsize); 2071 sbuf_printf(sb, "%s<fwheads>%ju</fwheads>\n", 2072 indent, (uintmax_t) mp->fwheads); 2073 sbuf_printf(sb, "%s<fwsectors>%ju</fwsectors>\n", 2074 indent, (uintmax_t) mp->fwsectors); 2075 if (mp->ident[0] != '\0') { 2076 sbuf_printf(sb, "%s<ident>", indent); 2077 g_conf_printf_escaped(sb, "%s", mp->ident); 2078 sbuf_printf(sb, "</ident>\n"); 2079 } 2080 sbuf_printf(sb, "%s<length>%ju</length>\n", 2081 indent, (uintmax_t) mp->mediasize); 2082 sbuf_printf(sb, "%s<compression>%s</compression>\n", indent, 2083 (mp->flags & MD_COMPRESS) == 0 ? "off": "on"); 2084 sbuf_printf(sb, "%s<access>%s</access>\n", indent, 2085 (mp->flags & MD_READONLY) == 0 ? "read-write": 2086 "read-only"); 2087 sbuf_printf(sb, "%s<type>%s</type>\n", indent, 2088 type); 2089 if ((mp->type == MD_VNODE && mp->vnode != NULL) || 2090 (mp->type == MD_PRELOAD && mp->file[0] != '\0')) { 2091 sbuf_printf(sb, "%s<file>", indent); 2092 g_conf_printf_escaped(sb, "%s", mp->file); 2093 sbuf_printf(sb, "</file>\n"); 2094 } 2095 sbuf_printf(sb, "%s<label>", indent); 2096 g_conf_printf_escaped(sb, "%s", mp->label); 2097 sbuf_printf(sb, "</label>\n"); 2098 } 2099 } 2100 } 2101 2102 static void 2103 g_md_fini(struct g_class *mp __unused) 2104 { 2105 2106 sx_destroy(&md_sx); 2107 if (status_dev != NULL) 2108 destroy_dev(status_dev); 2109 delete_unrhdr(md_uh); 2110 } 2111