1 /* ckrm.c - Class-based Kernel Resource Management (CKRM)
3 * Copyright (C) Hubertus Franke, IBM Corp. 2003, 2004
4 * (C) Shailabh Nagar, IBM Corp. 2003, 2004
5 * (C) Chandra Seetharaman, IBM Corp. 2003
6 * (C) Vivek Kashyap, IBM Corp. 2004
9 * Provides kernel API of CKRM for in-kernel,per-resource controllers
10 * (one each for cpu, memory, io, network) and callbacks for
11 * classification modules.
13 * Latest version, more details at http://ckrm.sf.net
15 * This program is free software; you can redistribute it and/or modify
16 * it under the terms of the GNU General Public License as published by
17 * the Free Software Foundation; either version 2 of the License, or
18 * (at your option) any later version.
28 * Made modifications to suit the new RBCE module.
30 * Fixed a bug in fork and exit callbacks. Added callbacks_active and
31 * surrounding logic. Added task paramter for all CE callbacks.
33 * moved to referenced counted class objects and correct locking
35 * Integrated ckrm hooks, classtypes, ...
39 #include <linux/config.h>
40 #include <linux/init.h>
41 #include <linux/linkage.h>
42 #include <linux/kernel.h>
43 #include <linux/errno.h>
44 #include <asm/uaccess.h>
46 #include <asm/errno.h>
47 #include <linux/string.h>
48 #include <linux/list.h>
49 #include <linux/spinlock.h>
50 #include <linux/module.h>
51 #include <linux/ckrm_rc.h>
52 #include <linux/rcfs.h>
56 rwlock_t ckrm_class_lock = RW_LOCK_UNLOCKED; /* protects classlists */
58 struct rcfs_functions rcfs_fn;
59 EXPORT_SYMBOL_GPL(rcfs_fn);
61 int rcfs_engine_regd; /* rcfs state needed by another module */
62 EXPORT_SYMBOL_GPL(rcfs_engine_regd);
65 EXPORT_SYMBOL_GPL(rcfs_mounted);
72 * Return TRUE if the given resource is registered.
74 inline unsigned int is_res_regd(struct ckrm_classtype *clstype, int resid)
76 return ((resid >= 0) && (resid < clstype->max_resid) &&
77 test_bit(resid, &clstype->bit_res_ctlrs)
82 * Return TRUE if the given core class pointer is valid.
84 static struct ckrm_res_ctlr *ckrm_resctlr_lookup(struct ckrm_classtype *clstype,
89 if (!clstype || !resname) {
92 for (resid = 0; resid < clstype->max_resid; resid++) {
93 if (test_bit(resid, &clstype->bit_res_ctlrs)) {
94 struct ckrm_res_ctlr *rctrl = clstype->res_ctlrs[resid];
95 if (!strncmp(resname, rctrl->res_name,
104 /* given a classname return the class handle and its classtype*/
105 void *ckrm_classobj(const char *classname, int *classTypeID)
110 if (!classname || !*classname) {
114 read_lock(&ckrm_class_lock);
115 for (i = 0; i < CKRM_MAX_CLASSTYPES; i++) {
116 struct ckrm_classtype *ctype = ckrm_classtypes[i];
117 struct ckrm_core_class *core;
121 list_for_each_entry(core, &ctype->classes, clslist) {
122 if (core->name && !strcmp(core->name, classname)) {
123 // FIXME: should grep reference..
124 read_unlock(&ckrm_class_lock);
125 *classTypeID = ctype->typeID;
130 read_unlock(&ckrm_class_lock);
134 EXPORT_SYMBOL_GPL(is_res_regd);
135 EXPORT_SYMBOL_GPL(ckrm_classobj);
138 * Internal Functions/macros
141 static inline void set_callbacks_active(struct ckrm_classtype *ctype)
143 ctype->ce_cb_active = ((atomic_read(&ctype->ce_regd) > 0) &&
144 (ctype->ce_callbacks.always_callback
145 || (ctype->num_classes > 1)));
148 int ckrm_validate_and_grab_core(struct ckrm_core_class *core)
151 read_lock(&ckrm_class_lock);
152 if (likely(ckrm_is_core_valid(core))) {
153 ckrm_core_grab(core);
156 read_unlock(&ckrm_class_lock);
161 * Interfaces for classification engine
165 * Registering a callback structure by the classification engine.
167 * Returns typeId of class on success -errno for failure.
169 int ckrm_register_engine(const char *typename, ckrm_eng_callback_t * ecbs)
171 struct ckrm_classtype *ctype;
173 ctype = ckrm_find_classtype_by_name(typename);
177 atomic_inc(&ctype->ce_regd);
179 /* another engine registered or trying to register ? */
180 if (atomic_read(&ctype->ce_regd) != 1) {
181 atomic_dec(&ctype->ce_regd);
186 * One of the following must be set:
187 * classify, class_delete (due to object reference) or
188 * notify (case where notification supported but not classification)
189 * The function pointer must be set the momement the mask is non-null
191 if (!(((ecbs->classify) && (ecbs->class_delete)) || (ecbs->notify)) ||
192 (ecbs->c_interest && ecbs->classify == NULL) ||
193 (ecbs->n_interest && ecbs->notify == NULL)) {
194 atomic_dec(&ctype->ce_regd);
198 ctype->ce_callbacks = *ecbs;
199 set_callbacks_active(ctype);
201 if (ctype->ce_callbacks.class_add) {
202 struct ckrm_core_class *core;
204 read_lock(&ckrm_class_lock);
205 list_for_each_entry(core, &ctype->classes, clslist) {
206 (*ctype->ce_callbacks.class_add) (core->name, core,
209 read_unlock(&ckrm_class_lock);
211 return ctype->typeID;
215 * Unregistering a callback structure by the classification engine.
217 * Returns 0 on success -errno for failure.
219 int ckrm_unregister_engine(const char *typename)
221 struct ckrm_classtype *ctype;
223 ctype = ckrm_find_classtype_by_name(typename);
227 ctype->ce_cb_active = 0;
228 if (atomic_read(&ctype->ce_nr_users) > 1) {
229 /* Somebody is currently using the engine, cannot deregister. */
232 atomic_set(&ctype->ce_regd, 0);
233 memset(&ctype->ce_callbacks, 0, sizeof(ckrm_eng_callback_t));
238 * Interfaces to manipulate class (core or resource) hierarchies
242 ckrm_add_child(struct ckrm_core_class *parent, struct ckrm_core_class *child)
244 struct ckrm_hnode *cnode = &child->hnode;
246 if (!ckrm_is_core_valid(child)) {
247 printk(KERN_ERR "Invalid child %p given in ckrm_add_child\n",
252 INIT_LIST_HEAD(&cnode->children);
253 INIT_LIST_HEAD(&cnode->siblings);
256 struct ckrm_hnode *pnode;
258 if (!ckrm_is_core_valid(parent)) {
260 "Invalid parent %p given in ckrm_add_child\n",
264 pnode = &parent->hnode;
265 write_lock(&parent->hnode_rwlock);
266 list_add(&cnode->siblings, &pnode->children);
267 write_unlock(&parent->hnode_rwlock);
270 cnode->parent = parent;
275 static int ckrm_remove_child(struct ckrm_core_class *child)
277 struct ckrm_hnode *cnode, *pnode;
278 struct ckrm_core_class *parent;
280 if (!ckrm_is_core_valid(child)) {
281 printk(KERN_ERR "Invalid child %p given"
282 " in ckrm_remove_child\n",
287 cnode = &child->hnode;
288 parent = cnode->parent;
289 if (!ckrm_is_core_valid(parent)) {
290 printk(KERN_ERR "Invalid parent %p in ckrm_remove_child\n",
295 pnode = &parent->hnode;
298 /* ensure that the node does not have children */
299 if (!list_empty(&cnode->children)) {
303 write_lock(&parent->hnode_rwlock);
304 list_del(&cnode->siblings);
305 write_unlock(&parent->hnode_rwlock);
306 cnode->parent = NULL;
311 void ckrm_lock_hier(struct ckrm_core_class *parent)
313 if (ckrm_is_core_valid(parent)) {
314 read_lock(&parent->hnode_rwlock);
318 void ckrm_unlock_hier(struct ckrm_core_class *parent)
320 if (ckrm_is_core_valid(parent)) {
321 read_unlock(&parent->hnode_rwlock);
326 * hnode_rwlock of the parent core class must held in read mode.
327 * external callers should 've called ckrm_lock_hier before calling this
330 #define hnode_2_core(ptr) \
331 ((ptr)? container_of(ptr, struct ckrm_core_class, hnode) : NULL)
333 struct ckrm_core_class *ckrm_get_next_child(struct ckrm_core_class *parent,
334 struct ckrm_core_class *child)
336 struct list_head *cnode;
337 struct ckrm_hnode *next_cnode;
338 struct ckrm_core_class *next_childcore;
340 if (!ckrm_is_core_valid(parent)) {
341 printk(KERN_ERR "Invalid parent %p in ckrm_get_next_child\n",
345 if (list_empty(&parent->hnode.children)) {
349 if (!ckrm_is_core_valid(child)) {
351 "Invalid child %p in ckrm_get_next_child\n",
355 cnode = child->hnode.siblings.next;
357 cnode = parent->hnode.children.next;
360 if (cnode == &parent->hnode.children) { /* back at the anchor */
364 next_cnode = container_of(cnode, struct ckrm_hnode, siblings);
365 next_childcore = hnode_2_core(next_cnode);
367 if (!ckrm_is_core_valid(next_childcore)) {
369 "Invalid next child %p in ckrm_get_next_child\n",
373 return next_childcore;
376 EXPORT_SYMBOL_GPL(ckrm_lock_hier);
377 EXPORT_SYMBOL_GPL(ckrm_unlock_hier);
378 EXPORT_SYMBOL_GPL(ckrm_get_next_child);
381 ckrm_alloc_res_class(struct ckrm_core_class *core,
382 struct ckrm_core_class *parent, int resid)
385 struct ckrm_classtype *clstype;
387 * Allocate a resource class only if the resource controller has
388 * registered with core and the engine requests for the class.
390 if (!ckrm_is_core_valid(core))
392 clstype = core->classtype;
393 core->res_class[resid] = NULL;
395 if (test_bit(resid, &clstype->bit_res_ctlrs)) {
396 ckrm_res_ctlr_t *rcbs;
398 atomic_inc(&clstype->nr_resusers[resid]);
399 rcbs = clstype->res_ctlrs[resid];
401 if (rcbs && rcbs->res_alloc) {
402 core->res_class[resid] =
403 (*rcbs->res_alloc) (core, parent);
404 if (core->res_class[resid])
406 printk(KERN_ERR "Error creating res class\n");
408 atomic_dec(&clstype->nr_resusers[resid]);
413 * Initialize a core class
417 #define CLS_DEBUG(fmt, args...) \
418 do { /* printk("%s: " fmt, __FUNCTION__ , ## args); */ } while (0)
421 ckrm_init_core_class(struct ckrm_classtype *clstype,
422 struct ckrm_core_class *dcore,
423 struct ckrm_core_class *parent, const char *name)
425 /* TODO: Should replace name with dentry or add dentry? */
428 /* TODO: How is this used in initialization? */
429 CLS_DEBUG("name %s => %p\n", name ? name : "default", dcore);
430 if ((dcore != clstype->default_class) && (!ckrm_is_core_valid(parent))){
431 printk(KERN_DEBUG "error not a valid parent %p\n", parent);
434 dcore->classtype = clstype;
435 dcore->magic = CKRM_CORE_MAGIC;
437 dcore->class_lock = SPIN_LOCK_UNLOCKED;
438 dcore->hnode_rwlock = RW_LOCK_UNLOCKED;
441 atomic_set(&dcore->refcnt, 0);
442 write_lock(&ckrm_class_lock);
444 INIT_LIST_HEAD(&dcore->objlist);
445 list_add_tail(&dcore->clslist, &clstype->classes);
447 clstype->num_classes++;
448 set_callbacks_active(clstype);
450 write_unlock(&ckrm_class_lock);
451 ckrm_add_child(parent, dcore);
453 for (i = 0; i < clstype->max_resid; i++)
454 ckrm_alloc_res_class(dcore, parent, i);
456 /* fix for race condition seen in stress with numtasks */
458 ckrm_core_grab(parent);
460 ckrm_core_grab(dcore);
464 static void ckrm_free_res_class(struct ckrm_core_class *core, int resid)
467 * Free a resource class only if the resource controller has
468 * registered with core
470 if (core->res_class[resid]) {
471 ckrm_res_ctlr_t *rcbs;
472 struct ckrm_classtype *clstype = core->classtype;
474 atomic_inc(&clstype->nr_resusers[resid]);
475 rcbs = clstype->res_ctlrs[resid];
477 if (rcbs->res_free) {
478 (*rcbs->res_free) (core->res_class[resid]);
479 // compensate inc in alloc
480 atomic_dec(&clstype->nr_resusers[resid]);
482 atomic_dec(&clstype->nr_resusers[resid]);
484 core->res_class[resid] = NULL;
489 * requires that all tasks were previously reassigned to another class
491 * Returns 0 on success -errno on failure.
494 void ckrm_free_core_class(struct ckrm_core_class *core)
497 struct ckrm_classtype *clstype = core->classtype;
498 struct ckrm_core_class *parent = core->hnode.parent;
500 CLS_DEBUG("core=%p:%s parent=%p:%s\n", core, core->name, parent,
503 /* this core was marked as late */
504 printk(KERN_DEBUG "class <%s> finally deleted %lu\n", core->name, jiffies);
506 if (ckrm_remove_child(core) == 0) {
507 printk(KERN_DEBUG "Core class removal failed. Chilren present\n");
509 for (i = 0; i < clstype->max_resid; i++) {
510 ckrm_free_res_class(core, i);
513 write_lock(&ckrm_class_lock);
514 /* Clear the magic, so we would know if this core is reused. */
516 #if 0 /* Dynamic not yet enabled */
517 core->res_class = NULL;
519 /* Remove this core class from its linked list. */
520 list_del(&core->clslist);
521 clstype->num_classes--;
522 set_callbacks_active(clstype);
523 write_unlock(&ckrm_class_lock);
525 /* fix for race condition seen in stress with numtasks */
527 ckrm_core_drop(parent);
532 int ckrm_release_core_class(struct ckrm_core_class *core)
534 if (!ckrm_is_core_valid(core)) {
539 if (core == core->classtype->default_class)
542 /* need to make sure that the classgot really dropped */
543 if (atomic_read(&core->refcnt) != 1) {
544 CLS_DEBUG("class <%s> deletion delayed refcnt=%d jif=%ld\n",
545 core->name, atomic_read(&core->refcnt), jiffies);
546 core->delayed = 1; /* just so we have a ref point */
548 ckrm_core_drop(core);
553 * Interfaces for the resource controller
556 * Registering a callback structure by the resource controller.
558 * Returns the resource id(0 or +ve) on success, -errno for failure.
561 ckrm_register_res_ctlr_intern(struct ckrm_classtype *clstype,
562 ckrm_res_ctlr_t * rcbs)
571 spin_lock(&clstype->res_ctlrs_lock);
572 printk(KERN_WARNING "resid is %d name is %s %s\n",
573 resid, rcbs->res_name, clstype->res_ctlrs[resid]->res_name);
575 if ((resid < CKRM_MAX_RES_CTLRS)
576 && (clstype->res_ctlrs[resid] == NULL)) {
577 clstype->res_ctlrs[resid] = rcbs;
578 atomic_set(&clstype->nr_resusers[resid], 0);
579 set_bit(resid, &clstype->bit_res_ctlrs);
581 if (resid >= clstype->max_resid) {
582 clstype->max_resid = resid + 1;
587 spin_unlock(&clstype->res_ctlrs_lock);
590 for (i = clstype->resid_reserved; i < clstype->max_res_ctlrs; i++) {
591 if (clstype->res_ctlrs[i] == NULL) {
592 clstype->res_ctlrs[i] = rcbs;
594 atomic_set(&clstype->nr_resusers[i], 0);
595 set_bit(i, &clstype->bit_res_ctlrs);
596 if (i >= clstype->max_resid) {
597 clstype->max_resid = i + 1;
599 spin_unlock(&clstype->res_ctlrs_lock);
603 spin_unlock(&clstype->res_ctlrs_lock);
608 ckrm_register_res_ctlr(struct ckrm_classtype *clstype, ckrm_res_ctlr_t * rcbs)
610 struct ckrm_core_class *core;
613 resid = ckrm_register_res_ctlr_intern(clstype, rcbs);
616 /* run through all classes and create the resource class
617 * object and if necessary "initialize" class in context
620 read_lock(&ckrm_class_lock);
621 list_for_each_entry(core, &clstype->classes, clslist) {
622 printk(KERN_INFO "CKRM .. create res clsobj for resouce <%s>"
623 "class <%s> par=%p\n", rcbs->res_name,
624 core->name, core->hnode.parent);
625 ckrm_alloc_res_class(core, core->hnode.parent, resid);
627 if (clstype->add_resctrl) {
628 /* FIXME: this should be mandatory */
629 (*clstype->add_resctrl) (core, resid);
632 read_unlock(&ckrm_class_lock);
638 * Unregistering a callback structure by the resource controller.
640 * Returns 0 on success -errno for failure.
642 int ckrm_unregister_res_ctlr(struct ckrm_res_ctlr *rcbs)
644 struct ckrm_classtype *clstype = rcbs->classtype;
645 struct ckrm_core_class *core = NULL;
646 int resid = rcbs->resid;
648 if ((clstype == NULL) || (resid < 0)) {
651 /* TODO: probably need to also call deregistration function */
653 read_lock(&ckrm_class_lock);
654 /* free up this resource from all the classes */
655 list_for_each_entry(core, &clstype->classes, clslist) {
656 ckrm_free_res_class(core, resid);
658 read_unlock(&ckrm_class_lock);
660 if (atomic_read(&clstype->nr_resusers[resid])) {
664 spin_lock(&clstype->res_ctlrs_lock);
665 clstype->res_ctlrs[resid] = NULL;
666 clear_bit(resid, &clstype->bit_res_ctlrs);
667 clstype->max_resid = fls(clstype->bit_res_ctlrs);
669 spin_unlock(&clstype->res_ctlrs_lock);
675 * Class Type Registration
678 /* TODO: What locking is needed here?*/
680 struct ckrm_classtype *ckrm_classtypes[CKRM_MAX_CLASSTYPES];
681 EXPORT_SYMBOL_GPL(ckrm_classtypes);
683 int ckrm_register_classtype(struct ckrm_classtype *clstype)
685 int tid = clstype->typeID;
688 if ((tid < 0) || (tid > CKRM_MAX_CLASSTYPES)
689 || (ckrm_classtypes[tid]))
693 for (i = CKRM_RESV_CLASSTYPES; i < CKRM_MAX_CLASSTYPES; i++) {
694 if (ckrm_classtypes[i] == NULL) {
702 clstype->typeID = tid;
703 ckrm_classtypes[tid] = clstype;
705 /* TODO: Need to call the callbacks of the RCFS client */
706 if (rcfs_fn.register_classtype) {
707 (*rcfs_fn.register_classtype) (clstype);
708 /* No error return for now. */
713 int ckrm_unregister_classtype(struct ckrm_classtype *clstype)
715 int tid = clstype->typeID;
717 if ((tid < 0) || (tid > CKRM_MAX_CLASSTYPES)
718 || (ckrm_classtypes[tid] != clstype))
721 if (rcfs_fn.deregister_classtype) {
722 (*rcfs_fn.deregister_classtype) (clstype);
723 // No error return for now
726 ckrm_classtypes[tid] = NULL;
727 clstype->typeID = -1;
731 struct ckrm_classtype *ckrm_find_classtype_by_name(const char *name)
734 for (i = 0; i < CKRM_MAX_CLASSTYPES; i++) {
735 struct ckrm_classtype *ctype = ckrm_classtypes[i];
736 if (ctype && !strncmp(ctype->name, name, CKRM_MAX_TYPENAME_LEN))
743 * Generic Functions that can be used as default functions
744 * in almost all classtypes
745 * (a) function iterator over all resource classes of a class
746 * (b) function invoker on a named resource
749 int ckrm_class_show_shares(struct ckrm_core_class *core, struct seq_file *seq)
752 struct ckrm_res_ctlr *rcbs;
753 struct ckrm_classtype *clstype = core->classtype;
754 struct ckrm_shares shares;
756 for (i = 0; i < clstype->max_resid; i++) {
757 atomic_inc(&clstype->nr_resusers[i]);
758 rcbs = clstype->res_ctlrs[i];
759 if (rcbs && rcbs->get_share_values) {
760 (*rcbs->get_share_values) (core->res_class[i], &shares);
761 seq_printf(seq,"res=%s,guarantee=%d,limit=%d,"
762 "total_guarantee=%d,max_limit=%d\n",
763 rcbs->res_name, shares.my_guarantee,
764 shares.my_limit, shares.total_guarantee,
767 atomic_dec(&clstype->nr_resusers[i]);
772 int ckrm_class_show_stats(struct ckrm_core_class *core, struct seq_file *seq)
775 struct ckrm_res_ctlr *rcbs;
776 struct ckrm_classtype *clstype = core->classtype;
778 for (i = 0; i < clstype->max_resid; i++) {
779 atomic_inc(&clstype->nr_resusers[i]);
780 rcbs = clstype->res_ctlrs[i];
781 if (rcbs && rcbs->get_stats)
782 (*rcbs->get_stats) (core->res_class[i], seq);
783 atomic_dec(&clstype->nr_resusers[i]);
788 int ckrm_class_show_config(struct ckrm_core_class *core, struct seq_file *seq)
791 struct ckrm_res_ctlr *rcbs;
792 struct ckrm_classtype *clstype = core->classtype;
794 for (i = 0; i < clstype->max_resid; i++) {
795 atomic_inc(&clstype->nr_resusers[i]);
796 rcbs = clstype->res_ctlrs[i];
797 if (rcbs && rcbs->show_config)
798 (*rcbs->show_config) (core->res_class[i], seq);
799 atomic_dec(&clstype->nr_resusers[i]);
804 int ckrm_class_set_config(struct ckrm_core_class *core, const char *resname,
807 struct ckrm_classtype *clstype = core->classtype;
808 struct ckrm_res_ctlr *rcbs = ckrm_resctlr_lookup(clstype, resname);
811 if (rcbs == NULL || rcbs->set_config == NULL)
813 rc = (*rcbs->set_config) (core->res_class[rcbs->resid], cfgstr);
817 #define legalshare(a) \
819 || ((a) == CKRM_SHARE_UNCHANGED) \
820 || ((a) == CKRM_SHARE_DONTCARE) )
822 int ckrm_class_set_shares(struct ckrm_core_class *core, const char *resname,
823 struct ckrm_shares *shares)
825 struct ckrm_classtype *clstype = core->classtype;
826 struct ckrm_res_ctlr *rcbs;
829 /* Check for legal values */
830 if (!legalshare(shares->my_guarantee) || !legalshare(shares->my_limit)
831 || !legalshare(shares->total_guarantee)
832 || !legalshare(shares->max_limit))
835 rcbs = ckrm_resctlr_lookup(clstype, resname);
836 if (rcbs == NULL || rcbs->set_share_values == NULL)
838 rc = (*rcbs->set_share_values) (core->res_class[rcbs->resid], shares);
842 int ckrm_class_reset_stats(struct ckrm_core_class *core, const char *resname,
845 struct ckrm_classtype *clstype = core->classtype;
846 struct ckrm_res_ctlr *rcbs = ckrm_resctlr_lookup(clstype, resname);
849 if (rcbs == NULL || rcbs->reset_stats == NULL)
851 rc = (*rcbs->reset_stats) (core->res_class[rcbs->resid]);
859 void ckrm_cb_newtask(struct task_struct *tsk)
862 spin_lock_init(&tsk->ckrm_tsklock);
863 ckrm_invoke_event_cb_chain(CKRM_EVENT_NEWTASK, tsk);
866 void ckrm_cb_exit(struct task_struct *tsk)
868 ckrm_invoke_event_cb_chain(CKRM_EVENT_EXIT, tsk);
872 void __init ckrm_init(void)
874 printk(KERN_DEBUG "CKRM Initialization\n");
876 // prepare init_task and then rely on inheritance of properties
877 ckrm_cb_newtask(&init_task);
879 // register/initialize the Metatypes
881 #ifdef CONFIG_CKRM_TYPE_TASKCLASS
883 extern void ckrm_meta_init_taskclass(void);
884 ckrm_meta_init_taskclass();
887 #ifdef CONFIG_CKRM_TYPE_SOCKETCLASS
889 extern void ckrm_meta_init_sockclass(void);
890 ckrm_meta_init_sockclass();
893 printk("CKRM Initialization done\n");
896 EXPORT_SYMBOL_GPL(ckrm_register_engine);
897 EXPORT_SYMBOL_GPL(ckrm_unregister_engine);
899 EXPORT_SYMBOL_GPL(ckrm_register_res_ctlr);
900 EXPORT_SYMBOL_GPL(ckrm_unregister_res_ctlr);
902 EXPORT_SYMBOL_GPL(ckrm_init_core_class);
903 EXPORT_SYMBOL_GPL(ckrm_free_core_class);
904 EXPORT_SYMBOL_GPL(ckrm_release_core_class);
906 EXPORT_SYMBOL_GPL(ckrm_register_classtype);
907 EXPORT_SYMBOL_GPL(ckrm_unregister_classtype);
908 EXPORT_SYMBOL_GPL(ckrm_find_classtype_by_name);
910 EXPORT_SYMBOL_GPL(ckrm_core_grab);
911 EXPORT_SYMBOL_GPL(ckrm_core_drop);
912 EXPORT_SYMBOL_GPL(ckrm_is_core_valid);
913 EXPORT_SYMBOL_GPL(ckrm_validate_and_grab_core);
915 EXPORT_SYMBOL_GPL(ckrm_register_event_set);
916 EXPORT_SYMBOL_GPL(ckrm_unregister_event_set);
917 EXPORT_SYMBOL_GPL(ckrm_register_event_cb);
918 EXPORT_SYMBOL_GPL(ckrm_unregister_event_cb);
920 EXPORT_SYMBOL_GPL(ckrm_class_show_stats);
921 EXPORT_SYMBOL_GPL(ckrm_class_show_config);
922 EXPORT_SYMBOL_GPL(ckrm_class_show_shares);
924 EXPORT_SYMBOL_GPL(ckrm_class_set_config);
925 EXPORT_SYMBOL_GPL(ckrm_class_set_shares);
927 EXPORT_SYMBOL_GPL(ckrm_class_reset_stats);