Whamcloud - gitweb
1. Fixed cleanup issue where I was *indeed* accesing a zapped pointer.
[fs/lustre-release.git] / lustre / obdclass / lprocfs_status.c
1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=8:tabstop=8:
3  *
4  *  Copyright (C) 2002 Cluster File Systems, Inc.
5  *
6  *   This file is part of Lustre, http://www.lustre.org.
7  *
8  *   Lustre is free software; you can redistribute it and/or
9  *   modify it under the terms of version 2 of the GNU General Public
10  *   License as published by the Free Software Foundation.
11  *
12  *   Lustre is distributed in the hope that it will be useful,
13  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  *   GNU General Public License for more details.
16  *
17  *   You should have received a copy of the GNU General Public License
18  *   along with Lustre; if not, write to the Free Software
19  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20  *
21  */
22
23 #define EXPORT_SYMTAB
24 #include <linux/config.h>
25 #include <linux/module.h>
26 #include <linux/version.h>
27 #include <linux/proc_fs.h>
28 #include <linux/slab.h>
29 #include <linux/types.h>
30
31 #define DEBUG_SUBSYSTEM S_CLASS
32 #define MAX_STRING_SIZE 100
33
34 #include <linux/lustre_lite.h>
35 #include <linux/lprocfs_status.h>
36
37 #ifdef LPROC_SNMP
38
39 #define DEFAULT_MODE 0444
40 /*
41  * Tokenizer array. Change this array to include special
42  * characters for string tokenizing
43  */
44 char tok[] = {'/', (char)0};
45
46 /*
47  * Externs
48  */
49 extern struct proc_dir_entry proc_root; /* Defined in proc/root.c */
50
51 /*
52  * Globals
53  */
54 struct proc_dir_entry *proc_lustre_root = 0;
55 struct proc_dir_entry *proc_lustre_dev_root = 0;
56 struct proc_dir_entry *proc_lustre_fs_root=0;
57
58 struct proc_dir_entry* lprocfs_mkdir(const char* dname,
59                                      struct proc_dir_entry *parent)
60 {
61         struct proc_dir_entry *child_dir_entry;
62
63         child_dir_entry = proc_mkdir(dname, parent);
64
65         if (!child_dir_entry)
66                 CERROR("lustre: failed to create /proc entry %s\n", dname);
67
68         return child_dir_entry;
69 }
70 struct proc_dir_entry* lprocfs_srch(struct proc_dir_entry* head,
71                                     const char* name)
72 {
73         struct proc_dir_entry* temp;
74         
75         if (!head)
76                 return 0;
77         temp = head->subdir;
78         while (temp != NULL) {
79                 if (!strcmp(temp->name, name))
80                         return temp;
81                 temp = temp->next;
82         }
83         
84         return 0;
85 }
86
87
88 void lprocfs_remove_all(struct proc_dir_entry* root)
89 {
90
91         struct proc_dir_entry *temp=root;
92         struct proc_dir_entry* rm_entry;
93         struct proc_dir_entry* parent=root->parent;
94
95         while(1){
96
97                 while(temp->subdir){
98                         temp=temp->subdir;
99                 }
100                 rm_entry=temp;
101                 temp=temp->parent;
102                 remove_proc_entry(rm_entry->name, rm_entry->parent);
103                 if(temp==parent) break;
104
105         }
106
107
108 }
109
110 struct proc_dir_entry* lprocfs_new_dir(struct proc_dir_entry* root,
111                                        const char* string, 
112                                        const char* tok)
113 {
114         struct proc_dir_entry* new_root = 0;
115         struct proc_dir_entry* temp_entry = 0;
116         
117         char temp_string[MAX_STRING_SIZE];
118         char* my_str;
119         char* mover_str;
120
121        
122         strncpy(temp_string, string, MAX_STRING_SIZE-1);
123         temp_string[strlen(string) + 1] = '\0';
124         
125         new_root=root;
126         mover_str=temp_string;
127         while ((my_str = strsep(&mover_str, tok))) {
128                 if(!*my_str)
129                         continue;
130                 CDEBUG(D_OTHER, "SEARCH= %s\t, ROOT=%s\n", my_str, 
131                        new_root->name);
132                 temp_entry = lprocfs_srch(new_root, my_str);
133                 if (temp_entry == 0) {
134                         CDEBUG(D_OTHER, "Adding: %s\n", my_str);
135                         temp_entry = lprocfs_mkdir(my_str, new_root);
136                         if (temp_entry == 0) {
137                                 CDEBUG(D_OTHER, 
138                                        "! Did not create new dir %s !!\n",
139                                        my_str);
140                                 return 0;
141                         }
142                 }
143                 new_root = temp_entry;
144         }
145
146         return new_root;
147 }
148
149 int lprocfs_new_vars(struct proc_dir_entry* root,
150                      struct lprocfs_vars* list,
151                      const char* tok, 
152                      void* data)
153 {
154         struct proc_dir_entry* temp_root=0;
155         struct proc_dir_entry* new_leaf=0;
156         struct proc_dir_entry* new_parent=0;
157         char temp_string[MAX_STRING_SIZE];
158         
159         if(!list)
160                 return 0;
161
162         while(list->name){
163                 temp_root=lprocfs_new_dir(root, list->name, tok);
164                 
165                 if(!temp_root){
166                         CDEBUG(D_OTHER, "!LProcFS: Mods: No root!");
167                         return -EINVAL;
168                 }
169                 /* Convert the last element into a leaf-node */
170                
171                 strncpy(temp_string, temp_root->name, MAX_STRING_SIZE-1);
172                 temp_string[strlen(temp_root->name) + 1] = '\0';
173                 new_parent=temp_root->parent;
174                 if (new_parent != 0){
175                         remove_proc_entry(temp_root->name, new_parent);
176                 } else {
177                         remove_proc_entry(temp_root->name, NULL);
178                 }
179                 new_leaf = create_proc_entry(temp_string, DEFAULT_MODE, 
180                                              new_parent);
181                 new_leaf->read_proc = list->read_fptr;
182                 new_leaf->write_proc = list->write_fptr;
183                 new_leaf->data=data;
184                 list++;
185         }
186         return 0;
187
188 }
189
190 /*
191  *  API implementations
192  */
193
194 int lprocfs_add_vars(struct proc_dir_entry* root,
195                      struct lprocfs_vars* var, 
196                      void* data)
197 {
198             
199         return lprocfs_new_vars(root, var, 
200                                 (const char*) tok, data);
201
202         
203 }
204
205 int lprocfs_reg_obd(struct obd_device* device, 
206                     struct lprocfs_vars* list, 
207                     void* data)
208 {
209         
210         int retval = 0;
211         struct proc_dir_entry* this_dev_root=0;
212         
213         /* Obtain this device root */
214         this_dev_root = lprocfs_mkdir(device->obd_name, 
215                                       device->obd_type->typ_procroot);
216             
217         device->obd_proc_entry=this_dev_root;
218         retval=lprocfs_add_vars(this_dev_root, list, 
219                                 data);
220                 
221         return retval;
222 }
223
224 int lprocfs_dereg_obd(struct obd_device* device)
225 {
226
227         CDEBUG(D_OTHER, "LPROCFS removing device = %s\n", device->obd_name);
228
229         if (!device) {
230                 CDEBUG(D_OTHER, "! LProcfs:  Null pointer !\n");
231                 return 0;
232         }
233
234         lprocfs_remove_all(device->obd_proc_entry);
235
236         if (device->counters)
237                 OBD_FREE(device->counters, device->cntr_mem_size);
238
239         return 0;
240 }
241
242 struct proc_dir_entry* lprocfs_reg_mnt(char* mnt_name)
243 {
244         return lprocfs_mkdir(mnt_name, proc_lustre_fs_root);
245                        
246 }
247
248 int lprocfs_dereg_mnt(struct proc_dir_entry* root)
249 {
250         lprocfs_remove_all(root);
251          return 0;
252         
253 }
254
255 int lprocfs_reg_class(struct obd_type* type,
256                       struct lprocfs_vars* list, 
257                       void* data)
258 {
259         struct proc_dir_entry* root;
260         int retval;
261
262         root=lprocfs_mkdir(type->typ_name, proc_lustre_dev_root);        
263         
264         type->typ_procroot=root;
265
266         retval=lprocfs_add_vars(root, list, data);
267
268         return retval;
269 }
270
271 int lprocfs_dereg_class(struct obd_type* class)
272 {
273         if(!class){
274                 CDEBUG(D_OTHER, "Non-existent class",
275                        class->typ_name);
276                 return 0;
277         }
278                 
279         lprocfs_remove_all(class->typ_procroot);
280       
281         CDEBUG(D_OTHER, "LPROCFS removed = %s\n", class->typ_name);
282
283         return 0;
284
285 }
286 int lprocfs_reg_main()
287 {
288         proc_lustre_root = lprocfs_mkdir("lustre", &proc_root);
289         if (!proc_lustre_root) {
290                 CERROR(" !! Cannot create /proc/lustre !! \n");
291                 return -EINVAL;
292         }
293                 
294         proc_lustre_dev_root =lprocfs_mkdir("devices", proc_lustre_root);
295         
296         if (!proc_lustre_dev_root) {
297                 CERROR(" !! Cannot create /proc/lustre/devices !! \n");
298                 return -EINVAL;
299         }
300         proc_lustre_fs_root=lprocfs_mkdir("mnt_pnt", proc_lustre_root);
301         
302         if (!proc_lustre_fs_root) {
303                 CERROR(" !! Cannot create /proc/lustre/mnt_pnt !! \n");
304                 return -EINVAL;
305         }
306         
307         return 0;
308
309 }
310
311 int lprocfs_dereg_main()
312 {
313         lprocfs_remove_all(proc_lustre_root);
314         proc_lustre_root=0;
315         proc_lustre_dev_root=0;
316         proc_lustre_fs_root=0;
317         return 0;
318
319 }
320
321
322 /* 
323  * Needs to go...
324  */
325
326 int lprocfs_ll_rd(char *page, char **start, off_t off,
327                   int count, int *eof, void *data)
328 {
329         __u64 *temp = (__u64 *)data;
330         int len;
331
332         len = snprintf(page, count, LPU64"\n", *temp);
333
334         return len;
335 }
336
337 #endif /* LPROC_SNMP */
338
339
340 EXPORT_SYMBOL(lprocfs_reg_obd);
341 EXPORT_SYMBOL(lprocfs_dereg_obd);
342 EXPORT_SYMBOL(lprocfs_reg_main);
343 EXPORT_SYMBOL(lprocfs_dereg_main);
344 EXPORT_SYMBOL(lprocfs_reg_mnt);
345 EXPORT_SYMBOL(lprocfs_dereg_mnt);
346 EXPORT_SYMBOL(lprocfs_add_vars);
347 EXPORT_SYMBOL(lprocfs_reg_class);
348 EXPORT_SYMBOL(lprocfs_dereg_class);
349 EXPORT_SYMBOL(lprocfs_ll_rd);
350
351