ceph: make mds ops interruptible
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / fs / ceph / debugfs.c
CommitLineData
76aa844d
SW
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"
0743304d
SW
10#include "mon_client.h"
11#include "auth.h"
76aa844d 12
039934b8
SW
13#ifdef CONFIG_DEBUG_FS
14
76aa844d
SW
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
29static struct dentry *ceph_debugfs_dir;
30
31static 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
51static 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
75static 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
109static 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
140static 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
215static 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
262static 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
276static 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) \
294static 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 \
305static const struct file_operations name##_fops = { \
306 .open = name##_open, \
307 .read = seq_read, \
308 .llseek = seq_lseek, \
309 .release = single_release, \
310};
311
312DEFINE_SHOW_FUNC(monmap_show)
313DEFINE_SHOW_FUNC(mdsmap_show)
314DEFINE_SHOW_FUNC(osdmap_show)
315DEFINE_SHOW_FUNC(monc_show)
316DEFINE_SHOW_FUNC(mdsc_show)
317DEFINE_SHOW_FUNC(osdc_show)
318DEFINE_SHOW_FUNC(dentry_lru_show)
319DEFINE_SHOW_FUNC(caps_show)
320
321int __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
329void ceph_debugfs_cleanup(void)
330{
331 debugfs_remove(ceph_debugfs_dir);
332}
333
334int 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",
0743304d 340 PR_FSID(&client->fsid), client->monc.auth->global_id);
76aa844d
SW
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
412out:
413 ceph_debugfs_client_cleanup(client);
414 return ret;
415}
416
417void 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
039934b8
SW
430#else // CONFIG_DEBUG_FS
431
432int __init ceph_debugfs_init(void)
433{
434 return 0;
435}
436
437void ceph_debugfs_cleanup(void)
438{
439}
440
441int ceph_debugfs_client_init(struct ceph_client *client)
442{
443 return 0;
444}
445
446void ceph_debugfs_client_cleanup(struct ceph_client *client)
447{
448}
449
450#endif // CONFIG_DEBUG_FS