lkml.org 
[lkml]   [2006]   [Apr]   [20]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Date
    Subject[RFC] [PATCH 02/12] Class creation/deletion
    02/12 - ckrm_core_class_support

    Provides functions to alloc and free a user defined class.
    Provides utility macro to walk through the class hierarchy
    --

    Signed-Off-By: Chandra Seetharaman <sekharan@us.ibm.com>
    Signed-Off-By: Hubertus Franke <frankeh@us.ibm.com>
    Signed-Off-By: Shailabh Nagar <nagar@watson.ibm.com>
    Signed-Off-By: Gerrit Huizenga <gh@us.ibm.com>
    Signed-Off-By: Vivek Kashyap <kashyapv@us.ibm.com>
    Signed-Off-By: Matt Helsley <matthltc@us.ibm.com>

    include/linux/ckrm.h | 8 ++
    include/linux/ckrm_rc.h | 9 ++
    kernel/ckrm/ckrm.c | 171 ++++++++++++++++++++++++++++++++++++++++++++----
    3 files changed, 175 insertions(+), 13 deletions(-)

    Index: linux2617-rc2/include/linux/ckrm.h
    ===================================================================
    --- linux2617-rc2.orig/include/linux/ckrm.h
    +++ linux2617-rc2/include/linux/ckrm.h
    @@ -61,6 +61,8 @@ struct ckrm_shares {
    * registered a resource controller (see include/linux/ckrm_rc.h).
    */
    struct ckrm_class {
    + const char *name;
    + struct kref ref;
    int depth; /* depth of this class. root == 0 */
    spinlock_t class_lock; /* protects task_list, shares and children
    * When grabbing class_lock in a hierarchy,
    @@ -70,6 +72,12 @@ struct ckrm_class {
    * grabbing resource specific lock */
    struct ckrm_shares *shares[CKRM_MAX_RES_CTLRS];/* resource shares */
    struct list_head class_list; /* entry in list of all classes */
    +
    + struct list_head task_list; /* this class's tasks */
    +
    + struct ckrm_class *parent;
    + struct list_head siblings; /* entry in list of siblings */
    + struct list_head children; /* head of children */
    };

    #endif /* CONFIG_CKRM */
    Index: linux2617-rc2/kernel/ckrm/ckrm.c
    ===================================================================
    --- linux2617-rc2.orig/kernel/ckrm/ckrm.c
    +++ linux2617-rc2/kernel/ckrm/ckrm.c
    @@ -19,14 +19,32 @@
    */

    #include <linux/module.h>
    -#include <linux/ckrm_rc.h>
    +#include "ckrm_local.h"

    static struct ckrm_controller *ckrm_controllers[CKRM_MAX_RES_CTLRS];
    /* res_ctlrs_lock protects ckrm_controllers array and count in controllers*/
    static spinlock_t res_ctlrs_lock = SPIN_LOCK_UNLOCKED;

    static LIST_HEAD(ckrm_classes);/* link all classes */
    -static rwlock_t ckrm_class_lock = RW_LOCK_UNLOCKED; /* protects ckrm_classes */
    +static int ckrm_num_classes; /* Number of user defined classes */
    +static rwlock_t ckrm_class_lock = RW_LOCK_UNLOCKED;
    + /* protects ckrm_classes list and ckrm_num_classes */
    +
    +struct ckrm_class ckrm_default_class = {
    + .task_list = LIST_HEAD_INIT(ckrm_default_class.task_list),
    + .class_lock = SPIN_LOCK_UNLOCKED,
    + .name = "task",
    + .class_list = LIST_HEAD_INIT(ckrm_default_class.class_list),
    + .siblings = LIST_HEAD_INIT(ckrm_default_class.siblings),
    + .children = LIST_HEAD_INIT(ckrm_default_class.children),
    +};
    +
    +/* Must be called with parent's class_lock held */
    +static inline void ckrm_remove_child(struct ckrm_class *child)
    +{
    + list_del(&child->siblings);
    + child->parent = CKRM_NO_CLASS;
    +}

    /* Must be called with res_ctlr_lock held */
    static inline int is_ctlr_id_valid(unsigned int ctlr_id)
    @@ -97,6 +115,55 @@ static void do_alloc_shares_struct(struc
    ckrm_get_controller(ctlr);
    }

    +static void ckrm_class_init(struct ckrm_class *class)
    +{
    + class->class_lock = SPIN_LOCK_UNLOCKED;
    + kref_init(&class->ref);
    + INIT_LIST_HEAD(&class->task_list);
    + INIT_LIST_HEAD(&class->children);
    + INIT_LIST_HEAD(&class->siblings);
    +}
    +
    +struct ckrm_class *ckrm_alloc_class(struct ckrm_class *parent,
    + const char *name)
    +{
    + int i;
    + struct ckrm_class *class;
    +
    + BUG_ON(parent == NULL);
    +
    + kref_get(&parent->ref);
    + class = kzalloc(sizeof(struct ckrm_class), GFP_KERNEL);
    + if (!class) {
    + kref_put(&parent->ref, ckrm_release_class);
    + return NULL;
    + }
    + ckrm_class_init(class);
    + class->name = name;
    + class->depth = parent->depth + 1;
    +
    + /* Add to parent */
    + spin_lock(&parent->class_lock);
    + class->parent = parent;
    + list_add(&class->siblings, &parent->children);
    + spin_unlock(&parent->class_lock);
    +
    + write_lock(&ckrm_class_lock);
    + list_add_tail(&class->class_list, &ckrm_classes);
    + ckrm_num_classes++;
    + write_unlock(&ckrm_class_lock);
    +
    + for (i = 0; i < CKRM_MAX_RES_CTLRS; i++) {
    + struct ckrm_controller *ctlr = ckrm_get_controller_by_id(i);
    + if (!ctlr)
    + continue;
    + do_alloc_shares_struct(class, ctlr);
    + ckrm_put_controller(ctlr);
    + }
    +
    + return class;
    +}
    +
    /* Free up the given resource specific information in a class */
    static void do_free_shares_struct(struct ckrm_class *class,
    struct ckrm_controller *ctlr)
    @@ -114,6 +181,59 @@ static void do_free_shares_struct(struct
    ckrm_put_controller(ctlr); /* Drop reference acquired in do_alloc */
    }

    +/*
    + * Release a class
    + * requires that all tasks were previously reassigned to another class
    + *
    + * Returns 0 on success -errno on failure.
    + */
    +void ckrm_release_class(struct kref *kref)
    +{
    + int i;
    + struct ckrm_class *class = container_of(kref,
    + struct ckrm_class, ref);
    + struct ckrm_class *parent = class->parent;
    +
    + BUG_ON(ckrm_is_class_root(class));
    +
    + for (i = 0; i < CKRM_MAX_RES_CTLRS; i++) {
    + struct ckrm_controller *ctlr = ckrm_get_controller_by_id(i);
    + if (!ctlr)
    + continue;
    + do_free_shares_struct(class, ctlr);
    + ckrm_put_controller(ctlr);
    + }
    +
    + /* Remove this class from the list of all classes */
    + write_lock(&ckrm_class_lock);
    + list_del(&class->class_list);
    + ckrm_num_classes--;
    + write_unlock(&ckrm_class_lock);
    +
    + /* remove from parent */
    + spin_lock(&parent->class_lock);
    + list_del(&class->siblings);
    + class->parent = CKRM_NO_CLASS;
    + spin_unlock(&parent->class_lock);
    +
    + kref_put(&parent->ref, ckrm_release_class);
    + kfree(class);
    +}
    +
    +int ckrm_free_class(struct ckrm_class *class)
    +{
    + BUG_ON(ckrm_is_class_root(class));
    + spin_lock(&class->class_lock);
    + if (!list_empty(&class->children)) {
    + spin_unlock(&class->class_lock);
    + return -EBUSY;
    + }
    + spin_unlock(&class->class_lock);
    + kref_put(&class->ref, ckrm_release_class);
    + return 0;
    +}
    +
    +
    static int add_controller(struct ckrm_controller *ctlr)
    {
    int ctlr_id, ret = -ENOSPC;
    @@ -128,7 +248,6 @@ static int add_controller(struct ckrm_co
    spin_unlock(&res_ctlrs_lock);
    return ret;
    }
    -
    /*
    * Interface for registering a resource controller.
    *
    @@ -138,7 +257,7 @@ static int add_controller(struct ckrm_co
    int ckrm_register_controller(struct ckrm_controller *ctlr)
    {
    int ret;
    - struct ckrm_class *class;
    + struct ckrm_class *class, *prev_class;

    if (!ctlr)
    return -EINVAL;
    @@ -160,10 +279,20 @@ int ckrm_register_controller(struct ckrm
    * Run through all classes and create the controller specific data
    * structures.
    */
    - read_lock(&ckrm_class_lock);
    - list_for_each_entry(class, &ckrm_classes, class_list)
    - do_alloc_shares_struct(class, ctlr);
    - read_unlock(&ckrm_class_lock);
    + prev_class = NULL;
    + read_lock(&ckrm_class_lock);
    + list_for_each_entry(class, &ckrm_classes, class_list) {
    + kref_get(&class->ref);
    + read_unlock(&ckrm_class_lock);
    + do_alloc_shares_struct(class, ctlr);
    + if (prev_class)
    + kref_put(&prev_class->ref, ckrm_release_class);
    + prev_class = class;
    + read_lock(&ckrm_class_lock);
    + }
    + read_unlock(&ckrm_class_lock);
    + if (prev_class)
    + kref_put(&prev_class->ref, ckrm_release_class);
    return 0;
    }

    @@ -188,7 +317,7 @@ static int remove_controller(struct ckrm
    */
    int ckrm_unregister_controller(struct ckrm_controller *ctlr)
    {
    - struct ckrm_class *class;
    + struct ckrm_class *class, *prev_class;

    if (!ctlr)
    return -EINVAL;
    @@ -197,10 +326,20 @@ int ckrm_unregister_controller(struct ck
    return -EINVAL;

    /* free shares structs for this resource from all the classes */
    - read_lock(&ckrm_class_lock);
    - list_for_each_entry_reverse(class, &ckrm_classes, class_list)
    - do_free_shares_struct(class, ctlr);
    - read_unlock(&ckrm_class_lock);
    + prev_class = NULL;
    + read_lock(&ckrm_class_lock);
    + list_for_each_entry_reverse(class, &ckrm_classes, class_list) {
    + kref_get(&class->ref);
    + read_unlock(&ckrm_class_lock);
    + do_free_shares_struct(class, ctlr);
    + if (prev_class)
    + kref_put(&prev_class->ref, ckrm_release_class);
    + prev_class = class;
    + read_lock(&ckrm_class_lock);
    + }
    + read_unlock(&ckrm_class_lock);
    + if (prev_class)
    + kref_put(&prev_class->ref, ckrm_release_class);

    ckrm_put_controller(ctlr);
    return remove_controller(ctlr);
    @@ -208,3 +347,9 @@ int ckrm_unregister_controller(struct ck

    EXPORT_SYMBOL_GPL(ckrm_register_controller);
    EXPORT_SYMBOL_GPL(ckrm_unregister_controller);
    +EXPORT_SYMBOL_GPL(ckrm_alloc_class);
    +EXPORT_SYMBOL_GPL(ckrm_free_class);
    +EXPORT_SYMBOL_GPL(ckrm_default_class);
    +EXPORT_SYMBOL_GPL(ckrm_get_controller_by_name);
    +EXPORT_SYMBOL_GPL(ckrm_get_controller_by_id);
    +EXPORT_SYMBOL_GPL(ckrm_put_controller);
    Index: linux2617-rc2/include/linux/ckrm_rc.h
    ===================================================================
    --- linux2617-rc2.orig/include/linux/ckrm_rc.h
    +++ linux2617-rc2/include/linux/ckrm_rc.h
    @@ -64,4 +64,13 @@ struct ckrm_controller {

    extern int ckrm_register_controller(struct ckrm_controller *);
    extern int ckrm_unregister_controller(struct ckrm_controller *);
    +extern struct ckrm_class ckrm_default_class;
    +static inline int ckrm_is_class_root(const struct ckrm_class* class)
    +{
    + return (class == &ckrm_default_class);
    +}
    +
    +#define for_each_child(child, parent) \
    + list_for_each_entry(child, &parent->children, siblings)
    +
    #endif /* _LINUX_CKRM_RC_H */
    --

    ----------------------------------------------------------------------
    Chandra Seetharaman | Be careful what you choose....
    - sekharan@us.ibm.com | .......you may get it.
    ----------------------------------------------------------------------
    -
    To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    the body of a message to majordomo@vger.kernel.org
    More majordomo info at http://vger.kernel.org/majordomo-info.html
    Please read the FAQ at http://www.tux.org/lkml/
    \
     
     \ /
      Last update: 2006-04-21 04:27    [W:0.037 / U:91.644 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site