18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
28c2ecf20Sopenharmony_ci#include <linux/ceph/ceph_debug.h>
38c2ecf20Sopenharmony_ci
48c2ecf20Sopenharmony_ci#include <linux/device.h>
58c2ecf20Sopenharmony_ci#include <linux/slab.h>
68c2ecf20Sopenharmony_ci#include <linux/module.h>
78c2ecf20Sopenharmony_ci#include <linux/ctype.h>
88c2ecf20Sopenharmony_ci#include <linux/debugfs.h>
98c2ecf20Sopenharmony_ci#include <linux/seq_file.h>
108c2ecf20Sopenharmony_ci
118c2ecf20Sopenharmony_ci#include <linux/ceph/libceph.h>
128c2ecf20Sopenharmony_ci#include <linux/ceph/mon_client.h>
138c2ecf20Sopenharmony_ci#include <linux/ceph/auth.h>
148c2ecf20Sopenharmony_ci#include <linux/ceph/debugfs.h>
158c2ecf20Sopenharmony_ci
168c2ecf20Sopenharmony_ci#ifdef CONFIG_DEBUG_FS
178c2ecf20Sopenharmony_ci
188c2ecf20Sopenharmony_ci/*
198c2ecf20Sopenharmony_ci * Implement /sys/kernel/debug/ceph fun
208c2ecf20Sopenharmony_ci *
218c2ecf20Sopenharmony_ci * /sys/kernel/debug/ceph/client*  - an instance of the ceph client
228c2ecf20Sopenharmony_ci *      .../osdmap      - current osdmap
238c2ecf20Sopenharmony_ci *      .../monmap      - current monmap
248c2ecf20Sopenharmony_ci *      .../osdc        - active osd requests
258c2ecf20Sopenharmony_ci *      .../monc        - mon client state
268c2ecf20Sopenharmony_ci *      .../client_options - libceph-only (i.e. not rbd or cephfs) options
278c2ecf20Sopenharmony_ci *      .../dentry_lru  - dump contents of dentry lru
288c2ecf20Sopenharmony_ci *      .../caps        - expose cap (reservation) stats
298c2ecf20Sopenharmony_ci *      .../bdi         - symlink to ../../bdi/something
308c2ecf20Sopenharmony_ci */
318c2ecf20Sopenharmony_ci
328c2ecf20Sopenharmony_cistatic struct dentry *ceph_debugfs_dir;
338c2ecf20Sopenharmony_ci
348c2ecf20Sopenharmony_cistatic int monmap_show(struct seq_file *s, void *p)
358c2ecf20Sopenharmony_ci{
368c2ecf20Sopenharmony_ci	int i;
378c2ecf20Sopenharmony_ci	struct ceph_client *client = s->private;
388c2ecf20Sopenharmony_ci
398c2ecf20Sopenharmony_ci	if (client->monc.monmap == NULL)
408c2ecf20Sopenharmony_ci		return 0;
418c2ecf20Sopenharmony_ci
428c2ecf20Sopenharmony_ci	seq_printf(s, "epoch %d\n", client->monc.monmap->epoch);
438c2ecf20Sopenharmony_ci	for (i = 0; i < client->monc.monmap->num_mon; i++) {
448c2ecf20Sopenharmony_ci		struct ceph_entity_inst *inst =
458c2ecf20Sopenharmony_ci			&client->monc.monmap->mon_inst[i];
468c2ecf20Sopenharmony_ci
478c2ecf20Sopenharmony_ci		seq_printf(s, "\t%s%lld\t%s\n",
488c2ecf20Sopenharmony_ci			   ENTITY_NAME(inst->name),
498c2ecf20Sopenharmony_ci			   ceph_pr_addr(&inst->addr));
508c2ecf20Sopenharmony_ci	}
518c2ecf20Sopenharmony_ci	return 0;
528c2ecf20Sopenharmony_ci}
538c2ecf20Sopenharmony_ci
548c2ecf20Sopenharmony_cistatic int osdmap_show(struct seq_file *s, void *p)
558c2ecf20Sopenharmony_ci{
568c2ecf20Sopenharmony_ci	int i;
578c2ecf20Sopenharmony_ci	struct ceph_client *client = s->private;
588c2ecf20Sopenharmony_ci	struct ceph_osd_client *osdc = &client->osdc;
598c2ecf20Sopenharmony_ci	struct ceph_osdmap *map = osdc->osdmap;
608c2ecf20Sopenharmony_ci	struct rb_node *n;
618c2ecf20Sopenharmony_ci
628c2ecf20Sopenharmony_ci	if (map == NULL)
638c2ecf20Sopenharmony_ci		return 0;
648c2ecf20Sopenharmony_ci
658c2ecf20Sopenharmony_ci	down_read(&osdc->lock);
668c2ecf20Sopenharmony_ci	seq_printf(s, "epoch %u barrier %u flags 0x%x\n", map->epoch,
678c2ecf20Sopenharmony_ci			osdc->epoch_barrier, map->flags);
688c2ecf20Sopenharmony_ci
698c2ecf20Sopenharmony_ci	for (n = rb_first(&map->pg_pools); n; n = rb_next(n)) {
708c2ecf20Sopenharmony_ci		struct ceph_pg_pool_info *pi =
718c2ecf20Sopenharmony_ci			rb_entry(n, struct ceph_pg_pool_info, node);
728c2ecf20Sopenharmony_ci
738c2ecf20Sopenharmony_ci		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",
748c2ecf20Sopenharmony_ci			   pi->id, pi->name, pi->type, pi->size, pi->min_size,
758c2ecf20Sopenharmony_ci			   pi->pg_num, pi->pg_num_mask, pi->flags,
768c2ecf20Sopenharmony_ci			   pi->last_force_request_resend, pi->read_tier,
778c2ecf20Sopenharmony_ci			   pi->write_tier);
788c2ecf20Sopenharmony_ci	}
798c2ecf20Sopenharmony_ci	for (i = 0; i < map->max_osd; i++) {
808c2ecf20Sopenharmony_ci		struct ceph_entity_addr *addr = &map->osd_addr[i];
818c2ecf20Sopenharmony_ci		u32 state = map->osd_state[i];
828c2ecf20Sopenharmony_ci		char sb[64];
838c2ecf20Sopenharmony_ci
848c2ecf20Sopenharmony_ci		seq_printf(s, "osd%d\t%s\t%3d%%\t(%s)\t%3d%%\t%2d\n",
858c2ecf20Sopenharmony_ci			   i, ceph_pr_addr(addr),
868c2ecf20Sopenharmony_ci			   ((map->osd_weight[i]*100) >> 16),
878c2ecf20Sopenharmony_ci			   ceph_osdmap_state_str(sb, sizeof(sb), state),
888c2ecf20Sopenharmony_ci			   ((ceph_get_primary_affinity(map, i)*100) >> 16),
898c2ecf20Sopenharmony_ci			   ceph_get_crush_locality(map, i,
908c2ecf20Sopenharmony_ci					   &client->options->crush_locs));
918c2ecf20Sopenharmony_ci	}
928c2ecf20Sopenharmony_ci	for (n = rb_first(&map->pg_temp); n; n = rb_next(n)) {
938c2ecf20Sopenharmony_ci		struct ceph_pg_mapping *pg =
948c2ecf20Sopenharmony_ci			rb_entry(n, struct ceph_pg_mapping, node);
958c2ecf20Sopenharmony_ci
968c2ecf20Sopenharmony_ci		seq_printf(s, "pg_temp %llu.%x [", pg->pgid.pool,
978c2ecf20Sopenharmony_ci			   pg->pgid.seed);
988c2ecf20Sopenharmony_ci		for (i = 0; i < pg->pg_temp.len; i++)
998c2ecf20Sopenharmony_ci			seq_printf(s, "%s%d", (i == 0 ? "" : ","),
1008c2ecf20Sopenharmony_ci				   pg->pg_temp.osds[i]);
1018c2ecf20Sopenharmony_ci		seq_printf(s, "]\n");
1028c2ecf20Sopenharmony_ci	}
1038c2ecf20Sopenharmony_ci	for (n = rb_first(&map->primary_temp); n; n = rb_next(n)) {
1048c2ecf20Sopenharmony_ci		struct ceph_pg_mapping *pg =
1058c2ecf20Sopenharmony_ci			rb_entry(n, struct ceph_pg_mapping, node);
1068c2ecf20Sopenharmony_ci
1078c2ecf20Sopenharmony_ci		seq_printf(s, "primary_temp %llu.%x %d\n", pg->pgid.pool,
1088c2ecf20Sopenharmony_ci			   pg->pgid.seed, pg->primary_temp.osd);
1098c2ecf20Sopenharmony_ci	}
1108c2ecf20Sopenharmony_ci	for (n = rb_first(&map->pg_upmap); n; n = rb_next(n)) {
1118c2ecf20Sopenharmony_ci		struct ceph_pg_mapping *pg =
1128c2ecf20Sopenharmony_ci			rb_entry(n, struct ceph_pg_mapping, node);
1138c2ecf20Sopenharmony_ci
1148c2ecf20Sopenharmony_ci		seq_printf(s, "pg_upmap %llu.%x [", pg->pgid.pool,
1158c2ecf20Sopenharmony_ci			   pg->pgid.seed);
1168c2ecf20Sopenharmony_ci		for (i = 0; i < pg->pg_upmap.len; i++)
1178c2ecf20Sopenharmony_ci			seq_printf(s, "%s%d", (i == 0 ? "" : ","),
1188c2ecf20Sopenharmony_ci				   pg->pg_upmap.osds[i]);
1198c2ecf20Sopenharmony_ci		seq_printf(s, "]\n");
1208c2ecf20Sopenharmony_ci	}
1218c2ecf20Sopenharmony_ci	for (n = rb_first(&map->pg_upmap_items); n; n = rb_next(n)) {
1228c2ecf20Sopenharmony_ci		struct ceph_pg_mapping *pg =
1238c2ecf20Sopenharmony_ci			rb_entry(n, struct ceph_pg_mapping, node);
1248c2ecf20Sopenharmony_ci
1258c2ecf20Sopenharmony_ci		seq_printf(s, "pg_upmap_items %llu.%x [", pg->pgid.pool,
1268c2ecf20Sopenharmony_ci			   pg->pgid.seed);
1278c2ecf20Sopenharmony_ci		for (i = 0; i < pg->pg_upmap_items.len; i++)
1288c2ecf20Sopenharmony_ci			seq_printf(s, "%s%d->%d", (i == 0 ? "" : ","),
1298c2ecf20Sopenharmony_ci				   pg->pg_upmap_items.from_to[i][0],
1308c2ecf20Sopenharmony_ci				   pg->pg_upmap_items.from_to[i][1]);
1318c2ecf20Sopenharmony_ci		seq_printf(s, "]\n");
1328c2ecf20Sopenharmony_ci	}
1338c2ecf20Sopenharmony_ci
1348c2ecf20Sopenharmony_ci	up_read(&osdc->lock);
1358c2ecf20Sopenharmony_ci	return 0;
1368c2ecf20Sopenharmony_ci}
1378c2ecf20Sopenharmony_ci
1388c2ecf20Sopenharmony_cistatic int monc_show(struct seq_file *s, void *p)
1398c2ecf20Sopenharmony_ci{
1408c2ecf20Sopenharmony_ci	struct ceph_client *client = s->private;
1418c2ecf20Sopenharmony_ci	struct ceph_mon_generic_request *req;
1428c2ecf20Sopenharmony_ci	struct ceph_mon_client *monc = &client->monc;
1438c2ecf20Sopenharmony_ci	struct rb_node *rp;
1448c2ecf20Sopenharmony_ci	int i;
1458c2ecf20Sopenharmony_ci
1468c2ecf20Sopenharmony_ci	mutex_lock(&monc->mutex);
1478c2ecf20Sopenharmony_ci
1488c2ecf20Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(monc->subs); i++) {
1498c2ecf20Sopenharmony_ci		seq_printf(s, "have %s %u", ceph_sub_str[i],
1508c2ecf20Sopenharmony_ci			   monc->subs[i].have);
1518c2ecf20Sopenharmony_ci		if (monc->subs[i].want)
1528c2ecf20Sopenharmony_ci			seq_printf(s, " want %llu%s",
1538c2ecf20Sopenharmony_ci				   le64_to_cpu(monc->subs[i].item.start),
1548c2ecf20Sopenharmony_ci				   (monc->subs[i].item.flags &
1558c2ecf20Sopenharmony_ci					CEPH_SUBSCRIBE_ONETIME ?  "" : "+"));
1568c2ecf20Sopenharmony_ci		seq_putc(s, '\n');
1578c2ecf20Sopenharmony_ci	}
1588c2ecf20Sopenharmony_ci	seq_printf(s, "fs_cluster_id %d\n", monc->fs_cluster_id);
1598c2ecf20Sopenharmony_ci
1608c2ecf20Sopenharmony_ci	for (rp = rb_first(&monc->generic_request_tree); rp; rp = rb_next(rp)) {
1618c2ecf20Sopenharmony_ci		__u16 op;
1628c2ecf20Sopenharmony_ci		req = rb_entry(rp, struct ceph_mon_generic_request, node);
1638c2ecf20Sopenharmony_ci		op = le16_to_cpu(req->request->hdr.type);
1648c2ecf20Sopenharmony_ci		if (op == CEPH_MSG_STATFS)
1658c2ecf20Sopenharmony_ci			seq_printf(s, "%llu statfs\n", req->tid);
1668c2ecf20Sopenharmony_ci		else if (op == CEPH_MSG_MON_GET_VERSION)
1678c2ecf20Sopenharmony_ci			seq_printf(s, "%llu mon_get_version", req->tid);
1688c2ecf20Sopenharmony_ci		else
1698c2ecf20Sopenharmony_ci			seq_printf(s, "%llu unknown\n", req->tid);
1708c2ecf20Sopenharmony_ci	}
1718c2ecf20Sopenharmony_ci
1728c2ecf20Sopenharmony_ci	mutex_unlock(&monc->mutex);
1738c2ecf20Sopenharmony_ci	return 0;
1748c2ecf20Sopenharmony_ci}
1758c2ecf20Sopenharmony_ci
1768c2ecf20Sopenharmony_cistatic void dump_spgid(struct seq_file *s, const struct ceph_spg *spgid)
1778c2ecf20Sopenharmony_ci{
1788c2ecf20Sopenharmony_ci	seq_printf(s, "%llu.%x", spgid->pgid.pool, spgid->pgid.seed);
1798c2ecf20Sopenharmony_ci	if (spgid->shard != CEPH_SPG_NOSHARD)
1808c2ecf20Sopenharmony_ci		seq_printf(s, "s%d", spgid->shard);
1818c2ecf20Sopenharmony_ci}
1828c2ecf20Sopenharmony_ci
1838c2ecf20Sopenharmony_cistatic void dump_target(struct seq_file *s, struct ceph_osd_request_target *t)
1848c2ecf20Sopenharmony_ci{
1858c2ecf20Sopenharmony_ci	int i;
1868c2ecf20Sopenharmony_ci
1878c2ecf20Sopenharmony_ci	seq_printf(s, "osd%d\t%llu.%x\t", t->osd, t->pgid.pool, t->pgid.seed);
1888c2ecf20Sopenharmony_ci	dump_spgid(s, &t->spgid);
1898c2ecf20Sopenharmony_ci	seq_puts(s, "\t[");
1908c2ecf20Sopenharmony_ci	for (i = 0; i < t->up.size; i++)
1918c2ecf20Sopenharmony_ci		seq_printf(s, "%s%d", (!i ? "" : ","), t->up.osds[i]);
1928c2ecf20Sopenharmony_ci	seq_printf(s, "]/%d\t[", t->up.primary);
1938c2ecf20Sopenharmony_ci	for (i = 0; i < t->acting.size; i++)
1948c2ecf20Sopenharmony_ci		seq_printf(s, "%s%d", (!i ? "" : ","), t->acting.osds[i]);
1958c2ecf20Sopenharmony_ci	seq_printf(s, "]/%d\te%u\t", t->acting.primary, t->epoch);
1968c2ecf20Sopenharmony_ci	if (t->target_oloc.pool_ns) {
1978c2ecf20Sopenharmony_ci		seq_printf(s, "%*pE/%*pE\t0x%x",
1988c2ecf20Sopenharmony_ci			(int)t->target_oloc.pool_ns->len,
1998c2ecf20Sopenharmony_ci			t->target_oloc.pool_ns->str,
2008c2ecf20Sopenharmony_ci			t->target_oid.name_len, t->target_oid.name, t->flags);
2018c2ecf20Sopenharmony_ci	} else {
2028c2ecf20Sopenharmony_ci		seq_printf(s, "%*pE\t0x%x", t->target_oid.name_len,
2038c2ecf20Sopenharmony_ci			t->target_oid.name, t->flags);
2048c2ecf20Sopenharmony_ci	}
2058c2ecf20Sopenharmony_ci	if (t->paused)
2068c2ecf20Sopenharmony_ci		seq_puts(s, "\tP");
2078c2ecf20Sopenharmony_ci}
2088c2ecf20Sopenharmony_ci
2098c2ecf20Sopenharmony_cistatic void dump_request(struct seq_file *s, struct ceph_osd_request *req)
2108c2ecf20Sopenharmony_ci{
2118c2ecf20Sopenharmony_ci	int i;
2128c2ecf20Sopenharmony_ci
2138c2ecf20Sopenharmony_ci	seq_printf(s, "%llu\t", req->r_tid);
2148c2ecf20Sopenharmony_ci	dump_target(s, &req->r_t);
2158c2ecf20Sopenharmony_ci
2168c2ecf20Sopenharmony_ci	seq_printf(s, "\t%d", req->r_attempts);
2178c2ecf20Sopenharmony_ci
2188c2ecf20Sopenharmony_ci	for (i = 0; i < req->r_num_ops; i++) {
2198c2ecf20Sopenharmony_ci		struct ceph_osd_req_op *op = &req->r_ops[i];
2208c2ecf20Sopenharmony_ci
2218c2ecf20Sopenharmony_ci		seq_printf(s, "%s%s", (i == 0 ? "\t" : ","),
2228c2ecf20Sopenharmony_ci			   ceph_osd_op_name(op->op));
2238c2ecf20Sopenharmony_ci		if (op->op == CEPH_OSD_OP_WATCH)
2248c2ecf20Sopenharmony_ci			seq_printf(s, "-%s",
2258c2ecf20Sopenharmony_ci				   ceph_osd_watch_op_name(op->watch.op));
2268c2ecf20Sopenharmony_ci		else if (op->op == CEPH_OSD_OP_CALL)
2278c2ecf20Sopenharmony_ci			seq_printf(s, "-%s/%s", op->cls.class_name,
2288c2ecf20Sopenharmony_ci				   op->cls.method_name);
2298c2ecf20Sopenharmony_ci	}
2308c2ecf20Sopenharmony_ci
2318c2ecf20Sopenharmony_ci	seq_putc(s, '\n');
2328c2ecf20Sopenharmony_ci}
2338c2ecf20Sopenharmony_ci
2348c2ecf20Sopenharmony_cistatic void dump_requests(struct seq_file *s, struct ceph_osd *osd)
2358c2ecf20Sopenharmony_ci{
2368c2ecf20Sopenharmony_ci	struct rb_node *n;
2378c2ecf20Sopenharmony_ci
2388c2ecf20Sopenharmony_ci	mutex_lock(&osd->lock);
2398c2ecf20Sopenharmony_ci	for (n = rb_first(&osd->o_requests); n; n = rb_next(n)) {
2408c2ecf20Sopenharmony_ci		struct ceph_osd_request *req =
2418c2ecf20Sopenharmony_ci		    rb_entry(n, struct ceph_osd_request, r_node);
2428c2ecf20Sopenharmony_ci
2438c2ecf20Sopenharmony_ci		dump_request(s, req);
2448c2ecf20Sopenharmony_ci	}
2458c2ecf20Sopenharmony_ci
2468c2ecf20Sopenharmony_ci	mutex_unlock(&osd->lock);
2478c2ecf20Sopenharmony_ci}
2488c2ecf20Sopenharmony_ci
2498c2ecf20Sopenharmony_cistatic void dump_linger_request(struct seq_file *s,
2508c2ecf20Sopenharmony_ci				struct ceph_osd_linger_request *lreq)
2518c2ecf20Sopenharmony_ci{
2528c2ecf20Sopenharmony_ci	seq_printf(s, "%llu\t", lreq->linger_id);
2538c2ecf20Sopenharmony_ci	dump_target(s, &lreq->t);
2548c2ecf20Sopenharmony_ci
2558c2ecf20Sopenharmony_ci	seq_printf(s, "\t%u\t%s%s/%d\n", lreq->register_gen,
2568c2ecf20Sopenharmony_ci		   lreq->is_watch ? "W" : "N", lreq->committed ? "C" : "",
2578c2ecf20Sopenharmony_ci		   lreq->last_error);
2588c2ecf20Sopenharmony_ci}
2598c2ecf20Sopenharmony_ci
2608c2ecf20Sopenharmony_cistatic void dump_linger_requests(struct seq_file *s, struct ceph_osd *osd)
2618c2ecf20Sopenharmony_ci{
2628c2ecf20Sopenharmony_ci	struct rb_node *n;
2638c2ecf20Sopenharmony_ci
2648c2ecf20Sopenharmony_ci	mutex_lock(&osd->lock);
2658c2ecf20Sopenharmony_ci	for (n = rb_first(&osd->o_linger_requests); n; n = rb_next(n)) {
2668c2ecf20Sopenharmony_ci		struct ceph_osd_linger_request *lreq =
2678c2ecf20Sopenharmony_ci		    rb_entry(n, struct ceph_osd_linger_request, node);
2688c2ecf20Sopenharmony_ci
2698c2ecf20Sopenharmony_ci		dump_linger_request(s, lreq);
2708c2ecf20Sopenharmony_ci	}
2718c2ecf20Sopenharmony_ci
2728c2ecf20Sopenharmony_ci	mutex_unlock(&osd->lock);
2738c2ecf20Sopenharmony_ci}
2748c2ecf20Sopenharmony_ci
2758c2ecf20Sopenharmony_cistatic void dump_snapid(struct seq_file *s, u64 snapid)
2768c2ecf20Sopenharmony_ci{
2778c2ecf20Sopenharmony_ci	if (snapid == CEPH_NOSNAP)
2788c2ecf20Sopenharmony_ci		seq_puts(s, "head");
2798c2ecf20Sopenharmony_ci	else if (snapid == CEPH_SNAPDIR)
2808c2ecf20Sopenharmony_ci		seq_puts(s, "snapdir");
2818c2ecf20Sopenharmony_ci	else
2828c2ecf20Sopenharmony_ci		seq_printf(s, "%llx", snapid);
2838c2ecf20Sopenharmony_ci}
2848c2ecf20Sopenharmony_ci
2858c2ecf20Sopenharmony_cistatic void dump_name_escaped(struct seq_file *s, unsigned char *name,
2868c2ecf20Sopenharmony_ci			      size_t len)
2878c2ecf20Sopenharmony_ci{
2888c2ecf20Sopenharmony_ci	size_t i;
2898c2ecf20Sopenharmony_ci
2908c2ecf20Sopenharmony_ci	for (i = 0; i < len; i++) {
2918c2ecf20Sopenharmony_ci		if (name[i] == '%' || name[i] == ':' || name[i] == '/' ||
2928c2ecf20Sopenharmony_ci		    name[i] < 32 || name[i] >= 127) {
2938c2ecf20Sopenharmony_ci			seq_printf(s, "%%%02x", name[i]);
2948c2ecf20Sopenharmony_ci		} else {
2958c2ecf20Sopenharmony_ci			seq_putc(s, name[i]);
2968c2ecf20Sopenharmony_ci		}
2978c2ecf20Sopenharmony_ci	}
2988c2ecf20Sopenharmony_ci}
2998c2ecf20Sopenharmony_ci
3008c2ecf20Sopenharmony_cistatic void dump_hoid(struct seq_file *s, const struct ceph_hobject_id *hoid)
3018c2ecf20Sopenharmony_ci{
3028c2ecf20Sopenharmony_ci	if (hoid->snapid == 0 && hoid->hash == 0 && !hoid->is_max &&
3038c2ecf20Sopenharmony_ci	    hoid->pool == S64_MIN) {
3048c2ecf20Sopenharmony_ci		seq_puts(s, "MIN");
3058c2ecf20Sopenharmony_ci		return;
3068c2ecf20Sopenharmony_ci	}
3078c2ecf20Sopenharmony_ci	if (hoid->is_max) {
3088c2ecf20Sopenharmony_ci		seq_puts(s, "MAX");
3098c2ecf20Sopenharmony_ci		return;
3108c2ecf20Sopenharmony_ci	}
3118c2ecf20Sopenharmony_ci	seq_printf(s, "%lld:%08x:", hoid->pool, hoid->hash_reverse_bits);
3128c2ecf20Sopenharmony_ci	dump_name_escaped(s, hoid->nspace, hoid->nspace_len);
3138c2ecf20Sopenharmony_ci	seq_putc(s, ':');
3148c2ecf20Sopenharmony_ci	dump_name_escaped(s, hoid->key, hoid->key_len);
3158c2ecf20Sopenharmony_ci	seq_putc(s, ':');
3168c2ecf20Sopenharmony_ci	dump_name_escaped(s, hoid->oid, hoid->oid_len);
3178c2ecf20Sopenharmony_ci	seq_putc(s, ':');
3188c2ecf20Sopenharmony_ci	dump_snapid(s, hoid->snapid);
3198c2ecf20Sopenharmony_ci}
3208c2ecf20Sopenharmony_ci
3218c2ecf20Sopenharmony_cistatic void dump_backoffs(struct seq_file *s, struct ceph_osd *osd)
3228c2ecf20Sopenharmony_ci{
3238c2ecf20Sopenharmony_ci	struct rb_node *n;
3248c2ecf20Sopenharmony_ci
3258c2ecf20Sopenharmony_ci	mutex_lock(&osd->lock);
3268c2ecf20Sopenharmony_ci	for (n = rb_first(&osd->o_backoffs_by_id); n; n = rb_next(n)) {
3278c2ecf20Sopenharmony_ci		struct ceph_osd_backoff *backoff =
3288c2ecf20Sopenharmony_ci		    rb_entry(n, struct ceph_osd_backoff, id_node);
3298c2ecf20Sopenharmony_ci
3308c2ecf20Sopenharmony_ci		seq_printf(s, "osd%d\t", osd->o_osd);
3318c2ecf20Sopenharmony_ci		dump_spgid(s, &backoff->spgid);
3328c2ecf20Sopenharmony_ci		seq_printf(s, "\t%llu\t", backoff->id);
3338c2ecf20Sopenharmony_ci		dump_hoid(s, backoff->begin);
3348c2ecf20Sopenharmony_ci		seq_putc(s, '\t');
3358c2ecf20Sopenharmony_ci		dump_hoid(s, backoff->end);
3368c2ecf20Sopenharmony_ci		seq_putc(s, '\n');
3378c2ecf20Sopenharmony_ci	}
3388c2ecf20Sopenharmony_ci
3398c2ecf20Sopenharmony_ci	mutex_unlock(&osd->lock);
3408c2ecf20Sopenharmony_ci}
3418c2ecf20Sopenharmony_ci
3428c2ecf20Sopenharmony_cistatic int osdc_show(struct seq_file *s, void *pp)
3438c2ecf20Sopenharmony_ci{
3448c2ecf20Sopenharmony_ci	struct ceph_client *client = s->private;
3458c2ecf20Sopenharmony_ci	struct ceph_osd_client *osdc = &client->osdc;
3468c2ecf20Sopenharmony_ci	struct rb_node *n;
3478c2ecf20Sopenharmony_ci
3488c2ecf20Sopenharmony_ci	down_read(&osdc->lock);
3498c2ecf20Sopenharmony_ci	seq_printf(s, "REQUESTS %d homeless %d\n",
3508c2ecf20Sopenharmony_ci		   atomic_read(&osdc->num_requests),
3518c2ecf20Sopenharmony_ci		   atomic_read(&osdc->num_homeless));
3528c2ecf20Sopenharmony_ci	for (n = rb_first(&osdc->osds); n; n = rb_next(n)) {
3538c2ecf20Sopenharmony_ci		struct ceph_osd *osd = rb_entry(n, struct ceph_osd, o_node);
3548c2ecf20Sopenharmony_ci
3558c2ecf20Sopenharmony_ci		dump_requests(s, osd);
3568c2ecf20Sopenharmony_ci	}
3578c2ecf20Sopenharmony_ci	dump_requests(s, &osdc->homeless_osd);
3588c2ecf20Sopenharmony_ci
3598c2ecf20Sopenharmony_ci	seq_puts(s, "LINGER REQUESTS\n");
3608c2ecf20Sopenharmony_ci	for (n = rb_first(&osdc->osds); n; n = rb_next(n)) {
3618c2ecf20Sopenharmony_ci		struct ceph_osd *osd = rb_entry(n, struct ceph_osd, o_node);
3628c2ecf20Sopenharmony_ci
3638c2ecf20Sopenharmony_ci		dump_linger_requests(s, osd);
3648c2ecf20Sopenharmony_ci	}
3658c2ecf20Sopenharmony_ci	dump_linger_requests(s, &osdc->homeless_osd);
3668c2ecf20Sopenharmony_ci
3678c2ecf20Sopenharmony_ci	seq_puts(s, "BACKOFFS\n");
3688c2ecf20Sopenharmony_ci	for (n = rb_first(&osdc->osds); n; n = rb_next(n)) {
3698c2ecf20Sopenharmony_ci		struct ceph_osd *osd = rb_entry(n, struct ceph_osd, o_node);
3708c2ecf20Sopenharmony_ci
3718c2ecf20Sopenharmony_ci		dump_backoffs(s, osd);
3728c2ecf20Sopenharmony_ci	}
3738c2ecf20Sopenharmony_ci
3748c2ecf20Sopenharmony_ci	up_read(&osdc->lock);
3758c2ecf20Sopenharmony_ci	return 0;
3768c2ecf20Sopenharmony_ci}
3778c2ecf20Sopenharmony_ci
3788c2ecf20Sopenharmony_cistatic int client_options_show(struct seq_file *s, void *p)
3798c2ecf20Sopenharmony_ci{
3808c2ecf20Sopenharmony_ci	struct ceph_client *client = s->private;
3818c2ecf20Sopenharmony_ci	int ret;
3828c2ecf20Sopenharmony_ci
3838c2ecf20Sopenharmony_ci	ret = ceph_print_client_options(s, client, true);
3848c2ecf20Sopenharmony_ci	if (ret)
3858c2ecf20Sopenharmony_ci		return ret;
3868c2ecf20Sopenharmony_ci
3878c2ecf20Sopenharmony_ci	seq_putc(s, '\n');
3888c2ecf20Sopenharmony_ci	return 0;
3898c2ecf20Sopenharmony_ci}
3908c2ecf20Sopenharmony_ci
3918c2ecf20Sopenharmony_ciDEFINE_SHOW_ATTRIBUTE(monmap);
3928c2ecf20Sopenharmony_ciDEFINE_SHOW_ATTRIBUTE(osdmap);
3938c2ecf20Sopenharmony_ciDEFINE_SHOW_ATTRIBUTE(monc);
3948c2ecf20Sopenharmony_ciDEFINE_SHOW_ATTRIBUTE(osdc);
3958c2ecf20Sopenharmony_ciDEFINE_SHOW_ATTRIBUTE(client_options);
3968c2ecf20Sopenharmony_ci
3978c2ecf20Sopenharmony_civoid __init ceph_debugfs_init(void)
3988c2ecf20Sopenharmony_ci{
3998c2ecf20Sopenharmony_ci	ceph_debugfs_dir = debugfs_create_dir("ceph", NULL);
4008c2ecf20Sopenharmony_ci}
4018c2ecf20Sopenharmony_ci
4028c2ecf20Sopenharmony_civoid ceph_debugfs_cleanup(void)
4038c2ecf20Sopenharmony_ci{
4048c2ecf20Sopenharmony_ci	debugfs_remove(ceph_debugfs_dir);
4058c2ecf20Sopenharmony_ci}
4068c2ecf20Sopenharmony_ci
4078c2ecf20Sopenharmony_civoid ceph_debugfs_client_init(struct ceph_client *client)
4088c2ecf20Sopenharmony_ci{
4098c2ecf20Sopenharmony_ci	char name[80];
4108c2ecf20Sopenharmony_ci
4118c2ecf20Sopenharmony_ci	snprintf(name, sizeof(name), "%pU.client%lld", &client->fsid,
4128c2ecf20Sopenharmony_ci		 client->monc.auth->global_id);
4138c2ecf20Sopenharmony_ci
4148c2ecf20Sopenharmony_ci	dout("ceph_debugfs_client_init %p %s\n", client, name);
4158c2ecf20Sopenharmony_ci
4168c2ecf20Sopenharmony_ci	client->debugfs_dir = debugfs_create_dir(name, ceph_debugfs_dir);
4178c2ecf20Sopenharmony_ci
4188c2ecf20Sopenharmony_ci	client->monc.debugfs_file = debugfs_create_file("monc",
4198c2ecf20Sopenharmony_ci						      0400,
4208c2ecf20Sopenharmony_ci						      client->debugfs_dir,
4218c2ecf20Sopenharmony_ci						      client,
4228c2ecf20Sopenharmony_ci						      &monc_fops);
4238c2ecf20Sopenharmony_ci
4248c2ecf20Sopenharmony_ci	client->osdc.debugfs_file = debugfs_create_file("osdc",
4258c2ecf20Sopenharmony_ci						      0400,
4268c2ecf20Sopenharmony_ci						      client->debugfs_dir,
4278c2ecf20Sopenharmony_ci						      client,
4288c2ecf20Sopenharmony_ci						      &osdc_fops);
4298c2ecf20Sopenharmony_ci
4308c2ecf20Sopenharmony_ci	client->debugfs_monmap = debugfs_create_file("monmap",
4318c2ecf20Sopenharmony_ci					0400,
4328c2ecf20Sopenharmony_ci					client->debugfs_dir,
4338c2ecf20Sopenharmony_ci					client,
4348c2ecf20Sopenharmony_ci					&monmap_fops);
4358c2ecf20Sopenharmony_ci
4368c2ecf20Sopenharmony_ci	client->debugfs_osdmap = debugfs_create_file("osdmap",
4378c2ecf20Sopenharmony_ci					0400,
4388c2ecf20Sopenharmony_ci					client->debugfs_dir,
4398c2ecf20Sopenharmony_ci					client,
4408c2ecf20Sopenharmony_ci					&osdmap_fops);
4418c2ecf20Sopenharmony_ci
4428c2ecf20Sopenharmony_ci	client->debugfs_options = debugfs_create_file("client_options",
4438c2ecf20Sopenharmony_ci					0400,
4448c2ecf20Sopenharmony_ci					client->debugfs_dir,
4458c2ecf20Sopenharmony_ci					client,
4468c2ecf20Sopenharmony_ci					&client_options_fops);
4478c2ecf20Sopenharmony_ci}
4488c2ecf20Sopenharmony_ci
4498c2ecf20Sopenharmony_civoid ceph_debugfs_client_cleanup(struct ceph_client *client)
4508c2ecf20Sopenharmony_ci{
4518c2ecf20Sopenharmony_ci	dout("ceph_debugfs_client_cleanup %p\n", client);
4528c2ecf20Sopenharmony_ci	debugfs_remove(client->debugfs_options);
4538c2ecf20Sopenharmony_ci	debugfs_remove(client->debugfs_osdmap);
4548c2ecf20Sopenharmony_ci	debugfs_remove(client->debugfs_monmap);
4558c2ecf20Sopenharmony_ci	debugfs_remove(client->osdc.debugfs_file);
4568c2ecf20Sopenharmony_ci	debugfs_remove(client->monc.debugfs_file);
4578c2ecf20Sopenharmony_ci	debugfs_remove(client->debugfs_dir);
4588c2ecf20Sopenharmony_ci}
4598c2ecf20Sopenharmony_ci
4608c2ecf20Sopenharmony_ci#else  /* CONFIG_DEBUG_FS */
4618c2ecf20Sopenharmony_ci
4628c2ecf20Sopenharmony_civoid __init ceph_debugfs_init(void)
4638c2ecf20Sopenharmony_ci{
4648c2ecf20Sopenharmony_ci}
4658c2ecf20Sopenharmony_ci
4668c2ecf20Sopenharmony_civoid ceph_debugfs_cleanup(void)
4678c2ecf20Sopenharmony_ci{
4688c2ecf20Sopenharmony_ci}
4698c2ecf20Sopenharmony_ci
4708c2ecf20Sopenharmony_civoid ceph_debugfs_client_init(struct ceph_client *client)
4718c2ecf20Sopenharmony_ci{
4728c2ecf20Sopenharmony_ci}
4738c2ecf20Sopenharmony_ci
4748c2ecf20Sopenharmony_civoid ceph_debugfs_client_cleanup(struct ceph_client *client)
4758c2ecf20Sopenharmony_ci{
4768c2ecf20Sopenharmony_ci}
4778c2ecf20Sopenharmony_ci
4788c2ecf20Sopenharmony_ci#endif  /* CONFIG_DEBUG_FS */
479