1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2 * vim:expandtab:shiftwidth=8:tabstop=8:
4 * Copyright (C) 2002 Cluster File Systems, Inc.
6 * This file is part of Lustre, http://www.lustre.org.
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.
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.
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.
24 #include <linux/config.h>
25 #include <linux/module.h>
26 #include <linux/version.h>
27 #include <linux/proc_fs.h>
28 #include <linux/slab.h>
29 #include <linux/types.h>
31 #define DEBUG_SUBSYSTEM S_CLASS
32 #define MAX_STRING_SIZE 100
34 #include <linux/obd_support.h>
35 #include <linux/obd_class.h>
36 #include <linux/lprocfs.h>
37 #include <linux/string.h>
38 #include <linux/lustre_lib.h>
42 #define DEFAULT_MODE 0644
44 * Tokenizer array. Change this array to include special
45 * characters for string tokenizing
47 char tok[] = {'/', (char)0};
54 extern struct proc_dir_entry proc_root; /* Defined in proc/root.c */
55 extern struct obd_type *class_nm_to_type(char *nm);
60 struct proc_dir_entry *proc_lustre_root = 0;
61 struct proc_dir_entry *proc_lustre_dev_root = 0;
67 * lprocfs_reg_obd: Registers an instance of the OBD device in the
71 int lprocfs_reg_obd(struct obd_device* device,
77 struct proc_dir_entry* this_dev_root=0;
80 /* Obtain this device root */
81 this_dev_root = lprocfs_mkinitdir(device);
82 if (this_dev_root == 0) {
83 CERROR("Could not create initial directory");
84 return LPROCFS_FAILURE;
87 device->obd_proc_entry=this_dev_root;
88 retval=lprocfs_new_vars(device, \
89 this_dev_root, list, \
96 int lprocfs_add_new_vars(struct obd_device* device,
102 CERROR("Null pointer passed!");
103 return LPROCFS_FAILURE;
105 if(!(device->obd_proc_entry)){
107 "Device instance not registered yet!!");
108 return LPROCFS_FAILURE;
111 retval=lprocfs_new_vars(device,
112 device->obd_proc_entry, \
113 var, (const char*) tok, data);
117 int lprocfs_dereg_obd(struct obd_device* device)
119 struct proc_dir_entry* parent;
121 CDEBUG(D_OTHER, "LPROCFS removing device = %s\n", \
125 CDEBUG(D_OTHER, "! LProcfs: Null pointer !\n");
126 return LPROCFS_SUCCESS;
129 if (!(device->obd_name)) {
130 CERROR(" !! Device does not have a name !! \n");
131 return LPROCFS_FAILURE;
133 if(!(device->obd_proc_entry)){
134 CERROR("This device has not been registered\n");
135 return LPROCFS_FAILURE;
137 parent=device->obd_proc_entry->parent;
138 lprocfs_remove_all(device->obd_proc_entry);
141 * Free the memory held by counters
143 if (device->counters)
144 OBD_FREE(device->counters, device->cntr_mem_size);
147 while((!(parent->subdir) && \
148 memcmp(parent, &proc_root, sizeof(*parent)))) {
149 remove_proc_entry(parent->name, parent->parent);
150 parent=parent->parent;
153 CDEBUG(D_OTHER, "LPROCFS removed device = %s\n", \
156 return LPROCFS_SUCCESS;
158 struct proc_dir_entry* lprocfs_mkinitdir(struct obd_device* device)
160 struct proc_dir_entry* this_dev_root = 0;
161 struct proc_dir_entry* temp_proc = 0;
164 * First check if /proc/lustre exits. If it does not,
165 * instantiate the same and the devices directory
167 if (proc_lustre_root==0) {
168 proc_lustre_root = lprocfs_mkdir("lustre", &proc_root);
169 if (!proc_lustre_root) {
170 CERROR(" !! Cannot create /proc/lustre !! \n");
174 if (proc_lustre_dev_root==0) {
175 proc_lustre_dev_root =
176 lprocfs_mkdir("devices", proc_lustre_root);
178 if (!proc_lustre_dev_root) {
179 CERROR(" !! Cannot create /proc/lustre/devices !! \n");
186 * Check if this is the first instance for a device of
187 * this class in the lprocfs hierarchy.
189 temp_proc = lprocfs_srch(proc_lustre_dev_root,
190 device->obd_type->typ_name);
193 temp_proc = lprocfs_mkdir(device->obd_type->typ_name,
194 proc_lustre_dev_root);
196 CERROR("! Proc dir for device class %s !!\n",
197 device->obd_type->typ_name);
202 /* Next create the proc_dir_entry for this instance */
203 this_dev_root = lprocfs_mkdir(device->obd_name, temp_proc);
204 if (!this_dev_root) {
205 CERROR("!Can't create proc entry for instance %s !! \n",
210 return this_dev_root;
213 struct proc_dir_entry* lprocfs_mkdir(const char* dname,
214 struct proc_dir_entry *parent)
216 struct proc_dir_entry *child_dir_entry;
218 child_dir_entry = proc_mkdir(dname, parent);
220 if (!child_dir_entry)
221 CERROR("lustre: failed to create /proc entry %s\n", dname);
223 return child_dir_entry;
225 struct proc_dir_entry* lprocfs_srch(struct proc_dir_entry* head,
228 struct proc_dir_entry* temp;
233 while (temp != NULL) {
234 if (!strcmp(temp->name, name))
242 #warning FIXME: recursive code is VERY bad in the kernel because of stack limit
243 struct proc_dir_entry* lprocfs_bfs_srch(struct proc_dir_entry* root,
246 struct proc_dir_entry* temp = root;
251 if (!strcmp(temp->name, name))
254 if ((temp = lprocfs_bfs_srch(root->next, name)) != 0)
257 if ((temp = lprocfs_bfs_srch(root->subdir, name)) != 0)
262 void lprocfs_remove_all(struct proc_dir_entry* root)
264 if (root->subdir != 0)
265 lprocfs_remove_all(root->subdir);
268 lprocfs_remove_all(root->next);
270 if (root->parent != 0)
271 remove_proc_entry(root->name, root->parent);
273 remove_proc_entry(root->name, NULL);
276 * This function will be invoked during a module loading. The path parameter
277 * is relative to /proc/lustre, and hence needs to begin as
279 * The list is a simple variable list of names, which will be created under
280 * the "path". If none is specified, no variable entries will be created.
281 * Returns: The root for this module.
284 struct proc_dir_entry* lprocfs_reg_module(char* name, char* path,
285 lprocfs_vars_t* list,
288 struct proc_dir_entry* root=0;
291 CERROR("LProcFS: Null pointer for name\n");
295 CERROR("LProcFS: Insertion path not provided\n");
298 if (proc_lustre_root==0) {
299 proc_lustre_root = lprocfs_mkdir("lustre", &proc_root);
300 if (!proc_lustre_root) {
301 CERROR(" !! Cannot create /proc/lustre !! \n");
305 if((root=lprocfs_new_dir(proc_lustre_root, \
306 path, (const char*)tok))==0){
308 CERROR("!! LProcFS: Failed to create dirs");
312 root=lprocfs_mkdir(name, root);
313 retVal=lprocfs_new_vars(NULL, root, list, \
314 (const char*)tok, data);
315 if(retVal==LPROCFS_FAILURE)
321 int lprocfs_dereg_module(char* name)
323 struct proc_dir_entry* temp=0;
324 struct proc_dir_entry* parent=0;
325 if (proc_lustre_root==0) {
326 CERROR(" !! LProc Does not exist !! \n");
329 temp = lprocfs_bfs_srch(proc_lustre_root->subdir, \
332 CDEBUG(D_OTHER, "!! Module not inserted!!");
333 return LPROCFS_FAILURE;
336 lprocfs_remove_all(temp);
337 while((!(parent->subdir) && \
338 memcmp(parent, &proc_root, sizeof(*parent)))) {
339 remove_proc_entry(parent->name, parent->parent);
340 parent=parent->parent;
343 CDEBUG(D_OTHER, "LPROCFS removed = %s\n", \
347 return LPROCFS_SUCCESS;
351 struct proc_dir_entry* lprocfs_new_dir(struct proc_dir_entry* root,
355 struct proc_dir_entry* new_root = 0;
356 struct proc_dir_entry* temp_entry = 0;
358 char temp_string[MAX_STRING_SIZE];
363 * Remove trailing escaping character
365 memset(temp_string, 0, MAX_STRING_SIZE);
366 if (strlen(string) >= MAX_STRING_SIZE) {
367 CDEBUG(D_OTHER, "Directory namespace too long");
371 strcpy(temp_string, string);
372 temp_string[strlen(string) + 1] = '\0';
375 mover_str=temp_string;
376 while ((my_str = strsep(&mover_str, tok))) {
379 CDEBUG(D_OTHER, "SEARCH= %s\t, ROOT=%s\n", \
380 my_str, new_root->name);
381 temp_entry = lprocfs_srch(new_root, my_str);
382 if (temp_entry == 0) {
383 CDEBUG(D_OTHER, "Adding: %s\n", my_str);
384 temp_entry = lprocfs_mkdir(my_str, new_root);
385 if (temp_entry == 0) {
387 "! Did not create new dir %s !!\n",
392 new_root = temp_entry;
399 int lprocfs_add_mod_vars(struct proc_dir_entry* root,
400 lprocfs_vars_t* list,
404 retval=lprocfs_new_vars(NULL, root, list, \
405 (const char*) tok, data);
409 int lprocfs_new_vars(struct obd_device* dev,
410 struct proc_dir_entry* root,
411 lprocfs_vars_t* list,
415 struct proc_dir_entry* temp_root=0;
416 struct proc_dir_entry* new_leaf=0;
417 struct proc_dir_entry* new_parent=0;
418 char temp_string[MAX_STRING_SIZE];
421 return LPROCFS_SUCCESS;
424 temp_root=lprocfs_new_dir(root, \
429 CDEBUG(D_OTHER, "!LProcFS: Mods: No root!");
430 return LPROCFS_FAILURE;
432 /* Convert the last element into a leaf-node */
433 memset(temp_string, 0, MAX_STRING_SIZE);
434 strcpy(temp_string, temp_root->name);
435 temp_string[strlen(temp_root->name) + 1] = '\0';
436 new_parent=temp_root->parent;
437 if (new_parent != 0){
438 remove_proc_entry(temp_root->name, new_parent);
440 remove_proc_entry(temp_root->name, NULL);
442 new_leaf = create_proc_entry(temp_string, \
445 new_leaf->read_proc = list->read_fptr;
446 new_leaf->write_proc = list->write_fptr;
452 return LPROCFS_SUCCESS;
455 int lprocfs_ll_rd(char *page, char **start, off_t off,
456 int count, int *eof, void *data)
458 __u64 *temp = (__u64 *)data;
461 len = snprintf(page, count, LPU64"\n", *temp);
466 #endif /* LPROCFS_EXISTS */
469 EXPORT_SYMBOL(lprocfs_reg_obd);
470 EXPORT_SYMBOL(lprocfs_dereg_obd);
471 EXPORT_SYMBOL(lprocfs_add_new_vars);
472 EXPORT_SYMBOL(lprocfs_reg_module);
473 EXPORT_SYMBOL(lprocfs_dereg_module);
474 EXPORT_SYMBOL(lprocfs_ll_rd);
475 EXPORT_SYMBOL(lprocfs_add_mod_vars);