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