1168404Spjd/* 2168404Spjd * CDDL HEADER START 3168404Spjd * 4168404Spjd * The contents of this file are subject to the terms of the 5168404Spjd * Common Development and Distribution License (the "License"). 6168404Spjd * You may not use this file except in compliance with the License. 7168404Spjd * 8168404Spjd * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9168404Spjd * or http://www.opensolaris.org/os/licensing. 10168404Spjd * See the License for the specific language governing permissions 11168404Spjd * and limitations under the License. 12168404Spjd * 13168404Spjd * When distributing Covered Code, include this CDDL HEADER in each 14168404Spjd * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15168404Spjd * If applicable, add the following below this CDDL HEADER, with the 16168404Spjd * fields enclosed by brackets "[]" replaced with your own identifying 17168404Spjd * information: Portions Copyright [yyyy] [name of copyright owner] 18168404Spjd * 19168404Spjd * CDDL HEADER END 20168404Spjd */ 21168404Spjd/* 22209962Smm * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23168404Spjd * Use is subject to license terms. 24168404Spjd */ 25243674Smm/* 26265751Sdelphij * Copyright (c) 2012, 2014 by Delphix. All rights reserved. 27243674Smm */ 28168404Spjd 29168404Spjd#include <sys/zfs_context.h> 30168404Spjd#include <sys/spa.h> 31168404Spjd#include <sys/dmu.h> 32262094Savg#include <sys/dmu_tx.h> 33262094Savg#include <sys/dnode.h> 34262094Savg#include <sys/dsl_pool.h> 35168404Spjd#include <sys/zio.h> 36168404Spjd#include <sys/space_map.h> 37262094Savg#include <sys/refcount.h> 38262094Savg#include <sys/zfeature.h> 39168404Spjd 40168404Spjd/* 41262094Savg * This value controls how the space map's block size is allowed to grow. 42262094Savg * If the value is set to the same size as SPACE_MAP_INITIAL_BLOCKSIZE then 43262094Savg * the space map block size will remain fixed. Setting this value to something 44262094Savg * greater than SPACE_MAP_INITIAL_BLOCKSIZE will allow the space map to 45262094Savg * increase its block size as needed. To maintain backwards compatibilty the 46262094Savg * space map's block size must be a power of 2 and SPACE_MAP_INITIAL_BLOCKSIZE 47262094Savg * or larger. 48168404Spjd */ 49262094Savgint space_map_max_blksz = (1 << 12); 50168404Spjd 51168404Spjd/* 52262094Savg * Load the space map disk into the specified range tree. Segments of maptype 53262094Savg * are added to the range tree, other segment types are removed. 54262094Savg * 55168404Spjd * Note: space_map_load() will drop sm_lock across dmu_read() calls. 56168404Spjd * The caller must be OK with this. 57168404Spjd */ 58168404Spjdint 59262094Savgspace_map_load(space_map_t *sm, range_tree_t *rt, maptype_t maptype) 60168404Spjd{ 61168404Spjd uint64_t *entry, *entry_map, *entry_map_end; 62168404Spjd uint64_t bufsize, size, offset, end, space; 63185029Spjd int error = 0; 64168404Spjd 65168404Spjd ASSERT(MUTEX_HELD(sm->sm_lock)); 66168404Spjd 67262094Savg end = space_map_length(sm); 68262094Savg space = space_map_allocated(sm); 69168404Spjd 70262094Savg VERIFY0(range_tree_space(rt)); 71168404Spjd 72168404Spjd if (maptype == SM_FREE) { 73262094Savg range_tree_add(rt, sm->sm_start, sm->sm_size); 74168404Spjd space = sm->sm_size - space; 75168404Spjd } 76168404Spjd 77262094Savg bufsize = MAX(sm->sm_blksz, SPA_MINBLOCKSIZE); 78168404Spjd entry_map = zio_buf_alloc(bufsize); 79168404Spjd 80168404Spjd mutex_exit(sm->sm_lock); 81262094Savg if (end > bufsize) { 82262094Savg dmu_prefetch(sm->sm_os, space_map_object(sm), bufsize, 83262094Savg end - bufsize); 84262094Savg } 85168404Spjd mutex_enter(sm->sm_lock); 86168404Spjd 87168404Spjd for (offset = 0; offset < end; offset += bufsize) { 88168404Spjd size = MIN(end - offset, bufsize); 89168404Spjd VERIFY(P2PHASE(size, sizeof (uint64_t)) == 0); 90168404Spjd VERIFY(size != 0); 91262094Savg ASSERT3U(sm->sm_blksz, !=, 0); 92168404Spjd 93168404Spjd dprintf("object=%llu offset=%llx size=%llx\n", 94262094Savg space_map_object(sm), offset, size); 95168404Spjd 96168404Spjd mutex_exit(sm->sm_lock); 97262094Savg error = dmu_read(sm->sm_os, space_map_object(sm), offset, size, 98262094Savg entry_map, DMU_READ_PREFETCH); 99168404Spjd mutex_enter(sm->sm_lock); 100185029Spjd if (error != 0) 101185029Spjd break; 102168404Spjd 103168404Spjd entry_map_end = entry_map + (size / sizeof (uint64_t)); 104168404Spjd for (entry = entry_map; entry < entry_map_end; entry++) { 105168404Spjd uint64_t e = *entry; 106262094Savg uint64_t offset, size; 107168404Spjd 108168404Spjd if (SM_DEBUG_DECODE(e)) /* Skip debug entries */ 109168404Spjd continue; 110168404Spjd 111262094Savg offset = (SM_OFFSET_DECODE(e) << sm->sm_shift) + 112262094Savg sm->sm_start; 113262094Savg size = SM_RUN_DECODE(e) << sm->sm_shift; 114262094Savg 115262094Savg VERIFY0(P2PHASE(offset, 1ULL << sm->sm_shift)); 116262094Savg VERIFY0(P2PHASE(size, 1ULL << sm->sm_shift)); 117262094Savg VERIFY3U(offset, >=, sm->sm_start); 118262094Savg VERIFY3U(offset + size, <=, sm->sm_start + sm->sm_size); 119262094Savg if (SM_TYPE_DECODE(e) == maptype) { 120262094Savg VERIFY3U(range_tree_space(rt) + size, <=, 121262094Savg sm->sm_size); 122262094Savg range_tree_add(rt, offset, size); 123262094Savg } else { 124262094Savg range_tree_remove(rt, offset, size); 125262094Savg } 126168404Spjd } 127168404Spjd } 128168404Spjd 129262094Savg if (error == 0) 130262094Savg VERIFY3U(range_tree_space(rt), ==, space); 131262094Savg else 132262094Savg range_tree_vacate(rt, NULL, NULL); 133185029Spjd 134168404Spjd zio_buf_free(entry_map, bufsize); 135262094Savg return (error); 136262094Savg} 137168404Spjd 138262094Savgvoid 139262094Savgspace_map_histogram_clear(space_map_t *sm) 140262094Savg{ 141262094Savg if (sm->sm_dbuf->db_size != sizeof (space_map_phys_t)) 142262094Savg return; 143168404Spjd 144262094Savg bzero(sm->sm_phys->smp_histogram, sizeof (sm->sm_phys->smp_histogram)); 145262094Savg} 146168404Spjd 147262094Savgboolean_t 148262094Savgspace_map_histogram_verify(space_map_t *sm, range_tree_t *rt) 149262094Savg{ 150262094Savg /* 151262094Savg * Verify that the in-core range tree does not have any 152262094Savg * ranges smaller than our sm_shift size. 153262094Savg */ 154262094Savg for (int i = 0; i < sm->sm_shift; i++) { 155262094Savg if (rt->rt_histogram[i] != 0) 156262094Savg return (B_FALSE); 157262094Savg } 158262094Savg return (B_TRUE); 159168404Spjd} 160168404Spjd 161168404Spjdvoid 162262094Savgspace_map_histogram_add(space_map_t *sm, range_tree_t *rt, dmu_tx_t *tx) 163168404Spjd{ 164262094Savg int idx = 0; 165168404Spjd 166262094Savg ASSERT(MUTEX_HELD(rt->rt_lock)); 167262094Savg ASSERT(dmu_tx_is_syncing(tx)); 168262094Savg VERIFY3U(space_map_object(sm), !=, 0); 169168404Spjd 170262094Savg if (sm->sm_dbuf->db_size != sizeof (space_map_phys_t)) 171262094Savg return; 172168404Spjd 173262094Savg dmu_buf_will_dirty(sm->sm_dbuf, tx); 174168404Spjd 175262094Savg ASSERT(space_map_histogram_verify(sm, rt)); 176262094Savg 177262094Savg /* 178262094Savg * Transfer the content of the range tree histogram to the space 179262094Savg * map histogram. The space map histogram contains 32 buckets ranging 180262094Savg * between 2^sm_shift to 2^(32+sm_shift-1). The range tree, 181262094Savg * however, can represent ranges from 2^0 to 2^63. Since the space 182262094Savg * map only cares about allocatable blocks (minimum of sm_shift) we 183262094Savg * can safely ignore all ranges in the range tree smaller than sm_shift. 184262094Savg */ 185262094Savg for (int i = sm->sm_shift; i < RANGE_TREE_HISTOGRAM_SIZE; i++) { 186262094Savg 187262094Savg /* 188262094Savg * Since the largest histogram bucket in the space map is 189262094Savg * 2^(32+sm_shift-1), we need to normalize the values in 190262094Savg * the range tree for any bucket larger than that size. For 191262094Savg * example given an sm_shift of 9, ranges larger than 2^40 192262094Savg * would get normalized as if they were 1TB ranges. Assume 193262094Savg * the range tree had a count of 5 in the 2^44 (16TB) bucket, 194262094Savg * the calculation below would normalize this to 5 * 2^4 (16). 195262094Savg */ 196262094Savg ASSERT3U(i, >=, idx + sm->sm_shift); 197262094Savg sm->sm_phys->smp_histogram[idx] += 198262094Savg rt->rt_histogram[i] << (i - idx - sm->sm_shift); 199262094Savg 200262094Savg /* 201262094Savg * Increment the space map's index as long as we haven't 202262094Savg * reached the maximum bucket size. Accumulate all ranges 203262094Savg * larger than the max bucket size into the last bucket. 204262094Savg */ 205262094Savg if (idx < SPACE_MAP_HISTOGRAM_SIZE(sm) - 1) { 206262094Savg ASSERT3U(idx + sm->sm_shift, ==, i); 207262094Savg idx++; 208262094Savg ASSERT3U(idx, <, SPACE_MAP_HISTOGRAM_SIZE(sm)); 209262094Savg } 210262094Savg } 211209962Smm} 212209962Smm 213209962Smmuint64_t 214262094Savgspace_map_entries(space_map_t *sm, range_tree_t *rt) 215168404Spjd{ 216262094Savg avl_tree_t *t = &rt->rt_root; 217262094Savg range_seg_t *rs; 218262094Savg uint64_t size, entries; 219168404Spjd 220262094Savg /* 221262094Savg * All space_maps always have a debug entry so account for it here. 222262094Savg */ 223262094Savg entries = 1; 224262094Savg 225262094Savg /* 226262094Savg * Traverse the range tree and calculate the number of space map 227262094Savg * entries that would be required to write out the range tree. 228262094Savg */ 229262094Savg for (rs = avl_first(t); rs != NULL; rs = AVL_NEXT(t, rs)) { 230262094Savg size = (rs->rs_end - rs->rs_start) >> sm->sm_shift; 231262094Savg entries += howmany(size, SM_RUN_MAX); 232262094Savg } 233262094Savg return (entries); 234168404Spjd} 235168404Spjd 236168404Spjdvoid 237262094Savgspace_map_set_blocksize(space_map_t *sm, uint64_t size, dmu_tx_t *tx) 238168404Spjd{ 239262094Savg uint32_t blksz; 240262094Savg u_longlong_t blocks; 241168404Spjd 242262094Savg ASSERT3U(sm->sm_blksz, !=, 0); 243262094Savg ASSERT3U(space_map_object(sm), !=, 0); 244262094Savg ASSERT(sm->sm_dbuf != NULL); 245262094Savg VERIFY(ISP2(space_map_max_blksz)); 246262094Savg 247262094Savg if (sm->sm_blksz >= space_map_max_blksz) 248262094Savg return; 249262094Savg 250262094Savg /* 251262094Savg * The object contains more than one block so we can't adjust 252262094Savg * its size. 253262094Savg */ 254262094Savg if (sm->sm_phys->smp_objsize > sm->sm_blksz) 255262094Savg return; 256262094Savg 257262094Savg if (size > sm->sm_blksz) { 258262094Savg uint64_t newsz; 259262094Savg 260262094Savg /* 261262094Savg * Older software versions treat space map blocks as fixed 262262094Savg * entities. The DMU is capable of handling different block 263262094Savg * sizes making it possible for us to increase the 264262094Savg * block size and maintain backwards compatibility. The 265262094Savg * caveat is that the new block sizes must be a 266262094Savg * power of 2 so that old software can append to the file, 267262094Savg * adding more blocks. The block size can grow until it 268262094Savg * reaches space_map_max_blksz. 269262094Savg */ 270265751Sdelphij newsz = ISP2(size) ? size : 1ULL << highbit64(size); 271262094Savg if (newsz > space_map_max_blksz) 272262094Savg newsz = space_map_max_blksz; 273262094Savg 274262094Savg VERIFY0(dmu_object_set_blocksize(sm->sm_os, 275262094Savg space_map_object(sm), newsz, 0, tx)); 276262094Savg dmu_object_size_from_db(sm->sm_dbuf, &blksz, &blocks); 277262094Savg 278262094Savg zfs_dbgmsg("txg %llu, spa %s, increasing blksz from %d to %d", 279262094Savg dmu_tx_get_txg(tx), spa_name(dmu_objset_spa(sm->sm_os)), 280262094Savg sm->sm_blksz, blksz); 281262094Savg 282262094Savg VERIFY3U(newsz, ==, blksz); 283262094Savg VERIFY3U(sm->sm_blksz, <, blksz); 284262094Savg sm->sm_blksz = blksz; 285262094Savg } 286168404Spjd} 287168404Spjd 288168404Spjd/* 289262094Savg * Note: space_map_write() will drop sm_lock across dmu_write() calls. 290168404Spjd */ 291168404Spjdvoid 292262094Savgspace_map_write(space_map_t *sm, range_tree_t *rt, maptype_t maptype, 293262094Savg dmu_tx_t *tx) 294168404Spjd{ 295262094Savg objset_t *os = sm->sm_os; 296168404Spjd spa_t *spa = dmu_objset_spa(os); 297262094Savg avl_tree_t *t = &rt->rt_root; 298262094Savg range_seg_t *rs; 299262094Savg uint64_t size, total, rt_space, nodes; 300168404Spjd uint64_t *entry, *entry_map, *entry_map_end; 301262094Savg uint64_t newsz, expected_entries, actual_entries = 1; 302168404Spjd 303262094Savg ASSERT(MUTEX_HELD(rt->rt_lock)); 304262094Savg ASSERT(dsl_pool_sync_context(dmu_objset_pool(os))); 305262094Savg VERIFY3U(space_map_object(sm), !=, 0); 306262094Savg dmu_buf_will_dirty(sm->sm_dbuf, tx); 307168404Spjd 308262094Savg /* 309262094Savg * This field is no longer necessary since the in-core space map 310262094Savg * now contains the object number but is maintained for backwards 311262094Savg * compatibility. 312262094Savg */ 313262094Savg sm->sm_phys->smp_object = sm->sm_object; 314262094Savg 315262094Savg if (range_tree_space(rt) == 0) { 316262094Savg VERIFY3U(sm->sm_object, ==, sm->sm_phys->smp_object); 317168404Spjd return; 318262094Savg } 319168404Spjd 320168404Spjd if (maptype == SM_ALLOC) 321262094Savg sm->sm_phys->smp_alloc += range_tree_space(rt); 322168404Spjd else 323262094Savg sm->sm_phys->smp_alloc -= range_tree_space(rt); 324168404Spjd 325262094Savg expected_entries = space_map_entries(sm, rt); 326262094Savg 327262094Savg /* 328262094Savg * Calculate the new size for the space map on-disk and see if 329262094Savg * we can grow the block size to accommodate the new size. 330262094Savg */ 331262094Savg newsz = sm->sm_phys->smp_objsize + expected_entries * sizeof (uint64_t); 332262094Savg space_map_set_blocksize(sm, newsz, tx); 333262094Savg 334262094Savg entry_map = zio_buf_alloc(sm->sm_blksz); 335262094Savg entry_map_end = entry_map + (sm->sm_blksz / sizeof (uint64_t)); 336168404Spjd entry = entry_map; 337168404Spjd 338168404Spjd *entry++ = SM_DEBUG_ENCODE(1) | 339168404Spjd SM_DEBUG_ACTION_ENCODE(maptype) | 340168404Spjd SM_DEBUG_SYNCPASS_ENCODE(spa_sync_pass(spa)) | 341168404Spjd SM_DEBUG_TXG_ENCODE(dmu_tx_get_txg(tx)); 342168404Spjd 343248369Smm total = 0; 344262094Savg nodes = avl_numnodes(&rt->rt_root); 345262094Savg rt_space = range_tree_space(rt); 346262094Savg for (rs = avl_first(t); rs != NULL; rs = AVL_NEXT(t, rs)) { 347262094Savg uint64_t start; 348168404Spjd 349262094Savg size = (rs->rs_end - rs->rs_start) >> sm->sm_shift; 350262094Savg start = (rs->rs_start - sm->sm_start) >> sm->sm_shift; 351168404Spjd 352262094Savg total += size << sm->sm_shift; 353262094Savg 354262094Savg while (size != 0) { 355262094Savg uint64_t run_len; 356262094Savg 357168404Spjd run_len = MIN(size, SM_RUN_MAX); 358168404Spjd 359168404Spjd if (entry == entry_map_end) { 360262094Savg mutex_exit(rt->rt_lock); 361262094Savg dmu_write(os, space_map_object(sm), 362262094Savg sm->sm_phys->smp_objsize, sm->sm_blksz, 363262094Savg entry_map, tx); 364262094Savg mutex_enter(rt->rt_lock); 365262094Savg sm->sm_phys->smp_objsize += sm->sm_blksz; 366168404Spjd entry = entry_map; 367168404Spjd } 368168404Spjd 369168404Spjd *entry++ = SM_OFFSET_ENCODE(start) | 370168404Spjd SM_TYPE_ENCODE(maptype) | 371168404Spjd SM_RUN_ENCODE(run_len); 372168404Spjd 373168404Spjd start += run_len; 374168404Spjd size -= run_len; 375262094Savg actual_entries++; 376168404Spjd } 377168404Spjd } 378168404Spjd 379168404Spjd if (entry != entry_map) { 380168404Spjd size = (entry - entry_map) * sizeof (uint64_t); 381262094Savg mutex_exit(rt->rt_lock); 382262094Savg dmu_write(os, space_map_object(sm), sm->sm_phys->smp_objsize, 383168404Spjd size, entry_map, tx); 384262094Savg mutex_enter(rt->rt_lock); 385262094Savg sm->sm_phys->smp_objsize += size; 386168404Spjd } 387262094Savg ASSERT3U(expected_entries, ==, actual_entries); 388168404Spjd 389244087Smm /* 390244087Smm * Ensure that the space_map's accounting wasn't changed 391244087Smm * while we were in the middle of writing it out. 392244087Smm */ 393262094Savg VERIFY3U(nodes, ==, avl_numnodes(&rt->rt_root)); 394262094Savg VERIFY3U(range_tree_space(rt), ==, rt_space); 395262094Savg VERIFY3U(range_tree_space(rt), ==, total); 396244087Smm 397262094Savg zio_buf_free(entry_map, sm->sm_blksz); 398168404Spjd} 399168404Spjd 400262094Savgstatic int 401262094Savgspace_map_open_impl(space_map_t *sm) 402168404Spjd{ 403262094Savg int error; 404262094Savg u_longlong_t blocks; 405168404Spjd 406262094Savg error = dmu_bonus_hold(sm->sm_os, sm->sm_object, sm, &sm->sm_dbuf); 407262094Savg if (error) 408262094Savg return (error); 409262094Savg 410262094Savg dmu_object_size_from_db(sm->sm_dbuf, &sm->sm_blksz, &blocks); 411262094Savg sm->sm_phys = sm->sm_dbuf->db_data; 412262094Savg return (0); 413168404Spjd} 414209962Smm 415262094Savgint 416262094Savgspace_map_open(space_map_t **smp, objset_t *os, uint64_t object, 417262094Savg uint64_t start, uint64_t size, uint8_t shift, kmutex_t *lp) 418209962Smm{ 419262094Savg space_map_t *sm; 420262094Savg int error; 421209962Smm 422262094Savg ASSERT(*smp == NULL); 423262094Savg ASSERT(os != NULL); 424262094Savg ASSERT(object != 0); 425209962Smm 426262094Savg sm = kmem_zalloc(sizeof (space_map_t), KM_SLEEP); 427209962Smm 428262094Savg sm->sm_start = start; 429262094Savg sm->sm_size = size; 430262094Savg sm->sm_shift = shift; 431262094Savg sm->sm_lock = lp; 432262094Savg sm->sm_os = os; 433262094Savg sm->sm_object = object; 434262094Savg 435262094Savg error = space_map_open_impl(sm); 436262094Savg if (error != 0) { 437262094Savg space_map_close(sm); 438262094Savg return (error); 439262094Savg } 440262094Savg 441262094Savg *smp = sm; 442262094Savg 443209962Smm return (0); 444209962Smm} 445209962Smm 446209962Smmvoid 447262094Savgspace_map_close(space_map_t *sm) 448209962Smm{ 449262094Savg if (sm == NULL) 450262094Savg return; 451209962Smm 452262094Savg if (sm->sm_dbuf != NULL) 453262094Savg dmu_buf_rele(sm->sm_dbuf, sm); 454262094Savg sm->sm_dbuf = NULL; 455262094Savg sm->sm_phys = NULL; 456209962Smm 457262094Savg kmem_free(sm, sizeof (*sm)); 458209962Smm} 459209962Smm 460209962Smmstatic void 461262094Savgspace_map_reallocate(space_map_t *sm, dmu_tx_t *tx) 462209962Smm{ 463262094Savg ASSERT(dmu_tx_is_syncing(tx)); 464209962Smm 465262094Savg space_map_free(sm, tx); 466262094Savg dmu_buf_rele(sm->sm_dbuf, sm); 467209962Smm 468262094Savg sm->sm_object = space_map_alloc(sm->sm_os, tx); 469262094Savg VERIFY0(space_map_open_impl(sm)); 470209962Smm} 471209962Smm 472209962Smmvoid 473262094Savgspace_map_truncate(space_map_t *sm, dmu_tx_t *tx) 474209962Smm{ 475262094Savg objset_t *os = sm->sm_os; 476262094Savg spa_t *spa = dmu_objset_spa(os); 477262094Savg dmu_object_info_t doi; 478262094Savg int bonuslen; 479262094Savg 480262094Savg ASSERT(dsl_pool_sync_context(dmu_objset_pool(os))); 481262094Savg ASSERT(dmu_tx_is_syncing(tx)); 482262094Savg 483262094Savg VERIFY0(dmu_free_range(os, space_map_object(sm), 0, -1ULL, tx)); 484262094Savg dmu_object_info_from_db(sm->sm_dbuf, &doi); 485262094Savg 486263391Sdelphij if (spa_feature_is_enabled(spa, SPA_FEATURE_SPACEMAP_HISTOGRAM)) { 487262094Savg bonuslen = sizeof (space_map_phys_t); 488262094Savg ASSERT3U(bonuslen, <=, dmu_bonus_max()); 489262094Savg } else { 490262094Savg bonuslen = SPACE_MAP_SIZE_V0; 491262094Savg } 492262094Savg 493262094Savg if (bonuslen != doi.doi_bonus_size || 494262094Savg doi.doi_data_block_size != SPACE_MAP_INITIAL_BLOCKSIZE) { 495262094Savg zfs_dbgmsg("txg %llu, spa %s, reallocating: " 496262094Savg "old bonus %u, old blocksz %u", dmu_tx_get_txg(tx), 497262094Savg spa_name(spa), doi.doi_bonus_size, doi.doi_data_block_size); 498262094Savg space_map_reallocate(sm, tx); 499262094Savg VERIFY3U(sm->sm_blksz, ==, SPACE_MAP_INITIAL_BLOCKSIZE); 500262094Savg } 501262094Savg 502262094Savg dmu_buf_will_dirty(sm->sm_dbuf, tx); 503262094Savg sm->sm_phys->smp_objsize = 0; 504262094Savg sm->sm_phys->smp_alloc = 0; 505209962Smm} 506209962Smm 507209962Smm/* 508262094Savg * Update the in-core space_map allocation and length values. 509209962Smm */ 510209962Smmvoid 511262094Savgspace_map_update(space_map_t *sm) 512209962Smm{ 513262094Savg if (sm == NULL) 514262094Savg return; 515209962Smm 516209962Smm ASSERT(MUTEX_HELD(sm->sm_lock)); 517209962Smm 518262094Savg sm->sm_alloc = sm->sm_phys->smp_alloc; 519262094Savg sm->sm_length = sm->sm_phys->smp_objsize; 520209962Smm} 521209962Smm 522262094Savguint64_t 523262094Savgspace_map_alloc(objset_t *os, dmu_tx_t *tx) 524262094Savg{ 525262094Savg spa_t *spa = dmu_objset_spa(os); 526262094Savg uint64_t object; 527262094Savg int bonuslen; 528262094Savg 529263391Sdelphij if (spa_feature_is_enabled(spa, SPA_FEATURE_SPACEMAP_HISTOGRAM)) { 530263391Sdelphij spa_feature_incr(spa, SPA_FEATURE_SPACEMAP_HISTOGRAM, tx); 531262094Savg bonuslen = sizeof (space_map_phys_t); 532262094Savg ASSERT3U(bonuslen, <=, dmu_bonus_max()); 533262094Savg } else { 534262094Savg bonuslen = SPACE_MAP_SIZE_V0; 535262094Savg } 536262094Savg 537262094Savg object = dmu_object_alloc(os, 538262094Savg DMU_OT_SPACE_MAP, SPACE_MAP_INITIAL_BLOCKSIZE, 539262094Savg DMU_OT_SPACE_MAP_HEADER, bonuslen, tx); 540262094Savg 541262094Savg return (object); 542262094Savg} 543262094Savg 544209962Smmvoid 545262094Savgspace_map_free(space_map_t *sm, dmu_tx_t *tx) 546209962Smm{ 547262094Savg spa_t *spa; 548209962Smm 549262094Savg if (sm == NULL) 550262094Savg return; 551209962Smm 552262094Savg spa = dmu_objset_spa(sm->sm_os); 553263391Sdelphij if (spa_feature_is_enabled(spa, SPA_FEATURE_SPACEMAP_HISTOGRAM)) { 554262094Savg dmu_object_info_t doi; 555209962Smm 556262094Savg dmu_object_info_from_db(sm->sm_dbuf, &doi); 557262094Savg if (doi.doi_bonus_size != SPACE_MAP_SIZE_V0) { 558263391Sdelphij VERIFY(spa_feature_is_active(spa, 559263391Sdelphij SPA_FEATURE_SPACEMAP_HISTOGRAM)); 560263391Sdelphij spa_feature_decr(spa, 561263391Sdelphij SPA_FEATURE_SPACEMAP_HISTOGRAM, tx); 562209962Smm } 563209962Smm } 564262094Savg 565262094Savg VERIFY3U(dmu_object_free(sm->sm_os, space_map_object(sm), tx), ==, 0); 566262094Savg sm->sm_object = 0; 567209962Smm} 568262094Savg 569262094Savguint64_t 570262094Savgspace_map_object(space_map_t *sm) 571262094Savg{ 572262094Savg return (sm != NULL ? sm->sm_object : 0); 573262094Savg} 574262094Savg 575262094Savg/* 576262094Savg * Returns the already synced, on-disk allocated space. 577262094Savg */ 578262094Savguint64_t 579262094Savgspace_map_allocated(space_map_t *sm) 580262094Savg{ 581262094Savg return (sm != NULL ? sm->sm_alloc : 0); 582262094Savg} 583262094Savg 584262094Savg/* 585262094Savg * Returns the already synced, on-disk length; 586262094Savg */ 587262094Savguint64_t 588262094Savgspace_map_length(space_map_t *sm) 589262094Savg{ 590262094Savg return (sm != NULL ? sm->sm_length : 0); 591262094Savg} 592262094Savg 593262094Savg/* 594262094Savg * Returns the allocated space that is currently syncing. 595262094Savg */ 596262094Savgint64_t 597262094Savgspace_map_alloc_delta(space_map_t *sm) 598262094Savg{ 599262094Savg if (sm == NULL) 600262094Savg return (0); 601262094Savg ASSERT(sm->sm_dbuf != NULL); 602262094Savg return (sm->sm_phys->smp_alloc - space_map_allocated(sm)); 603262094Savg} 604