Print this page
3748 zfs headers should be C++ compatible
Submitted by:   Justin Gibbs <justing@spectralogic.com>
Submitted by:   Will Andrews <willa@spectralogic.com>
Reviewed by:    Matthew Ahrens <mahrens@delphix.com>
Reviewed by:    Eric Schrock <eric.schrock@delphix.com>
Reviewed by:    Robert Mustacchi <rm@joyent.com>


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