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);
666 }
667
668 spa_history_log_internal_ds(rbsa->ds, "receive new", tx, "");
669 }
670
671 /* ARGSUSED */
672 static int
673 recv_existing_check(void *arg1, void *arg2, dmu_tx_t *tx)
674 {
675 dsl_dataset_t *ds = arg1;
676 struct recvbeginsyncarg *rbsa = arg2;
677 int err;
678 uint64_t val;
679
680 /* must not have any changes since most recent snapshot */
681 if (!rbsa->force && dsl_dataset_modified_since_lastsnap(ds))
682 return (ETXTBSY);
683
684 /* new snapshot name must not exist */
685 err = zap_lookup(ds->ds_dir->dd_pool->dp_meta_objset,
686 ds->ds_phys->ds_snapnames_zapobj, rbsa->tosnap, 8, 1, &val);
687 if (err == 0)
688 return (EEXIST);
689 if (err != ENOENT)
690 return (err);
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 err = dsl_dir_fscount_check(dd, 1, NULL, rbsa->cr);
652 if (err != 0)
653 return (err);
654
655 err = dsl_snapcount_check(dd, 1, NULL, rbsa->cr);
656 if (err != 0)
657 return (err);
658
659 return (0);
660 }
661
662 static void
663 recv_new_sync(void *arg1, void *arg2, dmu_tx_t *tx)
664 {
665 dsl_dir_t *dd = arg1;
666 struct recvbeginsyncarg *rbsa = arg2;
667 uint64_t flags = DS_FLAG_INCONSISTENT | rbsa->dsflags;
668 uint64_t dsobj;
669
670 /* Create and open new dataset. */
671 dsobj = dsl_dataset_create_sync(dd, strrchr(rbsa->tofs, '/') + 1,
672 rbsa->origin, flags, rbsa->cr, tx);
673 VERIFY(0 == dsl_dataset_own_obj(dd->dd_pool, dsobj,
674 B_TRUE, dmu_recv_tag, &rbsa->ds));
675
676 if (rbsa->origin == NULL) {
677 (void) dmu_objset_create_impl(dd->dd_pool->dp_spa,
678 rbsa->ds, &rbsa->ds->ds_phys->ds_bp, rbsa->type, tx);
679 }
680
681 spa_history_log_internal_ds(rbsa->ds, "receive new", tx, "");
682 }
683
684 /*
685 * Note that we do not check the file system limit with dsl_dir_fscount_check
686 * because the temporary %clones don't count against that limit.
687 */
688 /* ARGSUSED */
689 static int
690 recv_existing_check(void *arg1, void *arg2, dmu_tx_t *tx)
691 {
692 dsl_dataset_t *ds = arg1;
693 struct recvbeginsyncarg *rbsa = arg2;
694 int err;
695 uint64_t val;
696
697 /* must not have any changes since most recent snapshot */
698 if (!rbsa->force && dsl_dataset_modified_since_lastsnap(ds))
699 return (ETXTBSY);
700
701 /* new snapshot name must not exist */
702 err = zap_lookup(ds->ds_dir->dd_pool->dp_meta_objset,
703 ds->ds_phys->ds_snapnames_zapobj, rbsa->tosnap, 8, 1, &val);
704 if (err == 0)
705 return (EEXIST);
706 if (err != ENOENT)
707 return (err);
725 if (err)
726 return (ENODEV);
727 if (snap->ds_phys->ds_creation_txg < birth) {
728 dsl_dataset_rele(snap, FTAG);
729 return (ENODEV);
730 }
731 if (snap->ds_phys->ds_guid == rbsa->fromguid) {
732 dsl_dataset_rele(snap, FTAG);
733 break; /* it's ok */
734 }
735 obj = snap->ds_phys->ds_prev_snap_obj;
736 dsl_dataset_rele(snap, FTAG);
737 }
738 if (obj == 0)
739 return (ENODEV);
740 }
741 } else {
742 /* if full, most recent snapshot must be $ORIGIN */
743 if (ds->ds_phys->ds_prev_snap_txg >= TXG_INITIAL)
744 return (ENODEV);
745
746 /* Check snapshot limit before receiving */
747 err = dsl_snapcount_check(ds->ds_dir, 1, NULL, rbsa->cr);
748 if (err != 0)
749 return (err);
750 }
751
752 /* temporary clone name must not exist */
753 err = zap_lookup(ds->ds_dir->dd_pool->dp_meta_objset,
754 ds->ds_dir->dd_phys->dd_child_dir_zapobj,
755 rbsa->clonelastname, 8, 1, &val);
756 if (err == 0)
757 return (EEXIST);
758 if (err != ENOENT)
759 return (err);
760
761 return (0);
762 }
763
764 /* ARGSUSED */
765 static void
766 recv_existing_sync(void *arg1, void *arg2, dmu_tx_t *tx)
767 {
768 dsl_dataset_t *ohds = arg1;
769 struct recvbeginsyncarg *rbsa = arg2;
1552 */
1553 txg_wait_synced(drc->drc_real_ds->ds_dir->dd_pool, 0);
1554
1555 (void) dsl_dataset_destroy(drc->drc_real_ds, dmu_recv_tag,
1556 B_FALSE);
1557 if (drc->drc_real_ds != drc->drc_logical_ds) {
1558 mutex_exit(&drc->drc_logical_ds->ds_recvlock);
1559 dsl_dataset_rele(drc->drc_logical_ds, dmu_recv_tag);
1560 }
1561 }
1562
1563 kmem_free(ra.buf, ra.bufsize);
1564 *voffp = ra.voff;
1565 return (ra.err);
1566 }
1567
1568 struct recvendsyncarg {
1569 char *tosnap;
1570 uint64_t creation_time;
1571 uint64_t toguid;
1572 boolean_t is_new;
1573 cred_t *cr;
1574 };
1575
1576 static int
1577 recv_end_check(void *arg1, void *arg2, dmu_tx_t *tx)
1578 {
1579 dsl_dataset_t *ds = arg1;
1580 struct recvendsyncarg *resa = arg2;
1581
1582 if (resa->is_new) {
1583 /* re-check the filesystem limit now that recv is complete */
1584 int err;
1585
1586 err = dsl_dir_fscount_check(ds->ds_dir, 1, NULL, resa->cr);
1587 if (err != 0)
1588 return (err);
1589 }
1590
1591 return (dsl_dataset_snapshot_check(ds, resa->tosnap, 1, tx, resa->cr));
1592 }
1593
1594 static void
1595 recv_end_sync(void *arg1, void *arg2, dmu_tx_t *tx)
1596 {
1597 dsl_dataset_t *ds = arg1;
1598 struct recvendsyncarg *resa = arg2;
1599
1600 if (resa->is_new) {
1601 /* update the filesystem counts */
1602 dsl_dir_fscount_adjust(ds->ds_dir->dd_parent, tx, 1, B_TRUE);
1603 }
1604
1605 dsl_dataset_snapshot_sync(ds, resa->tosnap, tx);
1606
1607 /* set snapshot's creation time and guid */
1608 dmu_buf_will_dirty(ds->ds_prev->ds_dbuf, tx);
1609 ds->ds_prev->ds_phys->ds_creation_time = resa->creation_time;
1610 ds->ds_prev->ds_phys->ds_guid = resa->toguid;
1611 ds->ds_prev->ds_phys->ds_flags &= ~DS_FLAG_INCONSISTENT;
1612
1613 dmu_buf_will_dirty(ds->ds_dbuf, tx);
1614 ds->ds_phys->ds_flags &= ~DS_FLAG_INCONSISTENT;
1615 spa_history_log_internal_ds(ds, "finished receiving", tx, "");
1616 }
1617
1618 static int
1619 add_ds_to_guidmap(avl_tree_t *guid_map, dsl_dataset_t *ds)
1620 {
1621 dsl_pool_t *dp = ds->ds_dir->dd_pool;
1622 uint64_t snapobj = ds->ds_phys->ds_prev_snap_obj;
1623 dsl_dataset_t *snapds;
1624 guid_map_entry_t *gmep;
1645 struct recvendsyncarg resa;
1646 dsl_dataset_t *ds = drc->drc_logical_ds;
1647 int err, myerr;
1648
1649 if (dsl_dataset_tryown(ds, FALSE, dmu_recv_tag)) {
1650 err = dsl_dataset_clone_swap(drc->drc_real_ds, ds,
1651 drc->drc_force);
1652 if (err)
1653 goto out;
1654 } else {
1655 mutex_exit(&ds->ds_recvlock);
1656 dsl_dataset_rele(ds, dmu_recv_tag);
1657 (void) dsl_dataset_destroy(drc->drc_real_ds, dmu_recv_tag,
1658 B_FALSE);
1659 return (EBUSY);
1660 }
1661
1662 resa.creation_time = drc->drc_drrb->drr_creation_time;
1663 resa.toguid = drc->drc_drrb->drr_toguid;
1664 resa.tosnap = drc->drc_tosnap;
1665 resa.is_new = B_FALSE;
1666 resa.cr = CRED();
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 resa.cr = CRED();
1704
1705 err = dsl_sync_task_do(ds->ds_dir->dd_pool,
1706 recv_end_check, recv_end_sync, ds, &resa, 3);
1707 if (err) {
1708 /* clean up the fs we just recv'd into */
1709 (void) dsl_dataset_destroy(ds, dmu_recv_tag, B_FALSE);
1710 } else {
1711 if (drc->drc_guid_to_ds_map != NULL)
1712 (void) add_ds_to_guidmap(drc->drc_guid_to_ds_map, ds);
1713 /* release the hold from dmu_recv_begin */
1714 dsl_dataset_disown(ds, dmu_recv_tag);
1715 }
1716 return (err);
1717 }
1718
1719 int
1720 dmu_recv_end(dmu_recv_cookie_t *drc)
1721 {
1722 if (drc->drc_logical_ds != drc->drc_real_ds)
1723 return (dmu_recv_existing_end(drc));
|