at v2.6.34-rc2 483 lines 12 kB view raw
1#include "ceph_debug.h" 2 3#include <linux/device.h> 4#include <linux/module.h> 5#include <linux/ctype.h> 6#include <linux/debugfs.h> 7#include <linux/seq_file.h> 8 9#include "super.h" 10#include "mds_client.h" 11#include "mon_client.h" 12#include "auth.h" 13 14#ifdef CONFIG_DEBUG_FS 15 16/* 17 * Implement /sys/kernel/debug/ceph fun 18 * 19 * /sys/kernel/debug/ceph/client* - an instance of the ceph client 20 * .../osdmap - current osdmap 21 * .../mdsmap - current mdsmap 22 * .../monmap - current monmap 23 * .../osdc - active osd requests 24 * .../mdsc - active mds requests 25 * .../monc - mon client state 26 * .../dentry_lru - dump contents of dentry lru 27 * .../caps - expose cap (reservation) stats 28 * .../bdi - symlink to ../../bdi/something 29 */ 30 31static struct dentry *ceph_debugfs_dir; 32 33static 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 pr_addr(&inst->addr.in_addr)); 49 } 50 return 0; 51} 52 53static int mdsmap_show(struct seq_file *s, void *p) 54{ 55 int i; 56 struct ceph_client *client = s->private; 57 58 if (client->mdsc.mdsmap == NULL) 59 return 0; 60 seq_printf(s, "epoch %d\n", client->mdsc.mdsmap->m_epoch); 61 seq_printf(s, "root %d\n", client->mdsc.mdsmap->m_root); 62 seq_printf(s, "session_timeout %d\n", 63 client->mdsc.mdsmap->m_session_timeout); 64 seq_printf(s, "session_autoclose %d\n", 65 client->mdsc.mdsmap->m_session_autoclose); 66 for (i = 0; i < client->mdsc.mdsmap->m_max_mds; i++) { 67 struct ceph_entity_addr *addr = 68 &client->mdsc.mdsmap->m_info[i].addr; 69 int state = client->mdsc.mdsmap->m_info[i].state; 70 71 seq_printf(s, "\tmds%d\t%s\t(%s)\n", i, pr_addr(&addr->in_addr), 72 ceph_mds_state_name(state)); 73 } 74 return 0; 75} 76 77static int osdmap_show(struct seq_file *s, void *p) 78{ 79 int i; 80 struct ceph_client *client = s->private; 81 struct rb_node *n; 82 83 if (client->osdc.osdmap == NULL) 84 return 0; 85 seq_printf(s, "epoch %d\n", client->osdc.osdmap->epoch); 86 seq_printf(s, "flags%s%s\n", 87 (client->osdc.osdmap->flags & CEPH_OSDMAP_NEARFULL) ? 88 " NEARFULL" : "", 89 (client->osdc.osdmap->flags & CEPH_OSDMAP_FULL) ? 90 " FULL" : ""); 91 for (n = rb_first(&client->osdc.osdmap->pg_pools); n; n = rb_next(n)) { 92 struct ceph_pg_pool_info *pool = 93 rb_entry(n, struct ceph_pg_pool_info, node); 94 seq_printf(s, "pg_pool %d pg_num %d / %d, lpg_num %d / %d\n", 95 pool->id, pool->v.pg_num, pool->pg_num_mask, 96 pool->v.lpg_num, pool->lpg_num_mask); 97 } 98 for (i = 0; i < client->osdc.osdmap->max_osd; i++) { 99 struct ceph_entity_addr *addr = 100 &client->osdc.osdmap->osd_addr[i]; 101 int state = client->osdc.osdmap->osd_state[i]; 102 char sb[64]; 103 104 seq_printf(s, "\tosd%d\t%s\t%3d%%\t(%s)\n", 105 i, pr_addr(&addr->in_addr), 106 ((client->osdc.osdmap->osd_weight[i]*100) >> 16), 107 ceph_osdmap_state_str(sb, sizeof(sb), state)); 108 } 109 return 0; 110} 111 112static int monc_show(struct seq_file *s, void *p) 113{ 114 struct ceph_client *client = s->private; 115 struct ceph_mon_statfs_request *req; 116 struct ceph_mon_client *monc = &client->monc; 117 struct rb_node *rp; 118 119 mutex_lock(&monc->mutex); 120 121 if (monc->have_mdsmap) 122 seq_printf(s, "have mdsmap %u\n", (unsigned)monc->have_mdsmap); 123 if (monc->have_osdmap) 124 seq_printf(s, "have osdmap %u\n", (unsigned)monc->have_osdmap); 125 if (monc->want_next_osdmap) 126 seq_printf(s, "want next osdmap\n"); 127 128 for (rp = rb_first(&monc->statfs_request_tree); rp; rp = rb_next(rp)) { 129 req = rb_entry(rp, struct ceph_mon_statfs_request, node); 130 seq_printf(s, "%lld statfs\n", req->tid); 131 } 132 133 mutex_unlock(&monc->mutex); 134 return 0; 135} 136 137static int mdsc_show(struct seq_file *s, void *p) 138{ 139 struct ceph_client *client = s->private; 140 struct ceph_mds_client *mdsc = &client->mdsc; 141 struct ceph_mds_request *req; 142 struct rb_node *rp; 143 int pathlen; 144 u64 pathbase; 145 char *path; 146 147 mutex_lock(&mdsc->mutex); 148 for (rp = rb_first(&mdsc->request_tree); rp; rp = rb_next(rp)) { 149 req = rb_entry(rp, struct ceph_mds_request, r_node); 150 151 if (req->r_request) 152 seq_printf(s, "%lld\tmds%d\t", req->r_tid, req->r_mds); 153 else 154 seq_printf(s, "%lld\t(no request)\t", req->r_tid); 155 156 seq_printf(s, "%s", ceph_mds_op_name(req->r_op)); 157 158 if (req->r_got_unsafe) 159 seq_printf(s, "\t(unsafe)"); 160 else 161 seq_printf(s, "\t"); 162 163 if (req->r_inode) { 164 seq_printf(s, " #%llx", ceph_ino(req->r_inode)); 165 } else if (req->r_dentry) { 166 path = ceph_mdsc_build_path(req->r_dentry, &pathlen, 167 &pathbase, 0); 168 spin_lock(&req->r_dentry->d_lock); 169 seq_printf(s, " #%llx/%.*s (%s)", 170 ceph_ino(req->r_dentry->d_parent->d_inode), 171 req->r_dentry->d_name.len, 172 req->r_dentry->d_name.name, 173 path ? path : ""); 174 spin_unlock(&req->r_dentry->d_lock); 175 kfree(path); 176 } else if (req->r_path1) { 177 seq_printf(s, " #%llx/%s", req->r_ino1.ino, 178 req->r_path1); 179 } 180 181 if (req->r_old_dentry) { 182 path = ceph_mdsc_build_path(req->r_old_dentry, &pathlen, 183 &pathbase, 0); 184 spin_lock(&req->r_old_dentry->d_lock); 185 seq_printf(s, " #%llx/%.*s (%s)", 186 ceph_ino(req->r_old_dentry->d_parent->d_inode), 187 req->r_old_dentry->d_name.len, 188 req->r_old_dentry->d_name.name, 189 path ? path : ""); 190 spin_unlock(&req->r_old_dentry->d_lock); 191 kfree(path); 192 } else if (req->r_path2) { 193 if (req->r_ino2.ino) 194 seq_printf(s, " #%llx/%s", req->r_ino2.ino, 195 req->r_path2); 196 else 197 seq_printf(s, " %s", req->r_path2); 198 } 199 200 seq_printf(s, "\n"); 201 } 202 mutex_unlock(&mdsc->mutex); 203 204 return 0; 205} 206 207static int osdc_show(struct seq_file *s, void *pp) 208{ 209 struct ceph_client *client = s->private; 210 struct ceph_osd_client *osdc = &client->osdc; 211 struct rb_node *p; 212 213 mutex_lock(&osdc->request_mutex); 214 for (p = rb_first(&osdc->requests); p; p = rb_next(p)) { 215 struct ceph_osd_request *req; 216 struct ceph_osd_request_head *head; 217 struct ceph_osd_op *op; 218 int num_ops; 219 int opcode, olen; 220 int i; 221 222 req = rb_entry(p, struct ceph_osd_request, r_node); 223 224 seq_printf(s, "%lld\tosd%d\t%d.%x\t", req->r_tid, 225 req->r_osd ? req->r_osd->o_osd : -1, 226 le32_to_cpu(req->r_pgid.pool), 227 le16_to_cpu(req->r_pgid.ps)); 228 229 head = req->r_request->front.iov_base; 230 op = (void *)(head + 1); 231 232 num_ops = le16_to_cpu(head->num_ops); 233 olen = le32_to_cpu(head->object_len); 234 seq_printf(s, "%.*s", olen, 235 (const char *)(head->ops + num_ops)); 236 237 if (req->r_reassert_version.epoch) 238 seq_printf(s, "\t%u'%llu", 239 (unsigned)le32_to_cpu(req->r_reassert_version.epoch), 240 le64_to_cpu(req->r_reassert_version.version)); 241 else 242 seq_printf(s, "\t"); 243 244 for (i = 0; i < num_ops; i++) { 245 opcode = le16_to_cpu(op->op); 246 seq_printf(s, "\t%s", ceph_osd_op_name(opcode)); 247 op++; 248 } 249 250 seq_printf(s, "\n"); 251 } 252 mutex_unlock(&osdc->request_mutex); 253 return 0; 254} 255 256static int caps_show(struct seq_file *s, void *p) 257{ 258 struct ceph_client *client = p; 259 int total, avail, used, reserved, min; 260 261 ceph_reservation_status(client, &total, &avail, &used, &reserved, &min); 262 seq_printf(s, "total\t\t%d\n" 263 "avail\t\t%d\n" 264 "used\t\t%d\n" 265 "reserved\t%d\n" 266 "min\t%d\n", 267 total, avail, used, reserved, min); 268 return 0; 269} 270 271static int dentry_lru_show(struct seq_file *s, void *ptr) 272{ 273 struct ceph_client *client = s->private; 274 struct ceph_mds_client *mdsc = &client->mdsc; 275 struct ceph_dentry_info *di; 276 277 spin_lock(&mdsc->dentry_lru_lock); 278 list_for_each_entry(di, &mdsc->dentry_lru, lru) { 279 struct dentry *dentry = di->dentry; 280 seq_printf(s, "%p %p\t%.*s\n", 281 di, dentry, dentry->d_name.len, dentry->d_name.name); 282 } 283 spin_unlock(&mdsc->dentry_lru_lock); 284 285 return 0; 286} 287 288#define DEFINE_SHOW_FUNC(name) \ 289static int name##_open(struct inode *inode, struct file *file) \ 290{ \ 291 struct seq_file *sf; \ 292 int ret; \ 293 \ 294 ret = single_open(file, name, NULL); \ 295 sf = file->private_data; \ 296 sf->private = inode->i_private; \ 297 return ret; \ 298} \ 299 \ 300static const struct file_operations name##_fops = { \ 301 .open = name##_open, \ 302 .read = seq_read, \ 303 .llseek = seq_lseek, \ 304 .release = single_release, \ 305}; 306 307DEFINE_SHOW_FUNC(monmap_show) 308DEFINE_SHOW_FUNC(mdsmap_show) 309DEFINE_SHOW_FUNC(osdmap_show) 310DEFINE_SHOW_FUNC(monc_show) 311DEFINE_SHOW_FUNC(mdsc_show) 312DEFINE_SHOW_FUNC(osdc_show) 313DEFINE_SHOW_FUNC(dentry_lru_show) 314DEFINE_SHOW_FUNC(caps_show) 315 316static int congestion_kb_set(void *data, u64 val) 317{ 318 struct ceph_client *client = (struct ceph_client *)data; 319 320 if (client) 321 client->mount_args->congestion_kb = (int)val; 322 323 return 0; 324} 325 326static int congestion_kb_get(void *data, u64 *val) 327{ 328 struct ceph_client *client = (struct ceph_client *)data; 329 330 if (client) 331 *val = (u64)client->mount_args->congestion_kb; 332 333 return 0; 334} 335 336 337DEFINE_SIMPLE_ATTRIBUTE(congestion_kb_fops, congestion_kb_get, 338 congestion_kb_set, "%llu\n"); 339 340int __init ceph_debugfs_init(void) 341{ 342 ceph_debugfs_dir = debugfs_create_dir("ceph", NULL); 343 if (!ceph_debugfs_dir) 344 return -ENOMEM; 345 return 0; 346} 347 348void ceph_debugfs_cleanup(void) 349{ 350 debugfs_remove(ceph_debugfs_dir); 351} 352 353int ceph_debugfs_client_init(struct ceph_client *client) 354{ 355 int ret = 0; 356 char name[80]; 357 358 snprintf(name, sizeof(name), FSID_FORMAT ".client%lld", 359 PR_FSID(&client->fsid), client->monc.auth->global_id); 360 361 client->debugfs_dir = debugfs_create_dir(name, ceph_debugfs_dir); 362 if (!client->debugfs_dir) 363 goto out; 364 365 client->monc.debugfs_file = debugfs_create_file("monc", 366 0600, 367 client->debugfs_dir, 368 client, 369 &monc_show_fops); 370 if (!client->monc.debugfs_file) 371 goto out; 372 373 client->mdsc.debugfs_file = debugfs_create_file("mdsc", 374 0600, 375 client->debugfs_dir, 376 client, 377 &mdsc_show_fops); 378 if (!client->mdsc.debugfs_file) 379 goto out; 380 381 client->osdc.debugfs_file = debugfs_create_file("osdc", 382 0600, 383 client->debugfs_dir, 384 client, 385 &osdc_show_fops); 386 if (!client->osdc.debugfs_file) 387 goto out; 388 389 client->debugfs_monmap = debugfs_create_file("monmap", 390 0600, 391 client->debugfs_dir, 392 client, 393 &monmap_show_fops); 394 if (!client->debugfs_monmap) 395 goto out; 396 397 client->debugfs_mdsmap = debugfs_create_file("mdsmap", 398 0600, 399 client->debugfs_dir, 400 client, 401 &mdsmap_show_fops); 402 if (!client->debugfs_mdsmap) 403 goto out; 404 405 client->debugfs_osdmap = debugfs_create_file("osdmap", 406 0600, 407 client->debugfs_dir, 408 client, 409 &osdmap_show_fops); 410 if (!client->debugfs_osdmap) 411 goto out; 412 413 client->debugfs_dentry_lru = debugfs_create_file("dentry_lru", 414 0600, 415 client->debugfs_dir, 416 client, 417 &dentry_lru_show_fops); 418 if (!client->debugfs_dentry_lru) 419 goto out; 420 421 client->debugfs_caps = debugfs_create_file("caps", 422 0400, 423 client->debugfs_dir, 424 client, 425 &caps_show_fops); 426 if (!client->debugfs_caps) 427 goto out; 428 429 client->debugfs_congestion_kb = debugfs_create_file("writeback_congestion_kb", 430 0600, 431 client->debugfs_dir, 432 client, 433 &congestion_kb_fops); 434 if (!client->debugfs_congestion_kb) 435 goto out; 436 437 sprintf(name, "../../bdi/%s", dev_name(client->sb->s_bdi->dev)); 438 client->debugfs_bdi = debugfs_create_symlink("bdi", client->debugfs_dir, 439 name); 440 441 return 0; 442 443out: 444 ceph_debugfs_client_cleanup(client); 445 return ret; 446} 447 448void ceph_debugfs_client_cleanup(struct ceph_client *client) 449{ 450 debugfs_remove(client->debugfs_bdi); 451 debugfs_remove(client->debugfs_caps); 452 debugfs_remove(client->debugfs_dentry_lru); 453 debugfs_remove(client->debugfs_osdmap); 454 debugfs_remove(client->debugfs_mdsmap); 455 debugfs_remove(client->debugfs_monmap); 456 debugfs_remove(client->osdc.debugfs_file); 457 debugfs_remove(client->mdsc.debugfs_file); 458 debugfs_remove(client->monc.debugfs_file); 459 debugfs_remove(client->debugfs_congestion_kb); 460 debugfs_remove(client->debugfs_dir); 461} 462 463#else // CONFIG_DEBUG_FS 464 465int __init ceph_debugfs_init(void) 466{ 467 return 0; 468} 469 470void ceph_debugfs_cleanup(void) 471{ 472} 473 474int ceph_debugfs_client_init(struct ceph_client *client) 475{ 476 return 0; 477} 478 479void ceph_debugfs_client_cleanup(struct ceph_client *client) 480{ 481} 482 483#endif // CONFIG_DEBUG_FS