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