* Returns the configuration from the label of the given vdev. For vdevs * which don't have a txg value stored on their label (i.e. spares/cache) * or have not been completely initialized (txg = 0) just return * the configuration from the first valid label we find. Otherwise, * find the most up-to-date label that does not exceed the specified * 'txg' value. */
| 750 | * 'txg' value. |
| 751 | */ |
| 752 | nvlist_t * |
| 753 | vdev_label_read_config(vdev_t *vd, uint64_t txg) |
| 754 | { |
| 755 | spa_t *spa = vd->vdev_spa; |
| 756 | nvlist_t *config = NULL; |
| 757 | vdev_phys_t *vp; |
| 758 | abd_t *vp_abd; |
| 759 | zio_t *zio; |
| 760 | uint64_t best_txg = 0; |
| 761 | uint64_t label_txg = 0; |
| 762 | int error = 0; |
| 763 | int flags = ZIO_FLAG_CONFIG_WRITER | ZIO_FLAG_CANFAIL | |
| 764 | ZIO_FLAG_SPECULATIVE; |
| 765 | |
| 766 | ASSERT(spa_config_held(spa, SCL_STATE_ALL, RW_WRITER) == SCL_STATE_ALL); |
| 767 | |
| 768 | if (!vdev_readable(vd)) |
| 769 | return (NULL); |
| 770 | |
| 771 | /* |
| 772 | * The label for a dRAID distributed spare is not stored on disk. |
| 773 | * Instead it is generated when needed which allows us to bypass |
| 774 | * the pipeline when reading the config from the label. |
| 775 | */ |
| 776 | if (vd->vdev_ops == &vdev_draid_spare_ops) |
| 777 | return (vdev_draid_read_config_spare(vd)); |
| 778 | |
| 779 | vp_abd = abd_alloc_linear(sizeof (vdev_phys_t), B_TRUE); |
| 780 | vp = abd_to_buf(vp_abd); |
| 781 | |
| 782 | retry: |
| 783 | for (int l = 0; l < VDEV_LABELS; l++) { |
| 784 | nvlist_t *label = NULL; |
| 785 | |
| 786 | zio = zio_root(spa, NULL, NULL, flags); |
| 787 | |
| 788 | vdev_label_read(zio, vd, l, vp_abd, |
| 789 | offsetof(vdev_label_t, vl_vdev_phys), |
| 790 | sizeof (vdev_phys_t), NULL, NULL, flags); |
| 791 | |
| 792 | if (zio_wait(zio) == 0 && |
| 793 | nvlist_unpack(vp->vp_nvlist, sizeof (vp->vp_nvlist), |
| 794 | &label, 0) == 0) { |
| 795 | /* |
| 796 | * Auxiliary vdevs won't have txg values in their |
| 797 | * labels and newly added vdevs may not have been |
| 798 | * completely initialized so just return the |
| 799 | * configuration from the first valid label we |
| 800 | * encounter. |
| 801 | */ |
| 802 | error = nvlist_lookup_uint64(label, |
| 803 | ZPOOL_CONFIG_POOL_TXG, &label_txg); |
| 804 | if ((error || label_txg == 0) && !config) { |
| 805 | config = label; |
| 806 | break; |
| 807 | } else if (label_txg <= txg && label_txg > best_txg) { |
| 808 | best_txg = label_txg; |
| 809 | nvlist_free(config); |
no test coverage detected