Whamcloud - gitweb
e9fe7248714bc2903a749dad63c4a4adba8d1f4d
[fs/lustre-release.git] / lustre / obdclass / proc_lustre.c
1 /* proc_lustre.c manages /proc/lustre/obd. 
2  *
3  * OBD devices materialize in /proc as a directory:
4  *              /proc/lustre/obd/<number>
5  * when /dev/obd<number> is opened. When the device is closed, the 
6  * directory entry disappears. 
7  * 
8  * For each open OBD device, code in this file also creates a file
9  * named <status>. "cat /proc/lustre/obd/<number>/status" gives 
10  * information about the OBD device's configuration.
11  * The class driver manages the "status" entry.
12  *
13  * Other logical drivers can create their own entries. For example,
14  * the obdtrace driver creates /proc/lustre/obd/<obdid>/stats entry.
15  *
16  * This file defines three functions 
17  *               proc_lustre_register_obd_device()
18  *               proc_lustre_release_obd_device()
19  *               proc_lustre_remove_obd_entry() 
20  * that dynamically create/delete /proc/lustre/obd entries:
21  *
22  *     proc_lustre_register_obd_device() registers an obd device,
23  *     and, if this is the first OBD device, creates /proc/lustre/obd.
24  *
25  *     proc_lustre_release_obd_device() removes device information
26  *     from /proc/lustre/obd, and if this is the last OBD device
27  *     removes  /proc/lustre/obd.
28  *
29  *     proc_lustre_remove_obd_entry() removes a
30  *     /proc/lustre/obd/<obdid>/ entry by name. This is the only
31  *     function that is exported to other modules. 
32  *
33  * Copyright (c) 2001 Rumi Zahir <rumi.zahir@intel.com>
34  */
35
36 #include <linux/config.h>
37 #include <linux/module.h>
38 #include <linux/version.h>
39 #include <linux/proc_fs.h>
40
41 #include <linux/obd_support.h>
42 #include <linux/obd_class.h>
43
44
45 #ifdef CONFIG_PROC_FS
46 extern struct proc_dir_entry proc_root;
47
48 static struct proc_dir_entry *proc_lustre_dir_entry = 0;
49 static struct proc_dir_entry *proc_lustre_obd_dir_entry = 0;
50
51 static struct proc_dir_entry *
52 proc_lustre_mkdir(const char* dname, struct proc_dir_entry *parent)
53 {
54         struct proc_dir_entry *child_dir_entry;
55
56 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,0)  /*0x20300 */
57         child_dir_entry = proc_mkdir(dname, parent);
58 #else
59         child_dir_entry = create_proc_entry(dname,
60                                             S_IFDIR | S_IRUGO | S_IXUGO,
61                                             &proc_root);
62 #endif
63         if (!child_dir_entry)
64                 printk ("lustre: failed to create /proc  entry %s\n", dname);
65         
66         return child_dir_entry;
67 }
68
69 static int read_lustre_status(char *page, char **start, off_t offset,
70                               int count, int *eof, void *data)
71 {
72         struct obd_device * obddev = (struct obd_device *) data;
73         int p;
74
75         p = sprintf(&page[0], "/dev/obd%d: ", obddev->obd_minor);
76         
77         if (obddev->obd_refcnt==0) { 
78                 /* obd is unused */
79                 p += sprintf(&page[p], "open but unused\n\0");
80         }
81         else {  /* obd in use */
82                 p += sprintf(&page[p], "refcnt(%d)", obddev->obd_refcnt);
83                 
84                 if  (obddev->obd_flags & OBD_ATTACHED) {
85                         p += sprintf(&page[p], ", attached(%s)", 
86                                      obddev->obd_type->typ_name);
87                 }
88                 
89                 if  (obddev->obd_flags & OBD_SET_UP) {
90                         struct dentry   *my_dentry;
91                         struct vfsmount *root_mnt;
92                         char *path;
93                         char *pathpage;
94                         
95                         if (!(pathpage = (char*) __get_free_page(GFP_KERNEL)))
96                                 return -ENOMEM;
97                 
98                         my_dentry = obddev->obd_fsname.dentry;
99                         root_mnt = mntget(current->fs->rootmnt);
100                         path = d_path(my_dentry,root_mnt,pathpage,PAGE_SIZE);
101
102                         p += sprintf(&page[p], ", setup(%s)", path);
103                         
104                         free_page((unsigned long) pathpage);
105                 }
106                 
107                 /* print connections */
108                 {
109                         struct list_head * lh;
110                         struct obd_client * cli=0;
111                         
112                         lh = &obddev->obd_gen_clients;
113                         while ((lh = lh->next) != &obddev->obd_gen_clients) {
114                                 p += sprintf(&page[p],
115                                              ((cli==0) ? ", connections(" : ",") );
116                                 cli = list_entry(lh, struct obd_client, cli_chain);
117                                 p += sprintf(&page[p], "%d", cli->cli_id);
118                         } /* while */
119                         if (cli!=0) { /* there was at least one client */
120                                 p += sprintf(&page[p], ")");
121                         }
122                 }
123                 
124                 p += sprintf(&page[p], "\n\0");
125         }
126
127         /* Compute eof and return value */
128
129         if (offset + count >= p) {
130                 *eof=1;
131                 return (p - offset);
132         }
133         return count;
134 }
135
136 struct proc_dir_entry *
137 proc_lustre_register_obd_device(struct obd_device *obd)
138 {
139         char obdname[32];
140         struct proc_dir_entry *obd_dir;
141         struct proc_dir_entry *obd_status = 0;
142
143         if (!proc_lustre_dir_entry) {
144                 proc_lustre_dir_entry = 
145                         proc_lustre_mkdir("lustre", &proc_root);
146                 if (!proc_lustre_dir_entry)
147                         return 0;
148         
149                 proc_lustre_obd_dir_entry = 
150                         proc_lustre_mkdir("obd", proc_lustre_dir_entry);
151                 if (!proc_lustre_obd_dir_entry)
152                         return 0;
153         }
154
155         sprintf(obdname, "%d", obd->obd_minor);
156
157         obd_dir =  proc_lustre_mkdir(obdname, proc_lustre_obd_dir_entry);
158         
159         if (obd_dir) 
160                 obd_status = create_proc_entry("status", S_IRUSR | S_IFREG, obd_dir);
161
162         if (obd_status) {
163                 obd_status->read_proc = read_lustre_status;
164                 obd_status->data = (void*) obd;
165         }
166
167         return obd_dir;
168 }
169
170 void proc_lustre_remove_obd_entry(const char* name, struct obd_device *obd)
171 {
172         struct proc_dir_entry *obd_entry = 0;
173         struct proc_dir_entry *obd_dir = obd->obd_proc_entry;
174         
175         remove_proc_entry(name, obd_dir);
176
177         while (obd_dir->subdir==0) {
178                 /* if we removed last entry in this directory,
179                  * then remove parent directory unless this
180                  * is /proc itself
181                  */
182                 if (obd_dir == &proc_root) 
183                         break;
184                         
185                 obd_entry = obd_dir;
186                 obd_dir = obd_dir->parent;
187         
188                 /* If /proc/lustre/obd/XXX or /proc/lustre/obd or
189                  * /proc/lustre are being removed, then reset 
190                  * internal variables
191                  */
192                 
193                 if (obd_entry == obd->obd_proc_entry) 
194                         obd->obd_proc_entry=0; /* /proc/lustre/obd/XXX */
195                 else 
196                         if (obd_entry == proc_lustre_obd_dir_entry)
197                                 proc_lustre_obd_dir_entry=0;
198                         else 
199                                 if (obd_entry == proc_lustre_dir_entry) 
200                                         proc_lustre_dir_entry=0;
201
202                 remove_proc_entry(obd_entry->name, obd_dir);
203         }
204 }
205
206 void proc_lustre_release_obd_device(struct obd_device *obd)
207 {
208         proc_lustre_remove_obd_entry("status", obd);
209 }
210
211
212 #else  /* CONFIG_PROC_FS */
213
214 struct proc_dir_entry *proc_lustre_register_obd_device(struct obd_device *obd)
215 {
216         return 0;
217 }
218
219 void proc_lustre_remove_obd_entry(const char* name, struct obd_device *obd) {}
220 void proc_lustre_release_obd_device(struct obd_device *obd) {}
221
222 #endif   /* CONFIG_PROC_FS */
223                                    
224 EXPORT_SYMBOL(proc_lustre_remove_obd_entry);
225
226
227
228
229
230
231
232
233
234
235