621 VERIFY(nvlist_alloc(&mirror, NV_UNIQUE_NAME, 0) == 0); |
621 VERIFY(nvlist_alloc(&mirror, NV_UNIQUE_NAME, 0) == 0); |
622 VERIFY(nvlist_add_string(mirror, ZPOOL_CONFIG_TYPE, |
622 VERIFY(nvlist_add_string(mirror, ZPOOL_CONFIG_TYPE, |
623 VDEV_TYPE_MIRROR) == 0); |
623 VDEV_TYPE_MIRROR) == 0); |
624 VERIFY(nvlist_add_nvlist_array(mirror, ZPOOL_CONFIG_CHILDREN, |
624 VERIFY(nvlist_add_nvlist_array(mirror, ZPOOL_CONFIG_CHILDREN, |
625 child, m) == 0); |
625 child, m) == 0); |
626 VERIFY(nvlist_add_uint64(mirror, ZPOOL_CONFIG_IS_LOG, log) == 0); |
|
627 |
626 |
628 for (c = 0; c < m; c++) |
627 for (c = 0; c < m; c++) |
629 nvlist_free(child[c]); |
628 nvlist_free(child[c]); |
630 |
629 |
631 umem_free(child, m * sizeof (nvlist_t *)); |
630 umem_free(child, m * sizeof (nvlist_t *)); |
642 |
641 |
643 ASSERT(t > 0); |
642 ASSERT(t > 0); |
644 |
643 |
645 child = umem_alloc(t * sizeof (nvlist_t *), UMEM_NOFAIL); |
644 child = umem_alloc(t * sizeof (nvlist_t *), UMEM_NOFAIL); |
646 |
645 |
647 for (c = 0; c < t; c++) |
646 for (c = 0; c < t; c++) { |
648 child[c] = make_vdev_mirror(path, aux, size, ashift, log, r, m); |
647 child[c] = make_vdev_mirror(path, aux, size, ashift, r, m); |
|
648 VERIFY(nvlist_add_uint64(child[c], ZPOOL_CONFIG_IS_LOG, |
|
649 log) == 0); |
|
650 } |
649 |
651 |
650 VERIFY(nvlist_alloc(&root, NV_UNIQUE_NAME, 0) == 0); |
652 VERIFY(nvlist_alloc(&root, NV_UNIQUE_NAME, 0) == 0); |
651 VERIFY(nvlist_add_string(root, ZPOOL_CONFIG_TYPE, VDEV_TYPE_ROOT) == 0); |
653 VERIFY(nvlist_add_string(root, ZPOOL_CONFIG_TYPE, VDEV_TYPE_ROOT) == 0); |
652 VERIFY(nvlist_add_nvlist_array(root, aux ? aux : ZPOOL_CONFIG_CHILDREN, |
654 VERIFY(nvlist_add_nvlist_array(root, aux ? aux : ZPOOL_CONFIG_CHILDREN, |
653 child, t) == 0); |
655 child, t) == 0); |
944 } |
964 } |
945 |
965 |
946 (void) mutex_unlock(&ztest_shared->zs_vdev_lock); |
966 (void) mutex_unlock(&ztest_shared->zs_vdev_lock); |
947 } |
967 } |
948 |
968 |
949 static vdev_t * |
|
950 vdev_lookup_by_path(vdev_t *vd, const char *path) |
|
951 { |
|
952 int c; |
|
953 vdev_t *mvd; |
|
954 |
|
955 if (vd->vdev_path != NULL) { |
|
956 if (vd->vdev_wholedisk == 1) { |
|
957 /* |
|
958 * For whole disks, the internal path has 's0', but the |
|
959 * path passed in by the user doesn't. |
|
960 */ |
|
961 if (strlen(path) == strlen(vd->vdev_path) - 2 && |
|
962 strncmp(path, vd->vdev_path, strlen(path)) == 0) |
|
963 return (vd); |
|
964 } else if (strcmp(path, vd->vdev_path) == 0) { |
|
965 return (vd); |
|
966 } |
|
967 } |
|
968 |
|
969 for (c = 0; c < vd->vdev_children; c++) |
|
970 if ((mvd = vdev_lookup_by_path(vd->vdev_child[c], path)) != |
|
971 NULL) |
|
972 return (mvd); |
|
973 |
|
974 return (NULL); |
|
975 } |
|
976 |
|
977 /* |
969 /* |
978 * Verify that we can attach and detach devices. |
970 * Verify that we can attach and detach devices. |
979 */ |
971 */ |
980 void |
972 void |
981 ztest_vdev_attach_detach(ztest_args_t *za) |
973 ztest_vdev_attach_detach(ztest_args_t *za) |
982 { |
974 { |
983 spa_t *spa = za->za_spa; |
975 spa_t *spa = za->za_spa; |
|
976 spa_aux_vdev_t *sav = &spa->spa_spares; |
984 vdev_t *rvd = spa->spa_root_vdev; |
977 vdev_t *rvd = spa->spa_root_vdev; |
985 vdev_t *oldvd, *newvd, *pvd; |
978 vdev_t *oldvd, *newvd, *pvd; |
986 nvlist_t *root; |
979 nvlist_t *root; |
987 uint64_t leaves = MAX(zopt_mirrors, 1) * zopt_raidz; |
980 uint64_t leaves = MAX(zopt_mirrors, 1) * zopt_raidz; |
988 uint64_t leaf, top; |
981 uint64_t leaf, top; |
989 uint64_t ashift = ztest_get_ashift(); |
982 uint64_t ashift = ztest_get_ashift(); |
|
983 uint64_t oldguid; |
990 size_t oldsize, newsize; |
984 size_t oldsize, newsize; |
991 char oldpath[MAXPATHLEN], newpath[MAXPATHLEN]; |
985 char oldpath[MAXPATHLEN], newpath[MAXPATHLEN]; |
992 int replacing; |
986 int replacing; |
|
987 int newvd_is_spare = B_FALSE; |
|
988 int oldvd_is_log; |
993 int error, expected_error; |
989 int error, expected_error; |
994 |
990 |
995 (void) mutex_lock(&ztest_shared->zs_vdev_lock); |
991 (void) mutex_lock(&ztest_shared->zs_vdev_lock); |
996 |
992 |
997 spa_config_enter(spa, SCL_VDEV, FTAG, RW_READER); |
993 spa_config_enter(spa, SCL_VDEV, FTAG, RW_READER); |
1010 * Pick a random leaf within it. |
1006 * Pick a random leaf within it. |
1011 */ |
1007 */ |
1012 leaf = ztest_random(leaves); |
1008 leaf = ztest_random(leaves); |
1013 |
1009 |
1014 /* |
1010 /* |
1015 * Generate the path to this leaf. The filename will end with 'a'. |
1011 * Locate this vdev. |
1016 * We'll alternate replacements with a filename that ends with 'b'. |
1012 */ |
1017 */ |
1013 oldvd = rvd->vdev_child[top]; |
1018 (void) snprintf(oldpath, sizeof (oldpath), |
1014 if (zopt_mirrors >= 1) |
1019 ztest_dev_template, zopt_dir, zopt_pool, top * leaves + leaf); |
1015 oldvd = oldvd->vdev_child[leaf / zopt_raidz]; |
1020 |
1016 if (zopt_raidz > 1) |
1021 bcopy(oldpath, newpath, MAXPATHLEN); |
1017 oldvd = oldvd->vdev_child[leaf % zopt_raidz]; |
1022 |
1018 |
1023 /* |
1019 /* |
1024 * If the 'a' file isn't part of the pool, the 'b' file must be. |
1020 * If we're already doing an attach or replace, oldvd may be a |
1025 */ |
1021 * mirror vdev -- in which case, pick a random child. |
1026 if (vdev_lookup_by_path(rvd, oldpath) == NULL) |
1022 */ |
1027 oldpath[strlen(oldpath) - 1] = 'b'; |
1023 while (oldvd->vdev_children != 0) { |
1028 else |
1024 ASSERT(oldvd->vdev_children == 2); |
1029 newpath[strlen(newpath) - 1] = 'b'; |
1025 oldvd = oldvd->vdev_child[ztest_random(2)]; |
1030 |
1026 } |
1031 /* |
1027 |
1032 * Now oldpath represents something that's already in the pool, |
1028 oldguid = oldvd->vdev_guid; |
1033 * and newpath is the thing we'll try to attach. |
1029 oldsize = vdev_get_rsize(oldvd); |
1034 */ |
1030 oldvd_is_log = oldvd->vdev_top->vdev_islog; |
1035 oldvd = vdev_lookup_by_path(rvd, oldpath); |
1031 (void) strcpy(oldpath, oldvd->vdev_path); |
1036 newvd = vdev_lookup_by_path(rvd, newpath); |
|
1037 ASSERT(oldvd != NULL); |
|
1038 pvd = oldvd->vdev_parent; |
1032 pvd = oldvd->vdev_parent; |
1039 |
1033 |
1040 /* |
1034 /* |
1041 * Make newsize a little bigger or smaller than oldsize. |
1035 * For the new vdev, choose with equal probability between the two |
1042 * If it's smaller, the attach should fail. |
1036 * standard paths (ending in either 'a' or 'b') or a random hot spare. |
1043 * If it's larger, and we're doing a replace, |
1037 */ |
1044 * we should get dynamic LUN growth when we're done. |
1038 if (sav->sav_count != 0 && ztest_random(3) == 0) { |
1045 */ |
1039 newvd = sav->sav_vdevs[ztest_random(sav->sav_count)]; |
1046 oldsize = vdev_get_rsize(oldvd); |
1040 newvd_is_spare = B_TRUE; |
1047 newsize = 10 * oldsize / (9 + ztest_random(3)); |
1041 (void) strcpy(newpath, newvd->vdev_path); |
|
1042 } else { |
|
1043 (void) snprintf(newpath, sizeof (newpath), ztest_dev_template, |
|
1044 zopt_dir, zopt_pool, top * leaves + leaf); |
|
1045 if (ztest_random(2) == 0) |
|
1046 newpath[strlen(newpath) - 1] = 'b'; |
|
1047 newvd = vdev_lookup_by_path(rvd, newpath); |
|
1048 } |
|
1049 |
|
1050 if (newvd) { |
|
1051 newsize = vdev_get_rsize(newvd); |
|
1052 } else { |
|
1053 /* |
|
1054 * Make newsize a little bigger or smaller than oldsize. |
|
1055 * If it's smaller, the attach should fail. |
|
1056 * If it's larger, and we're doing a replace, |
|
1057 * we should get dynamic LUN growth when we're done. |
|
1058 */ |
|
1059 newsize = 10 * oldsize / (9 + ztest_random(3)); |
|
1060 } |
1048 |
1061 |
1049 /* |
1062 /* |
1050 * If pvd is not a mirror or root, the attach should fail with ENOTSUP, |
1063 * If pvd is not a mirror or root, the attach should fail with ENOTSUP, |
1051 * unless it's a replace; in that case any non-replacing parent is OK. |
1064 * unless it's a replace; in that case any non-replacing parent is OK. |
1052 * |
1065 * |
1053 * If newvd is already part of the pool, it should fail with EBUSY. |
1066 * If newvd is already part of the pool, it should fail with EBUSY. |
1054 * |
1067 * |
1055 * If newvd is too small, it should fail with EOVERFLOW. |
1068 * If newvd is too small, it should fail with EOVERFLOW. |
1056 */ |
1069 */ |
1057 if (newvd != NULL) |
1070 if (pvd->vdev_ops != &vdev_mirror_ops && |
|
1071 pvd->vdev_ops != &vdev_root_ops && (!replacing || |
|
1072 pvd->vdev_ops == &vdev_replacing_ops || |
|
1073 pvd->vdev_ops == &vdev_spare_ops)) |
|
1074 expected_error = ENOTSUP; |
|
1075 else if (newvd_is_spare && (!replacing || oldvd_is_log)) |
|
1076 expected_error = ENOTSUP; |
|
1077 else if (newvd == oldvd) |
|
1078 expected_error = replacing ? 0 : EBUSY; |
|
1079 else if (vdev_lookup_by_path(rvd, newpath) != NULL) |
1058 expected_error = EBUSY; |
1080 expected_error = EBUSY; |
1059 else if (pvd->vdev_ops != &vdev_mirror_ops && |
|
1060 pvd->vdev_ops != &vdev_root_ops && |
|
1061 (!replacing || pvd->vdev_ops == &vdev_replacing_ops)) |
|
1062 expected_error = ENOTSUP; |
|
1063 else if (newsize < oldsize) |
1081 else if (newsize < oldsize) |
1064 expected_error = EOVERFLOW; |
1082 expected_error = EOVERFLOW; |
1065 else if (ashift > oldvd->vdev_top->vdev_ashift) |
1083 else if (ashift > oldvd->vdev_top->vdev_ashift) |
1066 expected_error = EDOM; |
1084 expected_error = EDOM; |
1067 else |
1085 else |