#include <sys/zfs_context.h>
#include <sys/multilist.h>
-#include <sys/trace_defs.h>
-
-/* needed for spa_get_random() */
-#include <sys/spa.h>
+#include <sys/trace_zfs.h>
/*
* This overrides the number of sublists in each multilist_t, which defaults
* to the number of CPUs in the system (see multilist_create()).
*/
-int zfs_multilist_num_sublists = 0;
+uint_t zfs_multilist_num_sublists = 0;
/*
* Given the object contained on the list, return a pointer to the
* object's multilist_node_t structure it contains.
*/
-#ifdef DEBUG
+#ifdef ZFS_DEBUG
static multilist_node_t *
multilist_d2l(multilist_t *ml, void *obj)
{
return ((multilist_node_t *)((char *)obj + ml->ml_offset));
}
+#else
+#define multilist_d2l(ml, obj) ((void) sizeof (ml), (void) sizeof (obj), NULL)
#endif
/*
* requirement, but a general rule of thumb in order to garner the
* best multi-threaded performance out of the data structure.
*/
-static multilist_t *
-multilist_create_impl(size_t size, size_t offset,
- unsigned int num, multilist_sublist_index_func_t *index_func)
+static void
+multilist_create_impl(multilist_t *ml, size_t size, size_t offset,
+ uint_t num, multilist_sublist_index_func_t *index_func)
{
ASSERT3U(size, >, 0);
ASSERT3U(size, >=, offset + sizeof (multilist_node_t));
ASSERT3U(num, >, 0);
ASSERT3P(index_func, !=, NULL);
- multilist_t *ml = kmem_alloc(sizeof (*ml), KM_SLEEP);
ml->ml_offset = offset;
ml->ml_num_sublists = num;
ml->ml_index_func = index_func;
mutex_init(&mls->mls_lock, NULL, MUTEX_NOLOCKDEP, NULL);
list_create(&mls->mls_list, size, offset);
}
- return (ml);
}
/*
- * Allocate a new multilist, using the default number of sublists
- * (the number of CPUs, or at least 4, or the tunable
- * zfs_multilist_num_sublists).
+ * Allocate a new multilist, using the default number of sublists (the number
+ * of CPUs, or at least 4, or the tunable zfs_multilist_num_sublists). Note
+ * that the multilists do not expand if more CPUs are hot-added. In that case,
+ * we will have less fanout than boot_ncpus, but we don't want to always
+ * reserve the RAM necessary to create the extra slots for additional CPUs up
+ * front, and dynamically adding them is a complex task.
*/
-multilist_t *
-multilist_create(size_t size, size_t offset,
+void
+multilist_create(multilist_t *ml, size_t size, size_t offset,
multilist_sublist_index_func_t *index_func)
{
- int num_sublists;
+ uint_t num_sublists;
if (zfs_multilist_num_sublists > 0) {
num_sublists = zfs_multilist_num_sublists;
num_sublists = MAX(boot_ncpus, 4);
}
- return (multilist_create_impl(size, offset, num_sublists, index_func));
+ multilist_create_impl(ml, size, offset, num_sublists, index_func);
}
/*
ml->ml_num_sublists = 0;
ml->ml_offset = 0;
- kmem_free(ml, sizeof (multilist_t));
+ ml->ml_sublists = NULL;
}
/*
unsigned int
multilist_get_random_index(multilist_t *ml)
{
- return (spa_get_random(ml->ml_num_sublists));
+ return (random_in_range(ml->ml_num_sublists));
}
/* Lock and return the sublist specified at the given index */
return (list_link_active(link));
}
-/* BEGIN CSTYLED */
-ZFS_MODULE_PARAM(zfs, zfs_, multilist_num_sublists, INT, ZMOD_RW,
+ZFS_MODULE_PARAM(zfs, zfs_, multilist_num_sublists, UINT, ZMOD_RW,
"Number of sublists used in each multilist");
-/* END CSTYLED */