Subversion Repositories shark

Rev

Rev 456 | Details | Compare with Previous | Last modification | View Log | RSS feed

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