| Yehuda Sadeh | 3d14c5d | 2010-04-06 15:14:15 -0700 | [diff] [blame] | 1 | #include <linux/ceph/ceph_debug.h> | 
 | 2 |  | 
 | 3 | #include <linux/device.h> | 
 | 4 | #include <linux/slab.h> | 
 | 5 | #include <linux/module.h> | 
 | 6 | #include <linux/ctype.h> | 
 | 7 | #include <linux/debugfs.h> | 
 | 8 | #include <linux/seq_file.h> | 
 | 9 |  | 
 | 10 | #include <linux/ceph/libceph.h> | 
 | 11 | #include <linux/ceph/mon_client.h> | 
 | 12 | #include <linux/ceph/auth.h> | 
 | 13 | #include <linux/ceph/debugfs.h> | 
 | 14 |  | 
 | 15 | #ifdef CONFIG_DEBUG_FS | 
 | 16 |  | 
 | 17 | /* | 
 | 18 |  * Implement /sys/kernel/debug/ceph fun | 
 | 19 |  * | 
 | 20 |  * /sys/kernel/debug/ceph/client*  - an instance of the ceph client | 
 | 21 |  *      .../osdmap      - current osdmap | 
 | 22 |  *      .../monmap      - current monmap | 
 | 23 |  *      .../osdc        - active osd requests | 
 | 24 |  *      .../monc        - mon client state | 
| Ilya Dryomov | 5cf7bd3 | 2015-03-25 21:07:41 +0300 | [diff] [blame] | 25 |  *      .../client_options - libceph-only (i.e. not rbd or cephfs) options | 
| Yehuda Sadeh | 3d14c5d | 2010-04-06 15:14:15 -0700 | [diff] [blame] | 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 | 			   ceph_pr_addr(&inst->addr.in_addr)); | 
 | 49 | 	} | 
 | 50 | 	return 0; | 
 | 51 | } | 
 | 52 |  | 
 | 53 | static int osdmap_show(struct seq_file *s, void *p) | 
 | 54 | { | 
 | 55 | 	int i; | 
 | 56 | 	struct ceph_client *client = s->private; | 
| Ilya Dryomov | 35fea3a | 2014-03-13 16:36:12 +0200 | [diff] [blame] | 57 | 	struct ceph_osdmap *map = client->osdc.osdmap; | 
| Yehuda Sadeh | 3d14c5d | 2010-04-06 15:14:15 -0700 | [diff] [blame] | 58 | 	struct rb_node *n; | 
 | 59 |  | 
| Ilya Dryomov | 35fea3a | 2014-03-13 16:36:12 +0200 | [diff] [blame] | 60 | 	if (map == NULL) | 
| Yehuda Sadeh | 3d14c5d | 2010-04-06 15:14:15 -0700 | [diff] [blame] | 61 | 		return 0; | 
| Ilya Dryomov | 35fea3a | 2014-03-13 16:36:12 +0200 | [diff] [blame] | 62 |  | 
 | 63 | 	seq_printf(s, "epoch %d\n", map->epoch); | 
| Yehuda Sadeh | 3d14c5d | 2010-04-06 15:14:15 -0700 | [diff] [blame] | 64 | 	seq_printf(s, "flags%s%s\n", | 
| Ilya Dryomov | 35fea3a | 2014-03-13 16:36:12 +0200 | [diff] [blame] | 65 | 		   (map->flags & CEPH_OSDMAP_NEARFULL) ?  " NEARFULL" : "", | 
 | 66 | 		   (map->flags & CEPH_OSDMAP_FULL) ?  " FULL" : ""); | 
 | 67 |  | 
 | 68 | 	for (n = rb_first(&map->pg_pools); n; n = rb_next(n)) { | 
| Yehuda Sadeh | 3d14c5d | 2010-04-06 15:14:15 -0700 | [diff] [blame] | 69 | 		struct ceph_pg_pool_info *pool = | 
 | 70 | 			rb_entry(n, struct ceph_pg_pool_info, node); | 
| Ilya Dryomov | 35fea3a | 2014-03-13 16:36:12 +0200 | [diff] [blame] | 71 |  | 
| Ilya Dryomov | 8a53f23 | 2014-04-04 18:21:32 +0400 | [diff] [blame] | 72 | 		seq_printf(s, "pool %lld pg_num %u (%d) read_tier %lld write_tier %lld\n", | 
 | 73 | 			   pool->id, pool->pg_num, pool->pg_num_mask, | 
 | 74 | 			   pool->read_tier, pool->write_tier); | 
| Yehuda Sadeh | 3d14c5d | 2010-04-06 15:14:15 -0700 | [diff] [blame] | 75 | 	} | 
| Ilya Dryomov | 35fea3a | 2014-03-13 16:36:12 +0200 | [diff] [blame] | 76 | 	for (i = 0; i < map->max_osd; i++) { | 
 | 77 | 		struct ceph_entity_addr *addr = &map->osd_addr[i]; | 
 | 78 | 		int state = map->osd_state[i]; | 
| Yehuda Sadeh | 3d14c5d | 2010-04-06 15:14:15 -0700 | [diff] [blame] | 79 | 		char sb[64]; | 
 | 80 |  | 
| Ilya Dryomov | 2cfa34f | 2014-03-21 19:05:30 +0200 | [diff] [blame] | 81 | 		seq_printf(s, "osd%d\t%s\t%3d%%\t(%s)\t%3d%%\n", | 
| Yehuda Sadeh | 3d14c5d | 2010-04-06 15:14:15 -0700 | [diff] [blame] | 82 | 			   i, ceph_pr_addr(&addr->in_addr), | 
| Ilya Dryomov | 35fea3a | 2014-03-13 16:36:12 +0200 | [diff] [blame] | 83 | 			   ((map->osd_weight[i]*100) >> 16), | 
| Ilya Dryomov | 2cfa34f | 2014-03-21 19:05:30 +0200 | [diff] [blame] | 84 | 			   ceph_osdmap_state_str(sb, sizeof(sb), state), | 
 | 85 | 			   ((ceph_get_primary_affinity(map, i)*100) >> 16)); | 
| Yehuda Sadeh | 3d14c5d | 2010-04-06 15:14:15 -0700 | [diff] [blame] | 86 | 	} | 
| Ilya Dryomov | 1c00240 | 2014-03-13 16:36:13 +0200 | [diff] [blame] | 87 | 	for (n = rb_first(&map->pg_temp); n; n = rb_next(n)) { | 
 | 88 | 		struct ceph_pg_mapping *pg = | 
 | 89 | 			rb_entry(n, struct ceph_pg_mapping, node); | 
 | 90 |  | 
 | 91 | 		seq_printf(s, "pg_temp %llu.%x [", pg->pgid.pool, | 
 | 92 | 			   pg->pgid.seed); | 
| Ilya Dryomov | 35a935d | 2014-03-21 19:05:29 +0200 | [diff] [blame] | 93 | 		for (i = 0; i < pg->pg_temp.len; i++) | 
| Ilya Dryomov | 1c00240 | 2014-03-13 16:36:13 +0200 | [diff] [blame] | 94 | 			seq_printf(s, "%s%d", (i == 0 ? "" : ","), | 
| Ilya Dryomov | 35a935d | 2014-03-21 19:05:29 +0200 | [diff] [blame] | 95 | 				   pg->pg_temp.osds[i]); | 
| Ilya Dryomov | 1c00240 | 2014-03-13 16:36:13 +0200 | [diff] [blame] | 96 | 		seq_printf(s, "]\n"); | 
 | 97 | 	} | 
| Ilya Dryomov | 9686f94 | 2014-03-21 19:05:29 +0200 | [diff] [blame] | 98 | 	for (n = rb_first(&map->primary_temp); n; n = rb_next(n)) { | 
 | 99 | 		struct ceph_pg_mapping *pg = | 
 | 100 | 			rb_entry(n, struct ceph_pg_mapping, node); | 
 | 101 |  | 
 | 102 | 		seq_printf(s, "primary_temp %llu.%x %d\n", pg->pgid.pool, | 
 | 103 | 			   pg->pgid.seed, pg->primary_temp.osd); | 
 | 104 | 	} | 
| Ilya Dryomov | 35fea3a | 2014-03-13 16:36:12 +0200 | [diff] [blame] | 105 |  | 
| Yehuda Sadeh | 3d14c5d | 2010-04-06 15:14:15 -0700 | [diff] [blame] | 106 | 	return 0; | 
 | 107 | } | 
 | 108 |  | 
 | 109 | static int monc_show(struct seq_file *s, void *p) | 
 | 110 | { | 
 | 111 | 	struct ceph_client *client = s->private; | 
 | 112 | 	struct ceph_mon_generic_request *req; | 
 | 113 | 	struct ceph_mon_client *monc = &client->monc; | 
 | 114 | 	struct rb_node *rp; | 
 | 115 |  | 
 | 116 | 	mutex_lock(&monc->mutex); | 
 | 117 |  | 
 | 118 | 	if (monc->have_mdsmap) | 
| Eric Dumazet | 95c9617 | 2012-04-15 05:58:06 +0000 | [diff] [blame] | 119 | 		seq_printf(s, "have mdsmap %u\n", (unsigned int)monc->have_mdsmap); | 
| Yehuda Sadeh | 3d14c5d | 2010-04-06 15:14:15 -0700 | [diff] [blame] | 120 | 	if (monc->have_osdmap) | 
| Eric Dumazet | 95c9617 | 2012-04-15 05:58:06 +0000 | [diff] [blame] | 121 | 		seq_printf(s, "have osdmap %u\n", (unsigned int)monc->have_osdmap); | 
| Yehuda Sadeh | 3d14c5d | 2010-04-06 15:14:15 -0700 | [diff] [blame] | 122 | 	if (monc->want_next_osdmap) | 
 | 123 | 		seq_printf(s, "want next osdmap\n"); | 
 | 124 |  | 
 | 125 | 	for (rp = rb_first(&monc->generic_request_tree); rp; rp = rb_next(rp)) { | 
 | 126 | 		__u16 op; | 
 | 127 | 		req = rb_entry(rp, struct ceph_mon_generic_request, node); | 
 | 128 | 		op = le16_to_cpu(req->request->hdr.type); | 
 | 129 | 		if (op == CEPH_MSG_STATFS) | 
| Ilya Dryomov | 002b36b | 2014-05-12 13:05:47 +0400 | [diff] [blame] | 130 | 			seq_printf(s, "%llu statfs\n", req->tid); | 
| Ilya Dryomov | 513a824 | 2014-05-13 11:19:26 +0400 | [diff] [blame] | 131 | 		else if (op == CEPH_MSG_MON_GET_VERSION) | 
 | 132 | 			seq_printf(s, "%llu mon_get_version", req->tid); | 
| Yehuda Sadeh | 3d14c5d | 2010-04-06 15:14:15 -0700 | [diff] [blame] | 133 | 		else | 
| Ilya Dryomov | 002b36b | 2014-05-12 13:05:47 +0400 | [diff] [blame] | 134 | 			seq_printf(s, "%llu unknown\n", req->tid); | 
| Yehuda Sadeh | 3d14c5d | 2010-04-06 15:14:15 -0700 | [diff] [blame] | 135 | 	} | 
 | 136 |  | 
 | 137 | 	mutex_unlock(&monc->mutex); | 
 | 138 | 	return 0; | 
 | 139 | } | 
 | 140 |  | 
 | 141 | static int osdc_show(struct seq_file *s, void *pp) | 
 | 142 | { | 
 | 143 | 	struct ceph_client *client = s->private; | 
 | 144 | 	struct ceph_osd_client *osdc = &client->osdc; | 
 | 145 | 	struct rb_node *p; | 
 | 146 |  | 
 | 147 | 	mutex_lock(&osdc->request_mutex); | 
 | 148 | 	for (p = rb_first(&osdc->requests); p; p = rb_next(p)) { | 
 | 149 | 		struct ceph_osd_request *req; | 
| Alex Elder | 7952873 | 2013-04-03 21:32:51 -0500 | [diff] [blame] | 150 | 		unsigned int i; | 
| Sage Weil | 1b83bef | 2013-02-25 16:11:12 -0800 | [diff] [blame] | 151 | 		int opcode; | 
| Yehuda Sadeh | 3d14c5d | 2010-04-06 15:14:15 -0700 | [diff] [blame] | 152 |  | 
 | 153 | 		req = rb_entry(p, struct ceph_osd_request, r_node); | 
 | 154 |  | 
| Sage Weil | 5b191d9 | 2013-02-23 10:38:16 -0800 | [diff] [blame] | 155 | 		seq_printf(s, "%lld\tosd%d\t%lld.%x\t", req->r_tid, | 
| Yehuda Sadeh | 3d14c5d | 2010-04-06 15:14:15 -0700 | [diff] [blame] | 156 | 			   req->r_osd ? req->r_osd->o_osd : -1, | 
| Sage Weil | 5b191d9 | 2013-02-23 10:38:16 -0800 | [diff] [blame] | 157 | 			   req->r_pgid.pool, req->r_pgid.seed); | 
| Yehuda Sadeh | 3d14c5d | 2010-04-06 15:14:15 -0700 | [diff] [blame] | 158 |  | 
| Ilya Dryomov | 3c972c9 | 2014-01-27 17:40:20 +0200 | [diff] [blame] | 159 | 		seq_printf(s, "%.*s", req->r_base_oid.name_len, | 
 | 160 | 			   req->r_base_oid.name); | 
| Yehuda Sadeh | 3d14c5d | 2010-04-06 15:14:15 -0700 | [diff] [blame] | 161 |  | 
 | 162 | 		if (req->r_reassert_version.epoch) | 
 | 163 | 			seq_printf(s, "\t%u'%llu", | 
| Eric Dumazet | 95c9617 | 2012-04-15 05:58:06 +0000 | [diff] [blame] | 164 | 			   (unsigned int)le32_to_cpu(req->r_reassert_version.epoch), | 
| Yehuda Sadeh | 3d14c5d | 2010-04-06 15:14:15 -0700 | [diff] [blame] | 165 | 			   le64_to_cpu(req->r_reassert_version.version)); | 
 | 166 | 		else | 
 | 167 | 			seq_printf(s, "\t"); | 
 | 168 |  | 
| Sage Weil | 1b83bef | 2013-02-25 16:11:12 -0800 | [diff] [blame] | 169 | 		for (i = 0; i < req->r_num_ops; i++) { | 
| Alex Elder | 7952873 | 2013-04-03 21:32:51 -0500 | [diff] [blame] | 170 | 			opcode = req->r_ops[i].op; | 
| Ilya Dryomov | 25f8977 | 2014-10-06 18:40:27 +0400 | [diff] [blame] | 171 | 			seq_printf(s, "%s%s", (i == 0 ? "\t" : ","), | 
 | 172 | 				   ceph_osd_op_name(opcode)); | 
| Yehuda Sadeh | 3d14c5d | 2010-04-06 15:14:15 -0700 | [diff] [blame] | 173 | 		} | 
 | 174 |  | 
 | 175 | 		seq_printf(s, "\n"); | 
 | 176 | 	} | 
 | 177 | 	mutex_unlock(&osdc->request_mutex); | 
 | 178 | 	return 0; | 
 | 179 | } | 
 | 180 |  | 
| Ilya Dryomov | 5cf7bd3 | 2015-03-25 21:07:41 +0300 | [diff] [blame] | 181 | static int client_options_show(struct seq_file *s, void *p) | 
 | 182 | { | 
 | 183 | 	struct ceph_client *client = s->private; | 
 | 184 | 	int ret; | 
 | 185 |  | 
 | 186 | 	ret = ceph_print_client_options(s, client); | 
 | 187 | 	if (ret) | 
 | 188 | 		return ret; | 
 | 189 |  | 
 | 190 | 	seq_putc(s, '\n'); | 
 | 191 | 	return 0; | 
 | 192 | } | 
 | 193 |  | 
| Yehuda Sadeh | 3d14c5d | 2010-04-06 15:14:15 -0700 | [diff] [blame] | 194 | CEPH_DEFINE_SHOW_FUNC(monmap_show) | 
 | 195 | CEPH_DEFINE_SHOW_FUNC(osdmap_show) | 
 | 196 | CEPH_DEFINE_SHOW_FUNC(monc_show) | 
 | 197 | CEPH_DEFINE_SHOW_FUNC(osdc_show) | 
| Ilya Dryomov | 5cf7bd3 | 2015-03-25 21:07:41 +0300 | [diff] [blame] | 198 | CEPH_DEFINE_SHOW_FUNC(client_options_show) | 
| Yehuda Sadeh | 3d14c5d | 2010-04-06 15:14:15 -0700 | [diff] [blame] | 199 |  | 
 | 200 | int ceph_debugfs_init(void) | 
 | 201 | { | 
 | 202 | 	ceph_debugfs_dir = debugfs_create_dir("ceph", NULL); | 
 | 203 | 	if (!ceph_debugfs_dir) | 
 | 204 | 		return -ENOMEM; | 
 | 205 | 	return 0; | 
 | 206 | } | 
 | 207 |  | 
 | 208 | void ceph_debugfs_cleanup(void) | 
 | 209 | { | 
 | 210 | 	debugfs_remove(ceph_debugfs_dir); | 
 | 211 | } | 
 | 212 |  | 
 | 213 | int ceph_debugfs_client_init(struct ceph_client *client) | 
 | 214 | { | 
 | 215 | 	int ret = -ENOMEM; | 
 | 216 | 	char name[80]; | 
 | 217 |  | 
 | 218 | 	snprintf(name, sizeof(name), "%pU.client%lld", &client->fsid, | 
 | 219 | 		 client->monc.auth->global_id); | 
 | 220 |  | 
| Sage Weil | d1c338a | 2012-08-19 12:29:16 -0700 | [diff] [blame] | 221 | 	dout("ceph_debugfs_client_init %p %s\n", client, name); | 
 | 222 |  | 
 | 223 | 	BUG_ON(client->debugfs_dir); | 
| Yehuda Sadeh | 3d14c5d | 2010-04-06 15:14:15 -0700 | [diff] [blame] | 224 | 	client->debugfs_dir = debugfs_create_dir(name, ceph_debugfs_dir); | 
 | 225 | 	if (!client->debugfs_dir) | 
 | 226 | 		goto out; | 
 | 227 |  | 
 | 228 | 	client->monc.debugfs_file = debugfs_create_file("monc", | 
 | 229 | 						      0600, | 
 | 230 | 						      client->debugfs_dir, | 
 | 231 | 						      client, | 
 | 232 | 						      &monc_show_fops); | 
 | 233 | 	if (!client->monc.debugfs_file) | 
 | 234 | 		goto out; | 
 | 235 |  | 
 | 236 | 	client->osdc.debugfs_file = debugfs_create_file("osdc", | 
 | 237 | 						      0600, | 
 | 238 | 						      client->debugfs_dir, | 
 | 239 | 						      client, | 
 | 240 | 						      &osdc_show_fops); | 
 | 241 | 	if (!client->osdc.debugfs_file) | 
 | 242 | 		goto out; | 
 | 243 |  | 
 | 244 | 	client->debugfs_monmap = debugfs_create_file("monmap", | 
 | 245 | 					0600, | 
 | 246 | 					client->debugfs_dir, | 
 | 247 | 					client, | 
 | 248 | 					&monmap_show_fops); | 
 | 249 | 	if (!client->debugfs_monmap) | 
 | 250 | 		goto out; | 
 | 251 |  | 
 | 252 | 	client->debugfs_osdmap = debugfs_create_file("osdmap", | 
 | 253 | 					0600, | 
 | 254 | 					client->debugfs_dir, | 
 | 255 | 					client, | 
 | 256 | 					&osdmap_show_fops); | 
 | 257 | 	if (!client->debugfs_osdmap) | 
 | 258 | 		goto out; | 
 | 259 |  | 
| Ilya Dryomov | 5cf7bd3 | 2015-03-25 21:07:41 +0300 | [diff] [blame] | 260 | 	client->debugfs_options = debugfs_create_file("client_options", | 
 | 261 | 					0600, | 
 | 262 | 					client->debugfs_dir, | 
 | 263 | 					client, | 
 | 264 | 					&client_options_show_fops); | 
 | 265 | 	if (!client->debugfs_options) | 
 | 266 | 		goto out; | 
 | 267 |  | 
| Yehuda Sadeh | 3d14c5d | 2010-04-06 15:14:15 -0700 | [diff] [blame] | 268 | 	return 0; | 
 | 269 |  | 
 | 270 | out: | 
 | 271 | 	ceph_debugfs_client_cleanup(client); | 
 | 272 | 	return ret; | 
 | 273 | } | 
 | 274 |  | 
 | 275 | void ceph_debugfs_client_cleanup(struct ceph_client *client) | 
 | 276 | { | 
| Sage Weil | d1c338a | 2012-08-19 12:29:16 -0700 | [diff] [blame] | 277 | 	dout("ceph_debugfs_client_cleanup %p\n", client); | 
| Ilya Dryomov | 5cf7bd3 | 2015-03-25 21:07:41 +0300 | [diff] [blame] | 278 | 	debugfs_remove(client->debugfs_options); | 
| Yehuda Sadeh | 3d14c5d | 2010-04-06 15:14:15 -0700 | [diff] [blame] | 279 | 	debugfs_remove(client->debugfs_osdmap); | 
 | 280 | 	debugfs_remove(client->debugfs_monmap); | 
 | 281 | 	debugfs_remove(client->osdc.debugfs_file); | 
 | 282 | 	debugfs_remove(client->monc.debugfs_file); | 
 | 283 | 	debugfs_remove(client->debugfs_dir); | 
 | 284 | } | 
 | 285 |  | 
 | 286 | #else  /* CONFIG_DEBUG_FS */ | 
 | 287 |  | 
 | 288 | int ceph_debugfs_init(void) | 
 | 289 | { | 
 | 290 | 	return 0; | 
 | 291 | } | 
 | 292 |  | 
 | 293 | void ceph_debugfs_cleanup(void) | 
 | 294 | { | 
 | 295 | } | 
 | 296 |  | 
| Yehuda Sadeh | 602adf4 | 2010-08-12 16:11:25 -0700 | [diff] [blame] | 297 | int ceph_debugfs_client_init(struct ceph_client *client) | 
| Yehuda Sadeh | 3d14c5d | 2010-04-06 15:14:15 -0700 | [diff] [blame] | 298 | { | 
 | 299 | 	return 0; | 
 | 300 | } | 
 | 301 |  | 
 | 302 | void ceph_debugfs_client_cleanup(struct ceph_client *client) | 
 | 303 | { | 
 | 304 | } | 
 | 305 |  | 
 | 306 | #endif  /* CONFIG_DEBUG_FS */ | 
 | 307 |  | 
 | 308 | EXPORT_SYMBOL(ceph_debugfs_init); | 
 | 309 | EXPORT_SYMBOL(ceph_debugfs_cleanup); |