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 --- 11 unchanged lines hidden (view full) --- 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__FBSDID("$FreeBSD: head/sys/boot/zfs/zfsimpl.c 201689 2010-01-06 23:09:23Z delphij $"); |
29 30/* 31 * Stand-alone ZFS file reader. 32 */ 33 34#include "zfsimpl.h" 35#include "zfssubr.c" 36 --- 362 unchanged lines hidden (view full) --- 399 vdev->v_phys_read = 0; 400 vdev->v_read_priv = 0; 401 STAILQ_INSERT_TAIL(&zfs_vdevs, vdev, v_alllink); 402 403 return (vdev); 404} 405 406static int |
407vdev_init_from_nvlist(const unsigned char *nvlist, vdev_t **vdevp, int is_newer) |
408{ 409 int rc; 410 uint64_t guid, id, ashift, nparity; 411 const char *type; 412 const char *path; 413 vdev_t *vdev, *kid; 414 const unsigned char *kids; |
415 int nkids, i, is_new; 416 uint64_t is_offline, is_faulted, is_degraded, is_removed; |
417 418 if (nvlist_find(nvlist, ZPOOL_CONFIG_GUID, 419 DATA_TYPE_UINT64, 0, &guid) 420 || nvlist_find(nvlist, ZPOOL_CONFIG_ID, 421 DATA_TYPE_UINT64, 0, &id) 422 || nvlist_find(nvlist, ZPOOL_CONFIG_TYPE, 423 DATA_TYPE_STRING, 0, &type)) { 424 printf("ZFS: can't find vdev details\n"); 425 return (ENOENT); 426 } 427 |
428 if (strcmp(type, VDEV_TYPE_MIRROR) 429 && strcmp(type, VDEV_TYPE_DISK) 430 && strcmp(type, VDEV_TYPE_RAIDZ)) { 431 printf("ZFS: can only boot from disk, mirror or raidz vdevs\n"); 432 return (EIO); 433 } 434 |
435 is_offline = is_removed = is_faulted = is_degraded = 0; 436 437 nvlist_find(nvlist, ZPOOL_CONFIG_OFFLINE, DATA_TYPE_UINT64, 0, 438 &is_offline); 439 nvlist_find(nvlist, ZPOOL_CONFIG_REMOVED, DATA_TYPE_UINT64, 0, 440 &is_removed); 441 nvlist_find(nvlist, ZPOOL_CONFIG_FAULTED, DATA_TYPE_UINT64, 0, 442 &is_faulted); 443 nvlist_find(nvlist, ZPOOL_CONFIG_DEGRADED, DATA_TYPE_UINT64, 0, 444 &is_degraded); 445 446 vdev = vdev_find(guid); 447 if (!vdev) { 448 is_new = 1; 449 |
450 if (!strcmp(type, VDEV_TYPE_MIRROR)) 451 vdev = vdev_create(guid, vdev_mirror_read); 452 else if (!strcmp(type, VDEV_TYPE_RAIDZ)) 453 vdev = vdev_create(guid, vdev_raidz_read); 454 else 455 vdev = vdev_create(guid, vdev_disk_read); 456 457 vdev->v_id = id; --- 22 unchanged lines hidden (view full) --- 480 if (vdev->v_nparity == 1) 481 vdev->v_name = "raidz1"; 482 else 483 vdev->v_name = "raidz2"; 484 } else { 485 vdev->v_name = strdup(type); 486 } 487 } |
488 489 if (is_offline) 490 vdev->v_state = VDEV_STATE_OFFLINE; 491 else if (is_removed) 492 vdev->v_state = VDEV_STATE_REMOVED; 493 else if (is_faulted) 494 vdev->v_state = VDEV_STATE_FAULTED; 495 else if (is_degraded) 496 vdev->v_state = VDEV_STATE_DEGRADED; 497 else 498 vdev->v_state = VDEV_STATE_HEALTHY; 499 } else { 500 is_new = 0; 501 502 if (is_newer) { 503 /* 504 * We've already seen this vdev, but from an older 505 * vdev label, so let's refresh its state from the 506 * newer label. 507 */ 508 if (is_offline) 509 vdev->v_state = VDEV_STATE_OFFLINE; 510 else if (is_removed) 511 vdev->v_state = VDEV_STATE_REMOVED; 512 else if (is_faulted) 513 vdev->v_state = VDEV_STATE_FAULTED; 514 else if (is_degraded) 515 vdev->v_state = VDEV_STATE_DEGRADED; 516 else 517 vdev->v_state = VDEV_STATE_HEALTHY; 518 } 519 } 520 |
521 rc = nvlist_find(nvlist, ZPOOL_CONFIG_CHILDREN, 522 DATA_TYPE_NVLIST_ARRAY, &nkids, &kids); 523 /* 524 * Its ok if we don't have any kids. 525 */ 526 if (rc == 0) { 527 vdev->v_nchildren = nkids; 528 for (i = 0; i < nkids; i++) { |
529 rc = vdev_init_from_nvlist(kids, &kid, is_newer); |
530 if (rc) 531 return (rc); |
532 if (is_new) 533 STAILQ_INSERT_TAIL(&vdev->v_children, kid, 534 v_childlink); |
535 kids = nvlist_next(kids); 536 } 537 } else { 538 vdev->v_nchildren = 0; 539 } 540 541 if (vdevp) 542 *vdevp = vdev; --- 85 unchanged lines hidden (view full) --- 628 629static const char * 630state_name(vdev_state_t state) 631{ 632 static const char* names[] = { 633 "UNKNOWN", 634 "CLOSED", 635 "OFFLINE", |
636 "REMOVED", |
637 "CANT_OPEN", |
638 "FAULTED", |
639 "DEGRADED", 640 "ONLINE" 641 }; 642 return names[state]; 643} 644 645#ifdef BOOT2 646 --- 101 unchanged lines hidden (view full) --- 748 off_t off; 749 blkptr_t bp; 750 const unsigned char *nvlist; 751 uint64_t val; 752 uint64_t guid; 753 uint64_t pool_txg, pool_guid; 754 const char *pool_name; 755 const unsigned char *vdevs; |
756 int i, rc, is_newer; |
757 char upbuf[1024]; 758 const struct uberblock *up; 759 760 /* 761 * Load the vdev label and figure out which 762 * uberblock is most current. 763 */ 764 memset(&vtmp, 0, sizeof(vtmp)); --- 65 unchanged lines hidden (view full) --- 830 /* 831 * Create the pool if this is the first time we've seen it. 832 */ 833 spa = spa_find_by_guid(pool_guid); 834 if (!spa) { 835 spa = spa_create(pool_guid); 836 spa->spa_name = strdup(pool_name); 837 } |
838 if (pool_txg > spa->spa_txg) { |
839 spa->spa_txg = pool_txg; |
840 is_newer = 1; 841 } else 842 is_newer = 0; |
843 844 /* 845 * Get the vdev tree and create our in-core copy of it. |
846 * If we already have a vdev with this guid, this must |
847 * be some kind of alias (overlapping slices, dangerously dedicated 848 * disks etc). 849 */ 850 if (nvlist_find(nvlist, 851 ZPOOL_CONFIG_GUID, 852 DATA_TYPE_UINT64, 0, &guid)) { 853 return (EIO); 854 } 855 vdev = vdev_find(guid); |
856 if (vdev && vdev->v_phys_read) /* Has this vdev already been inited? */ |
857 return (EIO); |
858 859 if (nvlist_find(nvlist, 860 ZPOOL_CONFIG_VDEV_TREE, 861 DATA_TYPE_NVLIST, 0, &vdevs)) { 862 return (EIO); 863 } |
864 865 rc = vdev_init_from_nvlist(vdevs, &top_vdev, is_newer); |
866 if (rc) 867 return (rc); 868 869 /* 870 * Add the toplevel vdev to the pool if its not already there. 871 */ 872 STAILQ_FOREACH(pool_vdev, &spa->spa_vdevs, v_childlink) 873 if (top_vdev == pool_vdev) --- 4 unchanged lines hidden (view full) --- 878 /* 879 * We should already have created an incomplete vdev for this 880 * vdev. Find it and initialise it with our read proc. 881 */ 882 vdev = vdev_find(guid); 883 if (vdev) { 884 vdev->v_phys_read = read; 885 vdev->v_read_priv = read_priv; |
886 } else { 887 printf("ZFS: inconsistent nvlist contents\n"); 888 return (EIO); 889 } 890 891 /* 892 * Re-evaluate top-level vdev state. 893 */ --- 708 unchanged lines hidden --- |