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]); 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] = 0;
 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\n", __FUNCTION__, argv[0], argv[1],
 189                  envp[0], envp[1], envp[2], envp[3]);
 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#else
 202static void kset_hotplug(const char *action, struct kset *kset,
 203                         struct kobject *kobj)
 204{
 205        return;
 206}
 207#endif  /* CONFIG_HOTPLUG */
 208
 209/**
 210 *      kobject_init - initialize object.
 211 *      @kobj:  object in question.
 212 */
 213
 214void kobject_init(struct kobject * kobj)
 215{
 216        atomic_set(&kobj->refcount,1);
 217        INIT_LIST_HEAD(&kobj->entry);
 218        kobj->kset = kset_get(kobj->kset);
 219}
 220
 221
 222/**
 223 *      unlink - remove kobject from kset list.
 224 *      @kobj:  kobject.
 225 *
 226 *      Remove the kobject from the kset list and decrement
 227 *      its parent's refcount.
 228 *      This is separated out, so we can use it in both 
 229 *      kobject_del() and kobject_add() on error.
 230 */
 231
 232static void unlink(struct kobject * kobj)
 233{
 234        if (kobj->kset) {
 235                down_write(&kobj->kset->subsys->rwsem);
 236                list_del_init(&kobj->entry);
 237                up_write(&kobj->kset->subsys->rwsem);
 238        }
 239        kobject_put(kobj);
 240}
 241
 242/**
 243 *      kobject_add - add an object to the hierarchy.
 244 *      @kobj:  object.
 245 */
 246
 247int kobject_add(struct kobject * kobj)
 248{
 249        int error = 0;
 250        struct kobject * parent;
 251        struct kobject * top_kobj;
 252
 253        if (!(kobj = kobject_get(kobj)))
 254                return -ENOENT;
 255        if (!kobj->k_name)
 256                kobj->k_name = kobj->name;
 257        parent = kobject_get(kobj->parent);
 258
 259        pr_debug("kobject %s: registering. parent: %s, set: %s\n",
 260                 kobject_name(kobj), parent ? kobject_name(parent) : "<NULL>", 
 261                 kobj->kset ? kobj->kset->kobj.name : "<NULL>" );
 262
 263        if (kobj->kset) {
 264                down_write(&kobj->kset->subsys->rwsem);
 265
 266                if (!parent)
 267                        parent = kobject_get(&kobj->kset->kobj);
 268
 269                list_add_tail(&kobj->entry,&kobj->kset->list);
 270                up_write(&kobj->kset->subsys->rwsem);
 271        }
 272        kobj->parent = parent;
 273
 274        error = create_dir(kobj);
 275        if (error) {
 276                unlink(kobj);
 277                if (parent)
 278                        kobject_put(parent);
 279        } else {
 280                /* If this kobj does not belong to a kset,
 281                   try to find a parent that does. */
 282                top_kobj = kobj;
 283                if (!top_kobj->kset && top_kobj->parent) {
 284                        do {
 285                                top_kobj = top_kobj->parent;
 286                        } while (!top_kobj->kset && top_kobj->parent);
 287                }
 288        
 289                if (top_kobj->kset && top_kobj->kset->hotplug_ops)
 290                        kset_hotplug("add", top_kobj->kset, kobj);
 291        }
 292        return error;
 293}
 294
 295
 296/**
 297 *      kobject_register - initialize and add an object.
 298 *      @kobj:  object in question.
 299 */
 300
 301int kobject_register(struct kobject * kobj)
 302{
 303        int error = 0;
 304        if (kobj) {
 305                kobject_init(kobj);
 306                error = kobject_add(kobj);
 307                if (error) {
 308                        printk("kobject_register failed for %s (%d)\n",
 309                               kobject_name(kobj),error);
 310                        dump_stack();
 311                }
 312        } else
 313                error = -EINVAL;
 314        return error;
 315}
 316
 317
 318/**
 319 *      kobject_set_name - Set the name of an object
 320 *      @kobj:  object.
 321 *      @name:  name. 
 322 *
 323 *      If strlen(name) < KOBJ_NAME_LEN, then use a dynamically allocated
 324 *      string that @kobj->k_name points to. Otherwise, use the static 
 325 *      @kobj->name array.
 326 */
 327
 328int kobject_set_name(struct kobject * kobj, const char * fmt, ...)
 329{
 330        int error = 0;
 331        int limit = KOBJ_NAME_LEN;
 332        int need;
 333        va_list args;
 334        char * name;
 335
 336        va_start(args,fmt);
 337        /* 
 338         * First, try the static array 
 339         */
 340        need = vsnprintf(kobj->name,limit,fmt,args);
 341        if (need < limit) 
 342                name = kobj->name;
 343        else {
 344                /* 
 345                 * Need more space? Allocate it and try again 
 346                 */
 347                name = kmalloc(need,GFP_KERNEL);
 348                if (!name) {
 349                        error = -ENOMEM;
 350                        goto Done;
 351                }
 352                limit = need;
 353                need = vsnprintf(name,limit,fmt,args);
 354
 355                /* Still? Give up. */
 356                if (need > limit) {
 357                        kfree(name);
 358                        error = -EFAULT;
 359                        goto Done;
 360                }
 361        }
 362
 363        /* Free the old name, if necessary. */
 364        if (kobj->k_name && kobj->k_name != kobj->name)
 365                kfree(kobj->k_name);
 366
 367        /* Now, set the new name */
 368        kobj->k_name = name;
 369 Done:
 370        va_end(args);
 371        return error;
 372}
 373
 374EXPORT_SYMBOL(kobject_set_name);
 375
 376
 377/**
 378 *      kobject_rename - change the name of an object
 379 *      @kobj:  object in question.
 380 *      @new_name: object's new name
 381 */
 382
 383void kobject_rename(struct kobject * kobj, char *new_name)
 384{
 385        kobj = kobject_get(kobj);
 386        if (!kobj)
 387                return;
 388        sysfs_rename_dir(kobj, new_name);
 389        kobject_put(kobj);
 390}
 391
 392/**
 393 *      kobject_del - unlink kobject from hierarchy.
 394 *      @kobj:  object.
 395 */
 396
 397void kobject_del(struct kobject * kobj)
 398{
 399        struct kobject * top_kobj;
 400
 401        /* If this kobj does not belong to a kset,
 402           try to find a parent that does. */
 403        top_kobj = kobj;
 404        if (!top_kobj->kset && top_kobj->parent) {
 405                do {
 406                        top_kobj = top_kobj->parent;
 407                } while (!top_kobj->kset && top_kobj->parent);
 408        }
 409
 410        if (top_kobj->kset && top_kobj->kset->hotplug_ops)
 411                kset_hotplug("remove", top_kobj->kset, kobj);
 412
 413        sysfs_remove_dir(kobj);
 414        unlink(kobj);
 415}
 416
 417/**
 418 *      kobject_unregister - remove object from hierarchy and decrement refcount.
 419 *      @kobj:  object going away.
 420 */
 421
 422void kobject_unregister(struct kobject * kobj)
 423{
 424        pr_debug("kobject %s: unregistering\n",kobject_name(kobj));
 425        kobject_del(kobj);
 426        kobject_put(kobj);
 427}
 428
 429/**
 430 *      kobject_get - increment refcount for object.
 431 *      @kobj:  object.
 432 */
 433
 434struct kobject * kobject_get(struct kobject * kobj)
 435{
 436        struct kobject * ret = kobj;
 437
 438        if (kobj) {
 439                WARN_ON(!atomic_read(&kobj->refcount));
 440                atomic_inc(&kobj->refcount);
 441        } else
 442                ret = NULL;
 443        return ret;
 444}
 445
 446/**
 447 *      kobject_cleanup - free kobject resources. 
 448 *      @kobj:  object.
 449 */
 450
 451void kobject_cleanup(struct kobject * kobj)
 452{
 453        struct kobj_type * t = get_ktype(kobj);
 454        struct kset * s = kobj->kset;
 455        struct kobject * parent = kobj->parent;
 456
 457        pr_debug("kobject %s: cleaning up\n",kobject_name(kobj));
 458        if (kobj->k_name != kobj->name)
 459                kfree(kobj->k_name);
 460        kobj->k_name = NULL;
 461        if (t && t->release)
 462                t->release(kobj);
 463        if (s)
 464                kset_put(s);
 465        if (parent) 
 466                kobject_put(parent);
 467}
 468
 469/**
 470 *      kobject_put - decrement refcount for object.
 471 *      @kobj:  object.
 472 *
 473 *      Decrement the refcount, and if 0, call kobject_cleanup().
 474 */
 475
 476void kobject_put(struct kobject * kobj)
 477{
 478        if (atomic_dec_and_test(&kobj->refcount))
 479                kobject_cleanup(kobj);
 480}
 481
 482
 483/**
 484 *      kset_init - initialize a kset for use
 485 *      @k:     kset 
 486 */
 487
 488void kset_init(struct kset * k)
 489{
 490        kobject_init(&k->kobj);
 491        INIT_LIST_HEAD(&k->list);
 492}
 493
 494
 495/**
 496 *      kset_add - add a kset object to the hierarchy.
 497 *      @k:     kset.
 498 *
 499 *      Simply, this adds the kset's embedded kobject to the 
 500 *      hierarchy. 
 501 *      We also try to make sure that the kset's embedded kobject
 502 *      has a parent before it is added. We only care if the embedded
 503 *      kobject is not part of a kset itself, since kobject_add()
 504 *      assigns a parent in that case. 
 505 *      If that is the case, and the kset has a controlling subsystem,
 506 *      then we set the kset's parent to be said subsystem. 
 507 */
 508
 509int kset_add(struct kset * k)
 510{
 511        if (!k->kobj.parent && !k->kobj.kset && k->subsys)
 512                k->kobj.parent = &k->subsys->kset.kobj;
 513
 514        return kobject_add(&k->kobj);
 515}
 516
 517
 518/**
 519 *      kset_register - initialize and add a kset.
 520 *      @k:     kset.
 521 */
 522
 523int kset_register(struct kset * k)
 524{
 525        kset_init(k);
 526        return kset_add(k);
 527}
 528
 529
 530/**
 531 *      kset_unregister - remove a kset.
 532 *      @k:     kset.
 533 */
 534
 535void kset_unregister(struct kset * k)
 536{
 537        kobject_unregister(&k->kobj);
 538}
 539
 540
 541/**
 542 *      kset_find_obj - search for object in kset.
 543 *      @kset:  kset we're looking in.
 544 *      @name:  object's name.
 545 *
 546 *      Lock kset via @kset->subsys, and iterate over @kset->list,
 547 *      looking for a matching kobject. Return object if found.
 548 */
 549
 550struct kobject * kset_find_obj(struct kset * kset, const char * name)
 551{
 552        struct list_head * entry;
 553        struct kobject * ret = NULL;
 554
 555        down_read(&kset->subsys->rwsem);
 556        list_for_each(entry,&kset->list) {
 557                struct kobject * k = to_kobj(entry);
 558                if (!strcmp(kobject_name(k),name)) {
 559                        ret = k;
 560                        break;
 561                }
 562        }
 563        up_read(&kset->subsys->rwsem);
 564        return ret;
 565}
 566
 567
 568void subsystem_init(struct subsystem * s)
 569{
 570        init_rwsem(&s->rwsem);
 571        kset_init(&s->kset);
 572}
 573
 574/**
 575 *      subsystem_register - register a subsystem.
 576 *      @s:     the subsystem we're registering.
 577 *
 578 *      Once we register the subsystem, we want to make sure that 
 579 *      the kset points back to this subsystem for correct usage of 
 580 *      the rwsem. 
 581 */
 582
 583int subsystem_register(struct subsystem * s)
 584{
 585        int error;
 586
 587        subsystem_init(s);
 588        pr_debug("subsystem %s: registering\n",s->kset.kobj.name);
 589
 590        if (!(error = kset_add(&s->kset))) {
 591                if (!s->kset.subsys)
 592                        s->kset.subsys = s;
 593        }
 594        return error;
 595}
 596
 597void subsystem_unregister(struct subsystem * s)
 598{
 599        pr_debug("subsystem %s: unregistering\n",s->kset.kobj.name);
 600        kset_unregister(&s->kset);
 601}
 602
 603
 604/**
 605 *      subsystem_create_file - export sysfs attribute file.
 606 *      @s:     subsystem.
 607 *      @a:     subsystem attribute descriptor.
 608 */
 609
 610int subsys_create_file(struct subsystem * s, struct subsys_attribute * a)
 611{
 612        int error = 0;
 613        if (subsys_get(s)) {
 614                error = sysfs_create_file(&s->kset.kobj,&a->attr);
 615                subsys_put(s);
 616        }
 617        return error;
 618}
 619
 620
 621/**
 622 *      subsystem_remove_file - remove sysfs attribute file.
 623 *      @s:     subsystem.
 624 *      @a:     attribute desciptor.
 625 */
 626
 627void subsys_remove_file(struct subsystem * s, struct subsys_attribute * a)
 628{
 629        if (subsys_get(s)) {
 630                sysfs_remove_file(&s->kset.kobj,&a->attr);
 631                subsys_put(s);
 632        }
 633}
 634
 635
 636EXPORT_SYMBOL(kobject_init);
 637EXPORT_SYMBOL(kobject_register);
 638EXPORT_SYMBOL(kobject_unregister);
 639EXPORT_SYMBOL(kobject_get);
 640EXPORT_SYMBOL(kobject_put);
 641
 642EXPORT_SYMBOL(kset_register);
 643EXPORT_SYMBOL(kset_unregister);
 644EXPORT_SYMBOL(kset_find_obj);
 645
 646EXPORT_SYMBOL(subsystem_init);
 647EXPORT_SYMBOL(subsystem_register);
 648EXPORT_SYMBOL(subsystem_unregister);
 649EXPORT_SYMBOL(subsys_create_file);
 650EXPORT_SYMBOL(subsys_remove_file);
 651
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.