383 |
381 |
384 if (altroot != NULL && altroot[0] != '/') |
382 if (altroot != NULL && altroot[0] != '/') |
385 return (zfs_error(hdl, EZFS_BADPATH, |
383 return (zfs_error(hdl, EZFS_BADPATH, |
386 dgettext(TEXT_DOMAIN, "bad alternate root '%s'"), altroot)); |
384 dgettext(TEXT_DOMAIN, "bad alternate root '%s'"), altroot)); |
387 |
385 |
388 if (nvlist_size(nvroot, &len, NV_ENCODE_NATIVE) != 0) |
386 if (zcmd_write_src_nvlist(hdl, &zc, nvroot, NULL) != 0) |
389 return (no_memory(hdl)); |
|
390 |
|
391 if ((packed = zfs_alloc(hdl, len)) == NULL) |
|
392 return (-1); |
387 return (-1); |
393 |
388 |
394 if (nvlist_pack(nvroot, &packed, &len, |
|
395 NV_ENCODE_NATIVE, 0) != 0) { |
|
396 free(packed); |
|
397 return (no_memory(hdl)); |
|
398 } |
|
399 |
|
400 (void) strlcpy(zc.zc_name, pool, sizeof (zc.zc_name)); |
389 (void) strlcpy(zc.zc_name, pool, sizeof (zc.zc_name)); |
401 zc.zc_config_src = (uint64_t)(uintptr_t)packed; |
|
402 zc.zc_config_src_size = len; |
|
403 |
390 |
404 if (altroot != NULL) |
391 if (altroot != NULL) |
405 (void) strlcpy(zc.zc_root, altroot, sizeof (zc.zc_root)); |
392 (void) strlcpy(zc.zc_value, altroot, sizeof (zc.zc_value)); |
406 |
393 |
407 if (ioctl(hdl->libzfs_fd, ZFS_IOC_POOL_CREATE, &zc) != 0) { |
394 if (ioctl(hdl->libzfs_fd, ZFS_IOC_POOL_CREATE, &zc) != 0) { |
408 free(packed); |
395 zcmd_free_nvlists(&zc); |
409 |
396 |
410 switch (errno) { |
397 switch (errno) { |
411 case EBUSY: |
398 case EBUSY: |
412 /* |
399 /* |
413 * This can happen if the user has specified the same |
400 * This can happen if the user has specified the same |
445 default: |
432 default: |
446 return (zpool_standard_error(hdl, errno, msg)); |
433 return (zpool_standard_error(hdl, errno, msg)); |
447 } |
434 } |
448 } |
435 } |
449 |
436 |
450 free(packed); |
437 zcmd_free_nvlists(&zc); |
451 |
438 |
452 /* |
439 /* |
453 * If this is an alternate root pool, then we automatically set the |
440 * If this is an alternate root pool, then we automatically set the |
454 * moutnpoint of the root dataset to be '/'. |
441 * mountpoint of the root dataset to be '/'. |
455 */ |
442 */ |
456 if (altroot != NULL) { |
443 if (altroot != NULL) { |
457 zfs_handle_t *zhp; |
444 zfs_handle_t *zhp; |
458 |
445 |
459 verify((zhp = zfs_open(hdl, pool, ZFS_TYPE_ANY)) != NULL); |
446 verify((zhp = zfs_open(hdl, pool, ZFS_TYPE_ANY)) != NULL); |
460 verify(zfs_prop_set(zhp, ZFS_PROP_MOUNTPOINT, "/") == 0); |
447 verify(zfs_prop_set(zhp, zfs_prop_to_name(ZFS_PROP_MOUNTPOINT), |
|
448 "/") == 0); |
461 |
449 |
462 zfs_close(zhp); |
450 zfs_close(zhp); |
463 } |
451 } |
464 |
452 |
465 return (0); |
453 return (0); |
537 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "pool must be " |
523 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "pool must be " |
538 "upgraded to add hot spares")); |
524 "upgraded to add hot spares")); |
539 return (zfs_error(hdl, EZFS_BADVERSION, msg)); |
525 return (zfs_error(hdl, EZFS_BADVERSION, msg)); |
540 } |
526 } |
541 |
527 |
542 verify(nvlist_size(nvroot, &len, NV_ENCODE_NATIVE) == 0); |
528 if (zcmd_write_src_nvlist(hdl, &zc, nvroot, NULL) != 0) |
543 |
|
544 if ((packed = zfs_alloc(zhp->zpool_hdl, len)) == NULL) |
|
545 return (-1); |
529 return (-1); |
546 |
|
547 verify(nvlist_pack(nvroot, &packed, &len, NV_ENCODE_NATIVE, 0) == 0); |
|
548 |
|
549 (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); |
530 (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); |
550 zc.zc_config_src = (uint64_t)(uintptr_t)packed; |
|
551 zc.zc_config_src_size = len; |
|
552 |
531 |
553 if (ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_VDEV_ADD, &zc) != 0) { |
532 if (ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_VDEV_ADD, &zc) != 0) { |
554 switch (errno) { |
533 switch (errno) { |
555 case EBUSY: |
534 case EBUSY: |
556 /* |
535 /* |
661 altroot)); |
638 altroot)); |
662 |
639 |
663 (void) strlcpy(zc.zc_name, thename, sizeof (zc.zc_name)); |
640 (void) strlcpy(zc.zc_name, thename, sizeof (zc.zc_name)); |
664 |
641 |
665 if (altroot != NULL) |
642 if (altroot != NULL) |
666 (void) strlcpy(zc.zc_root, altroot, sizeof (zc.zc_root)); |
643 (void) strlcpy(zc.zc_value, altroot, sizeof (zc.zc_value)); |
667 else |
644 else |
668 zc.zc_root[0] = '\0'; |
645 zc.zc_value[0] = '\0'; |
669 |
646 |
670 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID, |
647 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID, |
671 &zc.zc_guid) == 0); |
648 &zc.zc_guid) == 0); |
672 |
649 |
673 verify(nvlist_size(config, &len, NV_ENCODE_NATIVE) == 0); |
650 if (zcmd_write_src_nvlist(hdl, &zc, config, NULL) != 0) |
674 |
|
675 if ((packed = zfs_alloc(hdl, len)) == NULL) |
|
676 return (-1); |
651 return (-1); |
677 |
|
678 verify(nvlist_pack(config, &packed, &len, NV_ENCODE_NATIVE, 0) == 0); |
|
679 |
|
680 zc.zc_config_src = (uint64_t)(uintptr_t)packed; |
|
681 zc.zc_config_src_size = len; |
|
682 |
652 |
683 ret = 0; |
653 ret = 0; |
684 if (ioctl(hdl->libzfs_fd, ZFS_IOC_POOL_IMPORT, &zc) != 0) { |
654 if (ioctl(hdl->libzfs_fd, ZFS_IOC_POOL_IMPORT, &zc) != 0) { |
685 char desc[1024]; |
655 char desc[1024]; |
686 if (newname == NULL) |
656 if (newname == NULL) |
1043 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, |
1011 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, |
1044 "device has already been replaced with a spare")); |
1012 "device has already been replaced with a spare")); |
1045 return (zfs_error(hdl, EZFS_BADTARGET, msg)); |
1013 return (zfs_error(hdl, EZFS_BADTARGET, msg)); |
1046 } |
1014 } |
1047 |
1015 |
1048 verify(nvlist_size(nvroot, &len, NV_ENCODE_NATIVE) == 0); |
1016 if (zcmd_write_src_nvlist(hdl, &zc, nvroot, NULL) != 0) |
1049 |
|
1050 if ((packed = zfs_alloc(zhp->zpool_hdl, len)) == NULL) |
|
1051 return (-1); |
1017 return (-1); |
1052 |
1018 |
1053 verify(nvlist_pack(nvroot, &packed, &len, NV_ENCODE_NATIVE, 0) == 0); |
|
1054 |
|
1055 zc.zc_config_src = (uint64_t)(uintptr_t)packed; |
|
1056 zc.zc_config_src_size = len; |
|
1057 |
|
1058 ret = ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_VDEV_ATTACH, &zc); |
1019 ret = ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_VDEV_ATTACH, &zc); |
1059 |
1020 |
1060 free(packed); |
1021 zcmd_free_nvlists(&zc); |
1061 |
1022 |
1062 if (ret == 0) |
1023 if (ret == 0) |
1063 return (0); |
1024 return (0); |
1064 |
1025 |
1065 switch (errno) { |
1026 switch (errno) { |
1382 set_path(zpool_handle_t *zhp, nvlist_t *nv, const char *path) |
1343 set_path(zpool_handle_t *zhp, nvlist_t *nv, const char *path) |
1383 { |
1344 { |
1384 zfs_cmd_t zc = { 0 }; |
1345 zfs_cmd_t zc = { 0 }; |
1385 |
1346 |
1386 (void) strncpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); |
1347 (void) strncpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); |
1387 (void) strncpy(zc.zc_prop_value, path, sizeof (zc.zc_prop_value)); |
1348 (void) strncpy(zc.zc_value, path, sizeof (zc.zc_value)); |
1388 verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID, |
1349 verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID, |
1389 &zc.zc_guid) == 0); |
1350 &zc.zc_guid) == 0); |
1390 |
1351 |
1391 (void) ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_VDEV_SETPATH, &zc); |
1352 (void) ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_VDEV_SETPATH, &zc); |
1392 } |
1353 } |
1508 * has increased, allocate more space and continue until we get the |
1470 * has increased, allocate more space and continue until we get the |
1509 * entire list. |
1471 * entire list. |
1510 */ |
1472 */ |
1511 verify(nvlist_lookup_uint64(zhp->zpool_config, ZPOOL_CONFIG_ERRCOUNT, |
1473 verify(nvlist_lookup_uint64(zhp->zpool_config, ZPOOL_CONFIG_ERRCOUNT, |
1512 &count) == 0); |
1474 &count) == 0); |
1513 if ((zc.zc_config_dst = (uintptr_t)zfs_alloc(zhp->zpool_hdl, |
1475 if ((zc.zc_nvlist_dst = (uintptr_t)zfs_alloc(zhp->zpool_hdl, |
1514 count * sizeof (zbookmark_t))) == NULL) |
1476 count * sizeof (zbookmark_t))) == NULL) |
1515 return (-1); |
1477 return (-1); |
1516 zc.zc_config_dst_size = count; |
1478 zc.zc_nvlist_dst_size = count; |
1517 (void) strcpy(zc.zc_name, zhp->zpool_name); |
1479 (void) strcpy(zc.zc_name, zhp->zpool_name); |
1518 for (;;) { |
1480 for (;;) { |
1519 if (ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_ERROR_LOG, |
1481 if (ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_ERROR_LOG, |
1520 &zc) != 0) { |
1482 &zc) != 0) { |
1521 free((void *)(uintptr_t)zc.zc_config_dst); |
1483 free((void *)(uintptr_t)zc.zc_nvlist_dst); |
1522 if (errno == ENOMEM) { |
1484 if (errno == ENOMEM) { |
1523 if ((zc.zc_config_dst = (uintptr_t) |
1485 if ((zc.zc_nvlist_dst = (uintptr_t) |
1524 zfs_alloc(zhp->zpool_hdl, |
1486 zfs_alloc(zhp->zpool_hdl, |
1525 zc.zc_config_dst_size)) == NULL) |
1487 zc.zc_nvlist_dst_size)) == NULL) |
1526 return (-1); |
1488 return (-1); |
1527 } else { |
1489 } else { |
1528 return (-1); |
1490 return (-1); |
1529 } |
1491 } |
1530 } else { |
1492 } else { |
1533 } |
1495 } |
1534 |
1496 |
1535 /* |
1497 /* |
1536 * Sort the resulting bookmarks. This is a little confusing due to the |
1498 * Sort the resulting bookmarks. This is a little confusing due to the |
1537 * implementation of ZFS_IOC_ERROR_LOG. The bookmarks are copied last |
1499 * implementation of ZFS_IOC_ERROR_LOG. The bookmarks are copied last |
1538 * to first, and 'zc_config_dst_size' indicates the number of boomarks |
1500 * to first, and 'zc_nvlist_dst_size' indicates the number of boomarks |
1539 * _not_ copied as part of the process. So we point the start of our |
1501 * _not_ copied as part of the process. So we point the start of our |
1540 * array appropriate and decrement the total number of elements. |
1502 * array appropriate and decrement the total number of elements. |
1541 */ |
1503 */ |
1542 zb = ((zbookmark_t *)(uintptr_t)zc.zc_config_dst) + |
1504 zb = ((zbookmark_t *)(uintptr_t)zc.zc_nvlist_dst) + |
1543 zc.zc_config_dst_size; |
1505 zc.zc_nvlist_dst_size; |
1544 count -= zc.zc_config_dst_size; |
1506 count -= zc.zc_nvlist_dst_size; |
|
1507 zc.zc_nvlist_dst = 0ULL; |
1545 |
1508 |
1546 qsort(zb, count, sizeof (zbookmark_t), zbookmark_compare); |
1509 qsort(zb, count, sizeof (zbookmark_t), zbookmark_compare); |
1547 |
1510 |
1548 /* |
1511 /* |
1549 * Count the number of unique elements |
1512 * Count the number of unique elements |
1560 * If the user has only requested the number of items, return it now |
1523 * If the user has only requested the number of items, return it now |
1561 * without bothering with the extra work. |
1524 * without bothering with the extra work. |
1562 */ |
1525 */ |
1563 if (list == NULL) { |
1526 if (list == NULL) { |
1564 *nelem = j; |
1527 *nelem = j; |
1565 free((void *)(uintptr_t)zc.zc_config_dst); |
1528 free((void *)(uintptr_t)zc.zc_nvlist_dst); |
1566 return (0); |
1529 return (0); |
1567 } |
1530 } |
1568 |
1531 |
1569 zhp->zpool_error_count = j; |
1532 zhp->zpool_error_count = j; |
1570 |
1533 |
1571 /* |
1534 /* |
1572 * Allocate an array of nvlists to hold the results |
1535 * Allocate an array of nvlists to hold the results |
1573 */ |
1536 */ |
1574 if ((zhp->zpool_error_log = zfs_alloc(zhp->zpool_hdl, |
1537 if ((zhp->zpool_error_log = zfs_alloc(zhp->zpool_hdl, |
1575 j * sizeof (nvlist_t *))) == NULL) { |
1538 j * sizeof (nvlist_t *))) == NULL) { |
1576 free((void *)(uintptr_t)zc.zc_config_dst); |
1539 free((void *)(uintptr_t)zc.zc_nvlist_dst); |
1577 return (-1); |
1540 return (-1); |
1578 } |
1541 } |
1579 |
1542 |
1580 /* |
1543 /* |
1581 * Fill in the results with names from the kernel. |
1544 * Fill in the results with names from the kernel. |
1587 |
1550 |
1588 if (i > 0 && memcmp(&zb[i - 1], &zb[i], |
1551 if (i > 0 && memcmp(&zb[i - 1], &zb[i], |
1589 sizeof (zbookmark_t)) == 0) |
1552 sizeof (zbookmark_t)) == 0) |
1590 continue; |
1553 continue; |
1591 |
1554 |
1592 if (nvlist_alloc(&nv, NV_UNIQUE_NAME, |
1555 if (zcmd_alloc_dst_nvlist(hdl, &zc, 0) != 0) |
1593 0) != 0) |
|
1594 goto nomem; |
1556 goto nomem; |
1595 zhp->zpool_error_log[j] = nv; |
|
1596 |
1557 |
1597 zc.zc_bookmark = zb[i]; |
1558 zc.zc_bookmark = zb[i]; |
1598 if (ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_BOOKMARK_NAME, |
1559 for (;;) { |
1599 &zc) == 0) { |
1560 if (ioctl(zhp->zpool_hdl->libzfs_fd, |
1600 if (nvlist_add_string(nv, ZPOOL_ERR_DATASET, |
1561 ZFS_IOC_BOOKMARK_NAME, &zc) != 0) { |
1601 zc.zc_prop_name) != 0 || |
1562 if (errno == ENOMEM) { |
1602 nvlist_add_string(nv, ZPOOL_ERR_OBJECT, |
1563 if (zcmd_expand_dst_nvlist(hdl, &zc) |
1603 zc.zc_prop_value) != 0 || |
1564 != 0) { |
1604 nvlist_add_string(nv, ZPOOL_ERR_RANGE, |
1565 zcmd_free_nvlists(&zc); |
1605 zc.zc_filename) != 0) |
1566 goto nomem; |
1606 goto nomem; |
1567 } |
1607 } else { |
1568 |
1608 (void) snprintf(buf, sizeof (buf), "%llx", |
1569 continue; |
1609 zb[i].zb_objset); |
1570 } else { |
1610 if (nvlist_add_string(nv, |
1571 if (nvlist_alloc(&nv, NV_UNIQUE_NAME, |
1611 ZPOOL_ERR_DATASET, buf) != 0) |
1572 0) != 0) |
1612 goto nomem; |
1573 goto nomem; |
1613 (void) snprintf(buf, sizeof (buf), "%llx", |
1574 |
1614 zb[i].zb_object); |
1575 zhp->zpool_error_log[j] = nv; |
1615 if (nvlist_add_string(nv, ZPOOL_ERR_OBJECT, |
1576 (void) snprintf(buf, sizeof (buf), |
1616 buf) != 0) |
1577 "%llx", zb[i].zb_objset); |
1617 goto nomem; |
1578 if (nvlist_add_string(nv, |
1618 (void) snprintf(buf, sizeof (buf), "lvl=%u blkid=%llu", |
1579 ZPOOL_ERR_DATASET, buf) != 0) |
1619 (int)zb[i].zb_level, (long long)zb[i].zb_blkid); |
1580 goto nomem; |
1620 if (nvlist_add_string(nv, ZPOOL_ERR_RANGE, |
1581 (void) snprintf(buf, sizeof (buf), |
1621 buf) != 0) |
1582 "%llx", zb[i].zb_object); |
1622 goto nomem; |
1583 if (nvlist_add_string(nv, |
|
1584 ZPOOL_ERR_OBJECT, buf) != 0) |
|
1585 goto nomem; |
|
1586 (void) snprintf(buf, sizeof (buf), |
|
1587 "lvl=%u blkid=%llu", |
|
1588 (int)zb[i].zb_level, |
|
1589 (long long)zb[i].zb_blkid); |
|
1590 if (nvlist_add_string(nv, |
|
1591 ZPOOL_ERR_RANGE, buf) != 0) |
|
1592 goto nomem; |
|
1593 } |
|
1594 } else { |
|
1595 if (zcmd_read_dst_nvlist(hdl, &zc, |
|
1596 &zhp->zpool_error_log[j]) != 0) { |
|
1597 zcmd_free_nvlists(&zc); |
|
1598 goto nomem; |
|
1599 } |
|
1600 } |
|
1601 |
|
1602 break; |
1623 } |
1603 } |
|
1604 |
|
1605 zcmd_free_nvlists(&zc); |
1624 |
1606 |
1625 j++; |
1607 j++; |
1626 } |
1608 } |
1627 |
1609 |
1628 *list = zhp->zpool_error_log; |
1610 *list = zhp->zpool_error_log; |
1629 *nelem = zhp->zpool_error_count; |
1611 *nelem = zhp->zpool_error_count; |
1630 |
1612 free(zb); |
1631 free((void *)(uintptr_t)zc.zc_config_dst); |
|
1632 |
1613 |
1633 return (0); |
1614 return (0); |
1634 |
1615 |
1635 nomem: |
1616 nomem: |
1636 free((void *)(uintptr_t)zc.zc_config_dst); |
1617 free(zb); |
1637 for (i = 0; i < zhp->zpool_error_count; i++) { |
1618 free((void *)(uintptr_t)zc.zc_nvlist_dst); |
1638 if (zhp->zpool_error_log[i]) |
1619 for (i = 0; i < zhp->zpool_error_count; i++) |
1639 free(zhp->zpool_error_log[i]); |
1620 nvlist_free(zhp->zpool_error_log[i]); |
1640 } |
|
1641 free(zhp->zpool_error_log); |
1621 free(zhp->zpool_error_log); |
1642 zhp->zpool_error_log = NULL; |
1622 zhp->zpool_error_log = NULL; |
1643 return (no_memory(zhp->zpool_hdl)); |
1623 return (no_memory(zhp->zpool_hdl)); |
1644 } |
1624 } |
1645 |
1625 |