1cde58dbMatthew Ahrens/*
2cde58dbMatthew Ahrens * CDDL HEADER START
3cde58dbMatthew Ahrens *
4cde58dbMatthew Ahrens * The contents of this file are subject to the terms of the
5cde58dbMatthew Ahrens * Common Development and Distribution License (the "License").
6cde58dbMatthew Ahrens * You may not use this file except in compliance with the License.
7cde58dbMatthew Ahrens *
8cde58dbMatthew Ahrens * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9cde58dbMatthew Ahrens * or http://www.opensolaris.org/os/licensing.
10cde58dbMatthew Ahrens * See the License for the specific language governing permissions
11cde58dbMatthew Ahrens * and limitations under the License.
12cde58dbMatthew Ahrens *
13cde58dbMatthew Ahrens * When distributing Covered Code, include this CDDL HEADER in each
14cde58dbMatthew Ahrens * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15cde58dbMatthew Ahrens * If applicable, add the following below this CDDL HEADER, with the
16cde58dbMatthew Ahrens * fields enclosed by brackets "[]" replaced with your own identifying
17cde58dbMatthew Ahrens * information: Portions Copyright [yyyy] [name of copyright owner]
18cde58dbMatthew Ahrens *
19cde58dbMatthew Ahrens * CDDL HEADER END
20cde58dbMatthew Ahrens */
21cde58dbMatthew Ahrens/*
22cde58dbMatthew Ahrens * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
235cabbc6Prashanth Sreenivasa * Copyright (c) 2012, 2015 by Delphix. All rights reserved.
24bc9014eJustin Gibbs * Copyright (c) 2014 Spectra Logic Corporation, All rights reserved.
25c3d26abMatthew Ahrens * Copyright (c) 2014 Integros [integros.com]
26cde58dbMatthew Ahrens */
27cde58dbMatthew Ahrens
28cde58dbMatthew Ahrens#include <sys/dsl_dataset.h>
29cde58dbMatthew Ahrens#include <sys/dmu.h>
30cde58dbMatthew Ahrens#include <sys/refcount.h>
31cde58dbMatthew Ahrens#include <sys/zap.h>
32cde58dbMatthew Ahrens#include <sys/zfs_context.h>
33cde58dbMatthew Ahrens#include <sys/dsl_pool.h>
34cde58dbMatthew Ahrens
3519b94dfMatthew Ahrens/*
3619b94dfMatthew Ahrens * Deadlist concurrency:
3719b94dfMatthew Ahrens *
3819b94dfMatthew Ahrens * Deadlists can only be modified from the syncing thread.
3919b94dfMatthew Ahrens *
4019b94dfMatthew Ahrens * Except for dsl_deadlist_insert(), it can only be modified with the
4119b94dfMatthew Ahrens * dp_config_rwlock held with RW_WRITER.
4219b94dfMatthew Ahrens *
4319b94dfMatthew Ahrens * The accessors (dsl_deadlist_space() and dsl_deadlist_space_range()) can
4419b94dfMatthew Ahrens * be called concurrently, from open context, with the dl_config_rwlock held
4519b94dfMatthew Ahrens * with RW_READER.
4619b94dfMatthew Ahrens *
4719b94dfMatthew Ahrens * Therefore, we only need to provide locking between dsl_deadlist_insert() and
4819b94dfMatthew Ahrens * the accessors, protecting:
4919b94dfMatthew Ahrens *     dl_phys->dl_used,comp,uncomp
5019b94dfMatthew Ahrens *     and protecting the dl_tree from being loaded.
5119b94dfMatthew Ahrens * The locking is provided by dl_lock.  Note that locking on the bpobj_t
5219b94dfMatthew Ahrens * provides its own locking, and dl_oldfmt is immutable.
5319b94dfMatthew Ahrens */
5419b94dfMatthew Ahrens
55cde58dbMatthew Ahrensstatic int
56cde58dbMatthew Ahrensdsl_deadlist_compare(const void *arg1, const void *arg2)
57cde58dbMatthew Ahrens{
58c4ab0d3Gvozden Neskovic	const dsl_deadlist_entry_t *dle1 = (const dsl_deadlist_entry_t *)arg1;
59c4ab0d3Gvozden Neskovic	const dsl_deadlist_entry_t *dle2 = (const dsl_deadlist_entry_t *)arg2;
60cde58dbMatthew Ahrens
614d7988dPaul Dagnelie	return (TREE_CMP(dle1->dle_mintxg, dle2->dle_mintxg));
62cde58dbMatthew Ahrens}
63cde58dbMatthew Ahrens
64cde58dbMatthew Ahrensstatic void
65cde58dbMatthew Ahrensdsl_deadlist_load_tree(dsl_deadlist_t *dl)
66cde58dbMatthew Ahrens{
67cde58dbMatthew Ahrens	zap_cursor_t zc;
68cde58dbMatthew Ahrens	zap_attribute_t za;
69cde58dbMatthew Ahrens
70a3905a4Serapheim Dimitropoulos	ASSERT(MUTEX_HELD(&dl->dl_lock));
71a3905a4Serapheim Dimitropoulos
72cde58dbMatthew Ahrens	ASSERT(!dl->dl_oldfmt);
73cde58dbMatthew Ahrens	if (dl->dl_havetree)
74cde58dbMatthew Ahrens		return;
75cde58dbMatthew Ahrens
76cde58dbMatthew Ahrens	avl_create(&dl->dl_tree, dsl_deadlist_compare,
77cde58dbMatthew Ahrens	    sizeof (dsl_deadlist_entry_t),
78cde58dbMatthew Ahrens	    offsetof(dsl_deadlist_entry_t, dle_node));
79cde58dbMatthew Ahrens	for (zap_cursor_init(&zc, dl->dl_os, dl->dl_object);
80cde58dbMatthew Ahrens	    zap_cursor_retrieve(&zc, &za) == 0;
81cde58dbMatthew Ahrens	    zap_cursor_advance(&zc)) {
82cde58dbMatthew Ahrens		dsl_deadlist_entry_t *dle = kmem_alloc(sizeof (*dle), KM_SLEEP);
834585130Yuri Pankov		dle->dle_mintxg = zfs_strtonum(za.za_name, NULL);
84b420f3aRichard Lowe		VERIFY3U(0, ==, bpobj_open(&dle->dle_bpobj, dl->dl_os,
85cde58dbMatthew Ahrens		    za.za_first_integer));
86cde58dbMatthew Ahrens		avl_add(&dl->dl_tree, dle);
87cde58dbMatthew Ahrens	}
88cde58dbMatthew Ahrens	zap_cursor_fini(&zc);
89cde58dbMatthew Ahrens	dl->dl_havetree = B_TRUE;
90cde58dbMatthew Ahrens}
91cde58dbMatthew Ahrens
92cde58dbMatthew Ahrensvoid
93cde58dbMatthew Ahrensdsl_deadlist_open(dsl_deadlist_t *dl, objset_t *os, uint64_t object)
94cde58dbMatthew Ahrens{
95cde58dbMatthew Ahrens	dmu_object_info_t doi;
96cde58dbMatthew Ahrens
975cabbc6Prashanth Sreenivasa	ASSERT(!dsl_deadlist_is_open(dl));
985cabbc6Prashanth Sreenivasa
99cde58dbMatthew Ahrens	mutex_init(&dl->dl_lock, NULL, MUTEX_DEFAULT, NULL);
100cde58dbMatthew Ahrens	dl->dl_os = os;
101cde58dbMatthew Ahrens	dl->dl_object = object;
102b420f3aRichard Lowe	VERIFY3U(0, ==, dmu_bonus_hold(os, object, dl, &dl->dl_dbuf));
103cde58dbMatthew Ahrens	dmu_object_info_from_db(dl->dl_dbuf, &doi);
104cde58dbMatthew Ahrens	if (doi.doi_type == DMU_OT_BPOBJ) {
105cde58dbMatthew Ahrens		dmu_buf_rele(dl->dl_dbuf, dl);
106cde58dbMatthew Ahrens		dl->dl_dbuf = NULL;
107cde58dbMatthew Ahrens		dl->dl_oldfmt = B_TRUE;
108b420f3aRichard Lowe		VERIFY3U(0, ==, bpobj_open(&dl->dl_bpobj, os, object));
109cde58dbMatthew Ahrens		return;
110cde58dbMatthew Ahrens	}
111cde58dbMatthew Ahrens
112cde58dbMatthew Ahrens	dl->dl_oldfmt = B_FALSE;
113cde58dbMatthew Ahrens	dl->dl_phys = dl->dl_dbuf->db_data;
114cde58dbMatthew Ahrens	dl->dl_havetree = B_FALSE;
115cde58dbMatthew Ahrens}
116cde58dbMatthew Ahrens
1175cabbc6Prashanth Sreenivasaboolean_t
1185cabbc6Prashanth Sreenivasadsl_deadlist_is_open(dsl_deadlist_t *dl)
1195cabbc6Prashanth Sreenivasa{
1205cabbc6Prashanth Sreenivasa	return (dl->dl_os != NULL);
1215cabbc6Prashanth Sreenivasa}
1225cabbc6Prashanth Sreenivasa
123cde58dbMatthew Ahrensvoid
124cde58dbMatthew Ahrensdsl_deadlist_close(dsl_deadlist_t *dl)
125cde58dbMatthew Ahrens{
126cde58dbMatthew Ahrens	void *cookie = NULL;
127cde58dbMatthew Ahrens	dsl_deadlist_entry_t *dle;
128cde58dbMatthew Ahrens
1295cabbc6Prashanth Sreenivasa	ASSERT(dsl_deadlist_is_open(dl));
130bc9014eJustin Gibbs
131cde58dbMatthew Ahrens	if (dl->dl_oldfmt) {
132cde58dbMatthew Ahrens		dl->dl_oldfmt = B_FALSE;
133cde58dbMatthew Ahrens		bpobj_close(&dl->dl_bpobj);
1345cabbc6Prashanth Sreenivasa		dl->dl_os = NULL;
1355cabbc6Prashanth Sreenivasa		dl->dl_object = 0;
136cde58dbMatthew Ahrens		return;
137cde58dbMatthew Ahrens	}
138cde58dbMatthew Ahrens
139cde58dbMatthew Ahrens	if (dl->dl_havetree) {
140cde58dbMatthew Ahrens		while ((dle = avl_destroy_nodes(&dl->dl_tree, &cookie))
141cde58dbMatthew Ahrens		    != NULL) {
142cde58dbMatthew Ahrens			bpobj_close(&dle->dle_bpobj);
143cde58dbMatthew Ahrens			kmem_free(dle, sizeof (*dle));
144cde58dbMatthew Ahrens		}
145cde58dbMatthew Ahrens		avl_destroy(&dl->dl_tree);
146cde58dbMatthew Ahrens	}
147cde58dbMatthew Ahrens	dmu_buf_rele(dl->dl_dbuf, dl);
148cde58dbMatthew Ahrens	mutex_destroy(&dl->dl_lock);
149cde58dbMatthew Ahrens	dl->dl_dbuf = NULL;
150cde58dbMatthew Ahrens	dl->dl_phys = NULL;
1515cabbc6Prashanth Sreenivasa	dl->dl_os = NULL;
1525cabbc6Prashanth Sreenivasa	dl->dl_object = 0;
153cde58dbMatthew Ahrens}
154cde58dbMatthew Ahrens
155cde58dbMatthew Ahrensuint64_t
156cde58dbMatthew Ahrensdsl_deadlist_alloc(objset_t *os, dmu_tx_t *tx)
157cde58dbMatthew Ahrens{
158cde58dbMatthew Ahrens	if (spa_version(dmu_objset_spa(os)) < SPA_VERSION_DEADLISTS)
159b515258Matthew Ahrens		return (bpobj_alloc(os, SPA_OLD_MAXBLOCKSIZE, tx));
160cde58dbMatthew Ahrens	return (zap_create(os, DMU_OT_DEADLIST, DMU_OT_DEADLIST_HDR,
161cde58dbMatthew Ahrens	    sizeof (dsl_deadlist_phys_t), tx));
162cde58dbMatthew Ahrens}
163cde58dbMatthew Ahrens
164cde58dbMatthew Ahrensvoid
165cde58dbMatthew Ahrensdsl_deadlist_free(objset_t *os, uint64_t dlobj, dmu_tx_t *tx)
166cde58dbMatthew Ahrens{
167cde58dbMatthew Ahrens	dmu_object_info_t doi;
168cde58dbMatthew Ahrens	zap_cursor_t zc;
169cde58dbMatthew Ahrens	zap_attribute_t za;
170cde58dbMatthew Ahrens
171b420f3aRichard Lowe	VERIFY3U(0, ==, dmu_object_info(os, dlobj, &doi));
172cde58dbMatthew Ahrens	if (doi.doi_type == DMU_OT_BPOBJ) {
173cde58dbMatthew Ahrens		bpobj_free(os, dlobj, tx);
174cde58dbMatthew Ahrens		return;
175cde58dbMatthew Ahrens	}
176cde58dbMatthew Ahrens
177cde58dbMatthew Ahrens	for (zap_cursor_init(&zc, os, dlobj);
178cde58dbMatthew Ahrens	    zap_cursor_retrieve(&zc, &za) == 0;
179f174573Matthew Ahrens	    zap_cursor_advance(&zc)) {
180f174573Matthew Ahrens		uint64_t obj = za.za_first_integer;
181f174573Matthew Ahrens		if (obj == dmu_objset_pool(os)->dp_empty_bpobj)
182f174573Matthew Ahrens			bpobj_decr_empty(os, tx);
183f174573Matthew Ahrens		else
184f174573Matthew Ahrens			bpobj_free(os, obj, tx);
185f174573Matthew Ahrens	}
186cde58dbMatthew Ahrens	zap_cursor_fini(&zc);
187b420f3aRichard Lowe	VERIFY3U(0, ==, dmu_object_free(os, dlobj, tx));
188cde58dbMatthew Ahrens}
189cde58dbMatthew Ahrens
190f174573Matthew Ahrensstatic void
191f174573Matthew Ahrensdle_enqueue(dsl_deadlist_t *dl, dsl_deadlist_entry_t *dle,
192f174573Matthew Ahrens    const blkptr_t *bp, dmu_tx_t *tx)
193f174573Matthew Ahrens{
194a3905a4Serapheim Dimitropoulos	ASSERT(MUTEX_HELD(&dl->dl_lock));
195f174573Matthew Ahrens	if (dle->dle_bpobj.bpo_object ==
196f174573Matthew Ahrens	    dmu_objset_pool(dl->dl_os)->dp_empty_bpobj) {
197b515258Matthew Ahrens		uint64_t obj = bpobj_alloc(dl->dl_os, SPA_OLD_MAXBLOCKSIZE, tx);
198f174573Matthew Ahrens		bpobj_close(&dle->dle_bpobj);
199f174573Matthew Ahrens		bpobj_decr_empty(dl->dl_os, tx);
200f174573Matthew Ahrens		VERIFY3U(0, ==, bpobj_open(&dle->dle_bpobj, dl->dl_os, obj));
201f174573Matthew Ahrens		VERIFY3U(0, ==, zap_update_int_key(dl->dl_os, dl->dl_object,
202f174573Matthew Ahrens		    dle->dle_mintxg, obj, tx));
203f174573Matthew Ahrens	}
204f174573Matthew Ahrens	bpobj_enqueue(&dle->dle_bpobj, bp, tx);
205f174573Matthew Ahrens}
206f174573Matthew Ahrens
207f174573Matthew Ahrensstatic void
208f174573Matthew Ahrensdle_enqueue_subobj(dsl_deadlist_t *dl, dsl_deadlist_entry_t *dle,
209f174573Matthew Ahrens    uint64_t obj, dmu_tx_t *tx)
210f174573Matthew Ahrens{
211a3905a4Serapheim Dimitropoulos	ASSERT(MUTEX_HELD(&dl->dl_lock));
212f174573Matthew Ahrens	if (dle->dle_bpobj.bpo_object !=
213f174573Matthew Ahrens	    dmu_objset_pool(dl->dl_os)->dp_empty_bpobj) {
214f174573Matthew Ahrens		bpobj_enqueue_subobj(&dle->dle_bpobj, obj, tx);
215f174573Matthew Ahrens	} else {
216f174573Matthew Ahrens		bpobj_close(&dle->dle_bpobj);
217f174573Matthew Ahrens		bpobj_decr_empty(dl->dl_os, tx);
218f174573Matthew Ahrens		VERIFY3U(0, ==, bpobj_open(&dle->dle_bpobj, dl->dl_os, obj));
219f174573Matthew Ahrens		VERIFY3U(0, ==, zap_update_int_key(dl->dl_os, dl->dl_object,
220f174573Matthew Ahrens		    dle->dle_mintxg, obj, tx));
221f174573Matthew Ahrens	}
222f174573Matthew Ahrens}
223f174573Matthew Ahrens
224cde58dbMatthew Ahrensvoid
225cde58dbMatthew Ahrensdsl_deadlist_insert(dsl_deadlist_t *dl, const blkptr_t *bp, dmu_tx_t *tx)
226cde58dbMatthew Ahrens{
227cde58dbMatthew Ahrens	dsl_deadlist_entry_t dle_tofind;
228cde58dbMatthew Ahrens	dsl_deadlist_entry_t *dle;
229cde58dbMatthew Ahrens	avl_index_t where;
230cde58dbMatthew Ahrens
231cde58dbMatthew Ahrens	if (dl->dl_oldfmt) {
232cde58dbMatthew Ahrens		bpobj_enqueue(&dl->dl_bpobj, bp, tx);
233cde58dbMatthew Ahrens		return;
234cde58dbMatthew Ahrens	}
235cde58dbMatthew Ahrens
236a3905a4Serapheim Dimitropoulos	mutex_enter(&dl->dl_lock);
237cde58dbMatthew Ahrens	dsl_deadlist_load_tree(dl);
238cde58dbMatthew Ahrens
239cde58dbMatthew Ahrens	dmu_buf_will_dirty(dl->dl_dbuf, tx);
240cde58dbMatthew Ahrens	dl->dl_phys->dl_used +=
241cde58dbMatthew Ahrens	    bp_get_dsize_sync(dmu_objset_spa(dl->dl_os), bp);
242cde58dbMatthew Ahrens	dl->dl_phys->dl_comp += BP_GET_PSIZE(bp);
243cde58dbMatthew Ahrens	dl->dl_phys->dl_uncomp += BP_GET_UCSIZE(bp);
244cde58dbMatthew Ahrens
245cde58dbMatthew Ahrens	dle_tofind.dle_mintxg = bp->blk_birth;
246cde58dbMatthew Ahrens	dle = avl_find(&dl->dl_tree, &dle_tofind, &where);
247cde58dbMatthew Ahrens	if (dle == NULL)
248cde58dbMatthew Ahrens		dle = avl_nearest(&dl->dl_tree, where, AVL_BEFORE);
249cde58dbMatthew Ahrens	else
250cde58dbMatthew Ahrens		dle = AVL_PREV(&dl->dl_tree, dle);
251f174573Matthew Ahrens	dle_enqueue(dl, dle, bp, tx);
252a3905a4Serapheim Dimitropoulos	mutex_exit(&dl->dl_lock);
253cde58dbMatthew Ahrens}
254cde58dbMatthew Ahrens
255cde58dbMatthew Ahrens/*
256cde58dbMatthew Ahrens * Insert new key in deadlist, which must be > all current entries.
257cde58dbMatthew Ahrens * mintxg is not inclusive.
258cde58dbMatthew Ahrens */
259cde58dbMatthew Ahrensvoid
260cde58dbMatthew Ahrensdsl_deadlist_add_key(dsl_deadlist_t *dl, uint64_t mintxg, dmu_tx_t *tx)
261cde58dbMatthew Ahrens{
262cde58dbMatthew Ahrens	uint64_t obj;
263cde58dbMatthew Ahrens	dsl_deadlist_entry_t *dle;
264cde58dbMatthew Ahrens
265cde58dbMatthew Ahrens	if (dl->dl_oldfmt)
266cde58dbMatthew Ahrens		return;
267cde58dbMatthew Ahrens
268cde58dbMatthew Ahrens	dle = kmem_alloc(sizeof (*dle), KM_SLEEP);
269cde58dbMatthew Ahrens	dle->dle_mintxg = mintxg;
270a3905a4Serapheim Dimitropoulos
271a3905a4Serapheim Dimitropoulos	mutex_enter(&dl->dl_lock);
272a3905a4Serapheim Dimitropoulos	dsl_deadlist_load_tree(dl);
273a3905a4Serapheim Dimitropoulos
274b515258Matthew Ahrens	obj = bpobj_alloc_empty(dl->dl_os, SPA_OLD_MAXBLOCKSIZE, tx);
275b420f3aRichard Lowe	VERIFY3U(0, ==, bpobj_open(&dle->dle_bpobj, dl->dl_os, obj));
276cde58dbMatthew Ahrens	avl_add(&dl->dl_tree, dle);
277cde58dbMatthew Ahrens
278b420f3aRichard Lowe	VERIFY3U(0, ==, zap_add_int_key(dl->dl_os, dl->dl_object,
279cde58dbMatthew Ahrens	    mintxg, obj, tx));
280a3905a4Serapheim Dimitropoulos	mutex_exit(&dl->dl_lock);
281cde58dbMatthew Ahrens}
282cde58dbMatthew Ahrens
283cde58dbMatthew Ahrens/*
284cde58dbMatthew Ahrens * Remove this key, merging its entries into the previous key.
285cde58dbMatthew Ahrens */
286cde58dbMatthew Ahrensvoid
287cde58dbMatthew Ahrensdsl_deadlist_remove_key(dsl_deadlist_t *dl, uint64_t mintxg, dmu_tx_t *tx)
288cde58dbMatthew Ahrens{
289cde58dbMatthew Ahrens	dsl_deadlist_entry_t dle_tofind;
290cde58dbMatthew Ahrens	dsl_deadlist_entry_t *dle, *dle_prev;
291cde58dbMatthew Ahrens
292cde58dbMatthew Ahrens	if (dl->dl_oldfmt)
293cde58dbMatthew Ahrens		return;
294cde58dbMatthew Ahrens
295a3905a4Serapheim Dimitropoulos	mutex_enter(&dl->dl_lock);
296cde58dbMatthew Ahrens	dsl_deadlist_load_tree(dl);
297cde58dbMatthew Ahrens
298cde58dbMatthew Ahrens	dle_tofind.dle_mintxg = mintxg;
299cde58dbMatthew Ahrens	dle = avl_find(&dl->dl_tree, &dle_tofind, NULL);
300cde58dbMatthew Ahrens	dle_prev = AVL_PREV(&dl->dl_tree, dle);
301cde58dbMatthew Ahrens
302f174573Matthew Ahrens	dle_enqueue_subobj(dl, dle_prev, dle->dle_bpobj.bpo_object, tx);
303cde58dbMatthew Ahrens
304cde58dbMatthew Ahrens	avl_remove(&dl->dl_tree, dle);
305cde58dbMatthew Ahrens	bpobj_close(&dle->dle_bpobj);
306cde58dbMatthew Ahrens	kmem_free(dle, sizeof (*dle));
307cde58dbMatthew Ahrens
308b420f3aRichard Lowe	VERIFY3U(0, ==, zap_remove_int(dl->dl_os, dl->dl_object, mintxg, tx));
309a3905a4Serapheim Dimitropoulos	mutex_exit(&dl->dl_lock);
310cde58dbMatthew Ahrens}
311cde58dbMatthew Ahrens
312cde58dbMatthew Ahrens/*
313cde58dbMatthew Ahrens * Walk ds's snapshots to regenerate generate ZAP & AVL.
314cde58dbMatthew Ahrens */
315cde58dbMatthew Ahrensstatic void
316cde58dbMatthew Ahrensdsl_deadlist_regenerate(objset_t *os, uint64_t dlobj,
317cde58dbMatthew Ahrens    uint64_t mrs_obj, dmu_tx_t *tx)
318cde58dbMatthew Ahrens{
3195cabbc6Prashanth Sreenivasa	dsl_deadlist_t dl = { 0 };
320cde58dbMatthew Ahrens	dsl_pool_t *dp = dmu_objset_pool(os);
321cde58dbMatthew Ahrens
322cde58dbMatthew Ahrens	dsl_deadlist_open(&dl, os, dlobj);
323cde58dbMatthew Ahrens	if (dl.dl_oldfmt) {
324cde58dbMatthew Ahrens		dsl_deadlist_close(&dl);
325cde58dbMatthew Ahrens		return;
326cde58dbMatthew Ahrens	}
327cde58dbMatthew Ahrens
328cde58dbMatthew Ahrens	while (mrs_obj != 0) {
329cde58dbMatthew Ahrens		dsl_dataset_t *ds;
330b420f3aRichard Lowe		VERIFY3U(0, ==, dsl_dataset_hold_obj(dp, mrs_obj, FTAG, &ds));
331c137962Justin T. Gibbs		dsl_deadlist_add_key(&dl,
332c137962Justin T. Gibbs		    dsl_dataset_phys(ds)->ds_prev_snap_txg, tx);
333c137962Justin T. Gibbs		mrs_obj = dsl_dataset_phys(ds)->ds_prev_snap_obj;
334cde58dbMatthew Ahrens		dsl_dataset_rele(ds, FTAG);
335cde58dbMatthew Ahrens	}
336cde58dbMatthew Ahrens	dsl_deadlist_close(&dl);
337cde58dbMatthew Ahrens}
338cde58dbMatthew Ahrens
339cde58dbMatthew Ahrensuint64_t
340cde58dbMatthew Ahrensdsl_deadlist_clone(dsl_deadlist_t *dl, uint64_t maxtxg,
341cde58dbMatthew Ahrens    uint64_t mrs_obj, dmu_tx_t *tx)
342cde58dbMatthew Ahrens{
343cde58dbMatthew Ahrens	dsl_deadlist_entry_t *dle;
344cde58dbMatthew Ahrens	uint64_t newobj;
345cde58dbMatthew Ahrens
346cde58dbMatthew Ahrens	newobj = dsl_deadlist_alloc(dl->dl_os, tx);
347cde58dbMatthew Ahrens
348cde58dbMatthew Ahrens	if (dl->dl_oldfmt) {
349cde58dbMatthew Ahrens		dsl_deadlist_regenerate(dl->dl_os, newobj, mrs_obj, tx);
350cde58dbMatthew Ahrens		return (newobj);
351cde58dbMatthew Ahrens	}
352cde58dbMatthew Ahrens
353a3905a4Serapheim Dimitropoulos	mutex_enter(&dl->dl_lock);
354cde58dbMatthew Ahrens	dsl_deadlist_load_tree(dl);
355cde58dbMatthew Ahrens
356cde58dbMatthew Ahrens	for (dle = avl_first(&dl->dl_tree); dle;
357cde58dbMatthew Ahrens	    dle = AVL_NEXT(&dl->dl_tree, dle)) {
358cde58dbMatthew Ahrens		uint64_t obj;
359cde58dbMatthew Ahrens
360cde58dbMatthew Ahrens		if (dle->dle_mintxg >= maxtxg)
361cde58dbMatthew Ahrens			break;
362cde58dbMatthew Ahrens
363b515258Matthew Ahrens		obj = bpobj_alloc_empty(dl->dl_os, SPA_OLD_MAXBLOCKSIZE, tx);
364b420f3aRichard Lowe		VERIFY3U(0, ==, zap_add_int_key(dl->dl_os, newobj,
365cde58dbMatthew Ahrens		    dle->dle_mintxg, obj, tx));
366cde58dbMatthew Ahrens	}
367a3905a4Serapheim Dimitropoulos	mutex_exit(&dl->dl_lock);
368cde58dbMatthew Ahrens	return (newobj);
369cde58dbMatthew Ahrens}
370cde58dbMatthew Ahrens
371cde58dbMatthew Ahrensvoid
372cde58dbMatthew Ahrensdsl_deadlist_space(dsl_deadlist_t *dl,
373cde58dbMatthew Ahrens    uint64_t *usedp, uint64_t *compp, uint64_t *uncompp)
374cde58dbMatthew Ahrens{
3755cabbc6Prashanth Sreenivasa	ASSERT(dsl_deadlist_is_open(dl));
376cde58dbMatthew Ahrens	if (dl->dl_oldfmt) {
377b420f3aRichard Lowe		VERIFY3U(0, ==, bpobj_space(&dl->dl_bpobj,
378cde58dbMatthew Ahrens		    usedp, compp, uncompp));
379cde58dbMatthew Ahrens		return;
380cde58dbMatthew Ahrens	}
381cde58dbMatthew Ahrens
382cde58dbMatthew Ahrens	mutex_enter(&dl->dl_lock);
383cde58dbMatthew Ahrens	*usedp = dl->dl_phys->dl_used;
384cde58dbMatthew Ahrens	*compp = dl->dl_phys->dl_comp;
385cde58dbMatthew Ahrens	*uncompp = dl->dl_phys->dl_uncomp;
386cde58dbMatthew Ahrens	mutex_exit(&dl->dl_lock);
387cde58dbMatthew Ahrens}
388cde58dbMatthew Ahrens
389cde58dbMatthew Ahrens/*
390cde58dbMatthew Ahrens * return space used in the range (mintxg, maxtxg].
391cde58dbMatthew Ahrens * Includes maxtxg, does not include mintxg.
392cde58dbMatthew Ahrens * mintxg and maxtxg must both be keys in the deadlist (unless maxtxg is
39319b94dfMatthew Ahrens * larger than any bp in the deadlist (eg. UINT64_MAX)).
394cde58dbMatthew Ahrens */
395cde58dbMatthew Ahrensvoid
396cde58dbMatthew Ahrensdsl_deadlist_space_range(dsl_deadlist_t *dl, uint64_t mintxg, uint64_t maxtxg,
397cde58dbMatthew Ahrens    uint64_t *usedp, uint64_t *compp, uint64_t *uncompp)
398cde58dbMatthew Ahrens{
3998ac09fcRichard Lowe	dsl_deadlist_entry_t *dle;
40019b94dfMatthew Ahrens	dsl_deadlist_entry_t dle_tofind;
401cde58dbMatthew Ahrens	avl_index_t where;
402cde58dbMatthew Ahrens
403cde58dbMatthew Ahrens	if (dl->dl_oldfmt) {
404b420f3aRichard Lowe		VERIFY3U(0, ==, bpobj_space_range(&dl->dl_bpobj,
405cde58dbMatthew Ahrens		    mintxg, maxtxg, usedp, compp, uncompp));
406cde58dbMatthew Ahrens		return;
407cde58dbMatthew Ahrens	}
408cde58dbMatthew Ahrens
409cde58dbMatthew Ahrens	*usedp = *compp = *uncompp = 0;
410cde58dbMatthew Ahrens
41119b94dfMatthew Ahrens	mutex_enter(&dl->dl_lock);
41219b94dfMatthew Ahrens	dsl_deadlist_load_tree(dl);
413cde58dbMatthew Ahrens	dle_tofind.dle_mintxg = mintxg;
414cde58dbMatthew Ahrens	dle = avl_find(&dl->dl_tree, &dle_tofind, &where);
415cde58dbMatthew Ahrens	/*
416cde58dbMatthew Ahrens	 * If we don't find this mintxg, there shouldn't be anything
417cde58dbMatthew Ahrens	 * after it either.
418cde58dbMatthew Ahrens	 */
419cde58dbMatthew Ahrens	ASSERT(dle != NULL ||
420cde58dbMatthew Ahrens	    avl_nearest(&dl->dl_tree, where, AVL_AFTER) == NULL);
42119b94dfMatthew Ahrens
422cde58dbMatthew Ahrens	for (; dle && dle->dle_mintxg < maxtxg;
423cde58dbMatthew Ahrens	    dle = AVL_NEXT(&dl->dl_tree, dle)) {
424cde58dbMatthew Ahrens		uint64_t used, comp, uncomp;
425cde58dbMatthew Ahrens
426b420f3aRichard Lowe		VERIFY3U(0, ==, bpobj_space(&dle->dle_bpobj,
427cde58dbMatthew Ahrens		    &used, &comp, &uncomp));
428cde58dbMatthew Ahrens
429cde58dbMatthew Ahrens		*usedp += used;
430cde58dbMatthew Ahrens		*compp += comp;
431cde58dbMatthew Ahrens		*uncompp += uncomp;
432cde58dbMatthew Ahrens	}
43319b94dfMatthew Ahrens	mutex_exit(&dl->dl_lock);
434cde58dbMatthew Ahrens}
435cde58dbMatthew Ahrens
436cde58dbMatthew Ahrensstatic void
437cde58dbMatthew Ahrensdsl_deadlist_insert_bpobj(dsl_deadlist_t *dl, uint64_t obj, uint64_t birth,
438cde58dbMatthew Ahrens    dmu_tx_t *tx)
439cde58dbMatthew Ahrens{
440cde58dbMatthew Ahrens	dsl_deadlist_entry_t dle_tofind;
441cde58dbMatthew Ahrens	dsl_deadlist_entry_t *dle;
442cde58dbMatthew Ahrens	avl_index_t where;
443cde58dbMatthew Ahrens	uint64_t used, comp, uncomp;
444cde58dbMatthew Ahrens	bpobj_t bpo;
445cde58dbMatthew Ahrens
446a3905a4Serapheim Dimitropoulos	ASSERT(MUTEX_HELD(&dl->dl_lock));
447a3905a4Serapheim Dimitropoulos
448b420f3aRichard Lowe	VERIFY3U(0, ==, bpobj_open(&bpo, dl->dl_os, obj));
449b420f3aRichard Lowe	VERIFY3U(0, ==, bpobj_space(&bpo, &used, &comp, &uncomp));
450cde58dbMatthew Ahrens	bpobj_close(&bpo);
451cde58dbMatthew Ahrens
452cde58dbMatthew Ahrens	dsl_deadlist_load_tree(dl);
453cde58dbMatthew Ahrens
454cde58dbMatthew Ahrens	dmu_buf_will_dirty(dl->dl_dbuf, tx);
455cde58dbMatthew Ahrens	dl->dl_phys->dl_used += used;
456cde58dbMatthew Ahrens	dl->dl_phys->dl_comp += comp;
457cde58dbMatthew Ahrens	dl->dl_phys->dl_uncomp += uncomp;
458cde58dbMatthew Ahrens
459cde58dbMatthew Ahrens	dle_tofind.dle_mintxg = birth;
460cde58dbMatthew Ahrens	dle = avl_find(&dl->dl_tree, &dle_tofind, &where);
461cde58dbMatthew Ahrens	if (dle == NULL)
462cde58dbMatthew Ahrens		dle = avl_nearest(&dl->dl_tree, where, AVL_BEFORE);
463f174573Matthew Ahrens	dle_enqueue_subobj(dl, dle, obj, tx);
464cde58dbMatthew Ahrens}
465cde58dbMatthew Ahrens
466cde58dbMatthew Ahrensstatic int
467cde58dbMatthew Ahrensdsl_deadlist_insert_cb(void *arg, const blkptr_t *bp, dmu_tx_t *tx)
468cde58dbMatthew Ahrens{
469cde58dbMatthew Ahrens	dsl_deadlist_t *dl = arg;
470cde58dbMatthew Ahrens	dsl_deadlist_insert(dl, bp, tx);
471cde58dbMatthew Ahrens	return (0);
472cde58dbMatthew Ahrens}
473cde58dbMatthew Ahrens
474cde58dbMatthew Ahrens/*
475cde58dbMatthew Ahrens * Merge the deadlist pointed to by 'obj' into dl.  obj will be left as
476cde58dbMatthew Ahrens * an empty deadlist.
477cde58dbMatthew Ahrens */
478cde58dbMatthew Ahrensvoid
479cde58dbMatthew Ahrensdsl_deadlist_merge(dsl_deadlist_t *dl, uint64_t obj, dmu_tx_t *tx)
480cde58dbMatthew Ahrens{
481cde58dbMatthew Ahrens	zap_cursor_t zc;
482cde58dbMatthew Ahrens	zap_attribute_t za;
483cde58dbMatthew Ahrens	dmu_buf_t *bonus;
484cde58dbMatthew Ahrens	dsl_deadlist_phys_t *dlp;
485cde58dbMatthew Ahrens	dmu_object_info_t doi;
486cde58dbMatthew Ahrens
487b420f3aRichard Lowe	VERIFY3U(0, ==, dmu_object_info(dl->dl_os, obj, &doi));
488cde58dbMatthew Ahrens	if (doi.doi_type == DMU_OT_BPOBJ) {
489cde58dbMatthew Ahrens		bpobj_t bpo;
490b420f3aRichard Lowe		VERIFY3U(0, ==, bpobj_open(&bpo, dl->dl_os, obj));
491b420f3aRichard Lowe		VERIFY3U(0, ==, bpobj_iterate(&bpo,
492cde58dbMatthew Ahrens		    dsl_deadlist_insert_cb, dl, tx));
493cde58dbMatthew Ahrens		bpobj_close(&bpo);
494cde58dbMatthew Ahrens		return;
495cde58dbMatthew Ahrens	}
496cde58dbMatthew Ahrens
497a3905a4Serapheim Dimitropoulos	mutex_enter(&dl->dl_lock);
498cde58dbMatthew Ahrens	for (zap_cursor_init(&zc, dl->dl_os, obj);
499cde58dbMatthew Ahrens	    zap_cursor_retrieve(&zc, &za) == 0;
500cde58dbMatthew Ahrens	    zap_cursor_advance(&zc)) {
5014585130Yuri Pankov		uint64_t mintxg = zfs_strtonum(za.za_name, NULL);
502cde58dbMatthew Ahrens		dsl_deadlist_insert_bpobj(dl, za.za_first_integer, mintxg, tx);
503b420f3aRichard Lowe		VERIFY3U(0, ==, zap_remove_int(dl->dl_os, obj, mintxg, tx));
504cde58dbMatthew Ahrens	}
505cde58dbMatthew Ahrens	zap_cursor_fini(&zc);
506cde58dbMatthew Ahrens
507b420f3aRichard Lowe	VERIFY3U(0, ==, dmu_bonus_hold(dl->dl_os, obj, FTAG, &bonus));
508cde58dbMatthew Ahrens	dlp = bonus->db_data;
509cde58dbMatthew Ahrens	dmu_buf_will_dirty(bonus, tx);
510cde58dbMatthew Ahrens	bzero(dlp, sizeof (*dlp));
511cde58dbMatthew Ahrens	dmu_buf_rele(bonus, FTAG);
512a3905a4Serapheim Dimitropoulos	mutex_exit(&dl->dl_lock);
513cde58dbMatthew Ahrens}
514cde58dbMatthew Ahrens
515cde58dbMatthew Ahrens/*
516cde58dbMatthew Ahrens * Remove entries on dl that are >= mintxg, and put them on the bpobj.
517cde58dbMatthew Ahrens */
518cde58dbMatthew Ahrensvoid
519cde58dbMatthew Ahrensdsl_deadlist_move_bpobj(dsl_deadlist_t *dl, bpobj_t *bpo, uint64_t mintxg,
520cde58dbMatthew Ahrens    dmu_tx_t *tx)
521cde58dbMatthew Ahrens{
522cde58dbMatthew Ahrens	dsl_deadlist_entry_t dle_tofind;
523cde58dbMatthew Ahrens	dsl_deadlist_entry_t *dle;
524cde58dbMatthew Ahrens	avl_index_t where;
525cde58dbMatthew Ahrens
526cde58dbMatthew Ahrens	ASSERT(!dl->dl_oldfmt);
527a3905a4Serapheim Dimitropoulos
528a3905a4Serapheim Dimitropoulos	mutex_enter(&dl->dl_lock);
529cde58dbMatthew Ahrens	dmu_buf_will_dirty(dl->dl_dbuf, tx);
530cde58dbMatthew Ahrens	dsl_deadlist_load_tree(dl);
531cde58dbMatthew Ahrens
532cde58dbMatthew Ahrens	dle_tofind.dle_mintxg = mintxg;
533cde58dbMatthew Ahrens	dle = avl_find(&dl->dl_tree, &dle_tofind, &where);
534cde58dbMatthew Ahrens	if (dle == NULL)
535cde58dbMatthew Ahrens		dle = avl_nearest(&dl->dl_tree, where, AVL_AFTER);
536cde58dbMatthew Ahrens	while (dle) {
537cde58dbMatthew Ahrens		uint64_t used, comp, uncomp;
538cde58dbMatthew Ahrens		dsl_deadlist_entry_t *dle_next;
539cde58dbMatthew Ahrens
540cde58dbMatthew Ahrens		bpobj_enqueue_subobj(bpo, dle->dle_bpobj.bpo_object, tx);
541cde58dbMatthew Ahrens
542b420f3aRichard Lowe		VERIFY3U(0, ==, bpobj_space(&dle->dle_bpobj,
543cde58dbMatthew Ahrens		    &used, &comp, &uncomp));
544cde58dbMatthew Ahrens		ASSERT3U(dl->dl_phys->dl_used, >=, used);
545cde58dbMatthew Ahrens		ASSERT3U(dl->dl_phys->dl_comp, >=, comp);
546cde58dbMatthew Ahrens		ASSERT3U(dl->dl_phys->dl_uncomp, >=, uncomp);
547cde58dbMatthew Ahrens		dl->dl_phys->dl_used -= used;
548cde58dbMatthew Ahrens		dl->dl_phys->dl_comp -= comp;
549cde58dbMatthew Ahrens		dl->dl_phys->dl_uncomp -= uncomp;
550cde58dbMatthew Ahrens
551b420f3aRichard Lowe		VERIFY3U(0, ==, zap_remove_int(dl->dl_os, dl->dl_object,
552cde58dbMatthew Ahrens		    dle->dle_mintxg, tx));
553cde58dbMatthew Ahrens
554cde58dbMatthew Ahrens		dle_next = AVL_NEXT(&dl->dl_tree, dle);
555cde58dbMatthew Ahrens		avl_remove(&dl->dl_tree, dle);
556cde58dbMatthew Ahrens		bpobj_close(&dle->dle_bpobj);
557cde58dbMatthew Ahrens		kmem_free(dle, sizeof (*dle));
558cde58dbMatthew Ahrens		dle = dle_next;
559cde58dbMatthew Ahrens	}
560a3905a4Serapheim Dimitropoulos	mutex_exit(&dl->dl_lock);
561cde58dbMatthew Ahrens}
562