15cabbc6Prashanth Sreenivasa/*
25cabbc6Prashanth Sreenivasa * CDDL HEADER START
35cabbc6Prashanth Sreenivasa *
45cabbc6Prashanth Sreenivasa * This file and its contents are supplied under the terms of the
55cabbc6Prashanth Sreenivasa * Common Development and Distribution License ("CDDL"), version 1.0.
65cabbc6Prashanth Sreenivasa * You may only use this file in accordance with the terms of version
75cabbc6Prashanth Sreenivasa * 1.0 of the CDDL.
85cabbc6Prashanth Sreenivasa *
95cabbc6Prashanth Sreenivasa * A full copy of the text of the CDDL should have accompanied this
105cabbc6Prashanth Sreenivasa * source.  A copy of the CDDL is also available via the Internet at
115cabbc6Prashanth Sreenivasa * http://www.illumos.org/license/CDDL.
125cabbc6Prashanth Sreenivasa *
135cabbc6Prashanth Sreenivasa * CDDL HEADER END
145cabbc6Prashanth Sreenivasa */
155cabbc6Prashanth Sreenivasa
165cabbc6Prashanth Sreenivasa/*
175cabbc6Prashanth Sreenivasa * Copyright (c) 2015 by Delphix. All rights reserved.
185cabbc6Prashanth Sreenivasa */
195cabbc6Prashanth Sreenivasa
205cabbc6Prashanth Sreenivasa#include <sys/dmu_tx.h>
215cabbc6Prashanth Sreenivasa#include <sys/spa.h>
225cabbc6Prashanth Sreenivasa#include <sys/dmu.h>
235cabbc6Prashanth Sreenivasa#include <sys/dsl_pool.h>
245cabbc6Prashanth Sreenivasa#include <sys/vdev_indirect_births.h>
255cabbc6Prashanth Sreenivasa
265cabbc6Prashanth Sreenivasastatic boolean_t
275cabbc6Prashanth Sreenivasavdev_indirect_births_verify(vdev_indirect_births_t *vib)
285cabbc6Prashanth Sreenivasa{
295cabbc6Prashanth Sreenivasa	ASSERT(vib != NULL);
305cabbc6Prashanth Sreenivasa
315cabbc6Prashanth Sreenivasa	ASSERT(vib->vib_object != 0);
325cabbc6Prashanth Sreenivasa	ASSERT(vib->vib_objset != NULL);
335cabbc6Prashanth Sreenivasa	ASSERT(vib->vib_phys != NULL);
345cabbc6Prashanth Sreenivasa	ASSERT(vib->vib_dbuf != NULL);
355cabbc6Prashanth Sreenivasa
365cabbc6Prashanth Sreenivasa	EQUIV(vib->vib_phys->vib_count > 0, vib->vib_entries != NULL);
375cabbc6Prashanth Sreenivasa
385cabbc6Prashanth Sreenivasa	return (B_TRUE);
395cabbc6Prashanth Sreenivasa}
405cabbc6Prashanth Sreenivasa
415cabbc6Prashanth Sreenivasauint64_t
425cabbc6Prashanth Sreenivasavdev_indirect_births_count(vdev_indirect_births_t *vib)
435cabbc6Prashanth Sreenivasa{
445cabbc6Prashanth Sreenivasa	ASSERT(vdev_indirect_births_verify(vib));
455cabbc6Prashanth Sreenivasa
465cabbc6Prashanth Sreenivasa	return (vib->vib_phys->vib_count);
475cabbc6Prashanth Sreenivasa}
485cabbc6Prashanth Sreenivasa
495cabbc6Prashanth Sreenivasauint64_t
505cabbc6Prashanth Sreenivasavdev_indirect_births_object(vdev_indirect_births_t *vib)
515cabbc6Prashanth Sreenivasa{
525cabbc6Prashanth Sreenivasa	ASSERT(vdev_indirect_births_verify(vib));
535cabbc6Prashanth Sreenivasa
545cabbc6Prashanth Sreenivasa	return (vib->vib_object);
555cabbc6Prashanth Sreenivasa}
565cabbc6Prashanth Sreenivasa
575cabbc6Prashanth Sreenivasastatic uint64_t
585cabbc6Prashanth Sreenivasavdev_indirect_births_size_impl(vdev_indirect_births_t *vib)
595cabbc6Prashanth Sreenivasa{
605cabbc6Prashanth Sreenivasa	return (vib->vib_phys->vib_count * sizeof (*vib->vib_entries));
615cabbc6Prashanth Sreenivasa}
625cabbc6Prashanth Sreenivasa
635cabbc6Prashanth Sreenivasavoid
645cabbc6Prashanth Sreenivasavdev_indirect_births_close(vdev_indirect_births_t *vib)
655cabbc6Prashanth Sreenivasa{
665cabbc6Prashanth Sreenivasa	ASSERT(vdev_indirect_births_verify(vib));
675cabbc6Prashanth Sreenivasa
685cabbc6Prashanth Sreenivasa	if (vib->vib_phys->vib_count > 0) {
695cabbc6Prashanth Sreenivasa		uint64_t births_size = vdev_indirect_births_size_impl(vib);
705cabbc6Prashanth Sreenivasa
715cabbc6Prashanth Sreenivasa		kmem_free(vib->vib_entries, births_size);
725cabbc6Prashanth Sreenivasa		vib->vib_entries = NULL;
735cabbc6Prashanth Sreenivasa	}
745cabbc6Prashanth Sreenivasa
755cabbc6Prashanth Sreenivasa	dmu_buf_rele(vib->vib_dbuf, vib);
765cabbc6Prashanth Sreenivasa
775cabbc6Prashanth Sreenivasa	vib->vib_objset = NULL;
785cabbc6Prashanth Sreenivasa	vib->vib_object = 0;
795cabbc6Prashanth Sreenivasa	vib->vib_dbuf = NULL;
805cabbc6Prashanth Sreenivasa	vib->vib_phys = NULL;
815cabbc6Prashanth Sreenivasa
825cabbc6Prashanth Sreenivasa	kmem_free(vib, sizeof (*vib));
835cabbc6Prashanth Sreenivasa}
845cabbc6Prashanth Sreenivasa
855cabbc6Prashanth Sreenivasauint64_t
865cabbc6Prashanth Sreenivasavdev_indirect_births_alloc(objset_t *os, dmu_tx_t *tx)
875cabbc6Prashanth Sreenivasa{
885cabbc6Prashanth Sreenivasa	ASSERT(dmu_tx_is_syncing(tx));
895cabbc6Prashanth Sreenivasa
905cabbc6Prashanth Sreenivasa	return (dmu_object_alloc(os,
915cabbc6Prashanth Sreenivasa	    DMU_OTN_UINT64_METADATA, SPA_OLD_MAXBLOCKSIZE,
925cabbc6Prashanth Sreenivasa	    DMU_OTN_UINT64_METADATA, sizeof (vdev_indirect_birth_phys_t),
935cabbc6Prashanth Sreenivasa	    tx));
945cabbc6Prashanth Sreenivasa}
955cabbc6Prashanth Sreenivasa
965cabbc6Prashanth Sreenivasavdev_indirect_births_t *
975cabbc6Prashanth Sreenivasavdev_indirect_births_open(objset_t *os, uint64_t births_object)
985cabbc6Prashanth Sreenivasa{
995cabbc6Prashanth Sreenivasa	vdev_indirect_births_t *vib = kmem_zalloc(sizeof (*vib), KM_SLEEP);
1005cabbc6Prashanth Sreenivasa
1015cabbc6Prashanth Sreenivasa	vib->vib_objset = os;
1025cabbc6Prashanth Sreenivasa	vib->vib_object = births_object;
1035cabbc6Prashanth Sreenivasa
1045cabbc6Prashanth Sreenivasa	VERIFY0(dmu_bonus_hold(os, vib->vib_object, vib, &vib->vib_dbuf));
1055cabbc6Prashanth Sreenivasa	vib->vib_phys = vib->vib_dbuf->db_data;
1065cabbc6Prashanth Sreenivasa
1075cabbc6Prashanth Sreenivasa	if (vib->vib_phys->vib_count > 0) {
1085cabbc6Prashanth Sreenivasa		uint64_t births_size = vdev_indirect_births_size_impl(vib);
1095cabbc6Prashanth Sreenivasa		vib->vib_entries = kmem_alloc(births_size, KM_SLEEP);
1105cabbc6Prashanth Sreenivasa		VERIFY0(dmu_read(vib->vib_objset, vib->vib_object, 0,
1115cabbc6Prashanth Sreenivasa		    births_size, vib->vib_entries, DMU_READ_PREFETCH));
1125cabbc6Prashanth Sreenivasa	}
1135cabbc6Prashanth Sreenivasa
1145cabbc6Prashanth Sreenivasa	ASSERT(vdev_indirect_births_verify(vib));
1155cabbc6Prashanth Sreenivasa
1165cabbc6Prashanth Sreenivasa	return (vib);
1175cabbc6Prashanth Sreenivasa}
1185cabbc6Prashanth Sreenivasa
1195cabbc6Prashanth Sreenivasavoid
1205cabbc6Prashanth Sreenivasavdev_indirect_births_free(objset_t *os, uint64_t object, dmu_tx_t *tx)
1215cabbc6Prashanth Sreenivasa{
1225cabbc6Prashanth Sreenivasa	VERIFY0(dmu_object_free(os, object, tx));
1235cabbc6Prashanth Sreenivasa}
1245cabbc6Prashanth Sreenivasa
1255cabbc6Prashanth Sreenivasavoid
1265cabbc6Prashanth Sreenivasavdev_indirect_births_add_entry(vdev_indirect_births_t *vib,
1275cabbc6Prashanth Sreenivasa    uint64_t max_offset, uint64_t txg, dmu_tx_t *tx)
1285cabbc6Prashanth Sreenivasa{
1295cabbc6Prashanth Sreenivasa	vdev_indirect_birth_entry_phys_t vibe;
1305cabbc6Prashanth Sreenivasa	uint64_t old_size;
1315cabbc6Prashanth Sreenivasa	uint64_t new_size;
1325cabbc6Prashanth Sreenivasa	vdev_indirect_birth_entry_phys_t *new_entries;
1335cabbc6Prashanth Sreenivasa
1345cabbc6Prashanth Sreenivasa	ASSERT(dmu_tx_is_syncing(tx));
1355cabbc6Prashanth Sreenivasa	ASSERT(dsl_pool_sync_context(dmu_tx_pool(tx)));
1365cabbc6Prashanth Sreenivasa	ASSERT(vdev_indirect_births_verify(vib));
1375cabbc6Prashanth Sreenivasa
1385cabbc6Prashanth Sreenivasa	dmu_buf_will_dirty(vib->vib_dbuf, tx);
1395cabbc6Prashanth Sreenivasa
1405cabbc6Prashanth Sreenivasa	vibe.vibe_offset = max_offset;
1415cabbc6Prashanth Sreenivasa	vibe.vibe_phys_birth_txg = txg;
1425cabbc6Prashanth Sreenivasa
1435cabbc6Prashanth Sreenivasa	old_size = vdev_indirect_births_size_impl(vib);
1445cabbc6Prashanth Sreenivasa	dmu_write(vib->vib_objset, vib->vib_object, old_size, sizeof (vibe),
1455cabbc6Prashanth Sreenivasa	    &vibe, tx);
1465cabbc6Prashanth Sreenivasa	vib->vib_phys->vib_count++;
1475cabbc6Prashanth Sreenivasa	new_size = vdev_indirect_births_size_impl(vib);
1485cabbc6Prashanth Sreenivasa
1495cabbc6Prashanth Sreenivasa	new_entries = kmem_alloc(new_size, KM_SLEEP);
1505cabbc6Prashanth Sreenivasa	if (old_size > 0) {
1515cabbc6Prashanth Sreenivasa		bcopy(vib->vib_entries, new_entries, old_size);
1525cabbc6Prashanth Sreenivasa		kmem_free(vib->vib_entries, old_size);
1535cabbc6Prashanth Sreenivasa	}
1545cabbc6Prashanth Sreenivasa	new_entries[vib->vib_phys->vib_count - 1] = vibe;
1555cabbc6Prashanth Sreenivasa	vib->vib_entries = new_entries;
1565cabbc6Prashanth Sreenivasa}
1575cabbc6Prashanth Sreenivasa
1585cabbc6Prashanth Sreenivasauint64_t
1595cabbc6Prashanth Sreenivasavdev_indirect_births_last_entry_txg(vdev_indirect_births_t *vib)
1605cabbc6Prashanth Sreenivasa{
1615cabbc6Prashanth Sreenivasa	ASSERT(vdev_indirect_births_verify(vib));
1625cabbc6Prashanth Sreenivasa	ASSERT(vib->vib_phys->vib_count > 0);
1635cabbc6Prashanth Sreenivasa
1645cabbc6Prashanth Sreenivasa	vdev_indirect_birth_entry_phys_t *last =
1655cabbc6Prashanth Sreenivasa	    &vib->vib_entries[vib->vib_phys->vib_count - 1];
1665cabbc6Prashanth Sreenivasa	return (last->vibe_phys_birth_txg);
1675cabbc6Prashanth Sreenivasa}
1685cabbc6Prashanth Sreenivasa
1695cabbc6Prashanth Sreenivasa/*
1705cabbc6Prashanth Sreenivasa * Return the txg in which the given range was copied (i.e. its physical
1715cabbc6Prashanth Sreenivasa * birth txg).  The specified offset+asize must be contiguously mapped
1725cabbc6Prashanth Sreenivasa * (i.e. not a split block).
1735cabbc6Prashanth Sreenivasa *
1745cabbc6Prashanth Sreenivasa * The entries are sorted by increasing phys_birth, and also by increasing
1755cabbc6Prashanth Sreenivasa * offset.  We find the specified offset by binary search.  Note that we
1765cabbc6Prashanth Sreenivasa * can not use bsearch() because looking at each entry independently is
1775cabbc6Prashanth Sreenivasa * insufficient to find the correct entry.  Each entry implicitly relies
1785cabbc6Prashanth Sreenivasa * on the previous entry: an entry indicates that the offsets from the
1795cabbc6Prashanth Sreenivasa * end of the previous entry to the end of this entry were written in the
1805cabbc6Prashanth Sreenivasa * specified txg.
1815cabbc6Prashanth Sreenivasa */
1825cabbc6Prashanth Sreenivasauint64_t
1835cabbc6Prashanth Sreenivasavdev_indirect_births_physbirth(vdev_indirect_births_t *vib, uint64_t offset,
1845cabbc6Prashanth Sreenivasa    uint64_t asize)
1855cabbc6Prashanth Sreenivasa{
1865cabbc6Prashanth Sreenivasa	vdev_indirect_birth_entry_phys_t *base;
1875cabbc6Prashanth Sreenivasa	vdev_indirect_birth_entry_phys_t *last;
1885cabbc6Prashanth Sreenivasa
1895cabbc6Prashanth Sreenivasa	ASSERT(vdev_indirect_births_verify(vib));
1905cabbc6Prashanth Sreenivasa	ASSERT(vib->vib_phys->vib_count > 0);
1915cabbc6Prashanth Sreenivasa
1925cabbc6Prashanth Sreenivasa	base = vib->vib_entries;
1935cabbc6Prashanth Sreenivasa	last = base + vib->vib_phys->vib_count - 1;
1945cabbc6Prashanth Sreenivasa
1955cabbc6Prashanth Sreenivasa	ASSERT3U(offset, <, last->vibe_offset);
1965cabbc6Prashanth Sreenivasa
1975cabbc6Prashanth Sreenivasa	while (last >= base) {
1985cabbc6Prashanth Sreenivasa		vdev_indirect_birth_entry_phys_t *p =
1995cabbc6Prashanth Sreenivasa		    base + ((last - base) / 2);
2005cabbc6Prashanth Sreenivasa		if (offset >= p->vibe_offset) {
2015cabbc6Prashanth Sreenivasa			base = p + 1;
2025cabbc6Prashanth Sreenivasa		} else if (p == vib->vib_entries ||
2035cabbc6Prashanth Sreenivasa		    offset >= (p - 1)->vibe_offset) {
2045cabbc6Prashanth Sreenivasa			ASSERT3U(offset + asize, <=, p->vibe_offset);
2055cabbc6Prashanth Sreenivasa			return (p->vibe_phys_birth_txg);
2065cabbc6Prashanth Sreenivasa		} else {
2075cabbc6Prashanth Sreenivasa			last = p - 1;
2085cabbc6Prashanth Sreenivasa		}
2095cabbc6Prashanth Sreenivasa	}
2105cabbc6Prashanth Sreenivasa	ASSERT(!"offset not found");
2115cabbc6Prashanth Sreenivasa	return (-1);
2125cabbc6Prashanth Sreenivasa}
213