* Initialize a vdev label. We check to make sure each leaf device is not in * use, and writable. We put down an initial label which we will later * overwrite with a complete label. Note that it's important to do this * sequentially, not in parallel, so that we catch cases of multiple use of the * same leaf vdev in the vdev we're creating -- e.g. mirroring a disk with * itself. */
| 962 | * itself. |
| 963 | */ |
| 964 | int |
| 965 | vdev_label_init(vdev_t *vd, uint64_t crtxg, vdev_labeltype_t reason) |
| 966 | { |
| 967 | spa_t *spa = vd->vdev_spa; |
| 968 | nvlist_t *label; |
| 969 | vdev_phys_t *vp; |
| 970 | abd_t *vp_abd; |
| 971 | abd_t *bootenv; |
| 972 | uberblock_t *ub; |
| 973 | abd_t *ub_abd; |
| 974 | zio_t *zio; |
| 975 | char *buf; |
| 976 | size_t buflen; |
| 977 | int error; |
| 978 | uint64_t spare_guid = 0, l2cache_guid = 0; |
| 979 | int flags = ZIO_FLAG_CONFIG_WRITER | ZIO_FLAG_CANFAIL; |
| 980 | |
| 981 | ASSERT(spa_config_held(spa, SCL_ALL, RW_WRITER) == SCL_ALL); |
| 982 | |
| 983 | for (int c = 0; c < vd->vdev_children; c++) |
| 984 | if ((error = vdev_label_init(vd->vdev_child[c], |
| 985 | crtxg, reason)) != 0) |
| 986 | return (error); |
| 987 | |
| 988 | /* Track the creation time for this vdev */ |
| 989 | vd->vdev_crtxg = crtxg; |
| 990 | |
| 991 | if (!vd->vdev_ops->vdev_op_leaf || !spa_writeable(spa)) |
| 992 | return (0); |
| 993 | |
| 994 | /* |
| 995 | * Dead vdevs cannot be initialized. |
| 996 | */ |
| 997 | if (vdev_is_dead(vd)) |
| 998 | return (SET_ERROR(EIO)); |
| 999 | |
| 1000 | /* |
| 1001 | * Determine if the vdev is in use. |
| 1002 | */ |
| 1003 | if (reason != VDEV_LABEL_REMOVE && reason != VDEV_LABEL_SPLIT && |
| 1004 | vdev_inuse(vd, crtxg, reason, &spare_guid, &l2cache_guid)) |
| 1005 | return (SET_ERROR(EBUSY)); |
| 1006 | |
| 1007 | /* |
| 1008 | * If this is a request to add or replace a spare or l2cache device |
| 1009 | * that is in use elsewhere on the system, then we must update the |
| 1010 | * guid (which was initialized to a random value) to reflect the |
| 1011 | * actual GUID (which is shared between multiple pools). |
| 1012 | */ |
| 1013 | if (reason != VDEV_LABEL_REMOVE && reason != VDEV_LABEL_L2CACHE && |
| 1014 | spare_guid != 0ULL) { |
| 1015 | uint64_t guid_delta = spare_guid - vd->vdev_guid; |
| 1016 | |
| 1017 | vd->vdev_guid += guid_delta; |
| 1018 | |
| 1019 | for (vdev_t *pvd = vd; pvd != NULL; pvd = pvd->vdev_parent) |
| 1020 | pvd->vdev_guid_sum += guid_delta; |
| 1021 |
no test coverage detected