3 * Copyright © 2010 - 2013 UNISYS CORPORATION
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or (at
9 * your option) any later version.
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
14 * NON INFRINGEMENT. See the GNU General Public License for more
18 #include "procobjecttree.h"
20 #define MYDRVNAME "procobjecttree"
24 /** This is context info that we stash in each /proc file entry, which we
25 * need in order to call the callback function that supplies the /proc read
29 void (*show_property)(struct seq_file *, void *, int);
30 MYPROCOBJECT *procObject;
33 } PROCDIRENTRYCONTEXT;
35 /** This describes the attributes of a tree rooted at
36 * <procDirRoot>/<name[0]>/<name[1]>/...
37 * Properties for each object of this type will be located under
38 * <procDirRoot>/<name[0]>/<name[1]>/.../<objectName>/<propertyName>.
40 struct MYPROCTYPE_Tag {
41 const char **name; /**< node names for this type, ending with NULL */
42 int nNames; /**< num of node names in <name> */
44 /** root dir for this type tree in /proc */
45 struct proc_dir_entry *procDirRoot;
47 struct proc_dir_entry **procDirs; /**< for each node in <name> */
49 /** bottom dir where objects will be rooted; i.e., this is
50 * <procDirRoot>/<name[0]>/<name[1]>/.../, which is the same as the
51 * last entry in the <procDirs> array. */
52 struct proc_dir_entry *procDir;
54 /** name for each property that objects of this type can have */
55 const char **propertyNames;
57 int nProperties; /**< num of names in <propertyNames> */
59 /** Call this, passing MYPROCOBJECT.context and the property index
60 * whenever someone reads the proc entry */
61 void (*show_property)(struct seq_file *, void *, int);
66 struct MYPROCOBJECT_Tag {
69 /** This is the name of the dir node in /proc under which the
70 * properties of this object will appear as files. */
73 int namesize; /**< number of bytes allocated for name */
74 void *context; /**< passed to MYPROCTYPE.show_property */
76 /** <type.procDirRoot>/<type.name[0]>/<type.name[1]>/.../<name> */
77 struct proc_dir_entry *procDir;
79 /** a proc dir entry for each of the properties of the object;
80 * properties are identified in MYPROCTYPE.propertyNames, so each of
81 * the <procDirProperties> describes a single file like
82 * <type.procDirRoot>/<type.name[0]>/<type.name[1]>/...
83 * /<name>/<propertyName>
85 struct proc_dir_entry **procDirProperties;
87 /** this is a holding area for the context information that is needed
88 * to run the /proc callback function */
89 PROCDIRENTRYCONTEXT *procDirPropertyContexts;
94 static struct proc_dir_entry *
95 createProcDir(const char *name, struct proc_dir_entry *parent)
97 struct proc_dir_entry *p = proc_mkdir_mode(name, S_IFDIR, parent);
99 ERRDRV("failed to create /proc directory %s", name);
103 static struct proc_dir_entry *
104 createProcFile(const char *name, struct proc_dir_entry *parent,
105 const struct file_operations *fops, void *data)
107 struct proc_dir_entry *p = proc_create_data(name, 0, parent,
110 ERRDRV("failed to create /proc file %s", name);
114 static int seq_show(struct seq_file *seq, void *offset);
115 static int proc_open(struct inode *inode, struct file *file)
117 return single_open(file, seq_show, PDE_DATA(inode));
120 static const struct file_operations proc_fops = {
124 .release = single_release,
129 MYPROCTYPE *visor_proc_CreateType(struct proc_dir_entry *procDirRoot,
131 const char **propertyNames,
132 void (*show_property)(struct seq_file *,
136 MYPROCTYPE *rc = NULL, *type = NULL;
137 struct proc_dir_entry *parent = NULL;
139 if (procDirRoot == NULL) {
140 ERRDRV("procDirRoot cannot be NULL!\n");
143 if (name == NULL || name[0] == NULL) {
144 ERRDRV("name must contain at least 1 node name!\n");
147 type = kzalloc(sizeof(MYPROCTYPE), GFP_KERNEL | __GFP_NORETRY);
149 ERRDRV("out of memory\n");
153 type->propertyNames = propertyNames;
154 type->nProperties = 0;
156 type->show_property = show_property;
157 type->procDirRoot = procDirRoot;
158 if (type->propertyNames != NULL)
159 while (type->propertyNames[type->nProperties] != NULL)
161 while (type->name[type->nNames] != NULL)
163 type->procDirs = kzalloc((type->nNames + 1) *
164 sizeof(struct proc_dir_entry *),
165 GFP_KERNEL | __GFP_NORETRY);
166 if (type->procDirs == NULL) {
167 ERRDRV("out of memory\n");
170 parent = procDirRoot;
171 for (i = 0; i < type->nNames; i++) {
172 type->procDirs[i] = createProcDir(type->name[i], parent);
173 if (type->procDirs[i] == NULL) {
177 parent = type->procDirs[i];
179 type->procDir = type->procDirs[type->nNames-1];
184 visor_proc_DestroyType(type);
190 EXPORT_SYMBOL_GPL(visor_proc_CreateType);
194 void visor_proc_DestroyType(MYPROCTYPE *type)
198 if (type->procDirs != NULL) {
199 int i = type->nNames-1;
201 if (type->procDirs[i] != NULL) {
202 struct proc_dir_entry *parent = NULL;
204 parent = type->procDirRoot;
206 parent = type->procDirs[i-1];
207 remove_proc_entry(type->name[i], parent);
211 kfree(type->procDirs);
212 type->procDirs = NULL;
216 EXPORT_SYMBOL_GPL(visor_proc_DestroyType);
220 MYPROCOBJECT *visor_proc_CreateObject(MYPROCTYPE *type,
221 const char *name, void *context)
223 MYPROCOBJECT *obj = NULL, *rc = NULL;
227 ERRDRV("type cannot be NULL\n");
230 obj = kzalloc(sizeof(MYPROCOBJECT), GFP_KERNEL | __GFP_NORETRY);
232 ERRDRV("out of memory\n");
236 obj->context = context;
239 obj->procDir = type->procDir;
241 obj->namesize = strlen(name)+1;
242 obj->name = kmalloc(obj->namesize, GFP_KERNEL | __GFP_NORETRY);
243 if (obj->name == NULL) {
245 ERRDRV("out of memory\n");
248 strcpy(obj->name, name);
249 obj->procDir = createProcDir(obj->name, type->procDir);
250 if (obj->procDir == NULL) {
254 obj->procDirPropertyContexts =
255 kzalloc((type->nProperties + 1) * sizeof(PROCDIRENTRYCONTEXT),
256 GFP_KERNEL | __GFP_NORETRY);
257 if (obj->procDirPropertyContexts == NULL) {
258 ERRDRV("out of memory\n");
261 obj->procDirProperties =
262 kzalloc((type->nProperties + 1) * sizeof(struct proc_dir_entry *),
263 GFP_KERNEL | __GFP_NORETRY);
264 if (obj->procDirProperties == NULL) {
265 ERRDRV("out of memory\n");
268 for (i = 0; i < type->nProperties; i++) {
269 obj->procDirPropertyContexts[i].procObject = obj;
270 obj->procDirPropertyContexts[i].propertyIndex = i;
271 obj->procDirPropertyContexts[i].show_property =
273 if (type->propertyNames[i][0] != '\0') {
274 /* only create properties that have names */
275 obj->procDirProperties[i] =
276 createProcFile(type->propertyNames[i],
277 obj->procDir, &proc_fops,
278 &obj->procDirPropertyContexts[i]);
279 if (obj->procDirProperties[i] == NULL) {
289 visor_proc_DestroyObject(obj);
295 EXPORT_SYMBOL_GPL(visor_proc_CreateObject);
299 void visor_proc_DestroyObject(MYPROCOBJECT *obj)
301 MYPROCTYPE *type = NULL;
307 if (obj->procDirProperties != NULL) {
309 for (i = 0; i < type->nProperties; i++) {
310 if (obj->procDirProperties[i] != NULL) {
311 remove_proc_entry(type->propertyNames[i],
313 obj->procDirProperties[i] = NULL;
316 kfree(obj->procDirProperties);
317 obj->procDirProperties = NULL;
319 if (obj->procDirPropertyContexts != NULL) {
320 kfree(obj->procDirPropertyContexts);
321 obj->procDirPropertyContexts = NULL;
323 if (obj->procDir != NULL) {
324 if (obj->name != NULL)
325 remove_proc_entry(obj->name, type->procDir);
328 if (obj->name != NULL) {
334 EXPORT_SYMBOL_GPL(visor_proc_DestroyObject);
338 static int seq_show(struct seq_file *seq, void *offset)
340 PROCDIRENTRYCONTEXT *ctx = (PROCDIRENTRYCONTEXT *)(seq->private);
342 ERRDRV("I don't have a freakin' clue...");
345 (*ctx->show_property)(seq, ctx->procObject->context,