2738 }
2739
2740 /*
2741 * Return (in *usedp) the amount of space written in new that is not
2742 * present in oldsnap. New may be a snapshot or the head. Old must be
2743 * a snapshot before new, in new's filesystem (or its origin). If not then
2744 * fail and return EINVAL.
2745 *
2746 * The written space is calculated by considering two components: First, we
2747 * ignore any freed space, and calculate the written as new's used space
2748 * minus old's used space. Next, we add in the amount of space that was freed
2749 * between the two snapshots, thus reducing new's used space relative to old's.
2750 * Specifically, this is the space that was born before old->ds_creation_txg,
2751 * and freed before new (ie. on new's deadlist or a previous deadlist).
2752 *
2753 * space freed [---------------------]
2754 * snapshots ---O-------O--------O-------O------
2755 * oldsnap new
2756 */
2757 int
2758 dsl_dataset_space_written(dsl_dataset_t *oldsnap, dsl_dataset_t *new,
2759 uint64_t *usedp, uint64_t *compp, uint64_t *uncompp)
2760 {
2761 int err = 0;
2762 uint64_t snapobj;
2763 dsl_pool_t *dp = new->ds_dir->dd_pool;
2764
2765 ASSERT(dsl_pool_config_held(dp));
2766
2767 *usedp = 0;
2768 *usedp += new->ds_phys->ds_referenced_bytes;
2769 *usedp -= oldsnap->ds_phys->ds_referenced_bytes;
2770
2771 *compp = 0;
2772 *compp += new->ds_phys->ds_compressed_bytes;
2773 *compp -= oldsnap->ds_phys->ds_compressed_bytes;
2774
2775 *uncompp = 0;
2776 *uncompp += new->ds_phys->ds_uncompressed_bytes;
2777 *uncompp -= oldsnap->ds_phys->ds_uncompressed_bytes;
2778
2779 snapobj = new->ds_object;
2780 while (snapobj != oldsnap->ds_object) {
2781 dsl_dataset_t *snap;
2782 uint64_t used, comp, uncomp;
2783
2784 if (snapobj == new->ds_object) {
2785 snap = new;
2786 } else {
2787 err = dsl_dataset_hold_obj(dp, snapobj, FTAG, &snap);
2788 if (err != 0)
2789 break;
2790 }
2791
2792 if (snap->ds_phys->ds_prev_snap_txg ==
2793 oldsnap->ds_phys->ds_creation_txg) {
2794 /*
2795 * The blocks in the deadlist can not be born after
2796 * ds_prev_snap_txg, so get the whole deadlist space,
2797 * which is more efficient (especially for old-format
2798 * deadlists). Unfortunately the deadlist code
2799 * doesn't have enough information to make this
2800 * optimization itself.
2801 */
2802 dsl_deadlist_space(&snap->ds_deadlist,
2803 &used, &comp, &uncomp);
2804 } else {
2805 dsl_deadlist_space_range(&snap->ds_deadlist,
2806 0, oldsnap->ds_phys->ds_creation_txg,
2807 &used, &comp, &uncomp);
2808 }
2809 *usedp += used;
2810 *compp += comp;
2811 *uncompp += uncomp;
2812
2813 /*
2814 * If we get to the beginning of the chain of snapshots
2815 * (ds_prev_snap_obj == 0) before oldsnap, then oldsnap
2816 * was not a snapshot of/before new.
2817 */
2818 snapobj = snap->ds_phys->ds_prev_snap_obj;
2819 if (snap != new)
2820 dsl_dataset_rele(snap, FTAG);
2821 if (snapobj == 0) {
2822 err = SET_ERROR(EINVAL);
2823 break;
2824 }
2825
2826 }
2827 return (err);
2828 }
2829
2830 /*
2831 * Return (in *usedp) the amount of space that will be reclaimed if firstsnap,
2832 * lastsnap, and all snapshots in between are deleted.
2833 *
2834 * blocks that would be freed [---------------------------]
2835 * snapshots ---O-------O--------O-------O--------O
2836 * firstsnap lastsnap
2837 *
2838 * This is the set of blocks that were born after the snap before firstsnap,
2839 * (birth > firstsnap->prev_snap_txg) and died before the snap after the
|
2738 }
2739
2740 /*
2741 * Return (in *usedp) the amount of space written in new that is not
2742 * present in oldsnap. New may be a snapshot or the head. Old must be
2743 * a snapshot before new, in new's filesystem (or its origin). If not then
2744 * fail and return EINVAL.
2745 *
2746 * The written space is calculated by considering two components: First, we
2747 * ignore any freed space, and calculate the written as new's used space
2748 * minus old's used space. Next, we add in the amount of space that was freed
2749 * between the two snapshots, thus reducing new's used space relative to old's.
2750 * Specifically, this is the space that was born before old->ds_creation_txg,
2751 * and freed before new (ie. on new's deadlist or a previous deadlist).
2752 *
2753 * space freed [---------------------]
2754 * snapshots ---O-------O--------O-------O------
2755 * oldsnap new
2756 */
2757 int
2758 dsl_dataset_space_written(dsl_dataset_t *oldsnap, dsl_dataset_t *newds,
2759 uint64_t *usedp, uint64_t *compp, uint64_t *uncompp)
2760 {
2761 int err = 0;
2762 uint64_t snapobj;
2763 dsl_pool_t *dp = newds->ds_dir->dd_pool;
2764
2765 ASSERT(dsl_pool_config_held(dp));
2766
2767 *usedp = 0;
2768 *usedp += newds->ds_phys->ds_referenced_bytes;
2769 *usedp -= oldsnap->ds_phys->ds_referenced_bytes;
2770
2771 *compp = 0;
2772 *compp += newds->ds_phys->ds_compressed_bytes;
2773 *compp -= oldsnap->ds_phys->ds_compressed_bytes;
2774
2775 *uncompp = 0;
2776 *uncompp += newds->ds_phys->ds_uncompressed_bytes;
2777 *uncompp -= oldsnap->ds_phys->ds_uncompressed_bytes;
2778
2779 snapobj = newds->ds_object;
2780 while (snapobj != oldsnap->ds_object) {
2781 dsl_dataset_t *snap;
2782 uint64_t used, comp, uncomp;
2783
2784 if (snapobj == newds->ds_object) {
2785 snap = newds;
2786 } else {
2787 err = dsl_dataset_hold_obj(dp, snapobj, FTAG, &snap);
2788 if (err != 0)
2789 break;
2790 }
2791
2792 if (snap->ds_phys->ds_prev_snap_txg ==
2793 oldsnap->ds_phys->ds_creation_txg) {
2794 /*
2795 * The blocks in the deadlist can not be born after
2796 * ds_prev_snap_txg, so get the whole deadlist space,
2797 * which is more efficient (especially for old-format
2798 * deadlists). Unfortunately the deadlist code
2799 * doesn't have enough information to make this
2800 * optimization itself.
2801 */
2802 dsl_deadlist_space(&snap->ds_deadlist,
2803 &used, &comp, &uncomp);
2804 } else {
2805 dsl_deadlist_space_range(&snap->ds_deadlist,
2806 0, oldsnap->ds_phys->ds_creation_txg,
2807 &used, &comp, &uncomp);
2808 }
2809 *usedp += used;
2810 *compp += comp;
2811 *uncompp += uncomp;
2812
2813 /*
2814 * If we get to the beginning of the chain of snapshots
2815 * (ds_prev_snap_obj == 0) before oldsnap, then oldsnap
2816 * was not a snapshot of/before newds.
2817 */
2818 snapobj = snap->ds_phys->ds_prev_snap_obj;
2819 if (snap != newds)
2820 dsl_dataset_rele(snap, FTAG);
2821 if (snapobj == 0) {
2822 err = SET_ERROR(EINVAL);
2823 break;
2824 }
2825
2826 }
2827 return (err);
2828 }
2829
2830 /*
2831 * Return (in *usedp) the amount of space that will be reclaimed if firstsnap,
2832 * lastsnap, and all snapshots in between are deleted.
2833 *
2834 * blocks that would be freed [---------------------------]
2835 * snapshots ---O-------O--------O-------O--------O
2836 * firstsnap lastsnap
2837 *
2838 * This is the set of blocks that were born after the snap before firstsnap,
2839 * (birth > firstsnap->prev_snap_txg) and died before the snap after the
|