Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/samples/kobject/kset-example.c
10818 views
1
/*
2
* Sample kset and ktype implementation
3
*
4
* Copyright (C) 2004-2007 Greg Kroah-Hartman <[email protected]>
5
* Copyright (C) 2007 Novell Inc.
6
*
7
* Released under the GPL version 2 only.
8
*
9
*/
10
#include <linux/kobject.h>
11
#include <linux/string.h>
12
#include <linux/sysfs.h>
13
#include <linux/slab.h>
14
#include <linux/module.h>
15
#include <linux/init.h>
16
17
/*
18
* This module shows how to create a kset in sysfs called
19
* /sys/kernel/kset-example
20
* Then tree kobjects are created and assigned to this kset, "foo", "baz",
21
* and "bar". In those kobjects, attributes of the same name are also
22
* created and if an integer is written to these files, it can be later
23
* read out of it.
24
*/
25
26
27
/*
28
* This is our "object" that we will create a few of and register them with
29
* sysfs.
30
*/
31
struct foo_obj {
32
struct kobject kobj;
33
int foo;
34
int baz;
35
int bar;
36
};
37
#define to_foo_obj(x) container_of(x, struct foo_obj, kobj)
38
39
/* a custom attribute that works just for a struct foo_obj. */
40
struct foo_attribute {
41
struct attribute attr;
42
ssize_t (*show)(struct foo_obj *foo, struct foo_attribute *attr, char *buf);
43
ssize_t (*store)(struct foo_obj *foo, struct foo_attribute *attr, const char *buf, size_t count);
44
};
45
#define to_foo_attr(x) container_of(x, struct foo_attribute, attr)
46
47
/*
48
* The default show function that must be passed to sysfs. This will be
49
* called by sysfs for whenever a show function is called by the user on a
50
* sysfs file associated with the kobjects we have registered. We need to
51
* transpose back from a "default" kobject to our custom struct foo_obj and
52
* then call the show function for that specific object.
53
*/
54
static ssize_t foo_attr_show(struct kobject *kobj,
55
struct attribute *attr,
56
char *buf)
57
{
58
struct foo_attribute *attribute;
59
struct foo_obj *foo;
60
61
attribute = to_foo_attr(attr);
62
foo = to_foo_obj(kobj);
63
64
if (!attribute->show)
65
return -EIO;
66
67
return attribute->show(foo, attribute, buf);
68
}
69
70
/*
71
* Just like the default show function above, but this one is for when the
72
* sysfs "store" is requested (when a value is written to a file.)
73
*/
74
static ssize_t foo_attr_store(struct kobject *kobj,
75
struct attribute *attr,
76
const char *buf, size_t len)
77
{
78
struct foo_attribute *attribute;
79
struct foo_obj *foo;
80
81
attribute = to_foo_attr(attr);
82
foo = to_foo_obj(kobj);
83
84
if (!attribute->store)
85
return -EIO;
86
87
return attribute->store(foo, attribute, buf, len);
88
}
89
90
/* Our custom sysfs_ops that we will associate with our ktype later on */
91
static const struct sysfs_ops foo_sysfs_ops = {
92
.show = foo_attr_show,
93
.store = foo_attr_store,
94
};
95
96
/*
97
* The release function for our object. This is REQUIRED by the kernel to
98
* have. We free the memory held in our object here.
99
*
100
* NEVER try to get away with just a "blank" release function to try to be
101
* smarter than the kernel. Turns out, no one ever is...
102
*/
103
static void foo_release(struct kobject *kobj)
104
{
105
struct foo_obj *foo;
106
107
foo = to_foo_obj(kobj);
108
kfree(foo);
109
}
110
111
/*
112
* The "foo" file where the .foo variable is read from and written to.
113
*/
114
static ssize_t foo_show(struct foo_obj *foo_obj, struct foo_attribute *attr,
115
char *buf)
116
{
117
return sprintf(buf, "%d\n", foo_obj->foo);
118
}
119
120
static ssize_t foo_store(struct foo_obj *foo_obj, struct foo_attribute *attr,
121
const char *buf, size_t count)
122
{
123
sscanf(buf, "%du", &foo_obj->foo);
124
return count;
125
}
126
127
static struct foo_attribute foo_attribute =
128
__ATTR(foo, 0666, foo_show, foo_store);
129
130
/*
131
* More complex function where we determine which variable is being accessed by
132
* looking at the attribute for the "baz" and "bar" files.
133
*/
134
static ssize_t b_show(struct foo_obj *foo_obj, struct foo_attribute *attr,
135
char *buf)
136
{
137
int var;
138
139
if (strcmp(attr->attr.name, "baz") == 0)
140
var = foo_obj->baz;
141
else
142
var = foo_obj->bar;
143
return sprintf(buf, "%d\n", var);
144
}
145
146
static ssize_t b_store(struct foo_obj *foo_obj, struct foo_attribute *attr,
147
const char *buf, size_t count)
148
{
149
int var;
150
151
sscanf(buf, "%du", &var);
152
if (strcmp(attr->attr.name, "baz") == 0)
153
foo_obj->baz = var;
154
else
155
foo_obj->bar = var;
156
return count;
157
}
158
159
static struct foo_attribute baz_attribute =
160
__ATTR(baz, 0666, b_show, b_store);
161
static struct foo_attribute bar_attribute =
162
__ATTR(bar, 0666, b_show, b_store);
163
164
/*
165
* Create a group of attributes so that we can create and destroy them all
166
* at once.
167
*/
168
static struct attribute *foo_default_attrs[] = {
169
&foo_attribute.attr,
170
&baz_attribute.attr,
171
&bar_attribute.attr,
172
NULL, /* need to NULL terminate the list of attributes */
173
};
174
175
/*
176
* Our own ktype for our kobjects. Here we specify our sysfs ops, the
177
* release function, and the set of default attributes we want created
178
* whenever a kobject of this type is registered with the kernel.
179
*/
180
static struct kobj_type foo_ktype = {
181
.sysfs_ops = &foo_sysfs_ops,
182
.release = foo_release,
183
.default_attrs = foo_default_attrs,
184
};
185
186
static struct kset *example_kset;
187
static struct foo_obj *foo_obj;
188
static struct foo_obj *bar_obj;
189
static struct foo_obj *baz_obj;
190
191
static struct foo_obj *create_foo_obj(const char *name)
192
{
193
struct foo_obj *foo;
194
int retval;
195
196
/* allocate the memory for the whole object */
197
foo = kzalloc(sizeof(*foo), GFP_KERNEL);
198
if (!foo)
199
return NULL;
200
201
/*
202
* As we have a kset for this kobject, we need to set it before calling
203
* the kobject core.
204
*/
205
foo->kobj.kset = example_kset;
206
207
/*
208
* Initialize and add the kobject to the kernel. All the default files
209
* will be created here. As we have already specified a kset for this
210
* kobject, we don't have to set a parent for the kobject, the kobject
211
* will be placed beneath that kset automatically.
212
*/
213
retval = kobject_init_and_add(&foo->kobj, &foo_ktype, NULL, "%s", name);
214
if (retval) {
215
kobject_put(&foo->kobj);
216
return NULL;
217
}
218
219
/*
220
* We are always responsible for sending the uevent that the kobject
221
* was added to the system.
222
*/
223
kobject_uevent(&foo->kobj, KOBJ_ADD);
224
225
return foo;
226
}
227
228
static void destroy_foo_obj(struct foo_obj *foo)
229
{
230
kobject_put(&foo->kobj);
231
}
232
233
static int __init example_init(void)
234
{
235
/*
236
* Create a kset with the name of "kset_example",
237
* located under /sys/kernel/
238
*/
239
example_kset = kset_create_and_add("kset_example", NULL, kernel_kobj);
240
if (!example_kset)
241
return -ENOMEM;
242
243
/*
244
* Create three objects and register them with our kset
245
*/
246
foo_obj = create_foo_obj("foo");
247
if (!foo_obj)
248
goto foo_error;
249
250
bar_obj = create_foo_obj("bar");
251
if (!bar_obj)
252
goto bar_error;
253
254
baz_obj = create_foo_obj("baz");
255
if (!baz_obj)
256
goto baz_error;
257
258
return 0;
259
260
baz_error:
261
destroy_foo_obj(bar_obj);
262
bar_error:
263
destroy_foo_obj(foo_obj);
264
foo_error:
265
return -EINVAL;
266
}
267
268
static void __exit example_exit(void)
269
{
270
destroy_foo_obj(baz_obj);
271
destroy_foo_obj(bar_obj);
272
destroy_foo_obj(foo_obj);
273
kset_unregister(example_kset);
274
}
275
276
module_init(example_init);
277
module_exit(example_exit);
278
MODULE_LICENSE("GPL");
279
MODULE_AUTHOR("Greg Kroah-Hartman <[email protected]>");
280
281