626 objset_t *mos = dd->dd_pool->dp_meta_objset;
627 uint64_t val;
628 int err;
629
630 err = zap_lookup(mos, dd->dd_phys->dd_child_dir_zapobj,
631 strrchr(rbsa->tofs, '/') + 1, sizeof (uint64_t), 1, &val);
632
633 if (err != ENOENT)
634 return (err ? err : EEXIST);
635
636 if (rbsa->origin) {
637 /* make sure it's a snap in the same pool */
638 if (rbsa->origin->ds_dir->dd_pool != dd->dd_pool)
639 return (EXDEV);
640 if (!dsl_dataset_is_snapshot(rbsa->origin))
641 return (EINVAL);
642 if (rbsa->origin->ds_phys->ds_guid != rbsa->fromguid)
643 return (ENODEV);
644 }
645
646 return (0);
647 }
648
649 static void
650 recv_new_sync(void *arg1, void *arg2, dmu_tx_t *tx)
651 {
652 dsl_dir_t *dd = arg1;
653 struct recvbeginsyncarg *rbsa = arg2;
654 uint64_t flags = DS_FLAG_INCONSISTENT | rbsa->dsflags;
655 uint64_t dsobj;
656
657 /* Create and open new dataset. */
658 dsobj = dsl_dataset_create_sync(dd, strrchr(rbsa->tofs, '/') + 1,
659 rbsa->origin, flags, rbsa->cr, tx);
660 VERIFY(0 == dsl_dataset_own_obj(dd->dd_pool, dsobj,
661 B_TRUE, dmu_recv_tag, &rbsa->ds));
662
663 if (rbsa->origin == NULL) {
664 (void) dmu_objset_create_impl(dd->dd_pool->dp_spa,
665 rbsa->ds, &rbsa->ds->ds_phys->ds_bp, rbsa->type, tx);
708 if (err)
709 return (ENODEV);
710 if (snap->ds_phys->ds_creation_txg < birth) {
711 dsl_dataset_rele(snap, FTAG);
712 return (ENODEV);
713 }
714 if (snap->ds_phys->ds_guid == rbsa->fromguid) {
715 dsl_dataset_rele(snap, FTAG);
716 break; /* it's ok */
717 }
718 obj = snap->ds_phys->ds_prev_snap_obj;
719 dsl_dataset_rele(snap, FTAG);
720 }
721 if (obj == 0)
722 return (ENODEV);
723 }
724 } else {
725 /* if full, most recent snapshot must be $ORIGIN */
726 if (ds->ds_phys->ds_prev_snap_txg >= TXG_INITIAL)
727 return (ENODEV);
728 }
729
730 /* temporary clone name must not exist */
731 err = zap_lookup(ds->ds_dir->dd_pool->dp_meta_objset,
732 ds->ds_dir->dd_phys->dd_child_dir_zapobj,
733 rbsa->clonelastname, 8, 1, &val);
734 if (err == 0)
735 return (EEXIST);
736 if (err != ENOENT)
737 return (err);
738
739 return (0);
740 }
741
742 /* ARGSUSED */
743 static void
744 recv_existing_sync(void *arg1, void *arg2, dmu_tx_t *tx)
745 {
746 dsl_dataset_t *ohds = arg1;
747 struct recvbeginsyncarg *rbsa = arg2;
1530 */
1531 txg_wait_synced(drc->drc_real_ds->ds_dir->dd_pool, 0);
1532
1533 (void) dsl_dataset_destroy(drc->drc_real_ds, dmu_recv_tag,
1534 B_FALSE);
1535 if (drc->drc_real_ds != drc->drc_logical_ds) {
1536 mutex_exit(&drc->drc_logical_ds->ds_recvlock);
1537 dsl_dataset_rele(drc->drc_logical_ds, dmu_recv_tag);
1538 }
1539 }
1540
1541 kmem_free(ra.buf, ra.bufsize);
1542 *voffp = ra.voff;
1543 return (ra.err);
1544 }
1545
1546 struct recvendsyncarg {
1547 char *tosnap;
1548 uint64_t creation_time;
1549 uint64_t toguid;
1550 };
1551
1552 static int
1553 recv_end_check(void *arg1, void *arg2, dmu_tx_t *tx)
1554 {
1555 dsl_dataset_t *ds = arg1;
1556 struct recvendsyncarg *resa = arg2;
1557
1558 return (dsl_dataset_snapshot_check(ds, resa->tosnap, tx));
1559 }
1560
1561 static void
1562 recv_end_sync(void *arg1, void *arg2, dmu_tx_t *tx)
1563 {
1564 dsl_dataset_t *ds = arg1;
1565 struct recvendsyncarg *resa = arg2;
1566
1567 dsl_dataset_snapshot_sync(ds, resa->tosnap, tx);
1568
1569 /* set snapshot's creation time and guid */
1570 dmu_buf_will_dirty(ds->ds_prev->ds_dbuf, tx);
1571 ds->ds_prev->ds_phys->ds_creation_time = resa->creation_time;
1572 ds->ds_prev->ds_phys->ds_guid = resa->toguid;
1573 ds->ds_prev->ds_phys->ds_flags &= ~DS_FLAG_INCONSISTENT;
1574
1575 dmu_buf_will_dirty(ds->ds_dbuf, tx);
1576 ds->ds_phys->ds_flags &= ~DS_FLAG_INCONSISTENT;
1577 spa_history_log_internal_ds(ds, "finished receiving", tx, "");
1578 }
1579
1580 static int
1581 add_ds_to_guidmap(avl_tree_t *guid_map, dsl_dataset_t *ds)
1582 {
1583 dsl_pool_t *dp = ds->ds_dir->dd_pool;
1584 uint64_t snapobj = ds->ds_phys->ds_prev_snap_obj;
1585 dsl_dataset_t *snapds;
1586 guid_map_entry_t *gmep;
1607 struct recvendsyncarg resa;
1608 dsl_dataset_t *ds = drc->drc_logical_ds;
1609 int err, myerr;
1610
1611 if (dsl_dataset_tryown(ds, FALSE, dmu_recv_tag)) {
1612 err = dsl_dataset_clone_swap(drc->drc_real_ds, ds,
1613 drc->drc_force);
1614 if (err)
1615 goto out;
1616 } else {
1617 mutex_exit(&ds->ds_recvlock);
1618 dsl_dataset_rele(ds, dmu_recv_tag);
1619 (void) dsl_dataset_destroy(drc->drc_real_ds, dmu_recv_tag,
1620 B_FALSE);
1621 return (EBUSY);
1622 }
1623
1624 resa.creation_time = drc->drc_drrb->drr_creation_time;
1625 resa.toguid = drc->drc_drrb->drr_toguid;
1626 resa.tosnap = drc->drc_tosnap;
1627
1628 err = dsl_sync_task_do(ds->ds_dir->dd_pool,
1629 recv_end_check, recv_end_sync, ds, &resa, 3);
1630 if (err) {
1631 /* swap back */
1632 (void) dsl_dataset_clone_swap(drc->drc_real_ds, ds, B_TRUE);
1633 }
1634
1635 out:
1636 mutex_exit(&ds->ds_recvlock);
1637 if (err == 0 && drc->drc_guid_to_ds_map != NULL)
1638 (void) add_ds_to_guidmap(drc->drc_guid_to_ds_map, ds);
1639 dsl_dataset_disown(ds, dmu_recv_tag);
1640 myerr = dsl_dataset_destroy(drc->drc_real_ds, dmu_recv_tag, B_FALSE);
1641 ASSERT0(myerr);
1642 return (err);
1643 }
1644
1645 static int
1646 dmu_recv_new_end(dmu_recv_cookie_t *drc)
1647 {
1648 struct recvendsyncarg resa;
1649 dsl_dataset_t *ds = drc->drc_logical_ds;
1650 int err;
1651
1652 /*
1653 * XXX hack; seems the ds is still dirty and dsl_pool_zil_clean()
1654 * expects it to have a ds_user_ptr (and zil), but clone_swap()
1655 * can close it.
1656 */
1657 txg_wait_synced(ds->ds_dir->dd_pool, 0);
1658
1659 resa.creation_time = drc->drc_drrb->drr_creation_time;
1660 resa.toguid = drc->drc_drrb->drr_toguid;
1661 resa.tosnap = drc->drc_tosnap;
1662
1663 err = dsl_sync_task_do(ds->ds_dir->dd_pool,
1664 recv_end_check, recv_end_sync, ds, &resa, 3);
1665 if (err) {
1666 /* clean up the fs we just recv'd into */
1667 (void) dsl_dataset_destroy(ds, dmu_recv_tag, B_FALSE);
1668 } else {
1669 if (drc->drc_guid_to_ds_map != NULL)
1670 (void) add_ds_to_guidmap(drc->drc_guid_to_ds_map, ds);
1671 /* release the hold from dmu_recv_begin */
1672 dsl_dataset_disown(ds, dmu_recv_tag);
1673 }
1674 return (err);
1675 }
1676
1677 int
1678 dmu_recv_end(dmu_recv_cookie_t *drc)
1679 {
1680 if (drc->drc_logical_ds != drc->drc_real_ds)
1681 return (dmu_recv_existing_end(drc));
|
626 objset_t *mos = dd->dd_pool->dp_meta_objset;
627 uint64_t val;
628 int err;
629
630 err = zap_lookup(mos, dd->dd_phys->dd_child_dir_zapobj,
631 strrchr(rbsa->tofs, '/') + 1, sizeof (uint64_t), 1, &val);
632
633 if (err != ENOENT)
634 return (err ? err : EEXIST);
635
636 if (rbsa->origin) {
637 /* make sure it's a snap in the same pool */
638 if (rbsa->origin->ds_dir->dd_pool != dd->dd_pool)
639 return (EXDEV);
640 if (!dsl_dataset_is_snapshot(rbsa->origin))
641 return (EINVAL);
642 if (rbsa->origin->ds_phys->ds_guid != rbsa->fromguid)
643 return (ENODEV);
644 }
645
646 /*
647 * Check filesystem and snapshot limits before receiving. We'll recheck
648 * again at the end, but might as well abort before receiving if we're
649 * already over the limit.
650 */
651 if (dd->dd_parent != NULL) {
652 err = dsl_dir_fscount_check(dd->dd_parent, 1, NULL);
653 if (err != 0)
654 return (err);
655 }
656
657 err = dsl_snapcount_check(dd, 1, NULL);
658 if (err != 0)
659 return (err);
660
661 return (0);
662 }
663
664 static void
665 recv_new_sync(void *arg1, void *arg2, dmu_tx_t *tx)
666 {
667 dsl_dir_t *dd = arg1;
668 struct recvbeginsyncarg *rbsa = arg2;
669 uint64_t flags = DS_FLAG_INCONSISTENT | rbsa->dsflags;
670 uint64_t dsobj;
671
672 /* Create and open new dataset. */
673 dsobj = dsl_dataset_create_sync(dd, strrchr(rbsa->tofs, '/') + 1,
674 rbsa->origin, flags, rbsa->cr, tx);
675 VERIFY(0 == dsl_dataset_own_obj(dd->dd_pool, dsobj,
676 B_TRUE, dmu_recv_tag, &rbsa->ds));
677
678 if (rbsa->origin == NULL) {
679 (void) dmu_objset_create_impl(dd->dd_pool->dp_spa,
680 rbsa->ds, &rbsa->ds->ds_phys->ds_bp, rbsa->type, tx);
723 if (err)
724 return (ENODEV);
725 if (snap->ds_phys->ds_creation_txg < birth) {
726 dsl_dataset_rele(snap, FTAG);
727 return (ENODEV);
728 }
729 if (snap->ds_phys->ds_guid == rbsa->fromguid) {
730 dsl_dataset_rele(snap, FTAG);
731 break; /* it's ok */
732 }
733 obj = snap->ds_phys->ds_prev_snap_obj;
734 dsl_dataset_rele(snap, FTAG);
735 }
736 if (obj == 0)
737 return (ENODEV);
738 }
739 } else {
740 /* if full, most recent snapshot must be $ORIGIN */
741 if (ds->ds_phys->ds_prev_snap_txg >= TXG_INITIAL)
742 return (ENODEV);
743
744 /* Check snapshot limit before receiving */
745 err = dsl_snapcount_check(ds->ds_dir, 1, NULL);
746 if (err != 0)
747 return (err);
748 }
749
750 /* temporary clone name must not exist */
751 err = zap_lookup(ds->ds_dir->dd_pool->dp_meta_objset,
752 ds->ds_dir->dd_phys->dd_child_dir_zapobj,
753 rbsa->clonelastname, 8, 1, &val);
754 if (err == 0)
755 return (EEXIST);
756 if (err != ENOENT)
757 return (err);
758
759 return (0);
760 }
761
762 /* ARGSUSED */
763 static void
764 recv_existing_sync(void *arg1, void *arg2, dmu_tx_t *tx)
765 {
766 dsl_dataset_t *ohds = arg1;
767 struct recvbeginsyncarg *rbsa = arg2;
1550 */
1551 txg_wait_synced(drc->drc_real_ds->ds_dir->dd_pool, 0);
1552
1553 (void) dsl_dataset_destroy(drc->drc_real_ds, dmu_recv_tag,
1554 B_FALSE);
1555 if (drc->drc_real_ds != drc->drc_logical_ds) {
1556 mutex_exit(&drc->drc_logical_ds->ds_recvlock);
1557 dsl_dataset_rele(drc->drc_logical_ds, dmu_recv_tag);
1558 }
1559 }
1560
1561 kmem_free(ra.buf, ra.bufsize);
1562 *voffp = ra.voff;
1563 return (ra.err);
1564 }
1565
1566 struct recvendsyncarg {
1567 char *tosnap;
1568 uint64_t creation_time;
1569 uint64_t toguid;
1570 boolean_t is_new;
1571 };
1572
1573 static int
1574 recv_end_check(void *arg1, void *arg2, dmu_tx_t *tx)
1575 {
1576 dsl_dataset_t *ds = arg1;
1577 struct recvendsyncarg *resa = arg2;
1578
1579 if (resa->is_new) {
1580 /* re-check the filesystem limit now that recv is complete */
1581 dsl_dir_t *dd;
1582 int err;
1583
1584 dd = ds->ds_dir;
1585 if (dd->dd_parent != NULL) {
1586 err = dsl_dir_fscount_check(dd->dd_parent, 1, NULL);
1587 if (err != 0)
1588 return (err);
1589 }
1590 }
1591
1592 return (dsl_dataset_snapshot_check(ds, resa->tosnap, 1, tx));
1593 }
1594
1595 static void
1596 recv_end_sync(void *arg1, void *arg2, dmu_tx_t *tx)
1597 {
1598 dsl_dataset_t *ds = arg1;
1599 struct recvendsyncarg *resa = arg2;
1600
1601 if (resa->is_new)
1602 /* update the filesystem counts */
1603 dsl_dir_fscount_adjust(ds->ds_dir->dd_parent, tx, 1, B_FALSE,
1604 B_TRUE);
1605
1606 dsl_dataset_snapshot_sync(ds, resa->tosnap, tx);
1607
1608 /* set snapshot's creation time and guid */
1609 dmu_buf_will_dirty(ds->ds_prev->ds_dbuf, tx);
1610 ds->ds_prev->ds_phys->ds_creation_time = resa->creation_time;
1611 ds->ds_prev->ds_phys->ds_guid = resa->toguid;
1612 ds->ds_prev->ds_phys->ds_flags &= ~DS_FLAG_INCONSISTENT;
1613
1614 dmu_buf_will_dirty(ds->ds_dbuf, tx);
1615 ds->ds_phys->ds_flags &= ~DS_FLAG_INCONSISTENT;
1616 spa_history_log_internal_ds(ds, "finished receiving", tx, "");
1617 }
1618
1619 static int
1620 add_ds_to_guidmap(avl_tree_t *guid_map, dsl_dataset_t *ds)
1621 {
1622 dsl_pool_t *dp = ds->ds_dir->dd_pool;
1623 uint64_t snapobj = ds->ds_phys->ds_prev_snap_obj;
1624 dsl_dataset_t *snapds;
1625 guid_map_entry_t *gmep;
1646 struct recvendsyncarg resa;
1647 dsl_dataset_t *ds = drc->drc_logical_ds;
1648 int err, myerr;
1649
1650 if (dsl_dataset_tryown(ds, FALSE, dmu_recv_tag)) {
1651 err = dsl_dataset_clone_swap(drc->drc_real_ds, ds,
1652 drc->drc_force);
1653 if (err)
1654 goto out;
1655 } else {
1656 mutex_exit(&ds->ds_recvlock);
1657 dsl_dataset_rele(ds, dmu_recv_tag);
1658 (void) dsl_dataset_destroy(drc->drc_real_ds, dmu_recv_tag,
1659 B_FALSE);
1660 return (EBUSY);
1661 }
1662
1663 resa.creation_time = drc->drc_drrb->drr_creation_time;
1664 resa.toguid = drc->drc_drrb->drr_toguid;
1665 resa.tosnap = drc->drc_tosnap;
1666 resa.is_new = B_FALSE;
1667
1668 err = dsl_sync_task_do(ds->ds_dir->dd_pool,
1669 recv_end_check, recv_end_sync, ds, &resa, 3);
1670 if (err) {
1671 /* swap back */
1672 (void) dsl_dataset_clone_swap(drc->drc_real_ds, ds, B_TRUE);
1673 }
1674
1675 out:
1676 mutex_exit(&ds->ds_recvlock);
1677 if (err == 0 && drc->drc_guid_to_ds_map != NULL)
1678 (void) add_ds_to_guidmap(drc->drc_guid_to_ds_map, ds);
1679 dsl_dataset_disown(ds, dmu_recv_tag);
1680 myerr = dsl_dataset_destroy(drc->drc_real_ds, dmu_recv_tag, B_FALSE);
1681 ASSERT0(myerr);
1682 return (err);
1683 }
1684
1685 static int
1686 dmu_recv_new_end(dmu_recv_cookie_t *drc)
1687 {
1688 struct recvendsyncarg resa;
1689 dsl_dataset_t *ds = drc->drc_logical_ds;
1690 int err;
1691
1692 /*
1693 * XXX hack; seems the ds is still dirty and dsl_pool_zil_clean()
1694 * expects it to have a ds_user_ptr (and zil), but clone_swap()
1695 * can close it.
1696 */
1697 txg_wait_synced(ds->ds_dir->dd_pool, 0);
1698
1699 resa.creation_time = drc->drc_drrb->drr_creation_time;
1700 resa.toguid = drc->drc_drrb->drr_toguid;
1701 resa.tosnap = drc->drc_tosnap;
1702 resa.is_new = B_TRUE;
1703
1704 err = dsl_sync_task_do(ds->ds_dir->dd_pool,
1705 recv_end_check, recv_end_sync, ds, &resa, 3);
1706 if (err) {
1707 /* clean up the fs we just recv'd into */
1708 (void) dsl_dataset_destroy(ds, dmu_recv_tag, B_FALSE);
1709 } else {
1710 if (drc->drc_guid_to_ds_map != NULL)
1711 (void) add_ds_to_guidmap(drc->drc_guid_to_ds_map, ds);
1712 /* release the hold from dmu_recv_begin */
1713 dsl_dataset_disown(ds, dmu_recv_tag);
1714 }
1715 return (err);
1716 }
1717
1718 int
1719 dmu_recv_end(dmu_recv_cookie_t *drc)
1720 {
1721 if (drc->drc_logical_ds != drc->drc_real_ds)
1722 return (dmu_recv_existing_end(drc));
|