Print this page
OS-1566 filesystem limits for ZFS datasets


 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));