Whamcloud - gitweb
Merge b_md to HEAD for 0.5.19 release.
[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  *   Author: Hariharan Thantry thantry@users.sourceforge.net
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 #include <linux/lustre_lite.h>
33 #include <linux/lprocfs_status.h>
34
35 #ifdef LPROC_SNMP
36
37 #define DEFAULT_MODE 0444
38 /*
39  * Tokenizer array. Change this array to include special
40  * characters for string tokenizing
41  */
42 const char tok[] = {'/', '\0'};
43
44 /*
45  * Externs
46  */
47 extern struct proc_dir_entry proc_root; /* Defined in proc/root.c */
48
49 /*
50  * Globals
51  */
52 struct proc_dir_entry *proc_lustre_root;
53 struct proc_dir_entry *proc_lustre_dev_root;
54 struct proc_dir_entry *proc_lustre_fs_root;
55
56 struct proc_dir_entry* lprocfs_mkdir(const char* dname,
57                                      struct proc_dir_entry *parent)
58 {
59         struct proc_dir_entry *child_dir_entry;
60         child_dir_entry = proc_mkdir(dname, parent);
61         if (!child_dir_entry)
62                 CERROR("lustre: failed to create /proc entry %s\n", dname);
63         return child_dir_entry;
64 }
65
66 struct proc_dir_entry* lprocfs_srch(struct proc_dir_entry* head,
67                                     const char* name)
68 {
69         struct proc_dir_entry* temp;
70         if (!head)
71                 return NULL;
72         temp = head->subdir;
73         while (temp != NULL) {
74                 if (!strcmp(temp->name, name))
75                         return temp;
76                 temp = temp->next;
77         }
78         return NULL;
79 }
80
81 void lprocfs_remove_all(struct proc_dir_entry* root)
82 {
83         struct proc_dir_entry *temp = root;
84         struct proc_dir_entry *rm_entry;
85         struct proc_dir_entry *parent = root->parent;
86
87         while (1) {
88                 while (temp->subdir)
89                         temp = temp->subdir;
90
91                 rm_entry = temp;
92                 temp = temp->parent;
93                 remove_proc_entry(rm_entry->name, rm_entry->parent);
94                 if (temp == parent)
95                         break;
96         }
97 }
98
99 #define MAX_STRING_SIZE 100
100 struct proc_dir_entry* lprocfs_new_dir(struct proc_dir_entry* root,
101                                        const char* string, const char* tok)
102 {
103         struct proc_dir_entry* new_root;
104         struct proc_dir_entry* temp_entry;
105         char temp_string[MAX_STRING_SIZE+1];
106         char* my_str;
107         char* mover_str;
108
109         strncpy(temp_string, string, MAX_STRING_SIZE);
110         temp_string[MAX_STRING_SIZE] = '\0';
111
112         new_root = root;
113         mover_str = temp_string;
114         while ((my_str = strsep(&mover_str, tok))) {
115                 if (!*my_str)
116                         continue;
117                 CDEBUG(D_OTHER, "SEARCH= %s\t, ROOT=%s\n", my_str,
118                        new_root->name);
119                 temp_entry = lprocfs_srch(new_root, my_str);
120                 if (temp_entry == NULL) {
121                         CDEBUG(D_OTHER, "Adding: %s\n", my_str);
122                         temp_entry = lprocfs_mkdir(my_str, new_root);
123                         if (temp_entry == NULL) {
124                                 CDEBUG(D_OTHER,
125                                        "! Did not create new dir %s !!\n",
126                                        my_str);
127                                 return temp_entry;
128                         }
129                 }
130                 new_root = temp_entry;
131         }
132         return new_root;
133 }
134
135 int lprocfs_new_vars(struct proc_dir_entry* root, struct lprocfs_vars* list,
136                      const char* tok, void* data)
137 {
138         struct proc_dir_entry *temp_root;
139         struct proc_dir_entry *new_leaf;
140         struct proc_dir_entry *new_parent;
141         char temp_string[MAX_STRING_SIZE+1];
142
143         if (list == NULL)
144                 return 0;
145
146         while (list->name) {
147                 temp_root = lprocfs_new_dir(root, list->name, tok);
148                 if (temp_root == NULL) {
149                         CDEBUG(D_OTHER, "!LProcFS: Mods: No root!");
150                         return -ENOMEM;
151                 }
152
153                 /* Convert the last element into a leaf-node */
154                 strncpy(temp_string, temp_root->name, MAX_STRING_SIZE);
155                 temp_string[MAX_STRING_SIZE] = '\0';
156                 new_parent = temp_root->parent;
157                 remove_proc_entry(temp_root->name, new_parent);
158                 new_leaf = create_proc_entry(temp_string, DEFAULT_MODE,
159                                              new_parent);
160                 if (new_leaf == NULL) {
161                         CERROR("LprocFS: No memory to create /proc entry %s",
162                                 temp_string);
163                         return -ENOMEM;
164                 }
165                 new_leaf->read_proc = list->read_fptr;
166                 new_leaf->write_proc = list->write_fptr;
167                 if (data)
168                         new_leaf->data=data;
169                 else
170                         new_leaf->data=list->data;
171                 list++;
172         }
173         return 0;
174
175 }
176 #undef MAX_STRING_SIZE
177 /*
178  *  API implementations
179  */
180 int lprocfs_add_vars(struct proc_dir_entry *root, struct lprocfs_vars *var,
181                      void *data)
182 {
183         return lprocfs_new_vars(root, var, tok, data);
184 }
185
186 int lprocfs_reg_obd(struct obd_device *device, struct lprocfs_vars *list,
187                     void *data)
188 {
189         struct proc_dir_entry* this_dev_root;
190         int retval;
191
192         if (lprocfs_srch(device->obd_type->typ_procroot, device->obd_name)) {
193                 CDEBUG(D_OTHER, "Device with name [%s] exists!",
194                                 device->obd_name);
195                 return 0;
196         }
197
198         /* Obtain this device root */
199         this_dev_root = lprocfs_mkdir(device->obd_name,
200                                       device->obd_type->typ_procroot);
201
202         device->obd_proc_entry = this_dev_root;
203         retval = lprocfs_add_vars(this_dev_root, list, data);
204
205         return retval;
206 }
207
208 int lprocfs_dereg_obd(struct obd_device* device)
209 {
210         CDEBUG(D_OTHER, "LPROCFS removing device = %s\n", device->obd_name);
211
212         if (device == NULL) {
213                 CDEBUG(D_OTHER, "! LProcfs:  Null pointer !\n");
214                 return 0;
215         }
216         if (device->obd_proc_entry == NULL) {
217                 CDEBUG(D_OTHER, "! Proc entry non-existent !");
218                 return 0;
219         }
220         lprocfs_remove_all(device->obd_proc_entry);
221         device->obd_proc_entry = NULL;
222         if (device->counters)
223                 OBD_FREE(device->counters, device->cntr_mem_size);
224
225         return 0;
226 }
227
228 struct proc_dir_entry* lprocfs_reg_mnt(char* mnt_name)
229 {
230         if (lprocfs_srch(proc_lustre_fs_root, mnt_name)) {
231                 CDEBUG(D_OTHER, "Mount with same name exists!");
232                 return 0;
233         }
234         return lprocfs_mkdir(mnt_name, proc_lustre_fs_root);
235 }
236
237 int lprocfs_dereg_mnt(struct proc_dir_entry* root)
238 {
239         if (root == NULL) {
240                 CDEBUG(D_OTHER, "Non-existent root!");
241                 return 0;
242         }
243         lprocfs_remove_all(root);
244         return 0;
245 }
246
247 int lprocfs_reg_class(struct obd_type* type, struct lprocfs_vars* list,
248                       void* data)
249 {
250         struct proc_dir_entry* root;
251         int retval;
252         root = lprocfs_mkdir(type->typ_name, proc_lustre_dev_root);
253         lprocfs_add_vars(root, list, data);
254         type->typ_procroot = root;
255         retval = lprocfs_add_vars(root, list, data);
256         return retval;
257 }
258
259 int lprocfs_dereg_class(struct obd_type* class)
260 {
261         if (class == NULL) {
262                 CDEBUG(D_OTHER, "Non-existent class");
263                 return 0;
264         }
265         lprocfs_remove_all(class->typ_procroot);
266         class->typ_procroot = NULL;
267         CDEBUG(D_OTHER, "LPROCFS removed = %s\n", class->typ_name);
268         return 0;
269
270 }
271
272 int lprocfs_reg_main()
273 {
274         proc_lustre_root = lprocfs_mkdir("lustre", &proc_root);
275         if (proc_lustre_root == NULL) {
276                 CERROR(" !! Cannot create /proc/lustre !! \n");
277                 return -EINVAL;
278         }
279
280         proc_lustre_dev_root = lprocfs_mkdir("devices", proc_lustre_root);
281         if (proc_lustre_dev_root == NULL) {
282                 CERROR(" !! Cannot create /proc/lustre/devices !! \n");
283                 return -EINVAL;
284         }
285         proc_lustre_fs_root = lprocfs_mkdir("mnt_pnt", proc_lustre_root);
286
287         if (proc_lustre_fs_root == NULL) {
288                 CERROR(" !! Cannot create /proc/lustre/mnt_pnt !! \n");
289                 return -EINVAL;
290         }
291
292         return 0;
293 }
294
295 int lprocfs_dereg_main()
296 {
297         lprocfs_remove_all(proc_lustre_root);
298         proc_lustre_root = NULL;
299         proc_lustre_dev_root = NULL;
300         proc_lustre_fs_root = NULL;
301         return 0;
302 }
303
304
305 /*
306  * Needs to go...
307  */
308 int lprocfs_ll_rd(char *page, char **start, off_t off,
309                   int count, int *eof, void *data)
310 {
311         __u64 *temp = (__u64 *)data;
312         int len;
313         len = snprintf(page, count, LPU64"\n", *temp);
314         return len;
315 }
316
317 #endif /* LPROC_SNMP */
318
319 EXPORT_SYMBOL(lprocfs_reg_obd);
320 EXPORT_SYMBOL(lprocfs_dereg_obd);
321 EXPORT_SYMBOL(lprocfs_reg_main);
322 EXPORT_SYMBOL(lprocfs_dereg_main);
323 EXPORT_SYMBOL(lprocfs_reg_mnt);
324 EXPORT_SYMBOL(lprocfs_dereg_mnt);
325 EXPORT_SYMBOL(lprocfs_add_vars);
326 EXPORT_SYMBOL(lprocfs_reg_class);
327 EXPORT_SYMBOL(lprocfs_dereg_class);
328 EXPORT_SYMBOL(lprocfs_ll_rd);
329
330