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