cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

debugfs.c (12615B)


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