Whamcloud - gitweb
d49a7a564198aa66861adbb5a1e961d236b8d06b
[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_flags & OBD_ATTACHED) {
83                 p += sprintf(&page[p], ", attached(%s)", 
84                              obddev->obd_type->typ_name);
85         }
86         
87         if  (obddev->obd_flags & OBD_SET_UP) {
88                 struct dentry   *my_dentry;
89                 struct vfsmount *root_mnt;
90                 char *path;
91                 char *pathpage;
92                 
93                 if (!(pathpage = (char*) __get_free_page(GFP_KERNEL)))
94                         return -ENOMEM;
95                 
96                 my_dentry = NULL;
97                 root_mnt = mntget(current->fs->rootmnt);
98                 path = d_path(my_dentry,root_mnt,pathpage,PAGE_SIZE);
99                 
100                 p += sprintf(&page[p], ", setup(%s)", path);
101                 
102                 free_page((unsigned long) pathpage);
103         }
104         
105         /* print connections */
106         {
107                 struct list_head * lh;
108                 struct obd_export * export=0;
109                 
110                 lh = &obddev->obd_exports;
111                 while ((lh = lh->next) != &obddev->obd_exports) {
112                         p += sprintf(&page[p],
113                                      ((export==0) ? ", connections(" : ",") );
114                         export = list_entry(lh, struct obd_export, export_chain);
115                         p += sprintf(&page[p], "%d", export->export_id);
116                 } /* while */
117                 if (export!=0) { /* there was at least one export */
118                         p += sprintf(&page[p], ")");
119                 }
120         }
121         
122         p += sprintf(&page[p], "\n");
123
124         /* Compute eof and return value */
125
126         if (offset + count >= p) {
127                 *eof=1;
128                 return (p - offset);
129         }
130         return count;
131 }
132
133 struct proc_dir_entry *
134 proc_lustre_register_obd_device(struct obd_device *obd)
135 {
136         char obdname[32];
137         struct proc_dir_entry *obd_dir;
138         struct proc_dir_entry *obd_status = 0;
139
140         if (!proc_lustre_dir_entry) {
141                 proc_lustre_dir_entry = 
142                         proc_lustre_mkdir("lustre", &proc_root);
143                 if (!proc_lustre_dir_entry)
144                         return 0;
145         
146                 proc_lustre_obd_dir_entry = 
147                         proc_lustre_mkdir("obd", proc_lustre_dir_entry);
148                 if (!proc_lustre_obd_dir_entry)
149                         return 0;
150         }
151
152         sprintf(obdname, "%d", obd->obd_minor);
153
154         obd_dir =  proc_lustre_mkdir(obdname, proc_lustre_obd_dir_entry);
155         
156         if (obd_dir) 
157                 obd_status = create_proc_entry("status", S_IRUSR | S_IFREG, obd_dir);
158
159         if (obd_status) {
160                 obd_status->read_proc = read_lustre_status;
161                 obd_status->data = (void*) obd;
162         }
163
164         return obd_dir;
165 }
166
167 void proc_lustre_remove_obd_entry(const char* name, struct obd_device *obd)
168 {
169         struct proc_dir_entry *obd_entry = 0;
170         struct proc_dir_entry *obd_dir = obd->obd_proc_entry;
171         
172         remove_proc_entry(name, obd_dir);
173
174         while (obd_dir->subdir==0) {
175                 /* if we removed last entry in this directory,
176                  * then remove parent directory unless this
177                  * is /proc itself
178                  */
179                 if (obd_dir == &proc_root) 
180                         break;
181                         
182                 obd_entry = obd_dir;
183                 obd_dir = obd_dir->parent;
184
185                 /* If /proc/lustre/obd/foo or /proc/lustre/obd or
186                  * /proc/lustre is being removed, then reset
187                  * internal variables
188                  */
189
190                 if (obd_entry == obd->obd_proc_entry)
191                         obd->obd_proc_entry=0; /* /proc/lustre/obd/foo */
192                 else 
193                         if (obd_entry == proc_lustre_obd_dir_entry)
194                                 proc_lustre_obd_dir_entry=0;
195                         else 
196                                 if (obd_entry == proc_lustre_dir_entry) 
197                                         proc_lustre_dir_entry=0;
198
199                 remove_proc_entry(obd_entry->name, obd_dir);
200         }
201 }
202
203 void proc_lustre_release_obd_device(struct obd_device *obd)
204 {
205         proc_lustre_remove_obd_entry("status", obd);
206 }
207
208
209 #else  /* CONFIG_PROC_FS */
210
211 struct proc_dir_entry *proc_lustre_register_obd_device(struct obd_device *obd)
212 {
213         return 0;
214 }
215
216 void proc_lustre_remove_obd_entry(const char* name, struct obd_device *obd) {}
217 void proc_lustre_release_obd_device(struct obd_device *obd) {}
218
219 #endif   /* CONFIG_PROC_FS */
220                                    
221 EXPORT_SYMBOL(proc_lustre_remove_obd_entry);
222
223
224
225
226
227
228
229
230
231
232