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