1*0a020d41SJiri Pirko // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 2*0a020d41SJiri Pirko /* Copyright (c) 2018 Mellanox Technologies. All rights reserved */ 3*0a020d41SJiri Pirko 4*0a020d41SJiri Pirko #include <linux/module.h> 5*0a020d41SJiri Pirko #include <linux/slab.h> 6*0a020d41SJiri Pirko #include <linux/rhashtable.h> 7*0a020d41SJiri Pirko #include <linux/list.h> 8*0a020d41SJiri Pirko #include <linux/sort.h> 9*0a020d41SJiri Pirko #include <linux/objagg.h> 10*0a020d41SJiri Pirko 11*0a020d41SJiri Pirko #define CREATE_TRACE_POINTS 12*0a020d41SJiri Pirko #include <trace/events/objagg.h> 13*0a020d41SJiri Pirko 14*0a020d41SJiri Pirko struct objagg { 15*0a020d41SJiri Pirko const struct objagg_ops *ops; 16*0a020d41SJiri Pirko void *priv; 17*0a020d41SJiri Pirko struct rhashtable obj_ht; 18*0a020d41SJiri Pirko struct rhashtable_params ht_params; 19*0a020d41SJiri Pirko struct list_head obj_list; 20*0a020d41SJiri Pirko unsigned int obj_count; 21*0a020d41SJiri Pirko }; 22*0a020d41SJiri Pirko 23*0a020d41SJiri Pirko struct objagg_obj { 24*0a020d41SJiri Pirko struct rhash_head ht_node; /* member of objagg->obj_ht */ 25*0a020d41SJiri Pirko struct list_head list; /* member of objagg->obj_list */ 26*0a020d41SJiri Pirko struct objagg_obj *parent; /* if the object is nested, this 27*0a020d41SJiri Pirko * holds pointer to parent, otherwise NULL 28*0a020d41SJiri Pirko */ 29*0a020d41SJiri Pirko union { 30*0a020d41SJiri Pirko void *delta_priv; /* user delta private */ 31*0a020d41SJiri Pirko void *root_priv; /* user root private */ 32*0a020d41SJiri Pirko }; 33*0a020d41SJiri Pirko unsigned int refcount; /* counts number of users of this object 34*0a020d41SJiri Pirko * including nested objects 35*0a020d41SJiri Pirko */ 36*0a020d41SJiri Pirko struct objagg_obj_stats stats; 37*0a020d41SJiri Pirko unsigned long obj[0]; 38*0a020d41SJiri Pirko }; 39*0a020d41SJiri Pirko 40*0a020d41SJiri Pirko static unsigned int objagg_obj_ref_inc(struct objagg_obj *objagg_obj) 41*0a020d41SJiri Pirko { 42*0a020d41SJiri Pirko return ++objagg_obj->refcount; 43*0a020d41SJiri Pirko } 44*0a020d41SJiri Pirko 45*0a020d41SJiri Pirko static unsigned int objagg_obj_ref_dec(struct objagg_obj *objagg_obj) 46*0a020d41SJiri Pirko { 47*0a020d41SJiri Pirko return --objagg_obj->refcount; 48*0a020d41SJiri Pirko } 49*0a020d41SJiri Pirko 50*0a020d41SJiri Pirko static void objagg_obj_stats_inc(struct objagg_obj *objagg_obj) 51*0a020d41SJiri Pirko { 52*0a020d41SJiri Pirko objagg_obj->stats.user_count++; 53*0a020d41SJiri Pirko objagg_obj->stats.delta_user_count++; 54*0a020d41SJiri Pirko if (objagg_obj->parent) 55*0a020d41SJiri Pirko objagg_obj->parent->stats.delta_user_count++; 56*0a020d41SJiri Pirko } 57*0a020d41SJiri Pirko 58*0a020d41SJiri Pirko static void objagg_obj_stats_dec(struct objagg_obj *objagg_obj) 59*0a020d41SJiri Pirko { 60*0a020d41SJiri Pirko objagg_obj->stats.user_count--; 61*0a020d41SJiri Pirko objagg_obj->stats.delta_user_count--; 62*0a020d41SJiri Pirko if (objagg_obj->parent) 63*0a020d41SJiri Pirko objagg_obj->parent->stats.delta_user_count--; 64*0a020d41SJiri Pirko } 65*0a020d41SJiri Pirko 66*0a020d41SJiri Pirko static bool objagg_obj_is_root(const struct objagg_obj *objagg_obj) 67*0a020d41SJiri Pirko { 68*0a020d41SJiri Pirko /* Nesting is not supported, so we can use ->parent 69*0a020d41SJiri Pirko * to figure out if the object is root. 70*0a020d41SJiri Pirko */ 71*0a020d41SJiri Pirko return !objagg_obj->parent; 72*0a020d41SJiri Pirko } 73*0a020d41SJiri Pirko 74*0a020d41SJiri Pirko /** 75*0a020d41SJiri Pirko * objagg_obj_root_priv - obtains root private for an object 76*0a020d41SJiri Pirko * @objagg_obj: objagg object instance 77*0a020d41SJiri Pirko * 78*0a020d41SJiri Pirko * Note: all locking must be provided by the caller. 79*0a020d41SJiri Pirko * 80*0a020d41SJiri Pirko * Either the object is root itself when the private is returned 81*0a020d41SJiri Pirko * directly, or the parent is root and its private is returned 82*0a020d41SJiri Pirko * instead. 83*0a020d41SJiri Pirko * 84*0a020d41SJiri Pirko * Returns a user private root pointer. 85*0a020d41SJiri Pirko */ 86*0a020d41SJiri Pirko const void *objagg_obj_root_priv(const struct objagg_obj *objagg_obj) 87*0a020d41SJiri Pirko { 88*0a020d41SJiri Pirko if (objagg_obj_is_root(objagg_obj)) 89*0a020d41SJiri Pirko return objagg_obj->root_priv; 90*0a020d41SJiri Pirko WARN_ON(!objagg_obj_is_root(objagg_obj->parent)); 91*0a020d41SJiri Pirko return objagg_obj->parent->root_priv; 92*0a020d41SJiri Pirko } 93*0a020d41SJiri Pirko EXPORT_SYMBOL(objagg_obj_root_priv); 94*0a020d41SJiri Pirko 95*0a020d41SJiri Pirko /** 96*0a020d41SJiri Pirko * objagg_obj_delta_priv - obtains delta private for an object 97*0a020d41SJiri Pirko * @objagg_obj: objagg object instance 98*0a020d41SJiri Pirko * 99*0a020d41SJiri Pirko * Note: all locking must be provided by the caller. 100*0a020d41SJiri Pirko * 101*0a020d41SJiri Pirko * Returns user private delta pointer or NULL in case the passed 102*0a020d41SJiri Pirko * object is root. 103*0a020d41SJiri Pirko */ 104*0a020d41SJiri Pirko const void *objagg_obj_delta_priv(const struct objagg_obj *objagg_obj) 105*0a020d41SJiri Pirko { 106*0a020d41SJiri Pirko if (objagg_obj_is_root(objagg_obj)) 107*0a020d41SJiri Pirko return NULL; 108*0a020d41SJiri Pirko return objagg_obj->delta_priv; 109*0a020d41SJiri Pirko } 110*0a020d41SJiri Pirko EXPORT_SYMBOL(objagg_obj_delta_priv); 111*0a020d41SJiri Pirko 112*0a020d41SJiri Pirko /** 113*0a020d41SJiri Pirko * objagg_obj_raw - obtains object user private pointer 114*0a020d41SJiri Pirko * @objagg_obj: objagg object instance 115*0a020d41SJiri Pirko * 116*0a020d41SJiri Pirko * Note: all locking must be provided by the caller. 117*0a020d41SJiri Pirko * 118*0a020d41SJiri Pirko * Returns user private pointer as was passed to objagg_obj_get() by "obj" arg. 119*0a020d41SJiri Pirko */ 120*0a020d41SJiri Pirko const void *objagg_obj_raw(const struct objagg_obj *objagg_obj) 121*0a020d41SJiri Pirko { 122*0a020d41SJiri Pirko return objagg_obj->obj; 123*0a020d41SJiri Pirko } 124*0a020d41SJiri Pirko EXPORT_SYMBOL(objagg_obj_raw); 125*0a020d41SJiri Pirko 126*0a020d41SJiri Pirko static struct objagg_obj *objagg_obj_lookup(struct objagg *objagg, void *obj) 127*0a020d41SJiri Pirko { 128*0a020d41SJiri Pirko return rhashtable_lookup_fast(&objagg->obj_ht, obj, objagg->ht_params); 129*0a020d41SJiri Pirko } 130*0a020d41SJiri Pirko 131*0a020d41SJiri Pirko static int objagg_obj_parent_assign(struct objagg *objagg, 132*0a020d41SJiri Pirko struct objagg_obj *objagg_obj, 133*0a020d41SJiri Pirko struct objagg_obj *parent) 134*0a020d41SJiri Pirko { 135*0a020d41SJiri Pirko void *delta_priv; 136*0a020d41SJiri Pirko 137*0a020d41SJiri Pirko delta_priv = objagg->ops->delta_create(objagg->priv, parent->obj, 138*0a020d41SJiri Pirko objagg_obj->obj); 139*0a020d41SJiri Pirko if (IS_ERR(delta_priv)) 140*0a020d41SJiri Pirko return PTR_ERR(delta_priv); 141*0a020d41SJiri Pirko 142*0a020d41SJiri Pirko /* User returned a delta private, that means that 143*0a020d41SJiri Pirko * our object can be aggregated into the parent. 144*0a020d41SJiri Pirko */ 145*0a020d41SJiri Pirko objagg_obj->parent = parent; 146*0a020d41SJiri Pirko objagg_obj->delta_priv = delta_priv; 147*0a020d41SJiri Pirko objagg_obj_ref_inc(objagg_obj->parent); 148*0a020d41SJiri Pirko trace_objagg_obj_parent_assign(objagg, objagg_obj, 149*0a020d41SJiri Pirko parent, 150*0a020d41SJiri Pirko parent->refcount); 151*0a020d41SJiri Pirko return 0; 152*0a020d41SJiri Pirko } 153*0a020d41SJiri Pirko 154*0a020d41SJiri Pirko static int objagg_obj_parent_lookup_assign(struct objagg *objagg, 155*0a020d41SJiri Pirko struct objagg_obj *objagg_obj) 156*0a020d41SJiri Pirko { 157*0a020d41SJiri Pirko struct objagg_obj *objagg_obj_cur; 158*0a020d41SJiri Pirko int err; 159*0a020d41SJiri Pirko 160*0a020d41SJiri Pirko list_for_each_entry(objagg_obj_cur, &objagg->obj_list, list) { 161*0a020d41SJiri Pirko /* Nesting is not supported. In case the object 162*0a020d41SJiri Pirko * is not root, it cannot be assigned as parent. 163*0a020d41SJiri Pirko */ 164*0a020d41SJiri Pirko if (!objagg_obj_is_root(objagg_obj_cur)) 165*0a020d41SJiri Pirko continue; 166*0a020d41SJiri Pirko err = objagg_obj_parent_assign(objagg, objagg_obj, 167*0a020d41SJiri Pirko objagg_obj_cur); 168*0a020d41SJiri Pirko if (!err) 169*0a020d41SJiri Pirko return 0; 170*0a020d41SJiri Pirko } 171*0a020d41SJiri Pirko return -ENOENT; 172*0a020d41SJiri Pirko } 173*0a020d41SJiri Pirko 174*0a020d41SJiri Pirko static void __objagg_obj_put(struct objagg *objagg, 175*0a020d41SJiri Pirko struct objagg_obj *objagg_obj); 176*0a020d41SJiri Pirko 177*0a020d41SJiri Pirko static void objagg_obj_parent_unassign(struct objagg *objagg, 178*0a020d41SJiri Pirko struct objagg_obj *objagg_obj) 179*0a020d41SJiri Pirko { 180*0a020d41SJiri Pirko trace_objagg_obj_parent_unassign(objagg, objagg_obj, 181*0a020d41SJiri Pirko objagg_obj->parent, 182*0a020d41SJiri Pirko objagg_obj->parent->refcount); 183*0a020d41SJiri Pirko objagg->ops->delta_destroy(objagg->priv, objagg_obj->delta_priv); 184*0a020d41SJiri Pirko __objagg_obj_put(objagg, objagg_obj->parent); 185*0a020d41SJiri Pirko } 186*0a020d41SJiri Pirko 187*0a020d41SJiri Pirko static int objagg_obj_root_create(struct objagg *objagg, 188*0a020d41SJiri Pirko struct objagg_obj *objagg_obj) 189*0a020d41SJiri Pirko { 190*0a020d41SJiri Pirko objagg_obj->root_priv = objagg->ops->root_create(objagg->priv, 191*0a020d41SJiri Pirko objagg_obj->obj); 192*0a020d41SJiri Pirko if (IS_ERR(objagg_obj->root_priv)) 193*0a020d41SJiri Pirko return PTR_ERR(objagg_obj->root_priv); 194*0a020d41SJiri Pirko 195*0a020d41SJiri Pirko trace_objagg_obj_root_create(objagg, objagg_obj); 196*0a020d41SJiri Pirko return 0; 197*0a020d41SJiri Pirko } 198*0a020d41SJiri Pirko 199*0a020d41SJiri Pirko static void objagg_obj_root_destroy(struct objagg *objagg, 200*0a020d41SJiri Pirko struct objagg_obj *objagg_obj) 201*0a020d41SJiri Pirko { 202*0a020d41SJiri Pirko trace_objagg_obj_root_destroy(objagg, objagg_obj); 203*0a020d41SJiri Pirko objagg->ops->root_destroy(objagg->priv, objagg_obj->root_priv); 204*0a020d41SJiri Pirko } 205*0a020d41SJiri Pirko 206*0a020d41SJiri Pirko static int objagg_obj_init(struct objagg *objagg, 207*0a020d41SJiri Pirko struct objagg_obj *objagg_obj) 208*0a020d41SJiri Pirko { 209*0a020d41SJiri Pirko int err; 210*0a020d41SJiri Pirko 211*0a020d41SJiri Pirko /* Try to find if the object can be aggregated under an existing one. */ 212*0a020d41SJiri Pirko err = objagg_obj_parent_lookup_assign(objagg, objagg_obj); 213*0a020d41SJiri Pirko if (!err) 214*0a020d41SJiri Pirko return 0; 215*0a020d41SJiri Pirko /* If aggregation is not possible, make the object a root. */ 216*0a020d41SJiri Pirko return objagg_obj_root_create(objagg, objagg_obj); 217*0a020d41SJiri Pirko } 218*0a020d41SJiri Pirko 219*0a020d41SJiri Pirko static void objagg_obj_fini(struct objagg *objagg, 220*0a020d41SJiri Pirko struct objagg_obj *objagg_obj) 221*0a020d41SJiri Pirko { 222*0a020d41SJiri Pirko if (!objagg_obj_is_root(objagg_obj)) 223*0a020d41SJiri Pirko objagg_obj_parent_unassign(objagg, objagg_obj); 224*0a020d41SJiri Pirko else 225*0a020d41SJiri Pirko objagg_obj_root_destroy(objagg, objagg_obj); 226*0a020d41SJiri Pirko } 227*0a020d41SJiri Pirko 228*0a020d41SJiri Pirko static struct objagg_obj *objagg_obj_create(struct objagg *objagg, void *obj) 229*0a020d41SJiri Pirko { 230*0a020d41SJiri Pirko struct objagg_obj *objagg_obj; 231*0a020d41SJiri Pirko int err; 232*0a020d41SJiri Pirko 233*0a020d41SJiri Pirko objagg_obj = kzalloc(sizeof(*objagg_obj) + objagg->ops->obj_size, 234*0a020d41SJiri Pirko GFP_KERNEL); 235*0a020d41SJiri Pirko if (!objagg_obj) 236*0a020d41SJiri Pirko return ERR_PTR(-ENOMEM); 237*0a020d41SJiri Pirko objagg_obj_ref_inc(objagg_obj); 238*0a020d41SJiri Pirko memcpy(objagg_obj->obj, obj, objagg->ops->obj_size); 239*0a020d41SJiri Pirko 240*0a020d41SJiri Pirko err = objagg_obj_init(objagg, objagg_obj); 241*0a020d41SJiri Pirko if (err) 242*0a020d41SJiri Pirko goto err_obj_init; 243*0a020d41SJiri Pirko 244*0a020d41SJiri Pirko err = rhashtable_insert_fast(&objagg->obj_ht, &objagg_obj->ht_node, 245*0a020d41SJiri Pirko objagg->ht_params); 246*0a020d41SJiri Pirko if (err) 247*0a020d41SJiri Pirko goto err_ht_insert; 248*0a020d41SJiri Pirko list_add(&objagg_obj->list, &objagg->obj_list); 249*0a020d41SJiri Pirko objagg->obj_count++; 250*0a020d41SJiri Pirko trace_objagg_obj_create(objagg, objagg_obj); 251*0a020d41SJiri Pirko 252*0a020d41SJiri Pirko return objagg_obj; 253*0a020d41SJiri Pirko 254*0a020d41SJiri Pirko err_ht_insert: 255*0a020d41SJiri Pirko objagg_obj_fini(objagg, objagg_obj); 256*0a020d41SJiri Pirko err_obj_init: 257*0a020d41SJiri Pirko kfree(objagg_obj); 258*0a020d41SJiri Pirko return ERR_PTR(err); 259*0a020d41SJiri Pirko } 260*0a020d41SJiri Pirko 261*0a020d41SJiri Pirko static struct objagg_obj *__objagg_obj_get(struct objagg *objagg, void *obj) 262*0a020d41SJiri Pirko { 263*0a020d41SJiri Pirko struct objagg_obj *objagg_obj; 264*0a020d41SJiri Pirko 265*0a020d41SJiri Pirko /* First, try to find the object exactly as user passed it, 266*0a020d41SJiri Pirko * perhaps it is already in use. 267*0a020d41SJiri Pirko */ 268*0a020d41SJiri Pirko objagg_obj = objagg_obj_lookup(objagg, obj); 269*0a020d41SJiri Pirko if (objagg_obj) { 270*0a020d41SJiri Pirko objagg_obj_ref_inc(objagg_obj); 271*0a020d41SJiri Pirko return objagg_obj; 272*0a020d41SJiri Pirko } 273*0a020d41SJiri Pirko 274*0a020d41SJiri Pirko return objagg_obj_create(objagg, obj); 275*0a020d41SJiri Pirko } 276*0a020d41SJiri Pirko 277*0a020d41SJiri Pirko /** 278*0a020d41SJiri Pirko * objagg_obj_get - gets an object within objagg instance 279*0a020d41SJiri Pirko * @objagg: objagg instance 280*0a020d41SJiri Pirko * @obj: user-specific private object pointer 281*0a020d41SJiri Pirko * 282*0a020d41SJiri Pirko * Note: all locking must be provided by the caller. 283*0a020d41SJiri Pirko * 284*0a020d41SJiri Pirko * Size of the "obj" memory is specified in "objagg->ops". 285*0a020d41SJiri Pirko * 286*0a020d41SJiri Pirko * There are 3 main options this function wraps: 287*0a020d41SJiri Pirko * 1) The object according to "obj" already exist. In that case 288*0a020d41SJiri Pirko * the reference counter is incrementes and the object is returned. 289*0a020d41SJiri Pirko * 2) The object does not exist, but it can be aggregated within 290*0a020d41SJiri Pirko * another object. In that case, user ops->delta_create() is called 291*0a020d41SJiri Pirko * to obtain delta data and a new object is created with returned 292*0a020d41SJiri Pirko * user-delta private pointer. 293*0a020d41SJiri Pirko * 3) The object does not exist and cannot be aggregated into 294*0a020d41SJiri Pirko * any of the existing objects. In that case, user ops->root_create() 295*0a020d41SJiri Pirko * is called to create the root and a new object is created with 296*0a020d41SJiri Pirko * returned user-root private pointer. 297*0a020d41SJiri Pirko * 298*0a020d41SJiri Pirko * Returns a pointer to objagg object instance in case of success, 299*0a020d41SJiri Pirko * otherwise it returns pointer error using ERR_PTR macro. 300*0a020d41SJiri Pirko */ 301*0a020d41SJiri Pirko struct objagg_obj *objagg_obj_get(struct objagg *objagg, void *obj) 302*0a020d41SJiri Pirko { 303*0a020d41SJiri Pirko struct objagg_obj *objagg_obj; 304*0a020d41SJiri Pirko 305*0a020d41SJiri Pirko objagg_obj = __objagg_obj_get(objagg, obj); 306*0a020d41SJiri Pirko if (IS_ERR(objagg_obj)) 307*0a020d41SJiri Pirko return objagg_obj; 308*0a020d41SJiri Pirko objagg_obj_stats_inc(objagg_obj); 309*0a020d41SJiri Pirko trace_objagg_obj_get(objagg, objagg_obj, objagg_obj->refcount); 310*0a020d41SJiri Pirko return objagg_obj; 311*0a020d41SJiri Pirko } 312*0a020d41SJiri Pirko EXPORT_SYMBOL(objagg_obj_get); 313*0a020d41SJiri Pirko 314*0a020d41SJiri Pirko static void objagg_obj_destroy(struct objagg *objagg, 315*0a020d41SJiri Pirko struct objagg_obj *objagg_obj) 316*0a020d41SJiri Pirko { 317*0a020d41SJiri Pirko trace_objagg_obj_destroy(objagg, objagg_obj); 318*0a020d41SJiri Pirko --objagg->obj_count; 319*0a020d41SJiri Pirko list_del(&objagg_obj->list); 320*0a020d41SJiri Pirko rhashtable_remove_fast(&objagg->obj_ht, &objagg_obj->ht_node, 321*0a020d41SJiri Pirko objagg->ht_params); 322*0a020d41SJiri Pirko objagg_obj_fini(objagg, objagg_obj); 323*0a020d41SJiri Pirko kfree(objagg_obj); 324*0a020d41SJiri Pirko } 325*0a020d41SJiri Pirko 326*0a020d41SJiri Pirko static void __objagg_obj_put(struct objagg *objagg, 327*0a020d41SJiri Pirko struct objagg_obj *objagg_obj) 328*0a020d41SJiri Pirko { 329*0a020d41SJiri Pirko if (!objagg_obj_ref_dec(objagg_obj)) 330*0a020d41SJiri Pirko objagg_obj_destroy(objagg, objagg_obj); 331*0a020d41SJiri Pirko } 332*0a020d41SJiri Pirko 333*0a020d41SJiri Pirko /** 334*0a020d41SJiri Pirko * objagg_obj_put - puts an object within objagg instance 335*0a020d41SJiri Pirko * @objagg: objagg instance 336*0a020d41SJiri Pirko * @objagg_obj: objagg object instance 337*0a020d41SJiri Pirko * 338*0a020d41SJiri Pirko * Note: all locking must be provided by the caller. 339*0a020d41SJiri Pirko * 340*0a020d41SJiri Pirko * Symmetric to objagg_obj_get(). 341*0a020d41SJiri Pirko */ 342*0a020d41SJiri Pirko void objagg_obj_put(struct objagg *objagg, struct objagg_obj *objagg_obj) 343*0a020d41SJiri Pirko { 344*0a020d41SJiri Pirko trace_objagg_obj_put(objagg, objagg_obj, objagg_obj->refcount); 345*0a020d41SJiri Pirko objagg_obj_stats_dec(objagg_obj); 346*0a020d41SJiri Pirko __objagg_obj_put(objagg, objagg_obj); 347*0a020d41SJiri Pirko } 348*0a020d41SJiri Pirko EXPORT_SYMBOL(objagg_obj_put); 349*0a020d41SJiri Pirko 350*0a020d41SJiri Pirko /** 351*0a020d41SJiri Pirko * objagg_create - creates a new objagg instance 352*0a020d41SJiri Pirko * @ops: user-specific callbacks 353*0a020d41SJiri Pirko * @priv: pointer to a private data passed to the ops 354*0a020d41SJiri Pirko * 355*0a020d41SJiri Pirko * Note: all locking must be provided by the caller. 356*0a020d41SJiri Pirko * 357*0a020d41SJiri Pirko * The purpose of the library is to provide an infrastructure to 358*0a020d41SJiri Pirko * aggregate user-specified objects. Library does not care about the type 359*0a020d41SJiri Pirko * of the object. User fills-up ops which take care of the specific 360*0a020d41SJiri Pirko * user object manipulation. 361*0a020d41SJiri Pirko * 362*0a020d41SJiri Pirko * As a very stupid example, consider integer numbers. For example 363*0a020d41SJiri Pirko * number 8 as a root object. That can aggregate number 9 with delta 1, 364*0a020d41SJiri Pirko * number 10 with delta 2, etc. This example is implemented as 365*0a020d41SJiri Pirko * a part of a testing module in test_objagg.c file. 366*0a020d41SJiri Pirko * 367*0a020d41SJiri Pirko * Each objagg instance contains multiple trees. Each tree node is 368*0a020d41SJiri Pirko * represented by "an object". In the current implementation there can be 369*0a020d41SJiri Pirko * only roots and leafs nodes. Leaf nodes are called deltas. 370*0a020d41SJiri Pirko * But in general, this can be easily extended for intermediate nodes. 371*0a020d41SJiri Pirko * In that extension, a delta would be associated with all non-root 372*0a020d41SJiri Pirko * nodes. 373*0a020d41SJiri Pirko * 374*0a020d41SJiri Pirko * Returns a pointer to newly created objagg instance in case of success, 375*0a020d41SJiri Pirko * otherwise it returns pointer error using ERR_PTR macro. 376*0a020d41SJiri Pirko */ 377*0a020d41SJiri Pirko struct objagg *objagg_create(const struct objagg_ops *ops, void *priv) 378*0a020d41SJiri Pirko { 379*0a020d41SJiri Pirko struct objagg *objagg; 380*0a020d41SJiri Pirko int err; 381*0a020d41SJiri Pirko 382*0a020d41SJiri Pirko if (WARN_ON(!ops || !ops->root_create || !ops->root_destroy || 383*0a020d41SJiri Pirko !ops->delta_create || !ops->delta_destroy)) 384*0a020d41SJiri Pirko return ERR_PTR(-EINVAL); 385*0a020d41SJiri Pirko objagg = kzalloc(sizeof(*objagg), GFP_KERNEL); 386*0a020d41SJiri Pirko if (!objagg) 387*0a020d41SJiri Pirko return ERR_PTR(-ENOMEM); 388*0a020d41SJiri Pirko objagg->ops = ops; 389*0a020d41SJiri Pirko objagg->priv = priv; 390*0a020d41SJiri Pirko INIT_LIST_HEAD(&objagg->obj_list); 391*0a020d41SJiri Pirko 392*0a020d41SJiri Pirko objagg->ht_params.key_len = ops->obj_size; 393*0a020d41SJiri Pirko objagg->ht_params.key_offset = offsetof(struct objagg_obj, obj); 394*0a020d41SJiri Pirko objagg->ht_params.head_offset = offsetof(struct objagg_obj, ht_node); 395*0a020d41SJiri Pirko 396*0a020d41SJiri Pirko err = rhashtable_init(&objagg->obj_ht, &objagg->ht_params); 397*0a020d41SJiri Pirko if (err) 398*0a020d41SJiri Pirko goto err_rhashtable_init; 399*0a020d41SJiri Pirko 400*0a020d41SJiri Pirko trace_objagg_create(objagg); 401*0a020d41SJiri Pirko return objagg; 402*0a020d41SJiri Pirko 403*0a020d41SJiri Pirko err_rhashtable_init: 404*0a020d41SJiri Pirko kfree(objagg); 405*0a020d41SJiri Pirko return ERR_PTR(err); 406*0a020d41SJiri Pirko } 407*0a020d41SJiri Pirko EXPORT_SYMBOL(objagg_create); 408*0a020d41SJiri Pirko 409*0a020d41SJiri Pirko /** 410*0a020d41SJiri Pirko * objagg_destroy - destroys a new objagg instance 411*0a020d41SJiri Pirko * @objagg: objagg instance 412*0a020d41SJiri Pirko * 413*0a020d41SJiri Pirko * Note: all locking must be provided by the caller. 414*0a020d41SJiri Pirko */ 415*0a020d41SJiri Pirko void objagg_destroy(struct objagg *objagg) 416*0a020d41SJiri Pirko { 417*0a020d41SJiri Pirko trace_objagg_destroy(objagg); 418*0a020d41SJiri Pirko WARN_ON(!list_empty(&objagg->obj_list)); 419*0a020d41SJiri Pirko rhashtable_destroy(&objagg->obj_ht); 420*0a020d41SJiri Pirko kfree(objagg); 421*0a020d41SJiri Pirko } 422*0a020d41SJiri Pirko EXPORT_SYMBOL(objagg_destroy); 423*0a020d41SJiri Pirko 424*0a020d41SJiri Pirko static int objagg_stats_info_sort_cmp_func(const void *a, const void *b) 425*0a020d41SJiri Pirko { 426*0a020d41SJiri Pirko const struct objagg_obj_stats_info *stats_info1 = a; 427*0a020d41SJiri Pirko const struct objagg_obj_stats_info *stats_info2 = b; 428*0a020d41SJiri Pirko 429*0a020d41SJiri Pirko if (stats_info1->is_root != stats_info2->is_root) 430*0a020d41SJiri Pirko return stats_info2->is_root - stats_info1->is_root; 431*0a020d41SJiri Pirko if (stats_info1->stats.delta_user_count != 432*0a020d41SJiri Pirko stats_info2->stats.delta_user_count) 433*0a020d41SJiri Pirko return stats_info2->stats.delta_user_count - 434*0a020d41SJiri Pirko stats_info1->stats.delta_user_count; 435*0a020d41SJiri Pirko return stats_info2->stats.user_count - stats_info1->stats.user_count; 436*0a020d41SJiri Pirko } 437*0a020d41SJiri Pirko 438*0a020d41SJiri Pirko /** 439*0a020d41SJiri Pirko * objagg_stats_get - obtains stats of the objagg instance 440*0a020d41SJiri Pirko * @objagg: objagg instance 441*0a020d41SJiri Pirko * 442*0a020d41SJiri Pirko * Note: all locking must be provided by the caller. 443*0a020d41SJiri Pirko * 444*0a020d41SJiri Pirko * The returned structure contains statistics of all object 445*0a020d41SJiri Pirko * currently in use, ordered by following rules: 446*0a020d41SJiri Pirko * 1) Root objects are always on lower indexes than the rest. 447*0a020d41SJiri Pirko * 2) Objects with higher delta user count are always on lower 448*0a020d41SJiri Pirko * indexes. 449*0a020d41SJiri Pirko * 3) In case more objects have the same delta user count, 450*0a020d41SJiri Pirko * the objects are ordered by user count. 451*0a020d41SJiri Pirko * 452*0a020d41SJiri Pirko * Returns a pointer to stats instance in case of success, 453*0a020d41SJiri Pirko * otherwise it returns pointer error using ERR_PTR macro. 454*0a020d41SJiri Pirko */ 455*0a020d41SJiri Pirko const struct objagg_stats *objagg_stats_get(struct objagg *objagg) 456*0a020d41SJiri Pirko { 457*0a020d41SJiri Pirko struct objagg_stats *objagg_stats; 458*0a020d41SJiri Pirko struct objagg_obj *objagg_obj; 459*0a020d41SJiri Pirko size_t alloc_size; 460*0a020d41SJiri Pirko int i; 461*0a020d41SJiri Pirko 462*0a020d41SJiri Pirko alloc_size = sizeof(*objagg_stats) + 463*0a020d41SJiri Pirko sizeof(objagg_stats->stats_info[0]) * objagg->obj_count; 464*0a020d41SJiri Pirko objagg_stats = kzalloc(alloc_size, GFP_KERNEL); 465*0a020d41SJiri Pirko if (!objagg_stats) 466*0a020d41SJiri Pirko return ERR_PTR(-ENOMEM); 467*0a020d41SJiri Pirko 468*0a020d41SJiri Pirko i = 0; 469*0a020d41SJiri Pirko list_for_each_entry(objagg_obj, &objagg->obj_list, list) { 470*0a020d41SJiri Pirko memcpy(&objagg_stats->stats_info[i].stats, &objagg_obj->stats, 471*0a020d41SJiri Pirko sizeof(objagg_stats->stats_info[0].stats)); 472*0a020d41SJiri Pirko objagg_stats->stats_info[i].objagg_obj = objagg_obj; 473*0a020d41SJiri Pirko objagg_stats->stats_info[i].is_root = 474*0a020d41SJiri Pirko objagg_obj_is_root(objagg_obj); 475*0a020d41SJiri Pirko i++; 476*0a020d41SJiri Pirko } 477*0a020d41SJiri Pirko objagg_stats->stats_info_count = i; 478*0a020d41SJiri Pirko 479*0a020d41SJiri Pirko sort(objagg_stats->stats_info, objagg_stats->stats_info_count, 480*0a020d41SJiri Pirko sizeof(struct objagg_obj_stats_info), 481*0a020d41SJiri Pirko objagg_stats_info_sort_cmp_func, NULL); 482*0a020d41SJiri Pirko 483*0a020d41SJiri Pirko return objagg_stats; 484*0a020d41SJiri Pirko } 485*0a020d41SJiri Pirko EXPORT_SYMBOL(objagg_stats_get); 486*0a020d41SJiri Pirko 487*0a020d41SJiri Pirko /** 488*0a020d41SJiri Pirko * objagg_stats_puts - puts stats of the objagg instance 489*0a020d41SJiri Pirko * @objagg_stats: objagg instance stats 490*0a020d41SJiri Pirko * 491*0a020d41SJiri Pirko * Note: all locking must be provided by the caller. 492*0a020d41SJiri Pirko */ 493*0a020d41SJiri Pirko void objagg_stats_put(const struct objagg_stats *objagg_stats) 494*0a020d41SJiri Pirko { 495*0a020d41SJiri Pirko kfree(objagg_stats); 496*0a020d41SJiri Pirko } 497*0a020d41SJiri Pirko EXPORT_SYMBOL(objagg_stats_put); 498*0a020d41SJiri Pirko 499*0a020d41SJiri Pirko MODULE_LICENSE("Dual BSD/GPL"); 500*0a020d41SJiri Pirko MODULE_AUTHOR("Jiri Pirko <jiri@mellanox.com>"); 501*0a020d41SJiri Pirko MODULE_DESCRIPTION("Object aggregation manager"); 502