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