Whamcloud - gitweb
Remove ___wait_on_page entirely. If we ever need it again, it will be
[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 #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
45 #define DEBUG_SUBSYSTEM S_CLASS
46
47 #include <linux/obd_support.h>
48 #include <linux/obd_class.h>
49
50 #ifdef CONFIG_PROC_FS
51 extern struct proc_dir_entry proc_root;
52
53 static struct proc_dir_entry *proc_lustre_dir_entry = 0;
54 static struct proc_dir_entry *proc_lustre_obd_dir_entry = 0;
55
56 static struct proc_dir_entry *
57 proc_lustre_mkdir(const char* dname, struct proc_dir_entry *parent)
58 {
59         struct proc_dir_entry *child_dir_entry;
60
61 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,0)  /*0x20300 */
62         child_dir_entry = proc_mkdir(dname, parent);
63 #else
64         child_dir_entry = create_proc_entry(dname,
65                                             S_IFDIR | S_IRUGO | S_IXUGO,
66                                             &proc_root);
67 #endif
68         if (!child_dir_entry)
69                 CERROR("lustre: failed to create /proc entry %s\n", dname);
70         
71         return child_dir_entry;
72 }
73
74 static int read_lustre_status(char *page, char **start, off_t offset,
75                               int count, int *eof, void *data)
76 {
77         struct obd_device * obddev = (struct obd_device *) data;
78         int p;
79
80         p = sprintf(&page[0], "/dev/obd%d: ", obddev->obd_minor);
81         
82         if (obddev->obd_refcnt==0) { 
83                 /* obd is unused */
84                 p += sprintf(&page[p], "open but unused\n");
85         }
86         else {  /* obd in use */
87                 p += sprintf(&page[p], "refcnt(%d)", obddev->obd_refcnt);
88                 
89                 if  (obddev->obd_flags & OBD_ATTACHED) {
90                         p += sprintf(&page[p], ", attached(%s)", 
91                                      obddev->obd_type->typ_name);
92                 }
93                 
94                 if  (obddev->obd_flags & OBD_SET_UP) {
95                         struct dentry   *my_dentry;
96                         struct vfsmount *root_mnt;
97                         char *path;
98                         char *pathpage;
99                         
100                         if (!(pathpage = (char*) __get_free_page(GFP_KERNEL)))
101                                 return -ENOMEM;
102                 
103                         my_dentry = obddev->obd_fsname.dentry;
104                         root_mnt = mntget(current->fs->rootmnt);
105                         path = d_path(my_dentry,root_mnt,pathpage,PAGE_SIZE);
106
107                         p += sprintf(&page[p], ", setup(%s)", path);
108                         
109                         free_page((unsigned long) pathpage);
110                 }
111                 
112                 /* print connections */
113                 {
114                         struct list_head * lh;
115                         struct obd_client * cli=0;
116                         
117                         lh = &obddev->obd_gen_clients;
118                         while ((lh = lh->next) != &obddev->obd_gen_clients) {
119                                 p += sprintf(&page[p],
120                                              ((cli==0) ? ", connections(" : ",") );
121                                 cli = list_entry(lh, struct obd_client, cli_chain);
122                                 p += sprintf(&page[p], "%d", cli->cli_id);
123                         } /* while */
124                         if (cli!=0) { /* there was at least one client */
125                                 p += sprintf(&page[p], ")");
126                         }
127                 }
128                 
129                 p += sprintf(&page[p], "\n");
130         }
131
132         /* Compute eof and return value */
133
134         if (offset + count >= p) {
135                 *eof=1;
136                 return (p - offset);
137         }
138         return count;
139 }
140
141 struct proc_dir_entry *
142 proc_lustre_register_obd_device(struct obd_device *obd)
143 {
144         char obdname[32];
145         struct proc_dir_entry *obd_dir;
146         struct proc_dir_entry *obd_status = 0;
147
148         if (!proc_lustre_dir_entry) {
149                 proc_lustre_dir_entry = 
150                         proc_lustre_mkdir("lustre", &proc_root);
151                 if (!proc_lustre_dir_entry)
152                         return 0;
153         
154                 proc_lustre_obd_dir_entry = 
155                         proc_lustre_mkdir("obd", proc_lustre_dir_entry);
156                 if (!proc_lustre_obd_dir_entry)
157                         return 0;
158         }
159
160         sprintf(obdname, "%d", obd->obd_minor);
161
162         obd_dir =  proc_lustre_mkdir(obdname, proc_lustre_obd_dir_entry);
163         
164         if (obd_dir) 
165                 obd_status = create_proc_entry("status", S_IRUSR | S_IFREG, obd_dir);
166
167         if (obd_status) {
168                 obd_status->read_proc = read_lustre_status;
169                 obd_status->data = (void*) obd;
170         }
171
172         return obd_dir;
173 }
174
175 void proc_lustre_remove_obd_entry(const char* name, struct obd_device *obd)
176 {
177         struct proc_dir_entry *obd_entry = 0;
178         struct proc_dir_entry *obd_dir = obd->obd_proc_entry;
179         
180         remove_proc_entry(name, obd_dir);
181
182         while (obd_dir->subdir==0) {
183                 /* if we removed last entry in this directory,
184                  * then remove parent directory unless this
185                  * is /proc itself
186                  */
187                 if (obd_dir == &proc_root) 
188                         break;
189                         
190                 obd_entry = obd_dir;
191                 obd_dir = obd_dir->parent;
192
193                 /* If /proc/lustre/obd/foo or /proc/lustre/obd or
194                  * /proc/lustre is being removed, then reset
195                  * internal variables
196                  */
197
198                 if (obd_entry == obd->obd_proc_entry)
199                         obd->obd_proc_entry=0; /* /proc/lustre/obd/foo */
200                 else 
201                         if (obd_entry == proc_lustre_obd_dir_entry)
202                                 proc_lustre_obd_dir_entry=0;
203                         else 
204                                 if (obd_entry == proc_lustre_dir_entry) 
205                                         proc_lustre_dir_entry=0;
206
207                 remove_proc_entry(obd_entry->name, obd_dir);
208         }
209 }
210
211 void proc_lustre_release_obd_device(struct obd_device *obd)
212 {
213         proc_lustre_remove_obd_entry("status", obd);
214 }
215
216
217 #else  /* CONFIG_PROC_FS */
218
219 struct proc_dir_entry *proc_lustre_register_obd_device(struct obd_device *obd)
220 {
221         return 0;
222 }
223
224 void proc_lustre_remove_obd_entry(const char* name, struct obd_device *obd) {}
225 void proc_lustre_release_obd_device(struct obd_device *obd) {}
226
227 #endif   /* CONFIG_PROC_FS */
228                                    
229 EXPORT_SYMBOL(proc_lustre_remove_obd_entry);
230
231
232
233
234
235
236
237
238
239
240