RHEL4/lib/kobject.c
<<
>>
Prefs
   1/*
   2 * kobject.c - library routines for handling generic kernel objects
   3 *
   4 * Copyright (c) 2002-2003 Patrick Mochel <mochel@osdl.org>
   5 *
   6 * This file is released under the GPLv2.
   7 *
   8 *
   9 * Please see the file Documentation/kobject.txt for critical information
  10 * about using the kobject interface.
  11 */
  12
  13#undef DEBUG
  14
  15#include <linux/kobject.h>
  16#include <linux/string.h>
  17#include <linux/module.h>
  18#include <linux/stat.h>
  19
  20/**
  21 *      populate_dir - populate directory with attributes.
  22 *      @kobj:  object we're working on.
  23 *
  24 *      Most subsystems have a set of default attributes that 
  25 *      are associated with an object that registers with them.
  26 *      This is a helper called during object registration that 
  27 *      loops through the default attributes of the subsystem 
  28 *      and creates attributes files for them in sysfs.
  29 *
  30 */
  31
  32static int populate_dir(struct kobject * kobj)
  33{
  34        struct kobj_type * t = get_ktype(kobj);
  35        struct attribute * attr;
  36        int error = 0;
  37        int i;
  38        
  39        if (t && t->default_attrs) {
  40                for (i = 0; (attr = t->default_attrs[i]) != NULL; i++) {
  41                        if ((error = sysfs_create_file(kobj,attr)))
  42                                break;
  43                }
  44        }
  45        return error;
  46}
  47
  48static int create_dir(struct kobject * kobj)
  49{
  50        int error = 0;
  51        if (kobject_name(kobj)) {
  52                error = sysfs_create_dir(kobj);
  53                if (!error) {
  54                        if ((error = populate_dir(kobj)))
  55                                sysfs_remove_dir(kobj);
  56                }
  57        }
  58        return error;
  59}
  60
  61static inline struct kobject * to_kobj(struct list_head * entry)
  62{
  63        return container_of(entry,struct kobject,entry);
  64}
  65
  66static int get_kobj_path_length(struct kset *kset, struct kobject *kobj)
  67{
  68        int length = 1;
  69        struct kobject * parent = kobj;
  70
  71        /* walk up the ancestors until we hit the one pointing to the 
  72         * root.
  73         * Add 1 to strlen for leading '/' of each level.
  74         */
  75        do {
  76                length += strlen(kobject_name(parent)) + 1;
  77                parent = parent->parent;
  78        } while (parent);
  79        return length;
  80}
  81
  82static void fill_kobj_path(struct kset *kset, struct kobject *kobj, char *path, int length)
  83{
  84        struct kobject * parent;
  85
  86        --length;
  87        for (parent = kobj; parent; parent = parent->parent) {
  88                int cur = strlen(kobject_name(parent));
  89                /* back up enough to print this name with '/' */
  90                length -= cur;
  91                strncpy (path + length, kobject_name(parent), cur);
  92                *(path + --length) = '/';
  93        }
  94
  95        pr_debug("%s: path = '%s'\n",__FUNCTION__,path);
  96}
  97
  98/**
  99 * kobject_get_path - generate and return the path associated with a given kobj
 100 * and kset pair.  The result must be freed by the caller with kfree().
 101 *
 102 * @kset:       kset in question, with which to build the path
 103 * @kobj:       kobject in question, with which to build the path
 104 * @gfp_mask:   the allocation type used to allocate the path
 105 */
 106char * kobject_get_path(struct kset *kset, struct kobject *kobj, int gfp_mask)
 107{
 108        char *path;
 109        int len;
 110
 111        len = get_kobj_path_length(kset, kobj);
 112        path = kmalloc(len, gfp_mask);
 113        if (!path)
 114                return NULL;
 115        memset(path, 0x00, len);
 116        fill_kobj_path(kset, kobj, path, len);
 117
 118        return path;
 119}
 120
 121#ifdef CONFIG_HOTPLUG
 122
 123#define BUFFER_SIZE     1024    /* should be enough memory for the env */
 124#define NUM_ENVP        32      /* number of env pointers */
 125static unsigned long sequence_num;
 126static spinlock_t sequence_lock = SPIN_LOCK_UNLOCKED;
 127
 128static void kset_hotplug(const char *action, struct kset *kset,
 129                         struct kobject *kobj)
 130{
 131        char *argv [3];
 132        char **envp = NULL;
 133        char *buffer = NULL;
 134        char *scratch;
 135        int i = 0;
 136        int retval;
 137        char *kobj_path = NULL;
 138        char *name = NULL;
 139        unsigned long seq;
 140
 141        /* If the kset has a filter operation, call it. If it returns
 142           failure, no hotplug event is required. */
 143        if (kset->hotplug_ops->filter) {
 144                if (!kset->hotplug_ops->filter(kset, kobj))
 145                        return;
 146        }
 147
 148        pr_debug ("%s\n", __FUNCTION__);
 149
 150        if (!hotplug_path[0])
 151                return;
 152
 153        envp = kmalloc(NUM_ENVP * sizeof (char *), GFP_KERNEL);
 154        if (!envp)
 155                return;
 156        memset (envp, 0x00, NUM_ENVP * sizeof (char *));
 157
 158        buffer = kmalloc(BUFFER_SIZE, GFP_KERNEL);
 159        if (!buffer)
 160                goto exit;
 161
 162        if (kset->hotplug_ops->name)
 163                name = kset->hotplug_ops->name(kset, kobj);
 164        if (name == NULL)
 165                name = kset->kobj.name;
 166
 167        argv [0] = hotplug_path;
 168        argv [1] = name;
 169        argv [2] = NULL;
 170
 171        /* minimal command environment */
 172        envp [i++] = "HOME=/";
 173        envp [i++] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin";
 174
 175        scratch = buffer;
 176
 177        envp [i++] = scratch;
 178        scratch += sprintf(scratch, "ACTION=%s", action) + 1;
 179
 180        spin_lock(&sequence_lock);
 181        seq = sequence_num++;
 182        spin_unlock(&sequence_lock);
 183
 184        envp [i++] = scratch;
 185        scratch += sprintf(scratch, "SEQNUM=%ld", seq) + 1;
 186
 187        kobj_path = kobject_get_path(kset, kobj, GFP_KERNEL);
 188        if (!kobj_path)
 189                goto exit;
 190
 191        envp [i++] = scratch;
 192        scratch += sprintf (scratch, "DEVPATH=%s", kobj_path) + 1;
 193
 194        if (kset->hotplug_ops->hotplug) {
 195                /* have the kset specific function add its stuff */
 196                retval = kset->hotplug_ops->hotplug (kset, kobj,
 197                                  &envp[i], NUM_ENVP - i, scratch,
 198                                  BUFFER_SIZE - (scratch - buffer));
 199                if (retval) {
 200                        pr_debug ("%s - hotplug() returned %d\n",
 201                                  __FUNCTION__, retval);
 202                        goto exit;
 203                }
 204        }
 205
 206        pr_debug ("%s: %s %s %s %s %s %s %s\n", __FUNCTION__, argv[0], argv[1],
 207                  envp[0], envp[1], envp[2], envp[3], envp[4]);
 208        retval = call_usermodehelper (argv[0], argv, envp, 0);
 209        if (retval)
 210                pr_debug ("%s - call_usermodehelper returned %d\n",
 211                          __FUNCTION__, retval);
 212
 213exit:
 214        kfree(kobj_path);
 215        kfree(buffer);
 216        kfree(envp);
 217        return;
 218}
 219
 220void kobject_hotplug(const char *action, struct kobject *kobj)
 221{
 222        struct kobject * top_kobj = kobj;
 223
 224        /* If this kobj does not belong to a kset,
 225           try to find a parent that does. */
 226        if (!top_kobj->kset && top_kobj->parent) {
 227                do {
 228                        top_kobj = top_kobj->parent;
 229                } while (!top_kobj->kset && top_kobj->parent);
 230        }
 231
 232        if (top_kobj->kset && top_kobj->kset->hotplug_ops)
 233                kset_hotplug(action, top_kobj->kset, kobj);
 234}
 235#else
 236void kobject_hotplug(const char *action, struct kobject *kobj)
 237{
 238        return;
 239}
 240#endif  /* CONFIG_HOTPLUG */
 241
 242/**
 243 *      kobject_init - initialize object.
 244 *      @kobj:  object in question.
 245 */
 246void kobject_init(struct kobject * kobj)
 247{
 248        kref_init(&kobj->kref);
 249        INIT_LIST_HEAD(&kobj->entry);
 250        kobj->kset = kset_get(kobj->kset);
 251}
 252
 253
 254/**
 255 *      unlink - remove kobject from kset list.
 256 *      @kobj:  kobject.
 257 *
 258 *      Remove the kobject from the kset list and decrement
 259 *      its parent's refcount.
 260 *      This is separated out, so we can use it in both 
 261 *      kobject_del() and kobject_add() on error.
 262 */
 263
 264static void unlink(struct kobject * kobj)
 265{
 266        if (kobj->kset) {
 267                down_write(&kobj->kset->subsys->rwsem);
 268                list_del_init(&kobj->entry);
 269                up_write(&kobj->kset->subsys->rwsem);
 270        }
 271        kobject_put(kobj);
 272}
 273
 274/**
 275 *      kobject_add - add an object to the hierarchy.
 276 *      @kobj:  object.
 277 */
 278
 279int kobject_add(struct kobject * kobj)
 280{
 281        int error = 0;
 282        struct kobject * parent;
 283
 284        if (!(kobj = kobject_get(kobj)))
 285                return -ENOENT;
 286        if (!kobj->k_name)
 287                kobj->k_name = kobj->name;
 288        parent = kobject_get(kobj->parent);
 289
 290        pr_debug("kobject %s: registering. parent: %s, set: %s\n",
 291                 kobject_name(kobj), parent ? kobject_name(parent) : "<NULL>", 
 292                 kobj->kset ? kobj->kset->kobj.name : "<NULL>" );
 293
 294        if (kobj->kset) {
 295                down_write(&kobj->kset->subsys->rwsem);
 296
 297                if (!parent)
 298                        parent = kobject_get(&kobj->kset->kobj);
 299
 300                list_add_tail(&kobj->entry,&kobj->kset->list);
 301                up_write(&kobj->kset->subsys->rwsem);
 302        }
 303        kobj->parent = parent;
 304
 305        error = create_dir(kobj);
 306        if (error) {
 307                unlink(kobj);
 308                if (parent)
 309                        kobject_put(parent);
 310        } else {
 311                kobject_hotplug("add", kobj);
 312        }
 313
 314        return error;
 315}
 316
 317
 318/**
 319 *      kobject_register - initialize and add an object.
 320 *      @kobj:  object in question.
 321 */
 322
 323int kobject_register(struct kobject * kobj)
 324{
 325        int error = 0;
 326        if (kobj) {
 327                kobject_init(kobj);
 328                error = kobject_add(kobj);
 329                if (error) {
 330                        printk("kobject_register failed for %s (%d)\n",
 331                               kobject_name(kobj),error);
 332                        dump_stack();
 333                }
 334        } else
 335                error = -EINVAL;
 336        return error;
 337}
 338
 339
 340/**
 341 *      kobject_set_name - Set the name of an object
 342 *      @kobj:  object.
 343 *      @name:  name. 
 344 *
 345 *      If strlen(name) >= KOBJ_NAME_LEN, then use a dynamically allocated
 346 *      string that @kobj->k_name points to. Otherwise, use the static 
 347 *      @kobj->name array.
 348 */
 349
 350int kobject_set_name(struct kobject * kobj, const char * fmt, ...)
 351{
 352        int error = 0;
 353        int limit = KOBJ_NAME_LEN;
 354        int need;
 355        va_list args;
 356        char * name;
 357
 358        va_start(args,fmt);
 359        /* 
 360         * First, try the static array 
 361         */
 362        need = vsnprintf(kobj->name,limit,fmt,args);
 363        if (need < limit) 
 364                name = kobj->name;
 365        else {
 366                /* 
 367                 * Need more space? Allocate it and try again 
 368                 */
 369                limit = need + 1;
 370                name = kmalloc(limit,GFP_KERNEL);
 371                if (!name) {
 372                        error = -ENOMEM;
 373                        goto Done;
 374                }
 375                need = vsnprintf(name,limit,fmt,args);
 376
 377                /* Still? Give up. */
 378                if (need >= limit) {
 379                        kfree(name);
 380                        error = -EFAULT;
 381                        goto Done;
 382                }
 383        }
 384
 385        /* Free the old name, if necessary. */
 386        if (kobj->k_name && kobj->k_name != kobj->name)
 387                kfree(kobj->k_name);
 388
 389        /* Now, set the new name */
 390        kobj->k_name = name;
 391 Done:
 392        va_end(args);
 393        return error;
 394}
 395
 396EXPORT_SYMBOL(kobject_set_name);
 397
 398
 399/**
 400 *      kobject_rename - change the name of an object
 401 *      @kobj:  object in question.
 402 *      @new_name: object's new name
 403 */
 404
 405int kobject_rename(struct kobject * kobj, char *new_name)
 406{
 407        int error = 0;
 408
 409        kobj = kobject_get(kobj);
 410        if (!kobj)
 411                return -EINVAL;
 412        error = sysfs_rename_dir(kobj, new_name);
 413        kobject_put(kobj);
 414
 415        return error;
 416}
 417
 418/**
 419 *      kobject_del - unlink kobject from hierarchy.
 420 *      @kobj:  object.
 421 */
 422
 423void kobject_del(struct kobject * kobj)
 424{
 425        kobject_hotplug("remove", kobj);
 426        sysfs_remove_dir(kobj);
 427        unlink(kobj);
 428}
 429
 430/**
 431 *      kobject_unregister - remove object from hierarchy and decrement refcount.
 432 *      @kobj:  object going away.
 433 */
 434
 435void kobject_unregister(struct kobject * kobj)
 436{
 437        pr_debug("kobject %s: unregistering\n",kobject_name(kobj));
 438        kobject_del(kobj);
 439        kobject_put(kobj);
 440}
 441
 442/**
 443 *      kobject_get - increment refcount for object.
 444 *      @kobj:  object.
 445 */
 446
 447struct kobject * kobject_get(struct kobject * kobj)
 448{
 449        if (kobj)
 450                kref_get(&kobj->kref);
 451        return kobj;
 452}
 453
 454/**
 455 *      kobject_cleanup - free kobject resources. 
 456 *      @kobj:  object.
 457 */
 458
 459void kobject_cleanup(struct kobject * kobj)
 460{
 461        struct kobj_type * t = get_ktype(kobj);
 462        struct kset * s = kobj->kset;
 463        struct kobject * parent = kobj->parent;
 464
 465        pr_debug("kobject %s: cleaning up\n",kobject_name(kobj));
 466        if (kobj->k_name != kobj->name)
 467                kfree(kobj->k_name);
 468        kobj->k_name = NULL;
 469        if (t && t->release)
 470                t->release(kobj);
 471        if (s)
 472                kset_put(s);
 473        if (parent) 
 474                kobject_put(parent);
 475}
 476
 477static void kobject_release(struct kref *kref)
 478{
 479        kobject_cleanup(container_of(kref, struct kobject, kref));
 480}
 481
 482/**
 483 *      kobject_put - decrement refcount for object.
 484 *      @kobj:  object.
 485 *
 486 *      Decrement the refcount, and if 0, call kobject_cleanup().
 487 */
 488void kobject_put(struct kobject * kobj)
 489{
 490        if (kobj)
 491                kref_put(&kobj->kref, kobject_release);
 492}
 493
 494
 495/**
 496 *      kset_init - initialize a kset for use
 497 *      @k:     kset 
 498 */
 499
 500void kset_init(struct kset * k)
 501{
 502        kobject_init(&k->kobj);
 503        INIT_LIST_HEAD(&k->list);
 504}
 505
 506
 507/**
 508 *      kset_add - add a kset object to the hierarchy.
 509 *      @k:     kset.
 510 *
 511 *      Simply, this adds the kset's embedded kobject to the 
 512 *      hierarchy. 
 513 *      We also try to make sure that the kset's embedded kobject
 514 *      has a parent before it is added. We only care if the embedded
 515 *      kobject is not part of a kset itself, since kobject_add()
 516 *      assigns a parent in that case. 
 517 *      If that is the case, and the kset has a controlling subsystem,
 518 *      then we set the kset's parent to be said subsystem. 
 519 */
 520
 521int kset_add(struct kset * k)
 522{
 523        if (!k->kobj.parent && !k->kobj.kset && k->subsys)
 524                k->kobj.parent = &k->subsys->kset.kobj;
 525
 526        return kobject_add(&k->kobj);
 527}
 528
 529
 530/**
 531 *      kset_register - initialize and add a kset.
 532 *      @k:     kset.
 533 */
 534
 535int kset_register(struct kset * k)
 536{
 537        kset_init(k);
 538        return kset_add(k);
 539}
 540
 541
 542/**
 543 *      kset_unregister - remove a kset.
 544 *      @k:     kset.
 545 */
 546
 547void kset_unregister(struct kset * k)
 548{
 549        kobject_unregister(&k->kobj);
 550}
 551
 552
 553/**
 554 *      kset_find_obj - search for object in kset.
 555 *      @kset:  kset we're looking in.
 556 *      @name:  object's name.
 557 *
 558 *      Lock kset via @kset->subsys, and iterate over @kset->list,
 559 *      looking for a matching kobject. If matching object is found
 560 *      take a reference and return the object.
 561 */
 562
 563struct kobject * kset_find_obj(struct kset * kset, const char * name)
 564{
 565        struct list_head * entry;
 566        struct kobject * ret = NULL;
 567
 568        down_read(&kset->subsys->rwsem);
 569        list_for_each(entry,&kset->list) {
 570                struct kobject * k = to_kobj(entry);
 571                if (kobject_name(k) && !strcmp(kobject_name(k),name)) {
 572                        ret = kobject_get(k);
 573                        break;
 574                }
 575        }
 576        up_read(&kset->subsys->rwsem);
 577        return ret;
 578}
 579
 580
 581void subsystem_init(struct subsystem * s)
 582{
 583        init_rwsem(&s->rwsem);
 584        kset_init(&s->kset);
 585}
 586
 587/**
 588 *      subsystem_register - register a subsystem.
 589 *      @s:     the subsystem we're registering.
 590 *
 591 *      Once we register the subsystem, we want to make sure that 
 592 *      the kset points back to this subsystem for correct usage of 
 593 *      the rwsem. 
 594 */
 595
 596int subsystem_register(struct subsystem * s)
 597{
 598        int error;
 599
 600        subsystem_init(s);
 601        pr_debug("subsystem %s: registering\n",s->kset.kobj.name);
 602
 603        if (!(error = kset_add(&s->kset))) {
 604                if (!s->kset.subsys)
 605                        s->kset.subsys = s;
 606        }
 607        return error;
 608}
 609
 610void subsystem_unregister(struct subsystem * s)
 611{
 612        pr_debug("subsystem %s: unregistering\n",s->kset.kobj.name);
 613        kset_unregister(&s->kset);
 614}
 615
 616
 617/**
 618 *      subsystem_create_file - export sysfs attribute file.
 619 *      @s:     subsystem.
 620 *      @a:     subsystem attribute descriptor.
 621 */
 622
 623int subsys_create_file(struct subsystem * s, struct subsys_attribute * a)
 624{
 625        int error = 0;
 626        if (subsys_get(s)) {
 627                error = sysfs_create_file(&s->kset.kobj,&a->attr);
 628                subsys_put(s);
 629        }
 630        return error;
 631}
 632
 633
 634/**
 635 *      subsystem_remove_file - remove sysfs attribute file.
 636 *      @s:     subsystem.
 637 *      @a:     attribute desciptor.
 638 */
 639
 640void subsys_remove_file(struct subsystem * s, struct subsys_attribute * a)
 641{
 642        if (subsys_get(s)) {
 643                sysfs_remove_file(&s->kset.kobj,&a->attr);
 644                subsys_put(s);
 645        }
 646}
 647
 648EXPORT_SYMBOL(kobject_get_path);
 649EXPORT_SYMBOL(kobject_init);
 650EXPORT_SYMBOL(kobject_register);
 651EXPORT_SYMBOL(kobject_unregister);
 652EXPORT_SYMBOL(kobject_get);
 653EXPORT_SYMBOL(kobject_put);
 654EXPORT_SYMBOL(kobject_add);
 655EXPORT_SYMBOL(kobject_del);
 656EXPORT_SYMBOL(kobject_rename);
 657EXPORT_SYMBOL(kobject_hotplug);
 658
 659EXPORT_SYMBOL(kset_register);
 660EXPORT_SYMBOL(kset_unregister);
 661EXPORT_SYMBOL(kset_find_obj);
 662
 663EXPORT_SYMBOL(subsystem_init);
 664EXPORT_SYMBOL(subsystem_register);
 665EXPORT_SYMBOL(subsystem_unregister);
 666EXPORT_SYMBOL(subsys_create_file);
 667EXPORT_SYMBOL(subsys_remove_file);
 668