19d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox/* procobjecttree.c 29d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox * 3f6d0c1e62b111bef3be279e4bf1bc2a6d560e205Benjamin Romer * Copyright (C) 2010 - 2013 UNISYS CORPORATION 49d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox * All rights reserved. 59d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox * 69d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox * This program is free software; you can redistribute it and/or modify 79d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox * it under the terms of the GNU General Public License as published by 89d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox * the Free Software Foundation; either version 2 of the License, or (at 99d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox * your option) any later version. 109d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox * 119d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox * This program is distributed in the hope that it will be useful, but 129d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox * WITHOUT ANY WARRANTY; without even the implied warranty of 139d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or 149d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox * NON INFRINGEMENT. See the GNU General Public License for more 159d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox * details. 169d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox */ 179d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox 189d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox#include "procobjecttree.h" 199d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox 209d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox#define MYDRVNAME "procobjecttree" 219d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox 229d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox 239d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox 249d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox/** This is context info that we stash in each /proc file entry, which we 259d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox * need in order to call the callback function that supplies the /proc read 269d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox * info for that file. 279d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox */ 289d9baadd4069c77a97bf530abad9ddb74875fe76Ken Coxtypedef struct { 299d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox void (*show_property)(struct seq_file *, void *, int); 309d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox MYPROCOBJECT *procObject; 319d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox int propertyIndex; 329d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox 339d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox} PROCDIRENTRYCONTEXT; 349d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox 359d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox/** This describes the attributes of a tree rooted at 369d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox * <procDirRoot>/<name[0]>/<name[1]>/... 379d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox * Properties for each object of this type will be located under 389d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox * <procDirRoot>/<name[0]>/<name[1]>/.../<objectName>/<propertyName>. 399d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox */ 409d9baadd4069c77a97bf530abad9ddb74875fe76Ken Coxstruct MYPROCTYPE_Tag { 419d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox const char **name; /**< node names for this type, ending with NULL */ 429d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox int nNames; /**< num of node names in <name> */ 439d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox 449d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox /** root dir for this type tree in /proc */ 459d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox struct proc_dir_entry *procDirRoot; 469d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox 479d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox struct proc_dir_entry **procDirs; /**< for each node in <name> */ 489d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox 499d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox /** bottom dir where objects will be rooted; i.e., this is 509d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox * <procDirRoot>/<name[0]>/<name[1]>/.../, which is the same as the 519d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox * last entry in the <procDirs> array. */ 529d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox struct proc_dir_entry *procDir; 539d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox 549d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox /** name for each property that objects of this type can have */ 559d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox const char **propertyNames; 569d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox 579d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox int nProperties; /**< num of names in <propertyNames> */ 589d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox 599d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox /** Call this, passing MYPROCOBJECT.context and the property index 609d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox * whenever someone reads the proc entry */ 619d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox void (*show_property)(struct seq_file *, void *, int); 629d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox}; 639d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox 649d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox 659d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox 669d9baadd4069c77a97bf530abad9ddb74875fe76Ken Coxstruct MYPROCOBJECT_Tag { 679d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox MYPROCTYPE *type; 689d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox 699d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox /** This is the name of the dir node in /proc under which the 709d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox * properties of this object will appear as files. */ 719d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox char *name; 729d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox 739d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox int namesize; /**< number of bytes allocated for name */ 749d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox void *context; /**< passed to MYPROCTYPE.show_property */ 759d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox 769d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox /** <type.procDirRoot>/<type.name[0]>/<type.name[1]>/.../<name> */ 779d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox struct proc_dir_entry *procDir; 789d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox 799d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox /** a proc dir entry for each of the properties of the object; 809d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox * properties are identified in MYPROCTYPE.propertyNames, so each of 819d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox * the <procDirProperties> describes a single file like 829d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox * <type.procDirRoot>/<type.name[0]>/<type.name[1]>/... 839d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox * /<name>/<propertyName> 849d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox */ 859d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox struct proc_dir_entry **procDirProperties; 869d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox 879d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox /** this is a holding area for the context information that is needed 889d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox * to run the /proc callback function */ 899d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox PROCDIRENTRYCONTEXT *procDirPropertyContexts; 909d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox}; 919d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox 929d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox 939d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox 949d9baadd4069c77a97bf530abad9ddb74875fe76Ken Coxstatic struct proc_dir_entry * 959d9baadd4069c77a97bf530abad9ddb74875fe76Ken CoxcreateProcDir(const char *name, struct proc_dir_entry *parent) 969d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox{ 979d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox struct proc_dir_entry *p = proc_mkdir_mode(name, S_IFDIR, parent); 98e03e1e39b6d66c11d71c91a080b479fb432e3674Masaru Nomura 999d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox if (p == NULL) 1009d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox ERRDRV("failed to create /proc directory %s", name); 1019d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox return p; 1029d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox} 1039d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox 1049d9baadd4069c77a97bf530abad9ddb74875fe76Ken Coxstatic struct proc_dir_entry * 1059d9baadd4069c77a97bf530abad9ddb74875fe76Ken CoxcreateProcFile(const char *name, struct proc_dir_entry *parent, 1069d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox const struct file_operations *fops, void *data) 1079d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox{ 1089d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox struct proc_dir_entry *p = proc_create_data(name, 0, parent, 1099d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox fops, data); 1109d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox if (p == NULL) 1119d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox ERRDRV("failed to create /proc file %s", name); 1129d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox return p; 1139d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox} 1149d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox 1159d9baadd4069c77a97bf530abad9ddb74875fe76Ken Coxstatic int seq_show(struct seq_file *seq, void *offset); 1169d9baadd4069c77a97bf530abad9ddb74875fe76Ken Coxstatic int proc_open(struct inode *inode, struct file *file) 1179d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox{ 1189d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox return single_open(file, seq_show, PDE_DATA(inode)); 1199d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox} 1209d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox 1219d9baadd4069c77a97bf530abad9ddb74875fe76Ken Coxstatic const struct file_operations proc_fops = { 1229d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox .open = proc_open, 1239d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox .read = seq_read, 1249d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox .llseek = seq_lseek, 1259d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox .release = single_release, 1269d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox}; 1279d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox 1289d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox 1299d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox 130927c7927eee73e195afc5b76ffb91bd72e3cb03dKen CoxMYPROCTYPE *visor_proc_CreateType(struct proc_dir_entry *procDirRoot, 131927c7927eee73e195afc5b76ffb91bd72e3cb03dKen Cox const char **name, 132927c7927eee73e195afc5b76ffb91bd72e3cb03dKen Cox const char **propertyNames, 133927c7927eee73e195afc5b76ffb91bd72e3cb03dKen Cox void (*show_property)(struct seq_file *, 134927c7927eee73e195afc5b76ffb91bd72e3cb03dKen Cox void *, int)) 1359d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox{ 1369d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox int i = 0; 1379d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox MYPROCTYPE *rc = NULL, *type = NULL; 1389d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox struct proc_dir_entry *parent = NULL; 1399d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox 1405e54c97dab0298cf5479bc1f2d3f42ef5605ce6eKen Cox if (procDirRoot == NULL) { 1415e54c97dab0298cf5479bc1f2d3f42ef5605ce6eKen Cox ERRDRV("procDirRoot cannot be NULL!\n"); 1425e54c97dab0298cf5479bc1f2d3f42ef5605ce6eKen Cox goto Away; 1435e54c97dab0298cf5479bc1f2d3f42ef5605ce6eKen Cox } 1445e54c97dab0298cf5479bc1f2d3f42ef5605ce6eKen Cox if (name == NULL || name[0] == NULL) { 1455e54c97dab0298cf5479bc1f2d3f42ef5605ce6eKen Cox ERRDRV("name must contain at least 1 node name!\n"); 1465e54c97dab0298cf5479bc1f2d3f42ef5605ce6eKen Cox goto Away; 1475e54c97dab0298cf5479bc1f2d3f42ef5605ce6eKen Cox } 14856116b2b09092565d140c0e72596d67a29dcf89cIulia Manda type = kzalloc(sizeof(MYPROCTYPE), GFP_KERNEL | __GFP_NORETRY); 1495e54c97dab0298cf5479bc1f2d3f42ef5605ce6eKen Cox if (type == NULL) { 1505e54c97dab0298cf5479bc1f2d3f42ef5605ce6eKen Cox ERRDRV("out of memory\n"); 1515e54c97dab0298cf5479bc1f2d3f42ef5605ce6eKen Cox goto Away; 1525e54c97dab0298cf5479bc1f2d3f42ef5605ce6eKen Cox } 1539d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox type->name = name; 1549d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox type->propertyNames = propertyNames; 1559d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox type->nProperties = 0; 1569d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox type->nNames = 0; 1579d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox type->show_property = show_property; 1589d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox type->procDirRoot = procDirRoot; 159a7710336596ecf49b3c1572dd40f4ecfefc6c9abKen Cox if (type->propertyNames != NULL) 1609d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox while (type->propertyNames[type->nProperties] != NULL) 1619d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox type->nProperties++; 1629d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox while (type->name[type->nNames] != NULL) 1639d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox type->nNames++; 16456116b2b09092565d140c0e72596d67a29dcf89cIulia Manda type->procDirs = kzalloc((type->nNames + 1) * 1659d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox sizeof(struct proc_dir_entry *), 16656116b2b09092565d140c0e72596d67a29dcf89cIulia Manda GFP_KERNEL | __GFP_NORETRY); 1675e54c97dab0298cf5479bc1f2d3f42ef5605ce6eKen Cox if (type->procDirs == NULL) { 1685e54c97dab0298cf5479bc1f2d3f42ef5605ce6eKen Cox ERRDRV("out of memory\n"); 1695e54c97dab0298cf5479bc1f2d3f42ef5605ce6eKen Cox goto Away; 1705e54c97dab0298cf5479bc1f2d3f42ef5605ce6eKen Cox } 1719d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox parent = procDirRoot; 1729d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox for (i = 0; i < type->nNames; i++) { 1739d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox type->procDirs[i] = createProcDir(type->name[i], parent); 174d9355f8934a4c54d81a29ae7bd5ae4329c02aa48Ken Cox if (type->procDirs[i] == NULL) { 175d9355f8934a4c54d81a29ae7bd5ae4329c02aa48Ken Cox rc = NULL; 176d9355f8934a4c54d81a29ae7bd5ae4329c02aa48Ken Cox goto Away; 177d9355f8934a4c54d81a29ae7bd5ae4329c02aa48Ken Cox } 1789d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox parent = type->procDirs[i]; 1799d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox } 1809d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox type->procDir = type->procDirs[type->nNames-1]; 181d9355f8934a4c54d81a29ae7bd5ae4329c02aa48Ken Cox rc = type; 1829d9baadd4069c77a97bf530abad9ddb74875fe76Ken CoxAway: 1839d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox if (rc == NULL) { 1849d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox if (type != NULL) { 185927c7927eee73e195afc5b76ffb91bd72e3cb03dKen Cox visor_proc_DestroyType(type); 1869d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox type = NULL; 1879d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox } 1889d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox } 1899d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox return rc; 1909d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox} 191927c7927eee73e195afc5b76ffb91bd72e3cb03dKen CoxEXPORT_SYMBOL_GPL(visor_proc_CreateType); 1929d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox 1939d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox 1949d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox 195927c7927eee73e195afc5b76ffb91bd72e3cb03dKen Coxvoid visor_proc_DestroyType(MYPROCTYPE *type) 1969d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox{ 1979d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox if (type == NULL) 1989d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox return; 1999d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox if (type->procDirs != NULL) { 2009d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox int i = type->nNames-1; 201e03e1e39b6d66c11d71c91a080b479fb432e3674Masaru Nomura 2029d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox while (i >= 0) { 2039d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox if (type->procDirs[i] != NULL) { 2049d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox struct proc_dir_entry *parent = NULL; 205e03e1e39b6d66c11d71c91a080b479fb432e3674Masaru Nomura 2069d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox if (i == 0) 2079d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox parent = type->procDirRoot; 2089d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox else 2099d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox parent = type->procDirs[i-1]; 2109d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox remove_proc_entry(type->name[i], parent); 2119d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox } 2129d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox i--; 2139d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox } 2149d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox kfree(type->procDirs); 2159d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox type->procDirs = NULL; 2169d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox } 2179d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox kfree(type); 2189d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox} 219927c7927eee73e195afc5b76ffb91bd72e3cb03dKen CoxEXPORT_SYMBOL_GPL(visor_proc_DestroyType); 2209d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox 2219d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox 2229d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox 223927c7927eee73e195afc5b76ffb91bd72e3cb03dKen CoxMYPROCOBJECT *visor_proc_CreateObject(MYPROCTYPE *type, 224927c7927eee73e195afc5b76ffb91bd72e3cb03dKen Cox const char *name, void *context) 2259d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox{ 2269d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox MYPROCOBJECT *obj = NULL, *rc = NULL; 2279d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox int i = 0; 2289d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox 2295e54c97dab0298cf5479bc1f2d3f42ef5605ce6eKen Cox if (type == NULL) { 2305e54c97dab0298cf5479bc1f2d3f42ef5605ce6eKen Cox ERRDRV("type cannot be NULL\n"); 2315e54c97dab0298cf5479bc1f2d3f42ef5605ce6eKen Cox goto Away; 2325e54c97dab0298cf5479bc1f2d3f42ef5605ce6eKen Cox } 23356116b2b09092565d140c0e72596d67a29dcf89cIulia Manda obj = kzalloc(sizeof(MYPROCOBJECT), GFP_KERNEL | __GFP_NORETRY); 2345e54c97dab0298cf5479bc1f2d3f42ef5605ce6eKen Cox if (obj == NULL) { 2355e54c97dab0298cf5479bc1f2d3f42ef5605ce6eKen Cox ERRDRV("out of memory\n"); 2365e54c97dab0298cf5479bc1f2d3f42ef5605ce6eKen Cox goto Away; 2375e54c97dab0298cf5479bc1f2d3f42ef5605ce6eKen Cox } 2389d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox obj->type = type; 2399d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox obj->context = context; 2409d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox if (name == NULL) { 2419d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox obj->name = NULL; 2429d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox obj->procDir = type->procDir; 2439d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox } else { 2449d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox obj->namesize = strlen(name)+1; 2459d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox obj->name = kmalloc(obj->namesize, GFP_KERNEL | __GFP_NORETRY); 2469d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox if (obj->name == NULL) { 2479d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox obj->namesize = 0; 2485e54c97dab0298cf5479bc1f2d3f42ef5605ce6eKen Cox ERRDRV("out of memory\n"); 2495e54c97dab0298cf5479bc1f2d3f42ef5605ce6eKen Cox goto Away; 2509d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox } 2519d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox strcpy(obj->name, name); 2529d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox obj->procDir = createProcDir(obj->name, type->procDir); 2536905cae3a86f6411b62fda0c7a8e1c0d04eaef88Catalina Mocanu if (obj->procDir == NULL) 254d9355f8934a4c54d81a29ae7bd5ae4329c02aa48Ken Cox goto Away; 2559d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox } 2569d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox obj->procDirPropertyContexts = 25756116b2b09092565d140c0e72596d67a29dcf89cIulia Manda kzalloc((type->nProperties + 1) * sizeof(PROCDIRENTRYCONTEXT), 25856116b2b09092565d140c0e72596d67a29dcf89cIulia Manda GFP_KERNEL | __GFP_NORETRY); 2595e54c97dab0298cf5479bc1f2d3f42ef5605ce6eKen Cox if (obj->procDirPropertyContexts == NULL) { 2605e54c97dab0298cf5479bc1f2d3f42ef5605ce6eKen Cox ERRDRV("out of memory\n"); 2615e54c97dab0298cf5479bc1f2d3f42ef5605ce6eKen Cox goto Away; 2625e54c97dab0298cf5479bc1f2d3f42ef5605ce6eKen Cox } 2639d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox obj->procDirProperties = 26456116b2b09092565d140c0e72596d67a29dcf89cIulia Manda kzalloc((type->nProperties + 1) * sizeof(struct proc_dir_entry *), 26556116b2b09092565d140c0e72596d67a29dcf89cIulia Manda GFP_KERNEL | __GFP_NORETRY); 2665e54c97dab0298cf5479bc1f2d3f42ef5605ce6eKen Cox if (obj->procDirProperties == NULL) { 2675e54c97dab0298cf5479bc1f2d3f42ef5605ce6eKen Cox ERRDRV("out of memory\n"); 2685e54c97dab0298cf5479bc1f2d3f42ef5605ce6eKen Cox goto Away; 2695e54c97dab0298cf5479bc1f2d3f42ef5605ce6eKen Cox } 2709d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox for (i = 0; i < type->nProperties; i++) { 2719d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox obj->procDirPropertyContexts[i].procObject = obj; 2729d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox obj->procDirPropertyContexts[i].propertyIndex = i; 2739d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox obj->procDirPropertyContexts[i].show_property = 2749d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox type->show_property; 2759d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox if (type->propertyNames[i][0] != '\0') { 2769d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox /* only create properties that have names */ 2779d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox obj->procDirProperties[i] = 2789d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox createProcFile(type->propertyNames[i], 2799d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox obj->procDir, &proc_fops, 2809d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox &obj->procDirPropertyContexts[i]); 281d9355f8934a4c54d81a29ae7bd5ae4329c02aa48Ken Cox if (obj->procDirProperties[i] == NULL) { 282d9355f8934a4c54d81a29ae7bd5ae4329c02aa48Ken Cox rc = NULL; 283d9355f8934a4c54d81a29ae7bd5ae4329c02aa48Ken Cox goto Away; 284d9355f8934a4c54d81a29ae7bd5ae4329c02aa48Ken Cox } 2859d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox } 2869d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox } 287d9355f8934a4c54d81a29ae7bd5ae4329c02aa48Ken Cox rc = obj; 2889d9baadd4069c77a97bf530abad9ddb74875fe76Ken CoxAway: 2899d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox if (rc == NULL) { 2909d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox if (obj != NULL) { 291927c7927eee73e195afc5b76ffb91bd72e3cb03dKen Cox visor_proc_DestroyObject(obj); 2929d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox obj = NULL; 2939d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox } 2949d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox } 2959d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox return rc; 2969d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox} 297927c7927eee73e195afc5b76ffb91bd72e3cb03dKen CoxEXPORT_SYMBOL_GPL(visor_proc_CreateObject); 2989d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox 2999d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox 3009d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox 301927c7927eee73e195afc5b76ffb91bd72e3cb03dKen Coxvoid visor_proc_DestroyObject(MYPROCOBJECT *obj) 3029d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox{ 3039d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox MYPROCTYPE *type = NULL; 304e03e1e39b6d66c11d71c91a080b479fb432e3674Masaru Nomura 3059d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox if (obj == NULL) 3069d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox return; 3079d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox type = obj->type; 3089d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox if (type == NULL) 3099d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox return; 3109d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox if (obj->procDirProperties != NULL) { 3119d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox int i = 0; 312e03e1e39b6d66c11d71c91a080b479fb432e3674Masaru Nomura 3139d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox for (i = 0; i < type->nProperties; i++) { 3149d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox if (obj->procDirProperties[i] != NULL) { 3159d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox remove_proc_entry(type->propertyNames[i], 3169d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox obj->procDir); 3179d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox obj->procDirProperties[i] = NULL; 3189d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox } 3199d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox } 3209d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox kfree(obj->procDirProperties); 3219d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox obj->procDirProperties = NULL; 3229d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox } 3239d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox if (obj->procDirPropertyContexts != NULL) { 3249d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox kfree(obj->procDirPropertyContexts); 3259d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox obj->procDirPropertyContexts = NULL; 3269d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox } 3279d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox if (obj->procDir != NULL) { 3289d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox if (obj->name != NULL) 3299d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox remove_proc_entry(obj->name, type->procDir); 3309d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox obj->procDir = NULL; 3319d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox } 3329d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox if (obj->name != NULL) { 3339d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox kfree(obj->name); 3349d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox obj->name = NULL; 3359d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox } 3369d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox kfree(obj); 3379d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox} 338927c7927eee73e195afc5b76ffb91bd72e3cb03dKen CoxEXPORT_SYMBOL_GPL(visor_proc_DestroyObject); 3399d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox 3409d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox 3419d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox 3429d9baadd4069c77a97bf530abad9ddb74875fe76Ken Coxstatic int seq_show(struct seq_file *seq, void *offset) 3439d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox{ 3449d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox PROCDIRENTRYCONTEXT *ctx = (PROCDIRENTRYCONTEXT *)(seq->private); 345e03e1e39b6d66c11d71c91a080b479fb432e3674Masaru Nomura 3469d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox if (ctx == NULL) { 3479d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox ERRDRV("I don't have a freakin' clue..."); 3489d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox return 0; 3499d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox } 3509d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox (*ctx->show_property)(seq, ctx->procObject->context, 3519d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox ctx->propertyIndex); 3529d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox return 0; 3539d9baadd4069c77a97bf530abad9ddb74875fe76Ken Cox} 354