ceph: fix debugfs entry, simplify fsid checks
[linux-3.10.git] / fs / ceph / debugfs.c
1 #include "ceph_debug.h"
2
3 #include <linux/module.h>
4 #include <linux/ctype.h>
5 #include <linux/debugfs.h>
6 #include <linux/seq_file.h>
7
8 #include "super.h"
9 #include "mds_client.h"
10 #include "mon_client.h"
11 #include "auth.h"
12
13 #ifdef CONFIG_DEBUG_FS
14
15 /*
16  * Implement /sys/kernel/debug/ceph fun
17  *
18  * /sys/kernel/debug/ceph/client*  - an instance of the ceph client
19  *      .../osdmap      - current osdmap
20  *      .../mdsmap      - current mdsmap
21  *      .../monmap      - current monmap
22  *      .../osdc        - active osd requests
23  *      .../mdsc        - active mds requests
24  *      .../monc        - mon client state
25  *      .../dentry_lru  - dump contents of dentry lru
26  *      .../caps        - expose cap (reservation) stats
27  */
28
29 static struct dentry *ceph_debugfs_dir;
30
31 static int monmap_show(struct seq_file *s, void *p)
32 {
33         int i;
34         struct ceph_client *client = s->private;
35
36         if (client->monc.monmap == NULL)
37                 return 0;
38
39         seq_printf(s, "epoch %d\n", client->monc.monmap->epoch);
40         for (i = 0; i < client->monc.monmap->num_mon; i++) {
41                 struct ceph_entity_inst *inst =
42                         &client->monc.monmap->mon_inst[i];
43
44                 seq_printf(s, "\t%s%lld\t%s\n",
45                            ENTITY_NAME(inst->name),
46                            pr_addr(&inst->addr.in_addr));
47         }
48         return 0;
49 }
50
51 static int mdsmap_show(struct seq_file *s, void *p)
52 {
53         int i;
54         struct ceph_client *client = s->private;
55
56         if (client->mdsc.mdsmap == NULL)
57                 return 0;
58         seq_printf(s, "epoch %d\n", client->mdsc.mdsmap->m_epoch);
59         seq_printf(s, "root %d\n", client->mdsc.mdsmap->m_root);
60         seq_printf(s, "session_timeout %d\n",
61                        client->mdsc.mdsmap->m_session_timeout);
62         seq_printf(s, "session_autoclose %d\n",
63                        client->mdsc.mdsmap->m_session_autoclose);
64         for (i = 0; i < client->mdsc.mdsmap->m_max_mds; i++) {
65                 struct ceph_entity_addr *addr =
66                         &client->mdsc.mdsmap->m_info[i].addr;
67                 int state = client->mdsc.mdsmap->m_info[i].state;
68
69                 seq_printf(s, "\tmds%d\t%s\t(%s)\n", i, pr_addr(&addr->in_addr),
70                                ceph_mds_state_name(state));
71         }
72         return 0;
73 }
74
75 static int osdmap_show(struct seq_file *s, void *p)
76 {
77         int i;
78         struct ceph_client *client = s->private;
79
80         if (client->osdc.osdmap == NULL)
81                 return 0;
82         seq_printf(s, "epoch %d\n", client->osdc.osdmap->epoch);
83         seq_printf(s, "flags%s%s\n",
84                    (client->osdc.osdmap->flags & CEPH_OSDMAP_NEARFULL) ?
85                    " NEARFULL" : "",
86                    (client->osdc.osdmap->flags & CEPH_OSDMAP_FULL) ?
87                    " FULL" : "");
88         for (i = 0; i < client->osdc.osdmap->num_pools; i++) {
89                 struct ceph_pg_pool_info *pool =
90                         &client->osdc.osdmap->pg_pool[i];
91                 seq_printf(s, "pg_pool %d pg_num %d / %d, lpg_num %d / %d\n",
92                            i, pool->v.pg_num, pool->pg_num_mask,
93                            pool->v.lpg_num, pool->lpg_num_mask);
94         }
95         for (i = 0; i < client->osdc.osdmap->max_osd; i++) {
96                 struct ceph_entity_addr *addr =
97                         &client->osdc.osdmap->osd_addr[i];
98                 int state = client->osdc.osdmap->osd_state[i];
99                 char sb[64];
100
101                 seq_printf(s, "\tosd%d\t%s\t%3d%%\t(%s)\n",
102                            i, pr_addr(&addr->in_addr),
103                            ((client->osdc.osdmap->osd_weight[i]*100) >> 16),
104                            ceph_osdmap_state_str(sb, sizeof(sb), state));
105         }
106         return 0;
107 }
108
109 static int monc_show(struct seq_file *s, void *p)
110 {
111         struct ceph_client *client = s->private;
112         struct ceph_mon_statfs_request *req;
113         u64 nexttid = 0;
114         int got;
115         struct ceph_mon_client *monc = &client->monc;
116
117         mutex_lock(&monc->mutex);
118
119         if (monc->have_mdsmap)
120                 seq_printf(s, "have mdsmap %u\n", (unsigned)monc->have_mdsmap);
121         if (monc->have_osdmap)
122                 seq_printf(s, "have osdmap %u\n", (unsigned)monc->have_osdmap);
123         if (monc->want_next_osdmap)
124                 seq_printf(s, "want next osdmap\n");
125
126         while (nexttid < monc->last_tid) {
127                 got = radix_tree_gang_lookup(&monc->statfs_request_tree,
128                                              (void **)&req, nexttid, 1);
129                 if (got == 0)
130                         break;
131                 nexttid = req->tid + 1;
132
133                 seq_printf(s, "%lld statfs\n", req->tid);
134         }
135         mutex_unlock(&monc->mutex);
136
137         return 0;
138 }
139
140 static int mdsc_show(struct seq_file *s, void *p)
141 {
142         struct ceph_client *client = s->private;
143         struct ceph_mds_request *req;
144         u64 nexttid = 0;
145         int got;
146         struct ceph_mds_client *mdsc = &client->mdsc;
147         int pathlen;
148         u64 pathbase;
149         char *path;
150
151         mutex_lock(&mdsc->mutex);
152         while (nexttid < mdsc->last_tid) {
153                 got = radix_tree_gang_lookup(&mdsc->request_tree,
154                                              (void **)&req, nexttid, 1);
155                 if (got == 0)
156                         break;
157                 nexttid = req->r_tid + 1;
158
159                 if (req->r_request)
160                         seq_printf(s, "%lld\tmds%d\t", req->r_tid, req->r_mds);
161                 else
162                         seq_printf(s, "%lld\t(no request)\t", req->r_tid);
163
164                 seq_printf(s, "%s", ceph_mds_op_name(req->r_op));
165
166                 if (req->r_got_unsafe)
167                         seq_printf(s, "\t(unsafe)");
168                 else
169                         seq_printf(s, "\t");
170
171                 if (req->r_inode) {
172                         seq_printf(s, " #%llx", ceph_ino(req->r_inode));
173                 } else if (req->r_dentry) {
174                         path = ceph_mdsc_build_path(req->r_dentry, &pathlen,
175                                                     &pathbase, 0);
176                         spin_lock(&req->r_dentry->d_lock);
177                         seq_printf(s, " #%llx/%.*s (%s)",
178                                    ceph_ino(req->r_dentry->d_parent->d_inode),
179                                    req->r_dentry->d_name.len,
180                                    req->r_dentry->d_name.name,
181                                    path ? path : "");
182                         spin_unlock(&req->r_dentry->d_lock);
183                         kfree(path);
184                 } else if (req->r_path1) {
185                         seq_printf(s, " #%llx/%s", req->r_ino1.ino,
186                                    req->r_path1);
187                 }
188
189                 if (req->r_old_dentry) {
190                         path = ceph_mdsc_build_path(req->r_old_dentry, &pathlen,
191                                                     &pathbase, 0);
192                         spin_lock(&req->r_old_dentry->d_lock);
193                         seq_printf(s, " #%llx/%.*s (%s)",
194                            ceph_ino(req->r_old_dentry->d_parent->d_inode),
195                                    req->r_old_dentry->d_name.len,
196                                    req->r_old_dentry->d_name.name,
197                                    path ? path : "");
198                         spin_unlock(&req->r_old_dentry->d_lock);
199                         kfree(path);
200                 } else if (req->r_path2) {
201                         if (req->r_ino2.ino)
202                                 seq_printf(s, " #%llx/%s", req->r_ino2.ino,
203                                            req->r_path2);
204                         else
205                                 seq_printf(s, " %s", req->r_path2);
206                 }
207
208                 seq_printf(s, "\n");
209         }
210         mutex_unlock(&mdsc->mutex);
211
212         return 0;
213 }
214
215 static int osdc_show(struct seq_file *s, void *pp)
216 {
217         struct ceph_client *client = s->private;
218         struct ceph_osd_client *osdc = &client->osdc;
219         struct rb_node *p;
220
221         mutex_lock(&osdc->request_mutex);
222         for (p = rb_first(&osdc->requests); p; p = rb_next(p)) {
223                 struct ceph_osd_request *req;
224                 struct ceph_osd_request_head *head;
225                 struct ceph_osd_op *op;
226                 int num_ops;
227                 int opcode, olen;
228                 int i;
229
230                 req = rb_entry(p, struct ceph_osd_request, r_node);
231
232                 seq_printf(s, "%lld\tosd%d\t", req->r_tid,
233                            req->r_osd ? req->r_osd->o_osd : -1);
234
235                 head = req->r_request->front.iov_base;
236                 op = (void *)(head + 1);
237
238                 num_ops = le16_to_cpu(head->num_ops);
239                 olen = le32_to_cpu(head->object_len);
240                 seq_printf(s, "%.*s", olen,
241                            (const char *)(head->ops + num_ops));
242
243                 if (req->r_reassert_version.epoch)
244                         seq_printf(s, "\t%u'%llu",
245                            (unsigned)le32_to_cpu(req->r_reassert_version.epoch),
246                            le64_to_cpu(req->r_reassert_version.version));
247                 else
248                         seq_printf(s, "\t");
249
250                 for (i = 0; i < num_ops; i++) {
251                         opcode = le16_to_cpu(op->op);
252                         seq_printf(s, "\t%s", ceph_osd_op_name(opcode));
253                         op++;
254                 }
255
256                 seq_printf(s, "\n");
257         }
258         mutex_unlock(&osdc->request_mutex);
259         return 0;
260 }
261
262 static int caps_show(struct seq_file *s, void *p)
263 {
264         struct ceph_client *client = p;
265         int total, avail, used, reserved;
266
267         ceph_reservation_status(client, &total, &avail, &used, &reserved);
268         seq_printf(s, "total\t\t%d\n"
269                       "avail\t\t%d\n"
270                       "used\t\t%d\n"
271                       "reserved\t%d\n",
272                    total, avail, used, reserved);
273         return 0;
274 }
275
276 static int dentry_lru_show(struct seq_file *s, void *ptr)
277 {
278         struct ceph_client *client = s->private;
279         struct ceph_mds_client *mdsc = &client->mdsc;
280         struct ceph_dentry_info *di;
281
282         spin_lock(&mdsc->dentry_lru_lock);
283         list_for_each_entry(di, &mdsc->dentry_lru, lru) {
284                 struct dentry *dentry = di->dentry;
285                 seq_printf(s, "%p %p\t%.*s\n",
286                            di, dentry, dentry->d_name.len, dentry->d_name.name);
287         }
288         spin_unlock(&mdsc->dentry_lru_lock);
289
290         return 0;
291 }
292
293 #define DEFINE_SHOW_FUNC(name)                                          \
294 static int name##_open(struct inode *inode, struct file *file)          \
295 {                                                                       \
296         struct seq_file *sf;                                            \
297         int ret;                                                        \
298                                                                         \
299         ret = single_open(file, name, NULL);                            \
300         sf = file->private_data;                                        \
301         sf->private = inode->i_private;                                 \
302         return ret;                                                     \
303 }                                                                       \
304                                                                         \
305 static const struct file_operations name##_fops = {                     \
306         .open           = name##_open,                                  \
307         .read           = seq_read,                                     \
308         .llseek         = seq_lseek,                                    \
309         .release        = single_release,                               \
310 };
311
312 DEFINE_SHOW_FUNC(monmap_show)
313 DEFINE_SHOW_FUNC(mdsmap_show)
314 DEFINE_SHOW_FUNC(osdmap_show)
315 DEFINE_SHOW_FUNC(monc_show)
316 DEFINE_SHOW_FUNC(mdsc_show)
317 DEFINE_SHOW_FUNC(osdc_show)
318 DEFINE_SHOW_FUNC(dentry_lru_show)
319 DEFINE_SHOW_FUNC(caps_show)
320
321 int __init ceph_debugfs_init(void)
322 {
323         ceph_debugfs_dir = debugfs_create_dir("ceph", NULL);
324         if (!ceph_debugfs_dir)
325                 return -ENOMEM;
326         return 0;
327 }
328
329 void ceph_debugfs_cleanup(void)
330 {
331         debugfs_remove(ceph_debugfs_dir);
332 }
333
334 int ceph_debugfs_client_init(struct ceph_client *client)
335 {
336         int ret = 0;
337         char name[80];
338
339         snprintf(name, sizeof(name), FSID_FORMAT ".client%lld",
340                  PR_FSID(&client->fsid), client->monc.auth->global_id);
341
342         client->debugfs_dir = debugfs_create_dir(name, ceph_debugfs_dir);
343         if (!client->debugfs_dir)
344                 goto out;
345
346         client->monc.debugfs_file = debugfs_create_file("monc",
347                                                       0600,
348                                                       client->debugfs_dir,
349                                                       client,
350                                                       &monc_show_fops);
351         if (!client->monc.debugfs_file)
352                 goto out;
353
354         client->mdsc.debugfs_file = debugfs_create_file("mdsc",
355                                                       0600,
356                                                       client->debugfs_dir,
357                                                       client,
358                                                       &mdsc_show_fops);
359         if (!client->mdsc.debugfs_file)
360                 goto out;
361
362         client->osdc.debugfs_file = debugfs_create_file("osdc",
363                                                       0600,
364                                                       client->debugfs_dir,
365                                                       client,
366                                                       &osdc_show_fops);
367         if (!client->osdc.debugfs_file)
368                 goto out;
369
370         client->debugfs_monmap = debugfs_create_file("monmap",
371                                         0600,
372                                         client->debugfs_dir,
373                                         client,
374                                         &monmap_show_fops);
375         if (!client->debugfs_monmap)
376                 goto out;
377
378         client->debugfs_mdsmap = debugfs_create_file("mdsmap",
379                                         0600,
380                                         client->debugfs_dir,
381                                         client,
382                                         &mdsmap_show_fops);
383         if (!client->debugfs_mdsmap)
384                 goto out;
385
386         client->debugfs_osdmap = debugfs_create_file("osdmap",
387                                         0600,
388                                         client->debugfs_dir,
389                                         client,
390                                         &osdmap_show_fops);
391         if (!client->debugfs_osdmap)
392                 goto out;
393
394         client->debugfs_dentry_lru = debugfs_create_file("dentry_lru",
395                                         0600,
396                                         client->debugfs_dir,
397                                         client,
398                                         &dentry_lru_show_fops);
399         if (!client->debugfs_dentry_lru)
400                 goto out;
401
402         client->debugfs_caps = debugfs_create_file("caps",
403                                                    0400,
404                                                    client->debugfs_dir,
405                                                    client,
406                                                    &caps_show_fops);
407         if (!client->debugfs_caps)
408                 goto out;
409
410         return 0;
411
412 out:
413         ceph_debugfs_client_cleanup(client);
414         return ret;
415 }
416
417 void ceph_debugfs_client_cleanup(struct ceph_client *client)
418 {
419         debugfs_remove(client->debugfs_caps);
420         debugfs_remove(client->debugfs_dentry_lru);
421         debugfs_remove(client->debugfs_osdmap);
422         debugfs_remove(client->debugfs_mdsmap);
423         debugfs_remove(client->debugfs_monmap);
424         debugfs_remove(client->osdc.debugfs_file);
425         debugfs_remove(client->mdsc.debugfs_file);
426         debugfs_remove(client->monc.debugfs_file);
427         debugfs_remove(client->debugfs_dir);
428 }
429
430 #else  // CONFIG_DEBUG_FS
431
432 int __init ceph_debugfs_init(void)
433 {
434         return 0;
435 }
436
437 void ceph_debugfs_cleanup(void)
438 {
439 }
440
441 int ceph_debugfs_client_init(struct ceph_client *client)
442 {
443         return 0;
444 }
445
446 void ceph_debugfs_client_cleanup(struct ceph_client *client)
447 {
448 }
449
450 #endif  // CONFIG_DEBUG_FS