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