1 /* 2 * Copyright (c) 2007 Doug Rabson 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 27 #include <sys/cdefs.h> 28 29 /* 30 * Stand-alone file reading package. 31 */ 32 33 #include <sys/disk.h> 34 #include <sys/param.h> 35 #include <sys/time.h> 36 #include <sys/queue.h> 37 #include <part.h> 38 #include <stddef.h> 39 #include <stdarg.h> 40 #include <string.h> 41 #include <stand.h> 42 #include <bootstrap.h> 43 44 #include "libzfs.h" 45 46 #include "zfsimpl.c" 47 48 /* Define the range of indexes to be populated with ZFS Boot Environments */ 49 #define ZFS_BE_FIRST 4 50 #define ZFS_BE_LAST 8 51 52 static int zfs_open(const char *path, struct open_file *f); 53 static int zfs_write(struct open_file *f, void *buf, size_t size, size_t *resid); 54 static int zfs_close(struct open_file *f); 55 static int zfs_read(struct open_file *f, void *buf, size_t size, size_t *resid); 56 static off_t zfs_seek(struct open_file *f, off_t offset, int where); 57 static int zfs_stat(struct open_file *f, struct stat *sb); 58 static int zfs_readdir(struct open_file *f, struct dirent *d); 59 60 struct devsw zfs_dev; 61 62 struct fs_ops zfs_fsops = { 63 "zfs", 64 zfs_open, 65 zfs_close, 66 zfs_read, 67 zfs_write, 68 zfs_seek, 69 zfs_stat, 70 zfs_readdir 71 }; 72 73 /* 74 * In-core open file. 75 */ 76 struct file { 77 off_t f_seekp; /* seek pointer */ 78 dnode_phys_t f_dnode; 79 uint64_t f_zap_type; /* zap type for readdir */ 80 uint64_t f_num_leafs; /* number of fzap leaf blocks */ 81 zap_leaf_phys_t *f_zap_leaf; /* zap leaf buffer */ 82 }; 83 84 #ifdef __FreeBSD__ 85 static int zfs_env_index; 86 static int zfs_env_count; 87 #endif 88 89 SLIST_HEAD(zfs_be_list, zfs_be_entry) zfs_be_head = SLIST_HEAD_INITIALIZER(zfs_be_head); 90 struct zfs_be_list *zfs_be_headp; 91 struct zfs_be_entry { 92 const char *name; 93 SLIST_ENTRY(zfs_be_entry) entries; 94 } *zfs_be, *zfs_be_tmp; 95 96 /* 97 * Open a file. 98 */ 99 static int 100 zfs_open(const char *upath, struct open_file *f) 101 { 102 struct zfsmount *mount = (struct zfsmount *)f->f_devdata; 103 struct file *fp; 104 int rc; 105 106 if (f->f_dev != &zfs_dev) 107 return (EINVAL); 108 109 /* allocate file system specific data structure */ 110 fp = malloc(sizeof(struct file)); 111 bzero(fp, sizeof(struct file)); 112 f->f_fsdata = (void *)fp; 113 114 rc = zfs_lookup(mount, upath, &fp->f_dnode); 115 fp->f_seekp = 0; 116 if (rc) { 117 f->f_fsdata = NULL; 118 free(fp); 119 } 120 return (rc); 121 } 122 123 static int 124 zfs_close(struct open_file *f) 125 { 126 struct file *fp = (struct file *)f->f_fsdata; 127 128 dnode_cache_obj = 0; 129 f->f_fsdata = (void *)0; 130 if (fp == (struct file *)0) 131 return (0); 132 133 free(fp); 134 return (0); 135 } 136 137 /* 138 * Copy a portion of a file into kernel memory. 139 * Cross block boundaries when necessary. 140 */ 141 static int 142 zfs_read(struct open_file *f, void *start, size_t size, size_t *resid /* out */) 143 { 144 const spa_t *spa = ((struct zfsmount *)f->f_devdata)->spa; 145 struct file *fp = (struct file *)f->f_fsdata; 146 struct stat sb; 147 size_t n; 148 int rc; 149 150 rc = zfs_stat(f, &sb); 151 if (rc) 152 return (rc); 153 n = size; 154 if (fp->f_seekp + n > sb.st_size) 155 n = sb.st_size - fp->f_seekp; 156 157 rc = dnode_read(spa, &fp->f_dnode, fp->f_seekp, start, n); 158 if (rc) 159 return (rc); 160 161 if (0) { 162 int i; 163 for (i = 0; i < n; i++) 164 putchar(((char*) start)[i]); 165 } 166 fp->f_seekp += n; 167 if (resid) 168 *resid = size - n; 169 170 return (0); 171 } 172 173 /* 174 * Don't be silly - the bootstrap has no business writing anything. 175 */ 176 static int 177 zfs_write(struct open_file *f, void *start, size_t size, size_t *resid /* out */) 178 { 179 180 return (EROFS); 181 } 182 183 static off_t 184 zfs_seek(struct open_file *f, off_t offset, int where) 185 { 186 struct file *fp = (struct file *)f->f_fsdata; 187 188 switch (where) { 189 case SEEK_SET: 190 fp->f_seekp = offset; 191 break; 192 case SEEK_CUR: 193 fp->f_seekp += offset; 194 break; 195 case SEEK_END: 196 { 197 struct stat sb; 198 int error; 199 200 error = zfs_stat(f, &sb); 201 if (error != 0) { 202 errno = error; 203 return (-1); 204 } 205 fp->f_seekp = sb.st_size - offset; 206 break; 207 } 208 default: 209 errno = EINVAL; 210 return (-1); 211 } 212 return (fp->f_seekp); 213 } 214 215 static int 216 zfs_stat(struct open_file *f, struct stat *sb) 217 { 218 const spa_t *spa = ((struct zfsmount *)f->f_devdata)->spa; 219 struct file *fp = (struct file *)f->f_fsdata; 220 221 return (zfs_dnode_stat(spa, &fp->f_dnode, sb)); 222 } 223 224 static int 225 zfs_readdir(struct open_file *f, struct dirent *d) 226 { 227 const spa_t *spa = ((struct zfsmount *)f->f_devdata)->spa; 228 struct file *fp = (struct file *)f->f_fsdata; 229 mzap_ent_phys_t mze; 230 struct stat sb; 231 size_t bsize = fp->f_dnode.dn_datablkszsec << SPA_MINBLOCKSHIFT; 232 int rc; 233 234 rc = zfs_stat(f, &sb); 235 if (rc) 236 return (rc); 237 if (!S_ISDIR(sb.st_mode)) 238 return (ENOTDIR); 239 240 /* 241 * If this is the first read, get the zap type. 242 */ 243 if (fp->f_seekp == 0) { 244 rc = dnode_read(spa, &fp->f_dnode, 245 0, &fp->f_zap_type, sizeof(fp->f_zap_type)); 246 if (rc) 247 return (rc); 248 249 if (fp->f_zap_type == ZBT_MICRO) { 250 fp->f_seekp = offsetof(mzap_phys_t, mz_chunk); 251 } else { 252 rc = dnode_read(spa, &fp->f_dnode, 253 offsetof(zap_phys_t, zap_num_leafs), 254 &fp->f_num_leafs, 255 sizeof(fp->f_num_leafs)); 256 if (rc) 257 return (rc); 258 259 fp->f_seekp = bsize; 260 fp->f_zap_leaf = (zap_leaf_phys_t *)malloc(bsize); 261 rc = dnode_read(spa, &fp->f_dnode, 262 fp->f_seekp, 263 fp->f_zap_leaf, 264 bsize); 265 if (rc) 266 return (rc); 267 } 268 } 269 270 if (fp->f_zap_type == ZBT_MICRO) { 271 mzap_next: 272 if (fp->f_seekp >= bsize) 273 return (ENOENT); 274 275 rc = dnode_read(spa, &fp->f_dnode, 276 fp->f_seekp, &mze, sizeof(mze)); 277 if (rc) 278 return (rc); 279 fp->f_seekp += sizeof(mze); 280 281 if (!mze.mze_name[0]) 282 goto mzap_next; 283 284 d->d_fileno = ZFS_DIRENT_OBJ(mze.mze_value); 285 d->d_type = ZFS_DIRENT_TYPE(mze.mze_value); 286 strcpy(d->d_name, mze.mze_name); 287 d->d_namlen = strlen(d->d_name); 288 return (0); 289 } else { 290 zap_leaf_t zl; 291 zap_leaf_chunk_t *zc, *nc; 292 int chunk; 293 size_t namelen; 294 char *p; 295 uint64_t value; 296 297 /* 298 * Initialise this so we can use the ZAP size 299 * calculating macros. 300 */ 301 zl.l_bs = ilog2(bsize); 302 zl.l_phys = fp->f_zap_leaf; 303 304 /* 305 * Figure out which chunk we are currently looking at 306 * and consider seeking to the next leaf. We use the 307 * low bits of f_seekp as a simple chunk index. 308 */ 309 fzap_next: 310 chunk = fp->f_seekp & (bsize - 1); 311 if (chunk == ZAP_LEAF_NUMCHUNKS(&zl)) { 312 fp->f_seekp = (fp->f_seekp & ~(bsize - 1)) + bsize; 313 chunk = 0; 314 315 /* 316 * Check for EOF and read the new leaf. 317 */ 318 if (fp->f_seekp >= bsize * fp->f_num_leafs) 319 return (ENOENT); 320 321 rc = dnode_read(spa, &fp->f_dnode, 322 fp->f_seekp, 323 fp->f_zap_leaf, 324 bsize); 325 if (rc) 326 return (rc); 327 } 328 329 zc = &ZAP_LEAF_CHUNK(&zl, chunk); 330 fp->f_seekp++; 331 if (zc->l_entry.le_type != ZAP_CHUNK_ENTRY) 332 goto fzap_next; 333 334 namelen = zc->l_entry.le_name_numints; 335 if (namelen > sizeof(d->d_name)) 336 namelen = sizeof(d->d_name); 337 338 /* 339 * Paste the name back together. 340 */ 341 nc = &ZAP_LEAF_CHUNK(&zl, zc->l_entry.le_name_chunk); 342 p = d->d_name; 343 while (namelen > 0) { 344 int len; 345 len = namelen; 346 if (len > ZAP_LEAF_ARRAY_BYTES) 347 len = ZAP_LEAF_ARRAY_BYTES; 348 memcpy(p, nc->l_array.la_array, len); 349 p += len; 350 namelen -= len; 351 nc = &ZAP_LEAF_CHUNK(&zl, nc->l_array.la_next); 352 } 353 d->d_name[sizeof(d->d_name) - 1] = 0; 354 355 /* 356 * Assume the first eight bytes of the value are 357 * a uint64_t. 358 */ 359 value = fzap_leaf_value(&zl, zc); 360 361 d->d_fileno = ZFS_DIRENT_OBJ(value); 362 d->d_type = ZFS_DIRENT_TYPE(value); 363 d->d_namlen = strlen(d->d_name); 364 365 return (0); 366 } 367 } 368 369 static int 370 vdev_read(vdev_t *vdev, void *priv, off_t offset, void *buf, size_t bytes) 371 { 372 int fd, ret; 373 size_t res, size, remainder, rb_size, blksz; 374 unsigned secsz; 375 off_t off; 376 char *bouncebuf, *rb_buf; 377 378 fd = (uintptr_t) priv; 379 bouncebuf = NULL; 380 381 ret = ioctl(fd, DIOCGSECTORSIZE, &secsz); 382 if (ret != 0) 383 return (ret); 384 385 off = offset / secsz; 386 remainder = offset % secsz; 387 if (lseek(fd, off * secsz, SEEK_SET) == -1) 388 return (errno); 389 390 rb_buf = buf; 391 rb_size = bytes; 392 size = roundup2(bytes + remainder, secsz); 393 blksz = size; 394 if (remainder != 0 || size != bytes) { 395 bouncebuf = zfs_alloc(secsz); 396 if (bouncebuf == NULL) { 397 printf("vdev_read: out of memory\n"); 398 return (ENOMEM); 399 } 400 rb_buf = bouncebuf; 401 blksz = rb_size - remainder; 402 } 403 404 while (bytes > 0) { 405 res = read(fd, rb_buf, rb_size); 406 if (res != rb_size) { 407 ret = EIO; 408 goto error; 409 } 410 if (bytes < blksz) 411 blksz = bytes; 412 if (bouncebuf != NULL) 413 memcpy(buf, rb_buf + remainder, blksz); 414 buf = (void *)((uintptr_t)buf + blksz); 415 bytes -= blksz; 416 remainder = 0; 417 blksz = rb_size; 418 } 419 420 ret = 0; 421 error: 422 if (bouncebuf != NULL) 423 zfs_free(bouncebuf, secsz); 424 return (ret); 425 } 426 427 static int 428 zfs_dev_init(void) 429 { 430 spa_t *spa; 431 spa_t *next; 432 spa_t *prev; 433 434 zfs_init(); 435 if (archsw.arch_zfs_probe == NULL) 436 return (ENXIO); 437 archsw.arch_zfs_probe(); 438 439 prev = NULL; 440 spa = STAILQ_FIRST(&zfs_pools); 441 while (spa != NULL) { 442 next = STAILQ_NEXT(spa, spa_link); 443 if (zfs_spa_init(spa)) { 444 if (prev == NULL) 445 STAILQ_REMOVE_HEAD(&zfs_pools, spa_link); 446 else 447 STAILQ_REMOVE_AFTER(&zfs_pools, prev, spa_link); 448 } else 449 prev = spa; 450 spa = next; 451 } 452 return (0); 453 } 454 455 struct zfs_probe_args { 456 int fd; 457 const char *devname; 458 uint64_t *pool_guid; 459 u_int secsz; 460 }; 461 462 static int 463 zfs_diskread(void *arg, void *buf, size_t blocks, uint64_t offset) 464 { 465 struct zfs_probe_args *ppa; 466 467 ppa = (struct zfs_probe_args *)arg; 468 return (vdev_read(NULL, (void *)(uintptr_t)ppa->fd, 469 offset * ppa->secsz, buf, blocks * ppa->secsz)); 470 } 471 472 static int 473 zfs_probe(int fd, uint64_t *pool_guid) 474 { 475 spa_t *spa; 476 int ret; 477 478 ret = vdev_probe(vdev_read, (void *)(uintptr_t)fd, &spa); 479 if (ret == 0 && pool_guid != NULL) 480 *pool_guid = spa->spa_guid; 481 return (ret); 482 } 483 484 static int 485 zfs_probe_partition(void *arg, const char *partname, 486 const struct ptable_entry *part) 487 { 488 struct zfs_probe_args *ppa, pa; 489 struct ptable *table; 490 char devname[32]; 491 int ret = 0; 492 493 /* filter out partitions *not* used by zfs */ 494 switch (part->type) { 495 case PART_RESERVED: /* efi reserverd */ 496 case PART_VTOC_BOOT: /* vtoc boot area */ 497 case PART_VTOC_SWAP: 498 return (ret); 499 default: 500 break;; 501 } 502 ppa = (struct zfs_probe_args *)arg; 503 strncpy(devname, ppa->devname, strlen(ppa->devname) - 1); 504 devname[strlen(ppa->devname) - 1] = '\0'; 505 sprintf(devname, "%s%s:", devname, partname); 506 pa.fd = open(devname, O_RDONLY); 507 if (pa.fd == -1) 508 return (ret); 509 ret = zfs_probe(pa.fd, ppa->pool_guid); 510 if (ret == 0) 511 return (ret); 512 if (part->type == PART_SOLARIS2) { 513 pa.devname = devname; 514 pa.pool_guid = ppa->pool_guid; 515 pa.secsz = ppa->secsz; 516 table = ptable_open(&pa, part->end - part->start + 1, 517 ppa->secsz, zfs_diskread); 518 if (table != NULL) { 519 ptable_iterate(table, &pa, zfs_probe_partition); 520 ptable_close(table); 521 } 522 } 523 close(pa.fd); 524 return (0); 525 } 526 527 int 528 zfs_probe_dev(const char *devname, uint64_t *pool_guid) 529 { 530 struct ptable *table; 531 struct zfs_probe_args pa; 532 uint64_t mediasz; 533 int ret; 534 535 if (pool_guid) 536 *pool_guid = 0; 537 pa.fd = open(devname, O_RDONLY); 538 if (pa.fd == -1) 539 return (ENXIO); 540 /* Probe the whole disk */ 541 ret = zfs_probe(pa.fd, pool_guid); 542 if (ret == 0) 543 return (0); 544 545 /* Probe each partition */ 546 ret = ioctl(pa.fd, DIOCGMEDIASIZE, &mediasz); 547 if (ret == 0) 548 ret = ioctl(pa.fd, DIOCGSECTORSIZE, &pa.secsz); 549 if (ret == 0) { 550 pa.devname = devname; 551 pa.pool_guid = pool_guid; 552 table = ptable_open(&pa, mediasz / pa.secsz, pa.secsz, 553 zfs_diskread); 554 if (table != NULL) { 555 ptable_iterate(table, &pa, zfs_probe_partition); 556 ptable_close(table); 557 } 558 } 559 close(pa.fd); 560 if (pool_guid && *pool_guid == 0) 561 ret = ENXIO; 562 return (ret); 563 } 564 565 /* 566 * Print information about ZFS pools 567 */ 568 static int 569 zfs_dev_print(int verbose) 570 { 571 spa_t *spa; 572 char line[80]; 573 int ret = 0; 574 575 if (STAILQ_EMPTY(&zfs_pools)) 576 return (0); 577 578 printf("%s devices:", zfs_dev.dv_name); 579 if ((ret = pager_output("\n")) != 0) 580 return (ret); 581 582 if (verbose) { 583 return (spa_all_status()); 584 } 585 STAILQ_FOREACH(spa, &zfs_pools, spa_link) { 586 sprintf(line, " zfs:%s\n", spa->spa_name); 587 ret = pager_output(line); 588 if (ret != 0) 589 break; 590 } 591 return (ret); 592 } 593 594 /* 595 * Attempt to open the pool described by (dev) for use by (f). 596 */ 597 static int 598 zfs_dev_open(struct open_file *f, ...) 599 { 600 va_list args; 601 struct zfs_devdesc *dev; 602 struct zfsmount *mount; 603 spa_t *spa; 604 int rv; 605 606 va_start(args, f); 607 dev = va_arg(args, struct zfs_devdesc *); 608 va_end(args); 609 610 if (dev->pool_guid == 0) 611 spa = STAILQ_FIRST(&zfs_pools); 612 else 613 spa = spa_find_by_guid(dev->pool_guid); 614 if (!spa) 615 return (ENXIO); 616 mount = malloc(sizeof(*mount)); 617 rv = zfs_mount(spa, dev->root_guid, mount); 618 if (rv != 0) { 619 free(mount); 620 return (rv); 621 } 622 if (mount->objset.os_type != DMU_OST_ZFS) { 623 printf("Unexpected object set type %ju\n", 624 (uintmax_t)mount->objset.os_type); 625 free(mount); 626 return (EIO); 627 } 628 f->f_devdata = mount; 629 free(dev); 630 return (0); 631 } 632 633 static int 634 zfs_dev_close(struct open_file *f) 635 { 636 637 free(f->f_devdata); 638 f->f_devdata = NULL; 639 return (0); 640 } 641 642 static int 643 zfs_dev_strategy(void *devdata, int rw, daddr_t dblk, size_t size, 644 char *buf, size_t *rsize) 645 { 646 647 return (ENOSYS); 648 } 649 650 struct devsw zfs_dev = { 651 .dv_name = "zfs", 652 .dv_type = DEVT_ZFS, 653 .dv_init = zfs_dev_init, 654 .dv_strategy = zfs_dev_strategy, 655 .dv_open = zfs_dev_open, 656 .dv_close = zfs_dev_close, 657 .dv_ioctl = noioctl, 658 .dv_print = zfs_dev_print, 659 .dv_cleanup = NULL 660 }; 661 662 int 663 zfs_parsedev(struct zfs_devdesc *dev, const char *devspec, const char **path) 664 { 665 static char rootname[ZFS_MAXNAMELEN]; 666 static char poolname[ZFS_MAXNAMELEN]; 667 spa_t *spa; 668 const char *end; 669 const char *np; 670 const char *sep; 671 int rv; 672 673 np = devspec; 674 if (*np != ':') 675 return (EINVAL); 676 np++; 677 end = strchr(np, ':'); 678 if (end == NULL) 679 return (EINVAL); 680 sep = strchr(np, '/'); 681 if (sep == NULL || sep >= end) 682 sep = end; 683 memcpy(poolname, np, sep - np); 684 poolname[sep - np] = '\0'; 685 if (sep < end) { 686 sep++; 687 memcpy(rootname, sep, end - sep); 688 rootname[end - sep] = '\0'; 689 } 690 else 691 rootname[0] = '\0'; 692 693 spa = spa_find_by_name(poolname); 694 if (!spa) 695 return (ENXIO); 696 dev->pool_guid = spa->spa_guid; 697 rv = zfs_lookup_dataset(spa, rootname, &dev->root_guid); 698 if (rv != 0) 699 return (rv); 700 if (path != NULL) 701 *path = (*end == '\0') ? end : end + 1; 702 dev->d_dev = &zfs_dev; 703 dev->d_type = zfs_dev.dv_type; 704 return (0); 705 } 706 707 char * 708 zfs_bootfs(void *zdev) 709 { 710 static char rootname[ZFS_MAXNAMELEN]; 711 static char buf[2 * ZFS_MAXNAMELEN]; 712 struct zfs_devdesc *dev = (struct zfs_devdesc *)zdev; 713 uint64_t objnum; 714 spa_t *spa; 715 vdev_t *vdev; 716 vdev_t *kid; 717 int n; 718 719 buf[0] = '\0'; 720 if (dev->d_type != DEVT_ZFS) 721 return (buf); 722 723 spa = spa_find_by_guid(dev->pool_guid); 724 if (spa == NULL) { 725 printf("ZFS: can't find pool by guid\n"); 726 return (buf); 727 } 728 if (zfs_rlookup(spa, dev->root_guid, rootname)) { 729 printf("ZFS: can't find filesystem by guid\n"); 730 return (buf); 731 } 732 if (zfs_lookup_dataset(spa, rootname, &objnum)) { 733 printf("ZFS: can't find filesystem by name\n"); 734 return (buf); 735 } 736 737 STAILQ_FOREACH(vdev, &spa->spa_vdevs, v_childlink) { 738 STAILQ_FOREACH(kid, &vdev->v_children, v_childlink) { 739 /* use this kid? */ 740 if (kid->v_state == VDEV_STATE_HEALTHY && 741 kid->v_phys_path != NULL) { 742 break; 743 } 744 } 745 if (kid != NULL) { 746 vdev = kid; 747 break; 748 } 749 if (vdev->v_state == VDEV_STATE_HEALTHY && 750 vdev->v_phys_path != NULL) { 751 break; 752 } 753 } 754 755 /* 756 * since this pool was used to read in the kernel and boot archive, 757 * there has to be at least one healthy vdev, therefore vdev 758 * can not be NULL. 759 */ 760 /* Set the environment. */ 761 snprintf(buf, sizeof (buf), "%s/%llu", spa->spa_name, 762 (unsigned long long)objnum); 763 setenv("zfs-bootfs", buf, 1); 764 if (vdev->v_phys_path != NULL) 765 setenv("bootpath", vdev->v_phys_path, 1); 766 if (vdev->v_devid != NULL) 767 setenv("diskdevid", vdev->v_devid, 1); 768 769 /* 770 * Build the command line string. Once our kernel will read 771 * the environment and we can stop caring about old kernels, 772 * we can remove this part. 773 */ 774 snprintf(buf, sizeof(buf), "zfs-bootfs=%s/%llu", spa->spa_name, 775 (unsigned long long)objnum); 776 n = strlen(buf); 777 if (vdev->v_phys_path != NULL) { 778 snprintf(buf+n, sizeof (buf) - n, ",bootpath=\"%s\"", 779 vdev->v_phys_path); 780 n = strlen(buf); 781 } 782 if (vdev->v_devid != NULL) { 783 snprintf(buf+n, sizeof (buf) - n, ",diskdevid=\"%s\"", 784 vdev->v_devid); 785 } 786 return (buf); 787 } 788 789 char * 790 zfs_fmtdev(void *vdev) 791 { 792 static char rootname[ZFS_MAXNAMELEN]; 793 static char buf[2 * ZFS_MAXNAMELEN + 8]; 794 struct zfs_devdesc *dev = (struct zfs_devdesc *)vdev; 795 spa_t *spa; 796 797 buf[0] = '\0'; 798 if (dev->d_type != DEVT_ZFS) 799 return (buf); 800 801 if (dev->pool_guid == 0) { 802 spa = STAILQ_FIRST(&zfs_pools); 803 dev->pool_guid = spa->spa_guid; 804 } else 805 spa = spa_find_by_guid(dev->pool_guid); 806 if (spa == NULL) { 807 printf("ZFS: can't find pool by guid\n"); 808 return (buf); 809 } 810 if (dev->root_guid == 0 && zfs_get_root(spa, &dev->root_guid)) { 811 printf("ZFS: can't find root filesystem\n"); 812 return (buf); 813 } 814 if (zfs_rlookup(spa, dev->root_guid, rootname)) { 815 printf("ZFS: can't find filesystem by guid\n"); 816 return (buf); 817 } 818 819 if (rootname[0] == '\0') 820 sprintf(buf, "%s:%s:", dev->d_dev->dv_name, spa->spa_name); 821 else 822 sprintf(buf, "%s:%s/%s:", dev->d_dev->dv_name, spa->spa_name, 823 rootname); 824 return (buf); 825 } 826 827 int 828 zfs_list(const char *name) 829 { 830 static char poolname[ZFS_MAXNAMELEN]; 831 uint64_t objid; 832 spa_t *spa; 833 const char *dsname; 834 int len; 835 int rv; 836 837 len = strlen(name); 838 dsname = strchr(name, '/'); 839 if (dsname != NULL) { 840 len = dsname - name; 841 dsname++; 842 } else 843 dsname = ""; 844 memcpy(poolname, name, len); 845 poolname[len] = '\0'; 846 847 spa = spa_find_by_name(poolname); 848 if (!spa) 849 return (ENXIO); 850 rv = zfs_lookup_dataset(spa, dsname, &objid); 851 if (rv != 0) 852 return (rv); 853 854 return (zfs_list_dataset(spa, objid)); 855 } 856 857 #ifdef __FreeBSD__ 858 void 859 init_zfs_bootenv(char *currdev) 860 { 861 char *beroot; 862 863 if (strlen(currdev) == 0) 864 return; 865 if(strncmp(currdev, "zfs:", 4) != 0) 866 return; 867 /* Remove the trailing : */ 868 currdev[strlen(currdev) - 1] = '\0'; 869 setenv("zfs_be_active", currdev, 1); 870 setenv("zfs_be_currpage", "1", 1); 871 /* Forward past zfs: */ 872 currdev = strchr(currdev, ':'); 873 currdev++; 874 /* Remove the last element (current bootenv) */ 875 beroot = strrchr(currdev, '/'); 876 if (beroot != NULL) 877 beroot[0] = '\0'; 878 beroot = currdev; 879 setenv("zfs_be_root", beroot, 1); 880 } 881 882 int 883 zfs_bootenv(const char *name) 884 { 885 static char poolname[ZFS_MAXNAMELEN], *dsname, *root; 886 char becount[4]; 887 uint64_t objid; 888 spa_t *spa; 889 int len, rv, pages, perpage, currpage; 890 891 if (name == NULL) 892 return (EINVAL); 893 if ((root = getenv("zfs_be_root")) == NULL) 894 return (EINVAL); 895 896 if (strcmp(name, root) != 0) { 897 if (setenv("zfs_be_root", name, 1) != 0) 898 return (ENOMEM); 899 } 900 901 SLIST_INIT(&zfs_be_head); 902 zfs_env_count = 0; 903 len = strlen(name); 904 dsname = strchr(name, '/'); 905 if (dsname != NULL) { 906 len = dsname - name; 907 dsname++; 908 } else 909 dsname = ""; 910 memcpy(poolname, name, len); 911 poolname[len] = '\0'; 912 913 spa = spa_find_by_name(poolname); 914 if (!spa) 915 return (ENXIO); 916 rv = zfs_lookup_dataset(spa, dsname, &objid); 917 if (rv != 0) 918 return (rv); 919 rv = zfs_callback_dataset(spa, objid, zfs_belist_add); 920 921 /* Calculate and store the number of pages of BEs */ 922 perpage = (ZFS_BE_LAST - ZFS_BE_FIRST + 1); 923 pages = (zfs_env_count / perpage) + ((zfs_env_count % perpage) > 0 ? 1 : 0); 924 snprintf(becount, 4, "%d", pages); 925 if (setenv("zfs_be_pages", becount, 1) != 0) 926 return (ENOMEM); 927 928 /* Roll over the page counter if it has exceeded the maximum */ 929 currpage = strtol(getenv("zfs_be_currpage"), NULL, 10); 930 if (currpage > pages) { 931 if (setenv("zfs_be_currpage", "1", 1) != 0) 932 return (ENOMEM); 933 } 934 935 /* Populate the menu environment variables */ 936 zfs_set_env(); 937 938 /* Clean up the SLIST of ZFS BEs */ 939 while (!SLIST_EMPTY(&zfs_be_head)) { 940 zfs_be = SLIST_FIRST(&zfs_be_head); 941 SLIST_REMOVE_HEAD(&zfs_be_head, entries); 942 free(zfs_be); 943 } 944 945 return (rv); 946 } 947 948 int 949 zfs_belist_add(const char *name, uint64_t value __unused) 950 { 951 952 /* Skip special datasets that start with a $ character */ 953 if (strncmp(name, "$", 1) == 0) { 954 return (0); 955 } 956 /* Add the boot environment to the head of the SLIST */ 957 zfs_be = malloc(sizeof(struct zfs_be_entry)); 958 if (zfs_be == NULL) { 959 return (ENOMEM); 960 } 961 zfs_be->name = name; 962 SLIST_INSERT_HEAD(&zfs_be_head, zfs_be, entries); 963 zfs_env_count++; 964 965 return (0); 966 } 967 968 int 969 zfs_set_env(void) 970 { 971 char envname[32], envval[256]; 972 char *beroot, *pagenum; 973 int rv, page, ctr; 974 975 beroot = getenv("zfs_be_root"); 976 if (beroot == NULL) { 977 return (1); 978 } 979 980 pagenum = getenv("zfs_be_currpage"); 981 if (pagenum != NULL) { 982 page = strtol(pagenum, NULL, 10); 983 } else { 984 page = 1; 985 } 986 987 ctr = 1; 988 rv = 0; 989 zfs_env_index = ZFS_BE_FIRST; 990 SLIST_FOREACH_SAFE(zfs_be, &zfs_be_head, entries, zfs_be_tmp) { 991 /* Skip to the requested page number */ 992 if (ctr <= ((ZFS_BE_LAST - ZFS_BE_FIRST + 1) * (page - 1))) { 993 ctr++; 994 continue; 995 } 996 997 snprintf(envname, sizeof(envname), "bootenvmenu_caption[%d]", zfs_env_index); 998 snprintf(envval, sizeof(envval), "%s", zfs_be->name); 999 rv = setenv(envname, envval, 1); 1000 if (rv != 0) { 1001 break; 1002 } 1003 1004 snprintf(envname, sizeof(envname), "bootenvansi_caption[%d]", zfs_env_index); 1005 rv = setenv(envname, envval, 1); 1006 if (rv != 0){ 1007 break; 1008 } 1009 1010 snprintf(envname, sizeof(envname), "bootenvmenu_command[%d]", zfs_env_index); 1011 rv = setenv(envname, "set_bootenv", 1); 1012 if (rv != 0){ 1013 break; 1014 } 1015 1016 snprintf(envname, sizeof(envname), "bootenv_root[%d]", zfs_env_index); 1017 snprintf(envval, sizeof(envval), "zfs:%s/%s", beroot, zfs_be->name); 1018 rv = setenv(envname, envval, 1); 1019 if (rv != 0){ 1020 break; 1021 } 1022 1023 zfs_env_index++; 1024 if (zfs_env_index > ZFS_BE_LAST) { 1025 break; 1026 } 1027 1028 } 1029 1030 for (; zfs_env_index <= ZFS_BE_LAST; zfs_env_index++) { 1031 snprintf(envname, sizeof(envname), "bootenvmenu_caption[%d]", zfs_env_index); 1032 (void)unsetenv(envname); 1033 snprintf(envname, sizeof(envname), "bootenvansi_caption[%d]", zfs_env_index); 1034 (void)unsetenv(envname); 1035 snprintf(envname, sizeof(envname), "bootenvmenu_command[%d]", zfs_env_index); 1036 (void)unsetenv(envname); 1037 snprintf(envname, sizeof(envname), "bootenv_root[%d]", zfs_env_index); 1038 (void)unsetenv(envname); 1039 } 1040 1041 return (rv); 1042 } 1043 #endif 1044