^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /* Copyright (c) 2018 Mellanox Technologies. All rights reserved */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) #include <linux/rhashtable.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include <linux/idr.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/list.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/sort.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/objagg.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #define CREATE_TRACE_POINTS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <trace/events/objagg.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) struct objagg_hints {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) struct rhashtable node_ht;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) struct rhashtable_params ht_params;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) struct list_head node_list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) unsigned int node_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) unsigned int root_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) unsigned int refcount;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) const struct objagg_ops *ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) struct objagg_hints_node {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) struct rhash_head ht_node; /* member of objagg_hints->node_ht */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) struct list_head list; /* member of objagg_hints->node_list */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) struct objagg_hints_node *parent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) unsigned int root_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) struct objagg_obj_stats_info stats_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) unsigned long obj[];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) static struct objagg_hints_node *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) objagg_hints_lookup(struct objagg_hints *objagg_hints, void *obj)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) if (!objagg_hints)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) return rhashtable_lookup_fast(&objagg_hints->node_ht, obj,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) objagg_hints->ht_params);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) struct objagg {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) const struct objagg_ops *ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) void *priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) struct rhashtable obj_ht;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) struct rhashtable_params ht_params;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) struct list_head obj_list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) unsigned int obj_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) struct ida root_ida;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) struct objagg_hints *hints;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) struct objagg_obj {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) struct rhash_head ht_node; /* member of objagg->obj_ht */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) struct list_head list; /* member of objagg->obj_list */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) struct objagg_obj *parent; /* if the object is nested, this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) * holds pointer to parent, otherwise NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) union {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) void *delta_priv; /* user delta private */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) void *root_priv; /* user root private */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) unsigned int root_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) unsigned int refcount; /* counts number of users of this object
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) * including nested objects
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) struct objagg_obj_stats stats;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) unsigned long obj[];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) static unsigned int objagg_obj_ref_inc(struct objagg_obj *objagg_obj)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) return ++objagg_obj->refcount;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) static unsigned int objagg_obj_ref_dec(struct objagg_obj *objagg_obj)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) return --objagg_obj->refcount;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) static void objagg_obj_stats_inc(struct objagg_obj *objagg_obj)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) objagg_obj->stats.user_count++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) objagg_obj->stats.delta_user_count++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) if (objagg_obj->parent)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) objagg_obj->parent->stats.delta_user_count++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) static void objagg_obj_stats_dec(struct objagg_obj *objagg_obj)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) objagg_obj->stats.user_count--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) objagg_obj->stats.delta_user_count--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) if (objagg_obj->parent)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) objagg_obj->parent->stats.delta_user_count--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) static bool objagg_obj_is_root(const struct objagg_obj *objagg_obj)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) /* Nesting is not supported, so we can use ->parent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) * to figure out if the object is root.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) return !objagg_obj->parent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) * objagg_obj_root_priv - obtains root private for an object
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) * @objagg_obj: objagg object instance
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) * Note: all locking must be provided by the caller.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) * Either the object is root itself when the private is returned
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) * directly, or the parent is root and its private is returned
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) * instead.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) * Returns a user private root pointer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) const void *objagg_obj_root_priv(const struct objagg_obj *objagg_obj)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) if (objagg_obj_is_root(objagg_obj))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) return objagg_obj->root_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) WARN_ON(!objagg_obj_is_root(objagg_obj->parent));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) return objagg_obj->parent->root_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) EXPORT_SYMBOL(objagg_obj_root_priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) * objagg_obj_delta_priv - obtains delta private for an object
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) * @objagg_obj: objagg object instance
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) * Note: all locking must be provided by the caller.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) * Returns user private delta pointer or NULL in case the passed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) * object is root.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) const void *objagg_obj_delta_priv(const struct objagg_obj *objagg_obj)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) if (objagg_obj_is_root(objagg_obj))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) return objagg_obj->delta_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) EXPORT_SYMBOL(objagg_obj_delta_priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) * objagg_obj_raw - obtains object user private pointer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) * @objagg_obj: objagg object instance
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) * Note: all locking must be provided by the caller.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) * Returns user private pointer as was passed to objagg_obj_get() by "obj" arg.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) const void *objagg_obj_raw(const struct objagg_obj *objagg_obj)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) return objagg_obj->obj;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) EXPORT_SYMBOL(objagg_obj_raw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) static struct objagg_obj *objagg_obj_lookup(struct objagg *objagg, void *obj)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) return rhashtable_lookup_fast(&objagg->obj_ht, obj, objagg->ht_params);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) static int objagg_obj_parent_assign(struct objagg *objagg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) struct objagg_obj *objagg_obj,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) struct objagg_obj *parent,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) bool take_parent_ref)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) void *delta_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) delta_priv = objagg->ops->delta_create(objagg->priv, parent->obj,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) objagg_obj->obj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) if (IS_ERR(delta_priv))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) return PTR_ERR(delta_priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) /* User returned a delta private, that means that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) * our object can be aggregated into the parent.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) objagg_obj->parent = parent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) objagg_obj->delta_priv = delta_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) if (take_parent_ref)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) objagg_obj_ref_inc(objagg_obj->parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) trace_objagg_obj_parent_assign(objagg, objagg_obj,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) parent,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) parent->refcount);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) static int objagg_obj_parent_lookup_assign(struct objagg *objagg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) struct objagg_obj *objagg_obj)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) struct objagg_obj *objagg_obj_cur;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) list_for_each_entry(objagg_obj_cur, &objagg->obj_list, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) /* Nesting is not supported. In case the object
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) * is not root, it cannot be assigned as parent.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) if (!objagg_obj_is_root(objagg_obj_cur))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) err = objagg_obj_parent_assign(objagg, objagg_obj,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) objagg_obj_cur, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) if (!err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) static void __objagg_obj_put(struct objagg *objagg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) struct objagg_obj *objagg_obj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) static void objagg_obj_parent_unassign(struct objagg *objagg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) struct objagg_obj *objagg_obj)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) trace_objagg_obj_parent_unassign(objagg, objagg_obj,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) objagg_obj->parent,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) objagg_obj->parent->refcount);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) objagg->ops->delta_destroy(objagg->priv, objagg_obj->delta_priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) __objagg_obj_put(objagg, objagg_obj->parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) static int objagg_obj_root_id_alloc(struct objagg *objagg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) struct objagg_obj *objagg_obj,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) struct objagg_hints_node *hnode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) unsigned int min, max;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) int root_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) /* In case there are no hints available, the root id is invalid. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) if (!objagg->hints) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) objagg_obj->root_id = OBJAGG_OBJ_ROOT_ID_INVALID;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) if (hnode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) min = hnode->root_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) max = hnode->root_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) /* For objects with no hint, start after the last
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) * hinted root_id.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) min = objagg->hints->root_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) max = ~0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) root_id = ida_alloc_range(&objagg->root_ida, min, max, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) if (root_id < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) return root_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) objagg_obj->root_id = root_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) static void objagg_obj_root_id_free(struct objagg *objagg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) struct objagg_obj *objagg_obj)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) if (!objagg->hints)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) ida_free(&objagg->root_ida, objagg_obj->root_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) static int objagg_obj_root_create(struct objagg *objagg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) struct objagg_obj *objagg_obj,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) struct objagg_hints_node *hnode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) err = objagg_obj_root_id_alloc(objagg, objagg_obj, hnode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) objagg_obj->root_priv = objagg->ops->root_create(objagg->priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) objagg_obj->obj,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) objagg_obj->root_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) if (IS_ERR(objagg_obj->root_priv)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) err = PTR_ERR(objagg_obj->root_priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) goto err_root_create;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) trace_objagg_obj_root_create(objagg, objagg_obj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) err_root_create:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) objagg_obj_root_id_free(objagg, objagg_obj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) static void objagg_obj_root_destroy(struct objagg *objagg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) struct objagg_obj *objagg_obj)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) trace_objagg_obj_root_destroy(objagg, objagg_obj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) objagg->ops->root_destroy(objagg->priv, objagg_obj->root_priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) objagg_obj_root_id_free(objagg, objagg_obj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) static struct objagg_obj *__objagg_obj_get(struct objagg *objagg, void *obj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) static int objagg_obj_init_with_hints(struct objagg *objagg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) struct objagg_obj *objagg_obj,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) bool *hint_found)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) struct objagg_hints_node *hnode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) struct objagg_obj *parent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) hnode = objagg_hints_lookup(objagg->hints, objagg_obj->obj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) if (!hnode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) *hint_found = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) *hint_found = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) if (!hnode->parent)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) return objagg_obj_root_create(objagg, objagg_obj, hnode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) parent = __objagg_obj_get(objagg, hnode->parent->obj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) if (IS_ERR(parent))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) return PTR_ERR(parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) err = objagg_obj_parent_assign(objagg, objagg_obj, parent, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) *hint_found = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) goto err_parent_assign;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) err_parent_assign:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) objagg_obj_put(objagg, parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) static int objagg_obj_init(struct objagg *objagg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) struct objagg_obj *objagg_obj)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) bool hint_found;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) /* First, try to use hints if they are available and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) * if they provide result.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) err = objagg_obj_init_with_hints(objagg, objagg_obj, &hint_found);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) if (hint_found)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) /* Try to find if the object can be aggregated under an existing one. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) err = objagg_obj_parent_lookup_assign(objagg, objagg_obj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) if (!err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) /* If aggregation is not possible, make the object a root. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) return objagg_obj_root_create(objagg, objagg_obj, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) static void objagg_obj_fini(struct objagg *objagg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) struct objagg_obj *objagg_obj)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) if (!objagg_obj_is_root(objagg_obj))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) objagg_obj_parent_unassign(objagg, objagg_obj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) objagg_obj_root_destroy(objagg, objagg_obj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) static struct objagg_obj *objagg_obj_create(struct objagg *objagg, void *obj)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) struct objagg_obj *objagg_obj;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) objagg_obj = kzalloc(sizeof(*objagg_obj) + objagg->ops->obj_size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) if (!objagg_obj)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) return ERR_PTR(-ENOMEM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) objagg_obj_ref_inc(objagg_obj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) memcpy(objagg_obj->obj, obj, objagg->ops->obj_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) err = objagg_obj_init(objagg, objagg_obj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) goto err_obj_init;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) err = rhashtable_insert_fast(&objagg->obj_ht, &objagg_obj->ht_node,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) objagg->ht_params);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) goto err_ht_insert;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) list_add(&objagg_obj->list, &objagg->obj_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) objagg->obj_count++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) trace_objagg_obj_create(objagg, objagg_obj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) return objagg_obj;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) err_ht_insert:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) objagg_obj_fini(objagg, objagg_obj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) err_obj_init:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) kfree(objagg_obj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) return ERR_PTR(err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) static struct objagg_obj *__objagg_obj_get(struct objagg *objagg, void *obj)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) struct objagg_obj *objagg_obj;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) /* First, try to find the object exactly as user passed it,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) * perhaps it is already in use.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) objagg_obj = objagg_obj_lookup(objagg, obj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) if (objagg_obj) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) objagg_obj_ref_inc(objagg_obj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) return objagg_obj;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) return objagg_obj_create(objagg, obj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) * objagg_obj_get - gets an object within objagg instance
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) * @objagg: objagg instance
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) * @obj: user-specific private object pointer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) * Note: all locking must be provided by the caller.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) * Size of the "obj" memory is specified in "objagg->ops".
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) * There are 3 main options this function wraps:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) * 1) The object according to "obj" already exist. In that case
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) * the reference counter is incrementes and the object is returned.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) * 2) The object does not exist, but it can be aggregated within
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) * another object. In that case, user ops->delta_create() is called
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) * to obtain delta data and a new object is created with returned
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) * user-delta private pointer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) * 3) The object does not exist and cannot be aggregated into
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) * any of the existing objects. In that case, user ops->root_create()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) * is called to create the root and a new object is created with
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) * returned user-root private pointer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) * Returns a pointer to objagg object instance in case of success,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) * otherwise it returns pointer error using ERR_PTR macro.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) struct objagg_obj *objagg_obj_get(struct objagg *objagg, void *obj)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) struct objagg_obj *objagg_obj;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) objagg_obj = __objagg_obj_get(objagg, obj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) if (IS_ERR(objagg_obj))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) return objagg_obj;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) objagg_obj_stats_inc(objagg_obj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) trace_objagg_obj_get(objagg, objagg_obj, objagg_obj->refcount);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) return objagg_obj;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) EXPORT_SYMBOL(objagg_obj_get);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) static void objagg_obj_destroy(struct objagg *objagg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) struct objagg_obj *objagg_obj)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) trace_objagg_obj_destroy(objagg, objagg_obj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) --objagg->obj_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) list_del(&objagg_obj->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) rhashtable_remove_fast(&objagg->obj_ht, &objagg_obj->ht_node,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) objagg->ht_params);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) objagg_obj_fini(objagg, objagg_obj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) kfree(objagg_obj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) static void __objagg_obj_put(struct objagg *objagg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) struct objagg_obj *objagg_obj)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) if (!objagg_obj_ref_dec(objagg_obj))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) objagg_obj_destroy(objagg, objagg_obj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) * objagg_obj_put - puts an object within objagg instance
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) * @objagg: objagg instance
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) * @objagg_obj: objagg object instance
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) * Note: all locking must be provided by the caller.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) * Symmetric to objagg_obj_get().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) void objagg_obj_put(struct objagg *objagg, struct objagg_obj *objagg_obj)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) trace_objagg_obj_put(objagg, objagg_obj, objagg_obj->refcount);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) objagg_obj_stats_dec(objagg_obj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) __objagg_obj_put(objagg, objagg_obj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) EXPORT_SYMBOL(objagg_obj_put);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) * objagg_create - creates a new objagg instance
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) * @ops: user-specific callbacks
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) * @objagg_hints: hints, can be NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) * @priv: pointer to a private data passed to the ops
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) * Note: all locking must be provided by the caller.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) * The purpose of the library is to provide an infrastructure to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) * aggregate user-specified objects. Library does not care about the type
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) * of the object. User fills-up ops which take care of the specific
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) * user object manipulation.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) * As a very stupid example, consider integer numbers. For example
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) * number 8 as a root object. That can aggregate number 9 with delta 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) * number 10 with delta 2, etc. This example is implemented as
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) * a part of a testing module in test_objagg.c file.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) * Each objagg instance contains multiple trees. Each tree node is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) * represented by "an object". In the current implementation there can be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) * only roots and leafs nodes. Leaf nodes are called deltas.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) * But in general, this can be easily extended for intermediate nodes.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) * In that extension, a delta would be associated with all non-root
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) * nodes.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) * Returns a pointer to newly created objagg instance in case of success,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) * otherwise it returns pointer error using ERR_PTR macro.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) struct objagg *objagg_create(const struct objagg_ops *ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) struct objagg_hints *objagg_hints, void *priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) struct objagg *objagg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) if (WARN_ON(!ops || !ops->root_create || !ops->root_destroy ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) !ops->delta_check || !ops->delta_create ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) !ops->delta_destroy))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) return ERR_PTR(-EINVAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) objagg = kzalloc(sizeof(*objagg), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) if (!objagg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) return ERR_PTR(-ENOMEM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) objagg->ops = ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) if (objagg_hints) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) objagg->hints = objagg_hints;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) objagg_hints->refcount++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) objagg->priv = priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) INIT_LIST_HEAD(&objagg->obj_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) objagg->ht_params.key_len = ops->obj_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) objagg->ht_params.key_offset = offsetof(struct objagg_obj, obj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) objagg->ht_params.head_offset = offsetof(struct objagg_obj, ht_node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) err = rhashtable_init(&objagg->obj_ht, &objagg->ht_params);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) goto err_rhashtable_init;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) ida_init(&objagg->root_ida);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) trace_objagg_create(objagg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) return objagg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) err_rhashtable_init:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) kfree(objagg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) return ERR_PTR(err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) EXPORT_SYMBOL(objagg_create);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) * objagg_destroy - destroys a new objagg instance
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) * @objagg: objagg instance
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) * Note: all locking must be provided by the caller.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) void objagg_destroy(struct objagg *objagg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) trace_objagg_destroy(objagg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) ida_destroy(&objagg->root_ida);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) WARN_ON(!list_empty(&objagg->obj_list));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) rhashtable_destroy(&objagg->obj_ht);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) if (objagg->hints)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) objagg_hints_put(objagg->hints);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) kfree(objagg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) EXPORT_SYMBOL(objagg_destroy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) static int objagg_stats_info_sort_cmp_func(const void *a, const void *b)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) const struct objagg_obj_stats_info *stats_info1 = a;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) const struct objagg_obj_stats_info *stats_info2 = b;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) if (stats_info1->is_root != stats_info2->is_root)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) return stats_info2->is_root - stats_info1->is_root;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) if (stats_info1->stats.delta_user_count !=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) stats_info2->stats.delta_user_count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) return stats_info2->stats.delta_user_count -
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) stats_info1->stats.delta_user_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) return stats_info2->stats.user_count - stats_info1->stats.user_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) * objagg_stats_get - obtains stats of the objagg instance
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) * @objagg: objagg instance
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) * Note: all locking must be provided by the caller.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) * The returned structure contains statistics of all object
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) * currently in use, ordered by following rules:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) * 1) Root objects are always on lower indexes than the rest.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) * 2) Objects with higher delta user count are always on lower
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) * indexes.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) * 3) In case more objects have the same delta user count,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) * the objects are ordered by user count.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) * Returns a pointer to stats instance in case of success,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) * otherwise it returns pointer error using ERR_PTR macro.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) const struct objagg_stats *objagg_stats_get(struct objagg *objagg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) struct objagg_stats *objagg_stats;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) struct objagg_obj *objagg_obj;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) objagg_stats = kzalloc(struct_size(objagg_stats, stats_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) objagg->obj_count), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) if (!objagg_stats)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) return ERR_PTR(-ENOMEM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) i = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) list_for_each_entry(objagg_obj, &objagg->obj_list, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) memcpy(&objagg_stats->stats_info[i].stats, &objagg_obj->stats,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) sizeof(objagg_stats->stats_info[0].stats));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) objagg_stats->stats_info[i].objagg_obj = objagg_obj;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) objagg_stats->stats_info[i].is_root =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) objagg_obj_is_root(objagg_obj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) if (objagg_stats->stats_info[i].is_root)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) objagg_stats->root_count++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) i++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) objagg_stats->stats_info_count = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) sort(objagg_stats->stats_info, objagg_stats->stats_info_count,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) sizeof(struct objagg_obj_stats_info),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) objagg_stats_info_sort_cmp_func, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) return objagg_stats;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) EXPORT_SYMBOL(objagg_stats_get);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) * objagg_stats_put - puts stats of the objagg instance
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) * @objagg_stats: objagg instance stats
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) * Note: all locking must be provided by the caller.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) void objagg_stats_put(const struct objagg_stats *objagg_stats)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) kfree(objagg_stats);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) EXPORT_SYMBOL(objagg_stats_put);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) static struct objagg_hints_node *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) objagg_hints_node_create(struct objagg_hints *objagg_hints,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) struct objagg_obj *objagg_obj, size_t obj_size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) struct objagg_hints_node *parent_hnode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) unsigned int user_count = objagg_obj->stats.user_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) struct objagg_hints_node *hnode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) hnode = kzalloc(sizeof(*hnode) + obj_size, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) if (!hnode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) return ERR_PTR(-ENOMEM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) memcpy(hnode->obj, &objagg_obj->obj, obj_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) hnode->stats_info.stats.user_count = user_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) hnode->stats_info.stats.delta_user_count = user_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) if (parent_hnode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) parent_hnode->stats_info.stats.delta_user_count += user_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) hnode->root_id = objagg_hints->root_count++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) hnode->stats_info.is_root = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) hnode->stats_info.objagg_obj = objagg_obj;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) err = rhashtable_insert_fast(&objagg_hints->node_ht, &hnode->ht_node,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) objagg_hints->ht_params);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) goto err_ht_insert;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) list_add(&hnode->list, &objagg_hints->node_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) hnode->parent = parent_hnode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) objagg_hints->node_count++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) return hnode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) err_ht_insert:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) kfree(hnode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) return ERR_PTR(err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) static void objagg_hints_flush(struct objagg_hints *objagg_hints)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) struct objagg_hints_node *hnode, *tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) list_for_each_entry_safe(hnode, tmp, &objagg_hints->node_list, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) list_del(&hnode->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) rhashtable_remove_fast(&objagg_hints->node_ht, &hnode->ht_node,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) objagg_hints->ht_params);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) kfree(hnode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) struct objagg_tmp_node {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) struct objagg_obj *objagg_obj;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) bool crossed_out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) struct objagg_tmp_graph {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) struct objagg_tmp_node *nodes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) unsigned long nodes_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) unsigned long *edges;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) static int objagg_tmp_graph_edge_index(struct objagg_tmp_graph *graph,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) int parent_index, int index)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) return index * graph->nodes_count + parent_index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) static void objagg_tmp_graph_edge_set(struct objagg_tmp_graph *graph,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) int parent_index, int index)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) int edge_index = objagg_tmp_graph_edge_index(graph, index,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) parent_index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) __set_bit(edge_index, graph->edges);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) static bool objagg_tmp_graph_is_edge(struct objagg_tmp_graph *graph,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) int parent_index, int index)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) int edge_index = objagg_tmp_graph_edge_index(graph, index,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) parent_index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) return test_bit(edge_index, graph->edges);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) static unsigned int objagg_tmp_graph_node_weight(struct objagg_tmp_graph *graph,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) unsigned int index)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) struct objagg_tmp_node *node = &graph->nodes[index];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) unsigned int weight = node->objagg_obj->stats.user_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) int j;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) /* Node weight is sum of node users and all other nodes users
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) * that this node can represent with delta.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) for (j = 0; j < graph->nodes_count; j++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) if (!objagg_tmp_graph_is_edge(graph, index, j))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) node = &graph->nodes[j];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) if (node->crossed_out)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) weight += node->objagg_obj->stats.user_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) return weight;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) static int objagg_tmp_graph_node_max_weight(struct objagg_tmp_graph *graph)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) struct objagg_tmp_node *node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) unsigned int max_weight = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) unsigned int weight;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) int max_index = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) for (i = 0; i < graph->nodes_count; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) node = &graph->nodes[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) if (node->crossed_out)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) weight = objagg_tmp_graph_node_weight(graph, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) if (weight >= max_weight) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) max_weight = weight;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) max_index = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) return max_index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) static struct objagg_tmp_graph *objagg_tmp_graph_create(struct objagg *objagg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) unsigned int nodes_count = objagg->obj_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) struct objagg_tmp_graph *graph;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) struct objagg_tmp_node *node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) struct objagg_tmp_node *pnode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) struct objagg_obj *objagg_obj;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) size_t alloc_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) int i, j;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) graph = kzalloc(sizeof(*graph), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) if (!graph)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) graph->nodes = kcalloc(nodes_count, sizeof(*graph->nodes), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) if (!graph->nodes)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) goto err_nodes_alloc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) graph->nodes_count = nodes_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) alloc_size = BITS_TO_LONGS(nodes_count * nodes_count) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) sizeof(unsigned long);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) graph->edges = kzalloc(alloc_size, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) if (!graph->edges)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) goto err_edges_alloc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) i = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) list_for_each_entry(objagg_obj, &objagg->obj_list, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) node = &graph->nodes[i++];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) node->objagg_obj = objagg_obj;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) /* Assemble a temporary graph. Insert edge X->Y in case Y can be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) * in delta of X.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) for (i = 0; i < nodes_count; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) for (j = 0; j < nodes_count; j++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) if (i == j)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) pnode = &graph->nodes[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) node = &graph->nodes[j];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) if (objagg->ops->delta_check(objagg->priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) pnode->objagg_obj->obj,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) node->objagg_obj->obj)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) objagg_tmp_graph_edge_set(graph, i, j);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) return graph;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) err_edges_alloc:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) kfree(graph->nodes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) err_nodes_alloc:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) kfree(graph);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) static void objagg_tmp_graph_destroy(struct objagg_tmp_graph *graph)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) kfree(graph->edges);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) kfree(graph->nodes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) kfree(graph);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) objagg_opt_simple_greedy_fillup_hints(struct objagg_hints *objagg_hints,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) struct objagg *objagg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) struct objagg_hints_node *hnode, *parent_hnode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) struct objagg_tmp_graph *graph;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) struct objagg_tmp_node *node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) int index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) int j;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) graph = objagg_tmp_graph_create(objagg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) if (!graph)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) /* Find the nodes from the ones that can accommodate most users
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) * and cross them out of the graph. Save them to the hint list.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) while ((index = objagg_tmp_graph_node_max_weight(graph)) != -1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) node = &graph->nodes[index];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) node->crossed_out = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) hnode = objagg_hints_node_create(objagg_hints,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) node->objagg_obj,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) objagg->ops->obj_size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) if (IS_ERR(hnode)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) err = PTR_ERR(hnode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) parent_hnode = hnode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) for (j = 0; j < graph->nodes_count; j++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) if (!objagg_tmp_graph_is_edge(graph, index, j))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) node = &graph->nodes[j];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) if (node->crossed_out)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) node->crossed_out = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) hnode = objagg_hints_node_create(objagg_hints,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) node->objagg_obj,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) objagg->ops->obj_size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) parent_hnode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) if (IS_ERR(hnode)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) err = PTR_ERR(hnode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) objagg_tmp_graph_destroy(graph);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) struct objagg_opt_algo {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) int (*fillup_hints)(struct objagg_hints *objagg_hints,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) struct objagg *objagg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) static const struct objagg_opt_algo objagg_opt_simple_greedy = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) .fillup_hints = objagg_opt_simple_greedy_fillup_hints,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) static const struct objagg_opt_algo *objagg_opt_algos[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) [OBJAGG_OPT_ALGO_SIMPLE_GREEDY] = &objagg_opt_simple_greedy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) static int objagg_hints_obj_cmp(struct rhashtable_compare_arg *arg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) const void *obj)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) struct rhashtable *ht = arg->ht;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) struct objagg_hints *objagg_hints =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) container_of(ht, struct objagg_hints, node_ht);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) const struct objagg_ops *ops = objagg_hints->ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) const char *ptr = obj;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) ptr += ht->p.key_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) return ops->hints_obj_cmp ? ops->hints_obj_cmp(ptr, arg->key) :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) memcmp(ptr, arg->key, ht->p.key_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) * objagg_hints_get - obtains hints instance
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) * @objagg: objagg instance
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) * @opt_algo_type: type of hints finding algorithm
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) * Note: all locking must be provided by the caller.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) * According to the algo type, the existing objects of objagg instance
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) * are going to be went-through to assemble an optimal tree. We call this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) * tree hints. These hints can be later on used for creation of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) * a new objagg instance. There, the future object creations are going
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) * to be consulted with these hints in order to find out, where exactly
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) * the new object should be put as a root or delta.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) * Returns a pointer to hints instance in case of success,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) * otherwise it returns pointer error using ERR_PTR macro.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) struct objagg_hints *objagg_hints_get(struct objagg *objagg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) enum objagg_opt_algo_type opt_algo_type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) const struct objagg_opt_algo *algo = objagg_opt_algos[opt_algo_type];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) struct objagg_hints *objagg_hints;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) objagg_hints = kzalloc(sizeof(*objagg_hints), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) if (!objagg_hints)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) return ERR_PTR(-ENOMEM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) objagg_hints->ops = objagg->ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) objagg_hints->refcount = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) INIT_LIST_HEAD(&objagg_hints->node_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) objagg_hints->ht_params.key_len = objagg->ops->obj_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) objagg_hints->ht_params.key_offset =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) offsetof(struct objagg_hints_node, obj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) objagg_hints->ht_params.head_offset =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) offsetof(struct objagg_hints_node, ht_node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) objagg_hints->ht_params.obj_cmpfn = objagg_hints_obj_cmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) err = rhashtable_init(&objagg_hints->node_ht, &objagg_hints->ht_params);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) goto err_rhashtable_init;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) err = algo->fillup_hints(objagg_hints, objagg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) goto err_fillup_hints;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) if (WARN_ON(objagg_hints->node_count != objagg->obj_count)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) err = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) goto err_node_count_check;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) return objagg_hints;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) err_node_count_check:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) err_fillup_hints:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) objagg_hints_flush(objagg_hints);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) rhashtable_destroy(&objagg_hints->node_ht);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) err_rhashtable_init:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) kfree(objagg_hints);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) return ERR_PTR(err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) EXPORT_SYMBOL(objagg_hints_get);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) * objagg_hints_put - puts hints instance
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) * @objagg_hints: objagg hints instance
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) * Note: all locking must be provided by the caller.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) void objagg_hints_put(struct objagg_hints *objagg_hints)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) if (--objagg_hints->refcount)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) objagg_hints_flush(objagg_hints);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) rhashtable_destroy(&objagg_hints->node_ht);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) kfree(objagg_hints);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) EXPORT_SYMBOL(objagg_hints_put);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) * objagg_hints_stats_get - obtains stats of the hints instance
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) * @objagg_hints: hints instance
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) * Note: all locking must be provided by the caller.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) * The returned structure contains statistics of all objects
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) * currently in use, ordered by following rules:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) * 1) Root objects are always on lower indexes than the rest.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) * 2) Objects with higher delta user count are always on lower
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) * indexes.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) * 3) In case multiple objects have the same delta user count,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) * the objects are ordered by user count.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) * Returns a pointer to stats instance in case of success,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) * otherwise it returns pointer error using ERR_PTR macro.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) const struct objagg_stats *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) objagg_hints_stats_get(struct objagg_hints *objagg_hints)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) struct objagg_stats *objagg_stats;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) struct objagg_hints_node *hnode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) objagg_stats = kzalloc(struct_size(objagg_stats, stats_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) objagg_hints->node_count),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) if (!objagg_stats)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) return ERR_PTR(-ENOMEM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) i = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) list_for_each_entry(hnode, &objagg_hints->node_list, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) memcpy(&objagg_stats->stats_info[i], &hnode->stats_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) sizeof(objagg_stats->stats_info[0]));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) if (objagg_stats->stats_info[i].is_root)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) objagg_stats->root_count++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) i++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) objagg_stats->stats_info_count = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) sort(objagg_stats->stats_info, objagg_stats->stats_info_count,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) sizeof(struct objagg_obj_stats_info),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) objagg_stats_info_sort_cmp_func, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) return objagg_stats;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) EXPORT_SYMBOL(objagg_hints_stats_get);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) MODULE_LICENSE("Dual BSD/GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) MODULE_AUTHOR("Jiri Pirko <jiri@mellanox.com>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) MODULE_DESCRIPTION("Object aggregation manager");