mirror of
https://git.proxmox.com/git/mirror_zfs.git
synced 2026-05-22 02:27:36 +03:00
Selectable block allocators
ZFS historically has had several space allocators that were dynamically selectable. While these have been retained in OpenZFS, only a single allocator has been statically compiled in. This patch compiles all allocators for OpenZFS and provides a module parameter to allow for manual selection between them. Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov> Reviewed-by: Ameer Hamza <ahamza@ixsystems.com> Reviewed-by: Alexander Motin <mav@FreeBSD.org> Signed-off-by: Edmund Nadolski <edmund.nadolski@ixsystems.com> Closes #15218
This commit is contained in:
+73
-25
@@ -40,8 +40,6 @@
|
||||
#include <sys/zap.h>
|
||||
#include <sys/btree.h>
|
||||
|
||||
#define WITH_DF_BLOCK_ALLOCATOR
|
||||
|
||||
#define GANG_ALLOCATION(flags) \
|
||||
((flags) & (METASLAB_GANG_CHILD | METASLAB_GANG_HEADER))
|
||||
|
||||
@@ -1622,9 +1620,6 @@ metaslab_block_find(zfs_btree_t *t, range_tree_t *rt, uint64_t start,
|
||||
return (rs);
|
||||
}
|
||||
|
||||
#if defined(WITH_DF_BLOCK_ALLOCATOR) || \
|
||||
defined(WITH_CF_BLOCK_ALLOCATOR)
|
||||
|
||||
/*
|
||||
* This is a helper function that can be used by the allocator to find a
|
||||
* suitable block to allocate. This will search the specified B-tree looking
|
||||
@@ -1659,9 +1654,74 @@ metaslab_block_picker(range_tree_t *rt, uint64_t *cursor, uint64_t size,
|
||||
*cursor = 0;
|
||||
return (-1ULL);
|
||||
}
|
||||
#endif /* WITH_DF/CF_BLOCK_ALLOCATOR */
|
||||
|
||||
#if defined(WITH_DF_BLOCK_ALLOCATOR)
|
||||
static uint64_t metaslab_df_alloc(metaslab_t *msp, uint64_t size);
|
||||
static uint64_t metaslab_cf_alloc(metaslab_t *msp, uint64_t size);
|
||||
static uint64_t metaslab_ndf_alloc(metaslab_t *msp, uint64_t size);
|
||||
metaslab_ops_t *metaslab_allocator(spa_t *spa);
|
||||
|
||||
static metaslab_ops_t metaslab_allocators[] = {
|
||||
{ "dynamic", metaslab_df_alloc },
|
||||
{ "cursor", metaslab_cf_alloc },
|
||||
{ "new-dynamic", metaslab_ndf_alloc },
|
||||
};
|
||||
|
||||
static int
|
||||
spa_find_allocator_byname(const char *val)
|
||||
{
|
||||
int a = ARRAY_SIZE(metaslab_allocators) - 1;
|
||||
if (strcmp("new-dynamic", val) == 0)
|
||||
return (-1); /* remove when ndf is working */
|
||||
for (; a >= 0; a--) {
|
||||
if (strcmp(val, metaslab_allocators[a].msop_name) == 0)
|
||||
return (a);
|
||||
}
|
||||
return (-1);
|
||||
}
|
||||
|
||||
void
|
||||
spa_set_allocator(spa_t *spa, const char *allocator)
|
||||
{
|
||||
int a = spa_find_allocator_byname(allocator);
|
||||
if (a < 0) a = 0;
|
||||
spa->spa_active_allocator = a;
|
||||
zfs_dbgmsg("spa allocator: %s\n", metaslab_allocators[a].msop_name);
|
||||
}
|
||||
|
||||
int
|
||||
spa_get_allocator(spa_t *spa)
|
||||
{
|
||||
return (spa->spa_active_allocator);
|
||||
}
|
||||
|
||||
#if defined(_KERNEL)
|
||||
int
|
||||
param_set_active_allocator_common(const char *val)
|
||||
{
|
||||
char *p;
|
||||
|
||||
if (val == NULL)
|
||||
return (SET_ERROR(EINVAL));
|
||||
|
||||
if ((p = strchr(val, '\n')) != NULL)
|
||||
*p = '\0';
|
||||
|
||||
int a = spa_find_allocator_byname(val);
|
||||
if (a < 0)
|
||||
return (SET_ERROR(EINVAL));
|
||||
|
||||
zfs_active_allocator = metaslab_allocators[a].msop_name;
|
||||
return (0);
|
||||
}
|
||||
#endif
|
||||
|
||||
metaslab_ops_t *
|
||||
metaslab_allocator(spa_t *spa)
|
||||
{
|
||||
int allocator = spa_get_allocator(spa);
|
||||
return (&metaslab_allocators[allocator]);
|
||||
}
|
||||
|
||||
/*
|
||||
* ==========================================================================
|
||||
* Dynamic Fit (df) block allocator
|
||||
@@ -1736,12 +1796,6 @@ metaslab_df_alloc(metaslab_t *msp, uint64_t size)
|
||||
return (offset);
|
||||
}
|
||||
|
||||
const metaslab_ops_t zfs_metaslab_ops = {
|
||||
metaslab_df_alloc
|
||||
};
|
||||
#endif /* WITH_DF_BLOCK_ALLOCATOR */
|
||||
|
||||
#if defined(WITH_CF_BLOCK_ALLOCATOR)
|
||||
/*
|
||||
* ==========================================================================
|
||||
* Cursor fit block allocator -
|
||||
@@ -1784,12 +1838,6 @@ metaslab_cf_alloc(metaslab_t *msp, uint64_t size)
|
||||
return (offset);
|
||||
}
|
||||
|
||||
const metaslab_ops_t zfs_metaslab_ops = {
|
||||
metaslab_cf_alloc
|
||||
};
|
||||
#endif /* WITH_CF_BLOCK_ALLOCATOR */
|
||||
|
||||
#if defined(WITH_NDF_BLOCK_ALLOCATOR)
|
||||
/*
|
||||
* ==========================================================================
|
||||
* New dynamic fit allocator -
|
||||
@@ -1846,12 +1894,6 @@ metaslab_ndf_alloc(metaslab_t *msp, uint64_t size)
|
||||
return (-1ULL);
|
||||
}
|
||||
|
||||
const metaslab_ops_t zfs_metaslab_ops = {
|
||||
metaslab_ndf_alloc
|
||||
};
|
||||
#endif /* WITH_NDF_BLOCK_ALLOCATOR */
|
||||
|
||||
|
||||
/*
|
||||
* ==========================================================================
|
||||
* Metaslabs
|
||||
@@ -6232,3 +6274,9 @@ ZFS_MODULE_PARAM(zfs_metaslab, zfs_metaslab_, try_hard_before_gang, INT,
|
||||
|
||||
ZFS_MODULE_PARAM(zfs_metaslab, zfs_metaslab_, find_max_tries, UINT, ZMOD_RW,
|
||||
"Normally only consider this many of the best metaslabs in each vdev");
|
||||
|
||||
/* BEGIN CSTYLED */
|
||||
ZFS_MODULE_PARAM_CALL(zfs, zfs_, active_allocator,
|
||||
param_set_active_allocator, param_get_charp, ZMOD_RW,
|
||||
"SPA active allocator");
|
||||
/* END CSTYLED */
|
||||
|
||||
+8
-6
@@ -1295,24 +1295,26 @@ spa_thread(void *arg)
|
||||
}
|
||||
#endif
|
||||
|
||||
extern metaslab_ops_t *metaslab_allocator(spa_t *spa);
|
||||
|
||||
/*
|
||||
* Activate an uninitialized pool.
|
||||
*/
|
||||
static void
|
||||
spa_activate(spa_t *spa, spa_mode_t mode)
|
||||
{
|
||||
metaslab_ops_t *msp = metaslab_allocator(spa);
|
||||
ASSERT(spa->spa_state == POOL_STATE_UNINITIALIZED);
|
||||
|
||||
spa->spa_state = POOL_STATE_ACTIVE;
|
||||
spa->spa_mode = mode;
|
||||
spa->spa_read_spacemaps = spa_mode_readable_spacemaps;
|
||||
|
||||
spa->spa_normal_class = metaslab_class_create(spa, &zfs_metaslab_ops);
|
||||
spa->spa_log_class = metaslab_class_create(spa, &zfs_metaslab_ops);
|
||||
spa->spa_embedded_log_class =
|
||||
metaslab_class_create(spa, &zfs_metaslab_ops);
|
||||
spa->spa_special_class = metaslab_class_create(spa, &zfs_metaslab_ops);
|
||||
spa->spa_dedup_class = metaslab_class_create(spa, &zfs_metaslab_ops);
|
||||
spa->spa_normal_class = metaslab_class_create(spa, msp);
|
||||
spa->spa_log_class = metaslab_class_create(spa, msp);
|
||||
spa->spa_embedded_log_class = metaslab_class_create(spa, msp);
|
||||
spa->spa_special_class = metaslab_class_create(spa, msp);
|
||||
spa->spa_dedup_class = metaslab_class_create(spa, msp);
|
||||
|
||||
/* Try to create a covering process */
|
||||
mutex_enter(&spa->spa_proc_lock);
|
||||
|
||||
@@ -389,6 +389,11 @@ static const uint64_t spa_min_slop = 128ULL * 1024 * 1024;
|
||||
static const uint64_t spa_max_slop = 128ULL * 1024 * 1024 * 1024;
|
||||
static const int spa_allocators = 4;
|
||||
|
||||
/*
|
||||
* Spa active allocator.
|
||||
* Valid values are zfs_active_allocator=<dynamic|cursor|new-dynamic>.
|
||||
*/
|
||||
const char *zfs_active_allocator = "dynamic";
|
||||
|
||||
void
|
||||
spa_load_failed(spa_t *spa, const char *fmt, ...)
|
||||
@@ -710,6 +715,7 @@ spa_add(const char *name, nvlist_t *config, const char *altroot)
|
||||
spa->spa_deadman_synctime = MSEC2NSEC(zfs_deadman_synctime_ms);
|
||||
spa->spa_deadman_ziotime = MSEC2NSEC(zfs_deadman_ziotime_ms);
|
||||
spa_set_deadman_failmode(spa, zfs_deadman_failmode);
|
||||
spa_set_allocator(spa, zfs_active_allocator);
|
||||
|
||||
zfs_refcount_create(&spa->spa_refcount);
|
||||
spa_config_lock_init(spa);
|
||||
|
||||
Reference in New Issue
Block a user