Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/net/ceph/debugfs.c
49081 views
1
// SPDX-License-Identifier: GPL-2.0
2
#include <linux/ceph/ceph_debug.h>
3
4
#include <linux/device.h>
5
#include <linux/slab.h>
6
#include <linux/module.h>
7
#include <linux/ctype.h>
8
#include <linux/debugfs.h>
9
#include <linux/seq_file.h>
10
11
#include <linux/ceph/libceph.h>
12
#include <linux/ceph/mon_client.h>
13
#include <linux/ceph/auth.h>
14
#include <linux/ceph/debugfs.h>
15
16
#ifdef CONFIG_DEBUG_FS
17
18
/*
19
* Implement /sys/kernel/debug/ceph fun
20
*
21
* /sys/kernel/debug/ceph/client* - an instance of the ceph client
22
* .../osdmap - current osdmap
23
* .../monmap - current monmap
24
* .../osdc - active osd requests
25
* .../monc - mon client state
26
* .../client_options - libceph-only (i.e. not rbd or cephfs) options
27
* .../dentry_lru - dump contents of dentry lru
28
* .../caps - expose cap (reservation) stats
29
* .../bdi - symlink to ../../bdi/something
30
*/
31
32
static struct dentry *ceph_debugfs_dir;
33
34
static int monmap_show(struct seq_file *s, void *p)
35
{
36
int i;
37
struct ceph_client *client = s->private;
38
39
mutex_lock(&client->monc.mutex);
40
if (client->monc.monmap == NULL)
41
goto out_unlock;
42
43
seq_printf(s, "epoch %d\n", client->monc.monmap->epoch);
44
for (i = 0; i < client->monc.monmap->num_mon; i++) {
45
struct ceph_entity_inst *inst =
46
&client->monc.monmap->mon_inst[i];
47
48
seq_printf(s, "\t%s%lld\t%s\n",
49
ENTITY_NAME(inst->name),
50
ceph_pr_addr(&inst->addr));
51
}
52
53
out_unlock:
54
mutex_unlock(&client->monc.mutex);
55
return 0;
56
}
57
58
static int osdmap_show(struct seq_file *s, void *p)
59
{
60
int i;
61
struct ceph_client *client = s->private;
62
struct ceph_osd_client *osdc = &client->osdc;
63
struct ceph_osdmap *map;
64
struct rb_node *n;
65
66
down_read(&osdc->lock);
67
map = osdc->osdmap;
68
if (map == NULL)
69
goto out_unlock;
70
71
seq_printf(s, "epoch %u barrier %u flags 0x%x\n", map->epoch,
72
osdc->epoch_barrier, map->flags);
73
74
for (n = rb_first(&map->pg_pools); n; n = rb_next(n)) {
75
struct ceph_pg_pool_info *pi =
76
rb_entry(n, struct ceph_pg_pool_info, node);
77
78
seq_printf(s, "pool %lld '%s' type %d size %d min_size %d pg_num %u pg_num_mask %d flags 0x%llx lfor %u read_tier %lld write_tier %lld\n",
79
pi->id, pi->name, pi->type, pi->size, pi->min_size,
80
pi->pg_num, pi->pg_num_mask, pi->flags,
81
pi->last_force_request_resend, pi->read_tier,
82
pi->write_tier);
83
}
84
for (i = 0; i < map->max_osd; i++) {
85
struct ceph_entity_addr *addr = &map->osd_addr[i];
86
u32 state = map->osd_state[i];
87
char sb[64];
88
89
seq_printf(s, "osd%d\t%s\t%3d%%\t(%s)\t%3d%%\t%2d\n",
90
i, ceph_pr_addr(addr),
91
((map->osd_weight[i]*100) >> 16),
92
ceph_osdmap_state_str(sb, sizeof(sb), state),
93
((ceph_get_primary_affinity(map, i)*100) >> 16),
94
ceph_get_crush_locality(map, i,
95
&client->options->crush_locs));
96
}
97
for (n = rb_first(&map->pg_temp); n; n = rb_next(n)) {
98
struct ceph_pg_mapping *pg =
99
rb_entry(n, struct ceph_pg_mapping, node);
100
101
seq_printf(s, "pg_temp %llu.%x [", pg->pgid.pool,
102
pg->pgid.seed);
103
for (i = 0; i < pg->pg_temp.len; i++)
104
seq_printf(s, "%s%d", (i == 0 ? "" : ","),
105
pg->pg_temp.osds[i]);
106
seq_printf(s, "]\n");
107
}
108
for (n = rb_first(&map->primary_temp); n; n = rb_next(n)) {
109
struct ceph_pg_mapping *pg =
110
rb_entry(n, struct ceph_pg_mapping, node);
111
112
seq_printf(s, "primary_temp %llu.%x %d\n", pg->pgid.pool,
113
pg->pgid.seed, pg->primary_temp.osd);
114
}
115
for (n = rb_first(&map->pg_upmap); n; n = rb_next(n)) {
116
struct ceph_pg_mapping *pg =
117
rb_entry(n, struct ceph_pg_mapping, node);
118
119
seq_printf(s, "pg_upmap %llu.%x [", pg->pgid.pool,
120
pg->pgid.seed);
121
for (i = 0; i < pg->pg_upmap.len; i++)
122
seq_printf(s, "%s%d", (i == 0 ? "" : ","),
123
pg->pg_upmap.osds[i]);
124
seq_printf(s, "]\n");
125
}
126
for (n = rb_first(&map->pg_upmap_items); n; n = rb_next(n)) {
127
struct ceph_pg_mapping *pg =
128
rb_entry(n, struct ceph_pg_mapping, node);
129
130
seq_printf(s, "pg_upmap_items %llu.%x [", pg->pgid.pool,
131
pg->pgid.seed);
132
for (i = 0; i < pg->pg_upmap_items.len; i++)
133
seq_printf(s, "%s%d->%d", (i == 0 ? "" : ","),
134
pg->pg_upmap_items.from_to[i][0],
135
pg->pg_upmap_items.from_to[i][1]);
136
seq_printf(s, "]\n");
137
}
138
139
out_unlock:
140
up_read(&osdc->lock);
141
return 0;
142
}
143
144
static int monc_show(struct seq_file *s, void *p)
145
{
146
struct ceph_client *client = s->private;
147
struct ceph_mon_generic_request *req;
148
struct ceph_mon_client *monc = &client->monc;
149
struct rb_node *rp;
150
int i;
151
152
mutex_lock(&monc->mutex);
153
154
for (i = 0; i < ARRAY_SIZE(monc->subs); i++) {
155
seq_printf(s, "have %s %u", ceph_sub_str[i],
156
monc->subs[i].have);
157
if (monc->subs[i].want)
158
seq_printf(s, " want %llu%s",
159
le64_to_cpu(monc->subs[i].item.start),
160
(monc->subs[i].item.flags &
161
CEPH_SUBSCRIBE_ONETIME ? "" : "+"));
162
seq_putc(s, '\n');
163
}
164
seq_printf(s, "fs_cluster_id %d\n", monc->fs_cluster_id);
165
166
for (rp = rb_first(&monc->generic_request_tree); rp; rp = rb_next(rp)) {
167
__u16 op;
168
req = rb_entry(rp, struct ceph_mon_generic_request, node);
169
op = le16_to_cpu(req->request->hdr.type);
170
if (op == CEPH_MSG_STATFS)
171
seq_printf(s, "%llu statfs\n", req->tid);
172
else if (op == CEPH_MSG_MON_GET_VERSION)
173
seq_printf(s, "%llu mon_get_version", req->tid);
174
else
175
seq_printf(s, "%llu unknown\n", req->tid);
176
}
177
178
mutex_unlock(&monc->mutex);
179
return 0;
180
}
181
182
static void dump_spgid(struct seq_file *s, const struct ceph_spg *spgid)
183
{
184
seq_printf(s, "%llu.%x", spgid->pgid.pool, spgid->pgid.seed);
185
if (spgid->shard != CEPH_SPG_NOSHARD)
186
seq_printf(s, "s%d", spgid->shard);
187
}
188
189
static void dump_target(struct seq_file *s, struct ceph_osd_request_target *t)
190
{
191
int i;
192
193
seq_printf(s, "osd%d\t%llu.%x\t", t->osd, t->pgid.pool, t->pgid.seed);
194
dump_spgid(s, &t->spgid);
195
seq_puts(s, "\t[");
196
for (i = 0; i < t->up.size; i++)
197
seq_printf(s, "%s%d", (!i ? "" : ","), t->up.osds[i]);
198
seq_printf(s, "]/%d\t[", t->up.primary);
199
for (i = 0; i < t->acting.size; i++)
200
seq_printf(s, "%s%d", (!i ? "" : ","), t->acting.osds[i]);
201
seq_printf(s, "]/%d\te%u\t", t->acting.primary, t->epoch);
202
if (t->target_oloc.pool_ns) {
203
seq_printf(s, "%*pE/%*pE\t0x%x",
204
(int)t->target_oloc.pool_ns->len,
205
t->target_oloc.pool_ns->str,
206
t->target_oid.name_len, t->target_oid.name, t->flags);
207
} else {
208
seq_printf(s, "%*pE\t0x%x", t->target_oid.name_len,
209
t->target_oid.name, t->flags);
210
}
211
if (t->paused)
212
seq_puts(s, "\tP");
213
}
214
215
static void dump_request(struct seq_file *s, struct ceph_osd_request *req)
216
{
217
int i;
218
219
seq_printf(s, "%llu\t", req->r_tid);
220
dump_target(s, &req->r_t);
221
222
seq_printf(s, "\t%d", req->r_attempts);
223
224
for (i = 0; i < req->r_num_ops; i++) {
225
struct ceph_osd_req_op *op = &req->r_ops[i];
226
227
seq_printf(s, "%s%s", (i == 0 ? "\t" : ","),
228
ceph_osd_op_name(op->op));
229
if (op->op == CEPH_OSD_OP_WATCH)
230
seq_printf(s, "-%s",
231
ceph_osd_watch_op_name(op->watch.op));
232
else if (op->op == CEPH_OSD_OP_CALL)
233
seq_printf(s, "-%s/%s", op->cls.class_name,
234
op->cls.method_name);
235
}
236
237
seq_putc(s, '\n');
238
}
239
240
static void dump_requests(struct seq_file *s, struct ceph_osd *osd)
241
{
242
struct rb_node *n;
243
244
mutex_lock(&osd->lock);
245
for (n = rb_first(&osd->o_requests); n; n = rb_next(n)) {
246
struct ceph_osd_request *req =
247
rb_entry(n, struct ceph_osd_request, r_node);
248
249
dump_request(s, req);
250
}
251
252
mutex_unlock(&osd->lock);
253
}
254
255
static void dump_linger_request(struct seq_file *s,
256
struct ceph_osd_linger_request *lreq)
257
{
258
seq_printf(s, "%llu\t", lreq->linger_id);
259
dump_target(s, &lreq->t);
260
261
seq_printf(s, "\t%u\t%s%s/%d\n", lreq->register_gen,
262
lreq->is_watch ? "W" : "N", lreq->committed ? "C" : "",
263
lreq->last_error);
264
}
265
266
static void dump_linger_requests(struct seq_file *s, struct ceph_osd *osd)
267
{
268
struct rb_node *n;
269
270
mutex_lock(&osd->lock);
271
for (n = rb_first(&osd->o_linger_requests); n; n = rb_next(n)) {
272
struct ceph_osd_linger_request *lreq =
273
rb_entry(n, struct ceph_osd_linger_request, node);
274
275
dump_linger_request(s, lreq);
276
}
277
278
mutex_unlock(&osd->lock);
279
}
280
281
static void dump_snapid(struct seq_file *s, u64 snapid)
282
{
283
if (snapid == CEPH_NOSNAP)
284
seq_puts(s, "head");
285
else if (snapid == CEPH_SNAPDIR)
286
seq_puts(s, "snapdir");
287
else
288
seq_printf(s, "%llx", snapid);
289
}
290
291
static void dump_name_escaped(struct seq_file *s, unsigned char *name,
292
size_t len)
293
{
294
size_t i;
295
296
for (i = 0; i < len; i++) {
297
if (name[i] == '%' || name[i] == ':' || name[i] == '/' ||
298
name[i] < 32 || name[i] >= 127) {
299
seq_printf(s, "%%%02x", name[i]);
300
} else {
301
seq_putc(s, name[i]);
302
}
303
}
304
}
305
306
static void dump_hoid(struct seq_file *s, const struct ceph_hobject_id *hoid)
307
{
308
if (hoid->snapid == 0 && hoid->hash == 0 && !hoid->is_max &&
309
hoid->pool == S64_MIN) {
310
seq_puts(s, "MIN");
311
return;
312
}
313
if (hoid->is_max) {
314
seq_puts(s, "MAX");
315
return;
316
}
317
seq_printf(s, "%lld:%08x:", hoid->pool, hoid->hash_reverse_bits);
318
dump_name_escaped(s, hoid->nspace, hoid->nspace_len);
319
seq_putc(s, ':');
320
dump_name_escaped(s, hoid->key, hoid->key_len);
321
seq_putc(s, ':');
322
dump_name_escaped(s, hoid->oid, hoid->oid_len);
323
seq_putc(s, ':');
324
dump_snapid(s, hoid->snapid);
325
}
326
327
static void dump_backoffs(struct seq_file *s, struct ceph_osd *osd)
328
{
329
struct rb_node *n;
330
331
mutex_lock(&osd->lock);
332
for (n = rb_first(&osd->o_backoffs_by_id); n; n = rb_next(n)) {
333
struct ceph_osd_backoff *backoff =
334
rb_entry(n, struct ceph_osd_backoff, id_node);
335
336
seq_printf(s, "osd%d\t", osd->o_osd);
337
dump_spgid(s, &backoff->spgid);
338
seq_printf(s, "\t%llu\t", backoff->id);
339
dump_hoid(s, backoff->begin);
340
seq_putc(s, '\t');
341
dump_hoid(s, backoff->end);
342
seq_putc(s, '\n');
343
}
344
345
mutex_unlock(&osd->lock);
346
}
347
348
static int osdc_show(struct seq_file *s, void *pp)
349
{
350
struct ceph_client *client = s->private;
351
struct ceph_osd_client *osdc = &client->osdc;
352
struct rb_node *n;
353
354
down_read(&osdc->lock);
355
seq_printf(s, "REQUESTS %d homeless %d\n",
356
atomic_read(&osdc->num_requests),
357
atomic_read(&osdc->num_homeless));
358
for (n = rb_first(&osdc->osds); n; n = rb_next(n)) {
359
struct ceph_osd *osd = rb_entry(n, struct ceph_osd, o_node);
360
361
dump_requests(s, osd);
362
}
363
dump_requests(s, &osdc->homeless_osd);
364
365
seq_puts(s, "LINGER REQUESTS\n");
366
for (n = rb_first(&osdc->osds); n; n = rb_next(n)) {
367
struct ceph_osd *osd = rb_entry(n, struct ceph_osd, o_node);
368
369
dump_linger_requests(s, osd);
370
}
371
dump_linger_requests(s, &osdc->homeless_osd);
372
373
seq_puts(s, "BACKOFFS\n");
374
for (n = rb_first(&osdc->osds); n; n = rb_next(n)) {
375
struct ceph_osd *osd = rb_entry(n, struct ceph_osd, o_node);
376
377
dump_backoffs(s, osd);
378
}
379
380
up_read(&osdc->lock);
381
return 0;
382
}
383
384
static int client_options_show(struct seq_file *s, void *p)
385
{
386
struct ceph_client *client = s->private;
387
int ret;
388
389
ret = ceph_print_client_options(s, client, true);
390
if (ret)
391
return ret;
392
393
seq_putc(s, '\n');
394
return 0;
395
}
396
397
DEFINE_SHOW_ATTRIBUTE(monmap);
398
DEFINE_SHOW_ATTRIBUTE(osdmap);
399
DEFINE_SHOW_ATTRIBUTE(monc);
400
DEFINE_SHOW_ATTRIBUTE(osdc);
401
DEFINE_SHOW_ATTRIBUTE(client_options);
402
403
void __init ceph_debugfs_init(void)
404
{
405
ceph_debugfs_dir = debugfs_create_dir("ceph", NULL);
406
}
407
408
void ceph_debugfs_cleanup(void)
409
{
410
debugfs_remove(ceph_debugfs_dir);
411
}
412
413
void ceph_debugfs_client_init(struct ceph_client *client)
414
{
415
char name[80];
416
417
snprintf(name, sizeof(name), "%pU.client%lld", &client->fsid,
418
client->monc.auth->global_id);
419
420
dout("ceph_debugfs_client_init %p %s\n", client, name);
421
422
client->debugfs_dir = debugfs_create_dir(name, ceph_debugfs_dir);
423
424
client->monc.debugfs_file = debugfs_create_file("monc",
425
0400,
426
client->debugfs_dir,
427
client,
428
&monc_fops);
429
430
client->osdc.debugfs_file = debugfs_create_file("osdc",
431
0400,
432
client->debugfs_dir,
433
client,
434
&osdc_fops);
435
436
client->debugfs_monmap = debugfs_create_file("monmap",
437
0400,
438
client->debugfs_dir,
439
client,
440
&monmap_fops);
441
442
client->debugfs_osdmap = debugfs_create_file("osdmap",
443
0400,
444
client->debugfs_dir,
445
client,
446
&osdmap_fops);
447
448
client->debugfs_options = debugfs_create_file("client_options",
449
0400,
450
client->debugfs_dir,
451
client,
452
&client_options_fops);
453
}
454
455
void ceph_debugfs_client_cleanup(struct ceph_client *client)
456
{
457
dout("ceph_debugfs_client_cleanup %p\n", client);
458
debugfs_remove(client->debugfs_options);
459
debugfs_remove(client->debugfs_osdmap);
460
debugfs_remove(client->debugfs_monmap);
461
debugfs_remove(client->osdc.debugfs_file);
462
debugfs_remove(client->monc.debugfs_file);
463
debugfs_remove(client->debugfs_dir);
464
}
465
466
#else /* CONFIG_DEBUG_FS */
467
468
void __init ceph_debugfs_init(void)
469
{
470
}
471
472
void ceph_debugfs_cleanup(void)
473
{
474
}
475
476
void ceph_debugfs_client_init(struct ceph_client *client)
477
{
478
}
479
480
void ceph_debugfs_client_cleanup(struct ceph_client *client)
481
{
482
}
483
484
#endif /* CONFIG_DEBUG_FS */
485
486