Whamcloud - gitweb
Header changes needed to compile under 2.5 (compiled also with 2.4 to verify).
[fs/lustre-release.git] / lustre / obdclass / lprocfs.c
1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=8:tabstop=8:
3  *
4  * Copyright (C) 2002 Intel Corporation
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  * Author: Hariharan Thantry
24  * File Name: lprocfs.c
25  *
26  * During initialization (of lustre), the following directory materializes
27  *          /proc/lustre
28  * When the first OBD device of a class is created (due to insmod)
29  * the directory
30  *         /proc/lustre/devices/<device-class> is created.
31  * When an instance of a device is created (during attach) the
32  * directory entry for that instance along with the variables for
33  * that entry gets created. These variables could be counters, string
34  * variables etc.
35  * Each API further describes the functionality offered.
36  *
37  */
38
39 #define EXPORT_SYMTAB
40 #include <linux/config.h>
41 #include <linux/module.h>
42 #include <linux/version.h>
43 #include <linux/proc_fs.h>
44 #include <linux/slab.h>
45 #include <linux/types.h>
46 #include <linux/string.h>
47
48 #define DEBUG_SUBSYSTEM S_CLASS
49 #define MAX_STRING_SIZE 100
50
51 #include <linux/obd_support.h>
52 #include <linux/obd_class.h>
53 #include <linux/lprocfs.h>
54 #include <linux/string.h>
55 #include <linux/lustre_lib.h>
56
57 #ifdef LPROCFS_EXISTS
58
59 #define DEFAULT_MODE 0644
60 /*
61  * Tokenizer array. Change this array to include special
62  * characters for string tokenizing
63  */
64 char tok[] = {'/', (char)0};
65 char enum_char = '_';
66 /*
67  * Escape character. To be used in directories that
68  * should not have any counter/variable entries under
69  * them. Used for hierarchical directories
70  */
71
72 char escape_char = '%';
73
74 /*
75  * Externs
76  */
77 extern struct proc_dir_entry proc_root; /* Defined in proc/root.c */
78
79
80 /*
81  * Globals
82  */
83
84 static struct proc_dir_entry *proc_lustre_root = 0;
85 static struct proc_dir_entry *proc_lustre_dev_root = 0;
86
87 /* struct lustre_lock proc_lustre_lock; */
88 /* static struct proc_dir_entry *proc_lustre_conn_root = 0; */
89 char *testStr = "General..";
90
91 /*
92  * Link the namespace with the internal array indices for
93  * each device class, only if proc lustre is defined
94  */
95
96 struct namespace_index dir_mdc_index[] = {
97         LPROCFS_DIR_INDEX(mdc, mgmt_setup),
98         LPROCFS_DIR_INDEX(mdc, mgmt_cleanup),
99         LPROCFS_DIR_INDEX(mdc, mgmt_connect),
100         LPROCFS_DIR_INDEX(mdc, mgmt_disconnect),
101         LPROCFS_DIR_INDEX(mdc, reint),
102         LPROCFS_DIR_INDEX(mdc, getstatus),
103         LPROCFS_DIR_INDEX(mdc, getattr),
104         LPROCFS_DIR_INDEX(mdc, setattr),
105         LPROCFS_DIR_INDEX(mdc, open),
106         LPROCFS_DIR_INDEX(mdc, readpage),
107         LPROCFS_DIR_INDEX(mdc, create),
108         LPROCFS_DIR_INDEX(mdc, unlink),
109         LPROCFS_DIR_INDEX(mdc, link),
110         LPROCFS_DIR_INDEX(mdc, rename),
111 };
112
113 struct namespace_index dir_mds_index[] = {
114         LPROCFS_DIR_INDEX(mds, mgmt_setup),
115         LPROCFS_DIR_INDEX(mds, mgmt_cleanup),
116         LPROCFS_DIR_INDEX(mds, mgmt_connect),
117         LPROCFS_DIR_INDEX(mds, mgmt_disconnect),
118         LPROCFS_DIR_INDEX(mds, getstatus),
119         LPROCFS_DIR_INDEX(mds, connect),
120         LPROCFS_DIR_INDEX(mds, disconnect_callback),
121         LPROCFS_DIR_INDEX(mds, getattr),
122         LPROCFS_DIR_INDEX(mds, readpage),
123         LPROCFS_DIR_INDEX(mds, open),
124         LPROCFS_DIR_INDEX(mds, close),
125         LPROCFS_DIR_INDEX(mds, create),
126         LPROCFS_DIR_INDEX(mds, unlink),
127         LPROCFS_DIR_INDEX(mds, link),
128         LPROCFS_DIR_INDEX(mds, rename),
129         LPROCFS_DIR_INDEX(mds, reint_summary),
130         LPROCFS_DIR_INDEX(mds, reint_setattr),
131         LPROCFS_DIR_INDEX(mds, reint_create),
132         LPROCFS_DIR_INDEX(mds, reint_unlink),
133         LPROCFS_DIR_INDEX(mds, reint_link),
134         LPROCFS_DIR_INDEX(mds, reint_rename),
135         LPROCFS_DIR_INDEX(mds, reint_recreate),
136 };
137
138 struct namespace_index dir_osc_index[] = {
139         LPROCFS_DIR_INDEX(osc, mgmt_setup),
140         LPROCFS_DIR_INDEX(osc, mgmt_cleanup),
141         LPROCFS_DIR_INDEX(osc, mgmt_connect),
142         LPROCFS_DIR_INDEX(osc, mgmt_disconnect),
143         LPROCFS_DIR_INDEX(osc, create),
144         LPROCFS_DIR_INDEX(osc, destroy),
145         LPROCFS_DIR_INDEX(osc, getattr),
146         LPROCFS_DIR_INDEX(osc, setattr),
147         LPROCFS_DIR_INDEX(osc, open),
148         LPROCFS_DIR_INDEX(osc, close),
149         LPROCFS_DIR_INDEX(osc, brw),
150         LPROCFS_DIR_INDEX(osc, punch),
151         LPROCFS_DIR_INDEX(osc, summary),
152         LPROCFS_DIR_INDEX(osc, cancel),
153 };
154
155 struct namespace_index dir_ost_index[] = {
156         LPROCFS_DIR_INDEX(ost, mgmt_setup),
157         LPROCFS_DIR_INDEX(ost, mgmt_cleanup),
158         LPROCFS_DIR_INDEX(ost, mgmt_connect),
159         LPROCFS_DIR_INDEX(ost, mgmt_disconnect),
160         LPROCFS_DIR_INDEX(ost, create),
161         LPROCFS_DIR_INDEX(ost, destroy),
162         LPROCFS_DIR_INDEX(ost, getattr),
163         LPROCFS_DIR_INDEX(ost, setattr),
164         LPROCFS_DIR_INDEX(ost, open),
165         LPROCFS_DIR_INDEX(ost, close),
166         LPROCFS_DIR_INDEX(ost, brw),
167         LPROCFS_DIR_INDEX(ost, punch),
168         LPROCFS_DIR_INDEX(ost, summary),
169         LPROCFS_DIR_INDEX(ost, cancel),
170         LPROCFS_DIR_INDEX(ost, getinfo),
171 };
172
173 struct namespace_index dir_lov_index[] = {
174         LPROCFS_DIR_INDEX(lov, mgmt_setup),
175         LPROCFS_DIR_INDEX(lov, mgmt_cleanup),
176         LPROCFS_DIR_INDEX(lov, mgmt_connect),
177         LPROCFS_DIR_INDEX(lov, mgmt_disconnect),
178         LPROCFS_DIR_INDEX(lov, create),
179         LPROCFS_DIR_INDEX(lov, destroy),
180         LPROCFS_DIR_INDEX(lov, getattr),
181         LPROCFS_DIR_INDEX(lov, setattr),
182         LPROCFS_DIR_INDEX(lov, open),
183         LPROCFS_DIR_INDEX(lov, close),
184         LPROCFS_DIR_INDEX(lov, brw),
185         LPROCFS_DIR_INDEX(lov, punch),
186         LPROCFS_DIR_INDEX(lov, summary),
187         LPROCFS_DIR_INDEX(lov, cancel),
188         LPROCFS_DIR_INDEX(lov, getinfo),
189 };
190
191 struct namespace_index dir_obdfilter_index[] = {
192         LPROCFS_DIR_INDEX(obdfilter, mgmt_setup),
193         LPROCFS_DIR_INDEX(obdfilter, mgmt_cleanup),
194         LPROCFS_DIR_INDEX(obdfilter, mgmt_connect),
195         LPROCFS_DIR_INDEX(obdfilter, mgmt_disconnect),
196         LPROCFS_DIR_INDEX(obdfilter, create),
197         LPROCFS_DIR_INDEX(obdfilter, destroy),
198         LPROCFS_DIR_INDEX(obdfilter, getattr),
199         LPROCFS_DIR_INDEX(obdfilter, setattr),
200         LPROCFS_DIR_INDEX(obdfilter, open),
201         LPROCFS_DIR_INDEX(obdfilter, close),
202         LPROCFS_DIR_INDEX(obdfilter, brw),
203         LPROCFS_DIR_INDEX(obdfilter, punch),
204         LPROCFS_DIR_INDEX(obdfilter, summary),
205         LPROCFS_DIR_INDEX(obdfilter, cancel),
206         LPROCFS_DIR_INDEX(obdfilter, getinfo),
207 };
208
209 struct namespace_index dir_ldlm_index[] = {
210         LPROCFS_DIR_INDEX(ldlm, mgmt_setup),
211         LPROCFS_DIR_INDEX(ldlm, mgmt_cleanup),
212         LPROCFS_DIR_INDEX(ldlm, mgmt_connect),
213         LPROCFS_DIR_INDEX(ldlm, mgmt_disconnect),
214         LPROCFS_DIR_INDEX(ldlm, locks_enqueus),
215         LPROCFS_DIR_INDEX(ldlm, locks_cancels),
216         LPROCFS_DIR_INDEX(ldlm, locks_converts),
217         LPROCFS_DIR_INDEX(ldlm, locks_matches),
218 };
219
220 struct namespace_index dir_ptlrpc_index[] = {
221         LPROCFS_DIR_INDEX(ptlrpc, mgmt_setup),
222         LPROCFS_DIR_INDEX(ptlrpc, mgmt_cleanup),
223         LPROCFS_DIR_INDEX(ptlrpc, mgmt_connect),
224         LPROCFS_DIR_INDEX(ptlrpc, mgmt_disconnect),
225         LPROCFS_DIR_INDEX(ptlrpc, counters),
226 };
227
228 struct namespace_index prof_mdc_index[] = {
229         LPROCFS_CNTR_INDEX(mdc, min_time),
230         LPROCFS_CNTR_INDEX(mdc, max_time),
231         LPROCFS_CNTR_INDEX(mdc, sum_time),
232         LPROCFS_CNTR_INDEX(mdc, num_ops),
233 };
234
235 struct namespace_index prof_mds_index[]= {
236         LPROCFS_CNTR_INDEX(mds, min_time),
237         LPROCFS_CNTR_INDEX(mds, max_time),
238         LPROCFS_CNTR_INDEX(mds, sum_time),
239         LPROCFS_CNTR_INDEX(mds, num_ops),
240 };
241
242 struct namespace_index prof_osc_index[]= {
243         LPROCFS_CNTR_INDEX(osc, min_time),
244         LPROCFS_CNTR_INDEX(osc, max_time),
245         LPROCFS_CNTR_INDEX(osc, sum_time),
246         LPROCFS_CNTR_INDEX(osc, num_ops),
247 };
248
249 struct namespace_index prof_ost_index[]= {
250         LPROCFS_CNTR_INDEX(ost, min_time),
251         LPROCFS_CNTR_INDEX(ost, max_time),
252         LPROCFS_CNTR_INDEX(ost, sum_time),
253         LPROCFS_CNTR_INDEX(ost, num_ops),
254 };
255
256 struct namespace_index prof_lov_index[]= {
257         LPROCFS_CNTR_INDEX(lov, min_time),
258         LPROCFS_CNTR_INDEX(lov, max_time),
259         LPROCFS_CNTR_INDEX(lov, sum_time),
260         LPROCFS_CNTR_INDEX(lov, num_ops),
261 };
262
263 struct namespace_index prof_obdfilter_index[]= {
264         LPROCFS_CNTR_INDEX(obdfilter, min_time),
265         LPROCFS_CNTR_INDEX(obdfilter, max_time),
266         LPROCFS_CNTR_INDEX(obdfilter, sum_time),
267         LPROCFS_CNTR_INDEX(obdfilter, num_ops),
268 };
269
270 struct namespace_index prof_ldlm_index[] = {
271         LPROCFS_CNTR_INDEX(ldlm, min_time),
272         LPROCFS_CNTR_INDEX(ldlm, max_time),
273         LPROCFS_CNTR_INDEX(ldlm, sum_time),
274         LPROCFS_CNTR_INDEX(ldlm, num_ops),
275         LPROCFS_CNTR_INDEX(ldlm, num_total),
276         LPROCFS_CNTR_INDEX(ldlm, num_zerolatency),
277         LPROCFS_CNTR_INDEX(ldlm, num_zerolatency_inflight),
278         LPROCFS_CNTR_INDEX(ldlm, num_zerolatency_done),
279         LPROCFS_CNTR_INDEX(ldlm, nonzero_mintime),
280         LPROCFS_CNTR_INDEX(ldlm, nonzero_maxtime),
281         LPROCFS_CNTR_INDEX(ldlm, nonzero_sumtime),
282 };
283
284 struct namespace_index prof_ptlrpc_index[] = {
285         LPROCFS_CNTR_INDEX(ptlrpc, min_time),
286         LPROCFS_CNTR_INDEX(ptlrpc, max_time),
287         LPROCFS_CNTR_INDEX(ptlrpc, sum_time),
288         LPROCFS_CNTR_INDEX(ptlrpc, num_ops),
289         LPROCFS_CNTR_INDEX(ptlrpc, msgs_alloc),
290         LPROCFS_CNTR_INDEX(ptlrpc, msgs_max),
291         LPROCFS_CNTR_INDEX(ptlrpc, recv_count),
292         LPROCFS_CNTR_INDEX(ptlrpc, recv_length),
293         LPROCFS_CNTR_INDEX(ptlrpc, send_count),
294         LPROCFS_CNTR_INDEX(ptlrpc, send_length),
295         LPROCFS_CNTR_INDEX(ptlrpc, portal_kmemory),
296 };
297
298 /*
299  * Group the device class name, its directory hierarchy and
300  * leaf nodes together
301  */
302
303 struct groupspace_index class_index[] = {
304         LPROCFS_GROUP_CREATE(mdc),
305         LPROCFS_GROUP_CREATE(mds),
306         LPROCFS_GROUP_CREATE(osc),
307         LPROCFS_GROUP_CREATE(ost),
308         LPROCFS_GROUP_CREATE(lov),
309         LPROCFS_GROUP_CREATE(obdfilter),
310         LPROCFS_GROUP_CREATE(ldlm),
311         LPROCFS_GROUP_CREATE(ptlrpc),
312 };
313
314
315 /*
316  *  API implementations
317  */
318
319 /*
320  * lprocfs_reg_dev: Registers an instance of the OBD device in the
321  *                       proc hierarchy
322  */
323
324 int lprocfs_reg_dev(struct obd_device* device, lprocfs_group_t* namespace,
325                     unsigned int cnt_struct_size)
326 {
327         unsigned int num_directories = 0;
328         int class_array_index = 0;
329         int retval = 0;
330         struct proc_dir_entry* this_dev_root=0;
331         unsigned int i = 0, j = 0;
332
333         /* Obtain this device root */
334         this_dev_root = lprocfs_mkinitdir(device);
335         if (this_dev_root == 0) {
336                 CERROR("Could not create initial directory");
337                 return LPROCFS_FAILURE;
338         }
339
340
341         /* Obtain the class-array index */
342         class_array_index = lprocfs_getclass_idx(class_index,
343                                                  device->obd_type->typ_name);
344
345         if (class_array_index == LPROCFS_FAILURE) {
346                 CERROR("!! Could not find class !! \n");
347                 return LPROCFS_FAILURE;
348         }
349
350         /* Create the directory namespace */
351         retval = lprocfs_create_dir_namespace(this_dev_root, namespace,
352                                               &num_directories);
353         if (retval == LPROCFS_FAILURE) {
354                 CERROR("!!Could not create proc directory structure !!\n");
355                 return LPROCFS_FAILURE;
356         }
357
358         /* Allocate memory managed by LProcFS for the device. */
359         if (cnt_struct_size != 0) {
360                 OBD_ALLOC(device->counters, num_directories*cnt_struct_size);
361                 device->cntr_mem_size = num_directories*cnt_struct_size;
362         }
363
364         /*
365          * Iterate the proc-dir-namespace, obtain corresponding
366          * directory(attribute)
367          * entries. Create the proc-counters from namespace, link them into
368          * dev counters
369          */
370         retval=lprocfs_link_dir_counters(device, this_dev_root, namespace,
371                                          cnt_struct_size, class_array_index);
372
373         if (retval == LPROCFS_FAILURE) {
374                 CERROR("!! Could not link proc counters to device !!");
375                 return LPROCFS_FAILURE;
376         }
377
378         /*
379          * Test code: This goes into individual modules. strcmp is
380          * unnecessary, since device knows its class. To see the values
381          * from the user space, do a cat on the respective variable
382          */
383         if (!(strcmp(device->obd_type->typ_name, "mds"))) {
384                 DEV_PROF_START(mds, device, gen, mgmt_setup);
385
386                 for (i = 0; i < 100; i++)
387                         for (j = 0; j < 100; j++)
388                                 continue;
389
390                 DEV_PROF_END(mds, device, gen, mgmt_setup);
391
392                 DEV_PROF_START(mds, device, gen, mgmt_setup);
393
394                 for (i = 0; i < 1000; i++)
395                         for (j = 0; j < 1000; j++)
396                                 continue;
397
398                 DEV_PROF_END(mds, device, gen, mgmt_setup);
399
400
401                 DEV_PROF_START(mds, device, gen, open);
402                 for (i = 0; i < 50; i++) {
403                         DEV_PROF_START(mds, device, gen, close);
404                         for (j = 0; j < 2000; j++)
405                                 continue;
406                         DEV_PROF_END(mds, device, gen, close);
407                 }
408                 DEV_PROF_END(mds, device, gen, open);
409         }
410
411         if (!(strcmp(device->obd_type->typ_name, "ldlm"))) {
412                 DEV_PROF_START(ldlm, device, ldlm, mgmt_connect);
413                 for (i = 0; i < 200; i++) {
414                         DEV_PROF_START(ldlm, device, ldlm, mgmt_disconnect);
415                         for (j = 0; j < 2000; j++)
416                                 continue;
417                         DEV_PROF_END(ldlm, device, ldlm, mgmt_disconnect);
418                 }
419                 DEV_PROF_END(ldlm, device, ldlm, mgmt_connect);
420         }
421
422         return LPROCFS_SUCCESS;
423 }
424
425 int lprocfs_link_dir_counters(struct obd_device* device,
426                               struct proc_dir_entry* root,
427                               lprocfs_group_t* namespace,
428                               unsigned int sz,
429                               unsigned int cl_idx)
430 {
431         struct proc_dir_entry* dir_root=0;
432         lprocfs_group_t* temp;
433         lprocfs_vars_t* fn_ctr;
434         struct namespace_index* cntr_names;
435         unsigned int i = 0;
436         unsigned int j = 0;
437         unsigned int k = 0;
438         unsigned int escape = 0;
439         int dir_idx = -1;
440         int cnt_idx = -1;
441
442         while(1) {
443                 temp = &namespace[i];
444                 dir_idx = -1;
445                 if (temp->count_func_namespace == 0)
446                         break;
447
448                 while ((temp->dir_namespace)[j] != 0) {
449                         dir_root = lprocfs_add_dir(root,
450                                                    (temp->dir_namespace)[j],
451                                                    (const char*)tok, &escape);
452                         if (escape) {
453                                 j++;
454                                 continue;
455                         }
456
457                         dir_idx = lprocfs_get_idx(class_index[cl_idx].directory,
458                                                   (temp->dir_namespace)[j]);
459                         while(1) {
460                                 cnt_idx = -1;
461                                 fn_ctr = &((temp->count_func_namespace)[k]);
462                                 if (fn_ctr->read_fptr == 0)
463                                         break;
464                                 cntr_names = class_index[cl_idx].counters;
465                                 cnt_idx = lprocfs_get_idx(cntr_names,
466                                                           fn_ctr->name);
467
468                                 if (lprocfs_add_var(device, dir_root, fn_ctr,
469                                                    dir_idx, cnt_idx, sz,
470                                                    temp->prof_type) ==
471                                    LPROCFS_FAILURE){
472                                         CERROR("Could not create leaf node!");
473                                         return LPROCFS_FAILURE;
474
475                                 }
476
477                                 k++;
478                         }
479
480                         k=0;
481                         j++;
482
483                 }
484                 k=0;
485                 j=0;
486                 i++;
487         }
488
489         return LPROCFS_SUCCESS;
490 }
491
492 int lprocfs_create_dir_namespace(struct proc_dir_entry* root,
493                                  lprocfs_group_t* namespace,
494                                  unsigned int *num_dirs)
495 {
496         unsigned int i = 0;
497         unsigned int j = 0;
498         struct proc_dir_entry* dir_root=0;
499         lprocfs_group_t* temp;
500         unsigned int escape = 0;
501
502         while (1) {
503                 temp = &namespace[i];
504                 if (temp->count_func_namespace == 0)
505                         break;
506                 while ((temp->dir_namespace)[j] != 0){
507                         dir_root = lprocfs_add_dir(root,
508                                                    (temp->dir_namespace)[j],
509                                                    (const char*)tok, &escape);
510                         if (dir_root == 0) {
511                                 CERROR("!! Could not create dir  %s !! \n",
512                                        (temp->dir_namespace)[j]);
513                                 return LPROCFS_FAILURE;
514                         }
515                         if (temp->prof_type != e_specific && !escape)
516                                 (*num_dirs)++;
517                         j++;
518                 }
519                 j = 0;
520                 i++;
521         }
522
523         return LPROCFS_SUCCESS;
524 }
525
526
527 int lprocfs_getclass_idx(struct groupspace_index* group, const char* classname)
528 {
529         unsigned int idx = 0;
530
531         while (group[idx].name != NULL) {
532                 if (!strcmp(group[idx].name, classname))
533                         return idx;
534                 idx++;
535         }
536
537         return LPROCFS_FAILURE;
538 }
539
540 struct proc_dir_entry* lprocfs_mkinitdir(struct obd_device* device)
541 {
542         struct proc_dir_entry* this_dev_root = 0;
543         struct proc_dir_entry* temp_proc = 0;
544
545         /*
546          * First check if /proc/lustre exits. If it does not,
547          * instantiate the same and the devices directory
548          */
549         if (!proc_lustre_root) {
550                 proc_lustre_root = lprocfs_mkdir("lustre", &proc_root);
551                 if (!proc_lustre_root) {
552                         CERROR(" !! Cannot create /proc/lustre !! \n");
553                         return 0;
554                 }
555                 proc_lustre_dev_root =
556                         lprocfs_mkdir("devices", proc_lustre_root);
557
558                 if (!proc_lustre_dev_root) {
559                         CERROR(" !! Cannot create /proc/lustre/devices !! \n");
560                         return 0;
561                 }
562         }
563
564         /*
565          * Check if this is the first instance for a device of
566          * this class in the lprocfs hierarchy.
567          */
568         temp_proc = lprocfs_srch(proc_lustre_dev_root,
569                                  device->obd_type->typ_name);
570
571         if (!temp_proc) {
572                 temp_proc = lprocfs_mkdir(device->obd_type->typ_name,
573                                           proc_lustre_dev_root);
574                 if (!temp_proc) {
575                         CERROR("! Proc dir for device class %s !!\n",
576                                device->obd_type->typ_name);
577                         return 0;
578                 }
579         }
580
581         /* Next create the proc_dir_entry for this instance */
582         this_dev_root = lprocfs_mkdir(device->obd_name, temp_proc);
583         if (!this_dev_root) {
584                 CERROR("!Can't create proc entry for instance %s !! \n",
585                        device->obd_name);
586                 return 0;
587         }
588
589         return this_dev_root;
590 }
591
592
593 int lprocfs_get_idx(struct namespace_index* class, const char* dir_name)
594 {
595         unsigned int index = 0;
596         char temp_string[MAX_STRING_SIZE];
597
598         /* First replace the string tokenizer with enum character */
599         memset(temp_string, 0, MAX_STRING_SIZE);
600         while (dir_name[index]!='\0' && index < MAX_STRING_SIZE) {
601                 if (dir_name[index] != tok[0])
602                         temp_string[index] = dir_name[index];
603                 else
604                         temp_string[index] = enum_char;
605                 index++;
606         }
607         temp_string[index] = '\0';
608
609         index = 0;
610         while (class[index].name) {
611                 if (!strcmp(class[index].name, temp_string))
612                         return index;
613                 index++;
614         }
615
616         CDEBUG(D_OTHER, "No profiling for %s\n", temp_string);
617         return -1;
618 }
619
620 struct proc_dir_entry* lprocfs_mkdir(const char* dname,
621                                      struct proc_dir_entry *parent)
622 {
623         struct proc_dir_entry *child_dir_entry;
624
625         child_dir_entry = proc_mkdir(dname, parent);
626
627         if (!child_dir_entry)
628                 CERROR("lustre: failed to create /proc entry %s\n", dname);
629
630         return child_dir_entry;
631 }
632
633 /*
634  * Create the variable struct entry for /proc. This will also
635  * register the read/write function pointers with
636  * /proc/lustre.
637  * Returns non-zero on success, zero on failure
638  */
639 unsigned int lprocfs_add_var(struct obd_device* device,
640                              struct proc_dir_entry* root,
641                              lprocfs_vars_t* variable, int dir_idx, int cnt_idx,
642                              unsigned int sz, lprofilers_e type)
643 {
644         struct proc_dir_entry* new_proc_entry;
645         __u64* temp;
646         unsigned int actual_idx;
647         unsigned int blk_size;
648
649         new_proc_entry = create_proc_entry(variable->name, DEFAULT_MODE, root);
650         if (!new_proc_entry)
651                 return LPROCFS_FAILURE;
652
653         new_proc_entry->read_proc = variable->read_fptr;
654         new_proc_entry->write_proc = variable->write_fptr;
655
656         switch(type){
657         case e_generic:
658                 if (device->counters) {
659                         if (dir_idx != -1 && cnt_idx != -1) {
660                                 temp = (__u64*)device->counters;
661                                 blk_size = ((sz) / (sizeof(__u64)));
662                                 actual_idx = (dir_idx*blk_size) + cnt_idx;
663                                 temp += actual_idx;
664                                 new_proc_entry->data = (__u64*)temp;
665                         }
666                 }
667                 break;
668         case e_specific:
669                  new_proc_entry->data = device;
670                  break;
671         }
672
673         return LPROCFS_SUCCESS;
674 }
675
676
677 /*
678  * Tokenize name, based on tok and end-of-string. Create and return the
679  * new directory entry. Set escape variable if the directory name contained
680  * the escaping character (#)
681  */
682
683 struct proc_dir_entry* lprocfs_add_dir(struct proc_dir_entry *root,
684                                        const char* string,
685                                        const char* tok,
686                                        unsigned int* escape)
687 {
688         struct proc_dir_entry* new_root = 0;
689         struct proc_dir_entry* temp_entry = 0;
690         struct proc_dir_entry* new_entry = 0;
691         char temp_string[MAX_STRING_SIZE];
692         char* my_str;
693         char* mover_str;
694
695         /*
696          * Remove trailing escaping character
697          */
698         memset(temp_string, 0, MAX_STRING_SIZE);
699         if (strlen(string) >= MAX_STRING_SIZE) {
700                 CERROR("Directory namespace too long");
701                 return 0;
702         }
703
704         if (strchr(string, escape_char)) {
705                 *escape = 1;
706                 strncpy(temp_string,string,strlen(string) - 1);
707                 temp_string[strlen(string)] = '\0';
708         } else {
709                 *escape = 0;
710                 strcpy(temp_string, string);
711                 temp_string[strlen(string) + 1] = '\0';
712         }
713
714         new_root=root;
715
716         /* Using strsep() instead */
717         mover_str=temp_string;
718         while ((my_str = strsep(&mover_str, tok))) {
719                 if(!*my_str)
720                         continue;
721                 temp_entry = lprocfs_srch(new_root, my_str);
722                 if (temp_entry == 0) {
723                         new_entry = lprocfs_mkdir(my_str, new_root);
724                         if (new_entry == 0) {
725                                 CERROR("! Did not create new dir %s !!\n",
726                                        my_str);
727                                 return 0;
728                         }
729                         return new_entry;
730                 }
731                 new_root = temp_entry;
732         }
733
734         return new_root;
735 }
736
737 struct proc_dir_entry* lprocfs_srch(struct proc_dir_entry* head,
738                                     const char* name)
739 {
740         struct proc_dir_entry* temp;
741
742         if (!head)
743                 return 0;
744         temp = head->subdir;
745         while (temp != NULL) {
746                 if (!strcmp(temp->name, name))
747                         return temp;
748                 temp = temp->next;
749         }
750
751         return 0;
752 }
753
754 #warning FIXME: recursive code is VERY bad in the kernel because of stack limit
755 struct proc_dir_entry* lprocfs_bfs_srch(struct proc_dir_entry* root,
756                                         const char* name)
757 {
758         struct proc_dir_entry* temp = root;
759
760         if (!temp)
761                 return 0;
762
763         if (!strcmp(temp->name, name))
764                 return temp;
765
766         if ((temp = lprocfs_bfs_srch(root->next, name)) != 0)
767                 return temp;
768
769         if ((temp = lprocfs_bfs_srch(root->subdir, name)) != 0)
770                 return temp;
771
772         return temp;
773 }
774
775 int lprocfs_get_nm(char* name, lprocfs_obd_nm_t* collection)
776 {
777         int i = 0;
778         while (collection[i].obd_names != 0) {
779                 if(!strcmp(collection[i].obd_clname, name))
780                         return i;
781                 i++;
782         }
783
784         return -1;
785 }
786
787 int lprocfs_dereg_dev(struct obd_device* device)
788 {
789         struct proc_dir_entry* temp;
790
791         CDEBUG(D_OTHER, "LPROCFS removing device = %s\n", \
792                device->obd_name);
793
794         if (!device) {
795                 CDEBUG(D_OTHER, "! LProcfs:  Null pointer !\n");
796                 return LPROCFS_SUCCESS;
797         }
798
799         if (!(device->obd_name)) {
800                 CERROR(" !! Device does not have a name !! \n");
801                 return LPROCFS_FAILURE;
802         }
803
804         temp = lprocfs_bfs_srch(proc_lustre_dev_root->subdir, \
805                                 device->obd_name);
806         if (temp == 0) {
807                 CERROR("!! No root obtained, device does not exist !!\n");
808                 return LPROCFS_FAILURE;
809         }
810
811         lprocfs_remove_all(temp);
812
813         /*
814          * Free the memory held by counters
815          */
816         if (device->counters)
817                 OBD_FREE(device->counters, device->cntr_mem_size);
818
819         CDEBUG(D_OTHER, "LPROCFS removed device = %s\n", \
820                device->obd_name);
821
822         return LPROCFS_SUCCESS;
823 }
824
825 void lprocfs_remove_all(struct proc_dir_entry* root)
826 {
827         if (root->subdir != 0)
828                 lprocfs_remove_all(root->subdir);
829
830         if (root->next != 0)
831                 lprocfs_remove_all(root->next);
832
833         if (root->parent != 0)
834                 remove_proc_entry(root->name, root->parent);
835         else
836                 remove_proc_entry(root->name, NULL);
837 }
838
839 int rd_uuid(char* page, char **start, off_t off,
840             int count, int *eof, void *data)
841 {
842         int len;
843         struct obd_device *temp = (struct obd_device *)data;
844
845         len = sprintf(page, "%s\n", temp->obd_uuid);
846
847         return len;
848 }
849
850 int wr_uuid(struct file* file, const char *buffer,
851             unsigned long count, void *data)
852 {
853
854         return 0;
855 }
856
857 int rd_blksize(char* page, char **start, off_t off,
858                int count, int *eof, void *data)
859 {
860         //int len=0;
861         //struct obd_device *temp = (struct obd_device *)data;
862
863         return 0;
864
865 }
866 int rd_blktotal(char* page, char **start, off_t off,
867                 int count, int *eof, void *data)
868 {
869         return 0;
870 }
871
872 int rd_blkfree(char* page, char **start, off_t off,
873                int count, int *eof, void *data)
874 {
875         return 0;
876 }
877
878 int rd_kbfree(char* page, char **start, off_t off,
879               int count, int *eof, void *data)
880 {
881         return 0;
882 }
883
884 int rd_numobjects(char* page, char **start, off_t off,
885                   int count, int *eof, void *data)
886 {
887         return 0;
888 }
889
890 int rd_objfree(char* page, char **start, off_t off,
891                int count, int *eof, void *data)
892 {
893         return 0;
894 }
895
896 int rd_objgroups(char* page, char **start, off_t off,
897                  int count, int *eof, void *data)
898 {
899         return 0;
900 }
901
902
903 int lprocfs_ll_rd(char *page, char **start, off_t off,
904                   int count, int *eof, void *data)
905 {
906         __u64 *temp = (__u64 *)data;
907         int len;
908
909         len = snprintf(page, count, LPU64"\n", *temp);
910
911         return len;
912 }
913
914 int rd_fs_type(char* page, char **start, off_t off,
915                int count, int *eof, void *data)
916 {
917         return 0;
918 }
919
920 int rd_other(char* page, char **start, off_t off, int count, int *eof,
921              void *data)
922 {
923         return 0;
924 }
925
926 int rd_string(char* page, char **start, off_t off, int count, int *eof,
927               void *data)
928 {
929         printk("Hello string");
930         return 0;
931 }
932
933 int lprocfs_ll_wr(struct file* file, const char *buffer, unsigned long count,
934                   void *data)
935 {
936         return 0;
937 }
938
939 int wr_other(struct file* file, const char *buffer, unsigned long count,
940              void *data)
941 {
942         return 0;
943 }
944
945 int wr_string(struct file* file, const char *buffer, unsigned long count,
946               void *data)
947 {
948         return 0;
949 }
950
951 int lprocfs_reg_conn(unsigned int conn_number,
952                      struct lprocfs_conn_namespace* namespace)
953 {
954         return 0;
955 }
956
957 int lprocfs_dereg_conn(unsigned int conn_number)
958 {
959         return 0;
960 }
961
962 /*
963  * Import/Export APIs
964  */
965 int lprocfs_add_export(unsigned int conn_number, struct obd_device* device)
966 {
967         return 0;
968 }
969
970 int lprocfs_add_import(unsigned int conn_number, struct obd_device* device)
971 {
972         return 0;
973 }
974
975 int lprocfs_remove_export(unsigned int conn_number, struct obd_device* device)
976 {
977         return 0;
978 }
979
980 int lprocfs_remove_import(unsigned int conn_number, struct obd_device* device)
981 {
982         return 0;
983 }
984
985 #endif