961 static int |
961 static int |
962 zfs_ioc_vdev_add(zfs_cmd_t *zc) |
962 zfs_ioc_vdev_add(zfs_cmd_t *zc) |
963 { |
963 { |
964 spa_t *spa; |
964 spa_t *spa; |
965 int error; |
965 int error; |
966 nvlist_t *config; |
966 nvlist_t *config, **l2cache; |
|
967 uint_t nl2cache; |
967 |
968 |
968 error = spa_open(zc->zc_name, &spa, FTAG); |
969 error = spa_open(zc->zc_name, &spa, FTAG); |
969 if (error != 0) |
970 if (error != 0) |
970 return (error); |
971 return (error); |
|
972 |
|
973 error = get_nvlist(zc->zc_nvlist_conf, zc->zc_nvlist_conf_size, |
|
974 &config); |
|
975 (void) nvlist_lookup_nvlist_array(config, ZPOOL_CONFIG_L2CACHE, |
|
976 &l2cache, &nl2cache); |
971 |
977 |
972 /* |
978 /* |
973 * A root pool with concatenated devices is not supported. |
979 * A root pool with concatenated devices is not supported. |
974 * Thus, can not add a device to a root pool with one device. |
980 * Thus, can not add a device to a root pool with one device. |
|
981 * Allow for l2cache devices to be added. |
975 */ |
982 */ |
976 if (spa->spa_root_vdev->vdev_children == 1 && spa->spa_bootfs != 0) { |
983 if (spa->spa_root_vdev->vdev_children == 1 && spa->spa_bootfs != 0 && |
|
984 nl2cache == 0) { |
977 spa_close(spa, FTAG); |
985 spa_close(spa, FTAG); |
978 return (EDOM); |
986 return (EDOM); |
979 } |
987 } |
980 |
988 |
981 if ((error = get_nvlist(zc->zc_nvlist_conf, zc->zc_nvlist_conf_size, |
989 if (error == 0) { |
982 &config)) == 0) { |
|
983 error = spa_vdev_add(spa, config); |
990 error = spa_vdev_add(spa, config); |
984 nvlist_free(config); |
991 nvlist_free(config); |
985 } |
992 } |
986 spa_close(spa, FTAG); |
993 spa_close(spa, FTAG); |
987 return (error); |
994 return (error); |
2571 txg = spa_vdev_enter(spa); |
2578 txg = spa_vdev_enter(spa); |
2572 |
2579 |
2573 if (zc->zc_guid == 0) { |
2580 if (zc->zc_guid == 0) { |
2574 vd = NULL; |
2581 vd = NULL; |
2575 } else if ((vd = spa_lookup_by_guid(spa, zc->zc_guid)) == NULL) { |
2582 } else if ((vd = spa_lookup_by_guid(spa, zc->zc_guid)) == NULL) { |
2576 (void) spa_vdev_exit(spa, NULL, txg, ENODEV); |
2583 spa_aux_vdev_t *sav; |
2577 spa_close(spa, FTAG); |
2584 int i; |
2578 return (ENODEV); |
2585 |
|
2586 /* |
|
2587 * Check if this is an l2cache device. |
|
2588 */ |
|
2589 ASSERT(spa != NULL); |
|
2590 sav = &spa->spa_l2cache; |
|
2591 for (i = 0; i < sav->sav_count; i++) { |
|
2592 if (sav->sav_vdevs[i]->vdev_guid == zc->zc_guid) { |
|
2593 vd = sav->sav_vdevs[i]; |
|
2594 break; |
|
2595 } |
|
2596 } |
|
2597 |
|
2598 if (vd == NULL) { |
|
2599 (void) spa_vdev_exit(spa, NULL, txg, ENODEV); |
|
2600 spa_close(spa, FTAG); |
|
2601 return (ENODEV); |
|
2602 } |
2579 } |
2603 } |
2580 |
2604 |
2581 vdev_clear(spa, vd, B_TRUE); |
2605 vdev_clear(spa, vd, B_TRUE); |
2582 |
2606 |
2583 (void) spa_vdev_exit(spa, NULL, txg, 0); |
2607 (void) spa_vdev_exit(spa, NULL, txg, 0); |