* Called once the vdevs are all opened, this routine validates the label * contents. This needs to be done before vdev_load() so that we don't * inadvertently do repair I/Os to the wrong device. * * This function will only return failure if one of the vdevs indicates that it * has since been destroyed or exported. This is only possible if * /etc/zfs/zpool.cache was readonly at the time. Ot
| 2048 | * will be updated but the function will return 0. |
| 2049 | */ |
| 2050 | int |
| 2051 | vdev_validate(vdev_t *vd) |
| 2052 | { |
| 2053 | spa_t *spa = vd->vdev_spa; |
| 2054 | nvlist_t *label; |
| 2055 | uint64_t guid = 0, aux_guid = 0, top_guid; |
| 2056 | uint64_t state; |
| 2057 | nvlist_t *nvl; |
| 2058 | uint64_t txg; |
| 2059 | |
| 2060 | if (vdev_validate_skip) |
| 2061 | return (0); |
| 2062 | |
| 2063 | for (uint64_t c = 0; c < vd->vdev_children; c++) |
| 2064 | if (vdev_validate(vd->vdev_child[c]) != 0) |
| 2065 | return (SET_ERROR(EBADF)); |
| 2066 | |
| 2067 | /* |
| 2068 | * If the device has already failed, or was marked offline, don't do |
| 2069 | * any further validation. Otherwise, label I/O will fail and we will |
| 2070 | * overwrite the previous state. |
| 2071 | */ |
| 2072 | if (!vd->vdev_ops->vdev_op_leaf || !vdev_readable(vd)) |
| 2073 | return (0); |
| 2074 | |
| 2075 | /* |
| 2076 | * If we are performing an extreme rewind, we allow for a label that |
| 2077 | * was modified at a point after the current txg. |
| 2078 | * If config lock is not held do not check for the txg. spa_sync could |
| 2079 | * be updating the vdev's label before updating spa_last_synced_txg. |
| 2080 | */ |
| 2081 | if (spa->spa_extreme_rewind || spa_last_synced_txg(spa) == 0 || |
| 2082 | spa_config_held(spa, SCL_CONFIG, RW_WRITER) != SCL_CONFIG) |
| 2083 | txg = UINT64_MAX; |
| 2084 | else |
| 2085 | txg = spa_last_synced_txg(spa); |
| 2086 | |
| 2087 | if ((label = vdev_label_read_config(vd, txg)) == NULL) { |
| 2088 | vdev_set_state(vd, B_TRUE, VDEV_STATE_CANT_OPEN, |
| 2089 | VDEV_AUX_BAD_LABEL); |
| 2090 | vdev_dbgmsg(vd, "vdev_validate: failed reading config for " |
| 2091 | "txg %llu", (u_longlong_t)txg); |
| 2092 | return (0); |
| 2093 | } |
| 2094 | |
| 2095 | /* |
| 2096 | * Determine if this vdev has been split off into another |
| 2097 | * pool. If so, then refuse to open it. |
| 2098 | */ |
| 2099 | if (nvlist_lookup_uint64(label, ZPOOL_CONFIG_SPLIT_GUID, |
| 2100 | &aux_guid) == 0 && aux_guid == spa_guid(spa)) { |
| 2101 | vdev_set_state(vd, B_FALSE, VDEV_STATE_CANT_OPEN, |
| 2102 | VDEV_AUX_SPLIT_POOL); |
| 2103 | nvlist_free(label); |
| 2104 | vdev_dbgmsg(vd, "vdev_validate: vdev split into other pool"); |
| 2105 | return (0); |
| 2106 | } |
| 2107 |
no test coverage detected