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