Changeset View
Changeset View
Standalone View
Standalone View
sys/cddl/contrib/opensolaris/uts/common/fs/zfs/metaslab.c
Show First 20 Lines • Show All 1,114 Lines • ▼ Show 20 Lines | metaslab_rangesize_compare(const void *x1, const void *x2) | ||||
if (r1->rs_start > r2->rs_start) | if (r1->rs_start > r2->rs_start) | ||||
return (1); | return (1); | ||||
return (0); | return (0); | ||||
} | } | ||||
/* | /* | ||||
* Create any block allocator specific components. The current allocators | |||||
* rely on using both a size-ordered range_tree_t and an array of uint64_t's. | |||||
*/ | |||||
static void | |||||
metaslab_rt_create(range_tree_t *rt, void *arg) | |||||
{ | |||||
metaslab_t *msp = arg; | |||||
ASSERT3P(rt->rt_arg, ==, msp); | |||||
ASSERT(msp->ms_allocatable == NULL); | |||||
avl_create(&msp->ms_allocatable_by_size, metaslab_rangesize_compare, | |||||
sizeof (range_seg_t), offsetof(range_seg_t, rs_pp_node)); | |||||
} | |||||
/* | |||||
* Destroy the block allocator specific components. | |||||
*/ | |||||
static void | |||||
metaslab_rt_destroy(range_tree_t *rt, void *arg) | |||||
{ | |||||
metaslab_t *msp = arg; | |||||
ASSERT3P(rt->rt_arg, ==, msp); | |||||
ASSERT3P(msp->ms_allocatable, ==, rt); | |||||
ASSERT0(avl_numnodes(&msp->ms_allocatable_by_size)); | |||||
avl_destroy(&msp->ms_allocatable_by_size); | |||||
} | |||||
static void | |||||
metaslab_rt_add(range_tree_t *rt, range_seg_t *rs, void *arg) | |||||
{ | |||||
metaslab_t *msp = arg; | |||||
ASSERT3P(rt->rt_arg, ==, msp); | |||||
ASSERT3P(msp->ms_allocatable, ==, rt); | |||||
VERIFY(!msp->ms_condensing); | |||||
avl_add(&msp->ms_allocatable_by_size, rs); | |||||
} | |||||
static void | |||||
metaslab_rt_remove(range_tree_t *rt, range_seg_t *rs, void *arg) | |||||
{ | |||||
metaslab_t *msp = arg; | |||||
ASSERT3P(rt->rt_arg, ==, msp); | |||||
ASSERT3P(msp->ms_allocatable, ==, rt); | |||||
VERIFY(!msp->ms_condensing); | |||||
avl_remove(&msp->ms_allocatable_by_size, rs); | |||||
} | |||||
static void | |||||
metaslab_rt_vacate(range_tree_t *rt, void *arg) | |||||
{ | |||||
metaslab_t *msp = arg; | |||||
ASSERT3P(rt->rt_arg, ==, msp); | |||||
ASSERT3P(msp->ms_allocatable, ==, rt); | |||||
/* | |||||
* Normally one would walk the tree freeing nodes along the way. | |||||
* Since the nodes are shared with the range trees we can avoid | |||||
* walking all nodes and just reinitialize the avl tree. The nodes | |||||
* will be freed by the range tree, so we don't want to free them here. | |||||
*/ | |||||
avl_create(&msp->ms_allocatable_by_size, metaslab_rangesize_compare, | |||||
sizeof (range_seg_t), offsetof(range_seg_t, rs_pp_node)); | |||||
} | |||||
static range_tree_ops_t metaslab_rt_ops = { | |||||
metaslab_rt_create, | |||||
metaslab_rt_destroy, | |||||
metaslab_rt_add, | |||||
metaslab_rt_remove, | |||||
metaslab_rt_vacate | |||||
}; | |||||
/* | |||||
* ========================================================================== | * ========================================================================== | ||||
* Common allocator routines | * Common allocator routines | ||||
* ========================================================================== | * ========================================================================== | ||||
*/ | */ | ||||
/* | /* | ||||
* Return the maximum contiguous segment within the metaslab. | * Return the maximum contiguous segment within the metaslab. | ||||
*/ | */ | ||||
▲ Show 20 Lines • Show All 359 Lines • ▼ Show 20 Lines | metaslab_init(metaslab_group_t *mg, uint64_t id, uint64_t object, uint64_t txg, | ||||
/* | /* | ||||
* We create the main range tree here, but we don't create the | * We create the main range tree here, but we don't create the | ||||
* other range trees until metaslab_sync_done(). This serves | * other range trees until metaslab_sync_done(). This serves | ||||
* two purposes: it allows metaslab_sync_done() to detect the | * two purposes: it allows metaslab_sync_done() to detect the | ||||
* addition of new space; and for debugging, it ensures that we'd | * addition of new space; and for debugging, it ensures that we'd | ||||
* data fault on any attempt to use this metaslab before it's ready. | * data fault on any attempt to use this metaslab before it's ready. | ||||
*/ | */ | ||||
ms->ms_allocatable = range_tree_create(&metaslab_rt_ops, ms); | ms->ms_allocatable = range_tree_create_impl(&rt_avl_ops, &ms->ms_allocatable_by_size, | ||||
metaslab_rangesize_compare, &ms->ms_lock, 0); | |||||
metaslab_group_add(mg, ms); | metaslab_group_add(mg, ms); | ||||
metaslab_set_fragmentation(ms); | metaslab_set_fragmentation(ms); | ||||
/* | /* | ||||
* If we're opening an existing pool (txg == 0) or creating | * If we're opening an existing pool (txg == 0) or creating | ||||
* a new one (txg == TXG_INITIAL), all space is available now. | * a new one (txg == TXG_INITIAL), all space is available now. | ||||
* If we're adding space to an existing pool, the new space | * If we're adding space to an existing pool, the new space | ||||
▲ Show 20 Lines • Show All 703 Lines • ▼ Show 20 Lines | metaslab_condense(metaslab_t *msp, uint64_t txg, dmu_tx_t *tx) | ||||
/* | /* | ||||
* Create an range tree that is 100% allocated. We remove segments | * Create an range tree that is 100% allocated. We remove segments | ||||
* that have been freed in this txg, any deferred frees that exist, | * that have been freed in this txg, any deferred frees that exist, | ||||
* and any allocation in the future. Removing segments should be | * and any allocation in the future. Removing segments should be | ||||
* a relatively inexpensive operation since we expect these trees to | * a relatively inexpensive operation since we expect these trees to | ||||
* have a small number of nodes. | * have a small number of nodes. | ||||
*/ | */ | ||||
condense_tree = range_tree_create(NULL, NULL); | condense_tree = range_tree_create(NULL, NULL, &msp->ms_lock); | ||||
range_tree_add(condense_tree, msp->ms_start, msp->ms_size); | range_tree_add(condense_tree, msp->ms_start, msp->ms_size); | ||||
range_tree_walk(msp->ms_freeing, range_tree_remove, condense_tree); | range_tree_walk(msp->ms_freeing, range_tree_remove, condense_tree); | ||||
range_tree_walk(msp->ms_freed, range_tree_remove, condense_tree); | range_tree_walk(msp->ms_freed, range_tree_remove, condense_tree); | ||||
for (int t = 0; t < TXG_DEFER_SIZE; t++) { | for (int t = 0; t < TXG_DEFER_SIZE; t++) { | ||||
range_tree_walk(msp->ms_defer[t], | range_tree_walk(msp->ms_defer[t], | ||||
range_tree_remove, condense_tree); | range_tree_remove, condense_tree); | ||||
▲ Show 20 Lines • Show All 271 Lines • ▼ Show 20 Lines | metaslab_sync_done(metaslab_t *msp, uint64_t txg) | ||||
/* | /* | ||||
* If this metaslab is just becoming available, initialize its | * If this metaslab is just becoming available, initialize its | ||||
* range trees and add its capacity to the vdev. | * range trees and add its capacity to the vdev. | ||||
*/ | */ | ||||
if (msp->ms_freed == NULL) { | if (msp->ms_freed == NULL) { | ||||
for (int t = 0; t < TXG_SIZE; t++) { | for (int t = 0; t < TXG_SIZE; t++) { | ||||
ASSERT(msp->ms_allocating[t] == NULL); | ASSERT(msp->ms_allocating[t] == NULL); | ||||
msp->ms_allocating[t] = range_tree_create(NULL, NULL); | msp->ms_allocating[t] = range_tree_create(NULL, NULL, &msp->ms_lock); | ||||
} | } | ||||
ASSERT3P(msp->ms_freeing, ==, NULL); | ASSERT3P(msp->ms_freeing, ==, NULL); | ||||
msp->ms_freeing = range_tree_create(NULL, NULL); | msp->ms_freeing = range_tree_create(NULL, NULL, &msp->ms_lock); | ||||
ASSERT3P(msp->ms_freed, ==, NULL); | ASSERT3P(msp->ms_freed, ==, NULL); | ||||
msp->ms_freed = range_tree_create(NULL, NULL); | msp->ms_freed = range_tree_create(NULL, NULL, &msp->ms_lock); | ||||
for (int t = 0; t < TXG_DEFER_SIZE; t++) { | for (int t = 0; t < TXG_DEFER_SIZE; t++) { | ||||
ASSERT(msp->ms_defer[t] == NULL); | ASSERT(msp->ms_defer[t] == NULL); | ||||
msp->ms_defer[t] = range_tree_create(NULL, NULL); | msp->ms_defer[t] = range_tree_create(NULL, NULL, &msp->ms_lock); | ||||
} | } | ||||
ASSERT3P(msp->ms_checkpointing, ==, NULL); | ASSERT3P(msp->ms_checkpointing, ==, NULL); | ||||
msp->ms_checkpointing = range_tree_create(NULL, NULL); | msp->ms_checkpointing = range_tree_create(NULL, NULL, &msp->ms_lock); | ||||
vdev_space_update(vd, 0, 0, msp->ms_size); | vdev_space_update(vd, 0, 0, msp->ms_size); | ||||
} | } | ||||
ASSERT0(range_tree_space(msp->ms_freeing)); | ASSERT0(range_tree_space(msp->ms_freeing)); | ||||
ASSERT0(range_tree_space(msp->ms_checkpointing)); | ASSERT0(range_tree_space(msp->ms_checkpointing)); | ||||
defer_tree = &msp->ms_defer[txg % TXG_DEFER_SIZE]; | defer_tree = &msp->ms_defer[txg % TXG_DEFER_SIZE]; | ||||
▲ Show 20 Lines • Show All 1,422 Lines • Show Last 20 Lines |