debugfs.c 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322
  1. // SPDX-License-Identifier: GPL-2.0
  2. #include <linux/ceph/ceph_debug.h>
  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. #include <linux/ceph/libceph.h>
  10. #include <linux/ceph/mon_client.h>
  11. #include <linux/ceph/auth.h>
  12. #include <linux/ceph/debugfs.h>
  13. #include "super.h"
  14. #ifdef CONFIG_DEBUG_FS
  15. #include "mds_client.h"
  16. static int mdsmap_show(struct seq_file *s, void *p)
  17. {
  18. int i;
  19. struct ceph_fs_client *fsc = s->private;
  20. struct ceph_mdsmap *mdsmap;
  21. if (!fsc->mdsc || !fsc->mdsc->mdsmap)
  22. return 0;
  23. mdsmap = fsc->mdsc->mdsmap;
  24. seq_printf(s, "epoch %d\n", mdsmap->m_epoch);
  25. seq_printf(s, "root %d\n", mdsmap->m_root);
  26. seq_printf(s, "max_mds %d\n", mdsmap->m_max_mds);
  27. seq_printf(s, "session_timeout %d\n", mdsmap->m_session_timeout);
  28. seq_printf(s, "session_autoclose %d\n", mdsmap->m_session_autoclose);
  29. for (i = 0; i < mdsmap->m_num_mds; i++) {
  30. struct ceph_entity_addr *addr = &mdsmap->m_info[i].addr;
  31. int state = mdsmap->m_info[i].state;
  32. seq_printf(s, "\tmds%d\t%s\t(%s)\n", i,
  33. ceph_pr_addr(&addr->in_addr),
  34. ceph_mds_state_name(state));
  35. }
  36. return 0;
  37. }
  38. /*
  39. * mdsc debugfs
  40. */
  41. static int mdsc_show(struct seq_file *s, void *p)
  42. {
  43. struct ceph_fs_client *fsc = s->private;
  44. struct ceph_mds_client *mdsc = fsc->mdsc;
  45. struct ceph_mds_request *req;
  46. struct rb_node *rp;
  47. int pathlen;
  48. u64 pathbase;
  49. char *path;
  50. mutex_lock(&mdsc->mutex);
  51. for (rp = rb_first(&mdsc->request_tree); rp; rp = rb_next(rp)) {
  52. req = rb_entry(rp, struct ceph_mds_request, r_node);
  53. if (req->r_request && req->r_session)
  54. seq_printf(s, "%lld\tmds%d\t", req->r_tid,
  55. req->r_session->s_mds);
  56. else if (!req->r_request)
  57. seq_printf(s, "%lld\t(no request)\t", req->r_tid);
  58. else
  59. seq_printf(s, "%lld\t(no session)\t", req->r_tid);
  60. seq_printf(s, "%s", ceph_mds_op_name(req->r_op));
  61. if (test_bit(CEPH_MDS_R_GOT_UNSAFE, &req->r_req_flags))
  62. seq_puts(s, "\t(unsafe)");
  63. else
  64. seq_puts(s, "\t");
  65. if (req->r_inode) {
  66. seq_printf(s, " #%llx", ceph_ino(req->r_inode));
  67. } else if (req->r_dentry) {
  68. path = ceph_mdsc_build_path(req->r_dentry, &pathlen,
  69. &pathbase, 0);
  70. if (IS_ERR(path))
  71. path = NULL;
  72. spin_lock(&req->r_dentry->d_lock);
  73. seq_printf(s, " #%llx/%pd (%s)",
  74. ceph_ino(d_inode(req->r_dentry->d_parent)),
  75. req->r_dentry,
  76. path ? path : "");
  77. spin_unlock(&req->r_dentry->d_lock);
  78. kfree(path);
  79. } else if (req->r_path1) {
  80. seq_printf(s, " #%llx/%s", req->r_ino1.ino,
  81. req->r_path1);
  82. } else {
  83. seq_printf(s, " #%llx", req->r_ino1.ino);
  84. }
  85. if (req->r_old_dentry) {
  86. path = ceph_mdsc_build_path(req->r_old_dentry, &pathlen,
  87. &pathbase, 0);
  88. if (IS_ERR(path))
  89. path = NULL;
  90. spin_lock(&req->r_old_dentry->d_lock);
  91. seq_printf(s, " #%llx/%pd (%s)",
  92. req->r_old_dentry_dir ?
  93. ceph_ino(req->r_old_dentry_dir) : 0,
  94. req->r_old_dentry,
  95. path ? path : "");
  96. spin_unlock(&req->r_old_dentry->d_lock);
  97. kfree(path);
  98. } else if (req->r_path2 && req->r_op != CEPH_MDS_OP_SYMLINK) {
  99. if (req->r_ino2.ino)
  100. seq_printf(s, " #%llx/%s", req->r_ino2.ino,
  101. req->r_path2);
  102. else
  103. seq_printf(s, " %s", req->r_path2);
  104. }
  105. seq_puts(s, "\n");
  106. }
  107. mutex_unlock(&mdsc->mutex);
  108. return 0;
  109. }
  110. static int caps_show(struct seq_file *s, void *p)
  111. {
  112. struct ceph_fs_client *fsc = s->private;
  113. int total, avail, used, reserved, min;
  114. ceph_reservation_status(fsc, &total, &avail, &used, &reserved, &min);
  115. seq_printf(s, "total\t\t%d\n"
  116. "avail\t\t%d\n"
  117. "used\t\t%d\n"
  118. "reserved\t%d\n"
  119. "min\t%d\n",
  120. total, avail, used, reserved, min);
  121. return 0;
  122. }
  123. static int dentry_lru_show(struct seq_file *s, void *ptr)
  124. {
  125. struct ceph_fs_client *fsc = s->private;
  126. struct ceph_mds_client *mdsc = fsc->mdsc;
  127. struct ceph_dentry_info *di;
  128. spin_lock(&mdsc->dentry_lru_lock);
  129. list_for_each_entry(di, &mdsc->dentry_lru, lru) {
  130. struct dentry *dentry = di->dentry;
  131. seq_printf(s, "%p %p\t%pd\n",
  132. di, dentry, dentry);
  133. }
  134. spin_unlock(&mdsc->dentry_lru_lock);
  135. return 0;
  136. }
  137. static int mds_sessions_show(struct seq_file *s, void *ptr)
  138. {
  139. struct ceph_fs_client *fsc = s->private;
  140. struct ceph_mds_client *mdsc = fsc->mdsc;
  141. struct ceph_auth_client *ac = fsc->client->monc.auth;
  142. struct ceph_options *opt = fsc->client->options;
  143. int mds = -1;
  144. mutex_lock(&mdsc->mutex);
  145. /* The 'num' portion of an 'entity name' */
  146. seq_printf(s, "global_id %llu\n", ac->global_id);
  147. /* The -o name mount argument */
  148. seq_printf(s, "name \"%s\"\n", opt->name ? opt->name : "");
  149. /* The list of MDS session rank+state */
  150. for (mds = 0; mds < mdsc->max_sessions; mds++) {
  151. struct ceph_mds_session *session =
  152. __ceph_lookup_mds_session(mdsc, mds);
  153. if (!session) {
  154. continue;
  155. }
  156. mutex_unlock(&mdsc->mutex);
  157. seq_printf(s, "mds.%d %s\n",
  158. session->s_mds,
  159. ceph_session_state_name(session->s_state));
  160. ceph_put_mds_session(session);
  161. mutex_lock(&mdsc->mutex);
  162. }
  163. mutex_unlock(&mdsc->mutex);
  164. return 0;
  165. }
  166. CEPH_DEFINE_SHOW_FUNC(mdsmap_show)
  167. CEPH_DEFINE_SHOW_FUNC(mdsc_show)
  168. CEPH_DEFINE_SHOW_FUNC(caps_show)
  169. CEPH_DEFINE_SHOW_FUNC(dentry_lru_show)
  170. CEPH_DEFINE_SHOW_FUNC(mds_sessions_show)
  171. /*
  172. * debugfs
  173. */
  174. static int congestion_kb_set(void *data, u64 val)
  175. {
  176. struct ceph_fs_client *fsc = (struct ceph_fs_client *)data;
  177. fsc->mount_options->congestion_kb = (int)val;
  178. return 0;
  179. }
  180. static int congestion_kb_get(void *data, u64 *val)
  181. {
  182. struct ceph_fs_client *fsc = (struct ceph_fs_client *)data;
  183. *val = (u64)fsc->mount_options->congestion_kb;
  184. return 0;
  185. }
  186. DEFINE_SIMPLE_ATTRIBUTE(congestion_kb_fops, congestion_kb_get,
  187. congestion_kb_set, "%llu\n");
  188. void ceph_fs_debugfs_cleanup(struct ceph_fs_client *fsc)
  189. {
  190. dout("ceph_fs_debugfs_cleanup\n");
  191. debugfs_remove(fsc->debugfs_bdi);
  192. debugfs_remove(fsc->debugfs_congestion_kb);
  193. debugfs_remove(fsc->debugfs_mdsmap);
  194. debugfs_remove(fsc->debugfs_mds_sessions);
  195. debugfs_remove(fsc->debugfs_caps);
  196. debugfs_remove(fsc->debugfs_mdsc);
  197. debugfs_remove(fsc->debugfs_dentry_lru);
  198. }
  199. int ceph_fs_debugfs_init(struct ceph_fs_client *fsc)
  200. {
  201. char name[100];
  202. int err = -ENOMEM;
  203. dout("ceph_fs_debugfs_init\n");
  204. BUG_ON(!fsc->client->debugfs_dir);
  205. fsc->debugfs_congestion_kb =
  206. debugfs_create_file("writeback_congestion_kb",
  207. 0600,
  208. fsc->client->debugfs_dir,
  209. fsc,
  210. &congestion_kb_fops);
  211. if (!fsc->debugfs_congestion_kb)
  212. goto out;
  213. snprintf(name, sizeof(name), "../../bdi/%s",
  214. dev_name(fsc->sb->s_bdi->dev));
  215. fsc->debugfs_bdi =
  216. debugfs_create_symlink("bdi",
  217. fsc->client->debugfs_dir,
  218. name);
  219. if (!fsc->debugfs_bdi)
  220. goto out;
  221. fsc->debugfs_mdsmap = debugfs_create_file("mdsmap",
  222. 0400,
  223. fsc->client->debugfs_dir,
  224. fsc,
  225. &mdsmap_show_fops);
  226. if (!fsc->debugfs_mdsmap)
  227. goto out;
  228. fsc->debugfs_mds_sessions = debugfs_create_file("mds_sessions",
  229. 0400,
  230. fsc->client->debugfs_dir,
  231. fsc,
  232. &mds_sessions_show_fops);
  233. if (!fsc->debugfs_mds_sessions)
  234. goto out;
  235. fsc->debugfs_mdsc = debugfs_create_file("mdsc",
  236. 0400,
  237. fsc->client->debugfs_dir,
  238. fsc,
  239. &mdsc_show_fops);
  240. if (!fsc->debugfs_mdsc)
  241. goto out;
  242. fsc->debugfs_caps = debugfs_create_file("caps",
  243. 0400,
  244. fsc->client->debugfs_dir,
  245. fsc,
  246. &caps_show_fops);
  247. if (!fsc->debugfs_caps)
  248. goto out;
  249. fsc->debugfs_dentry_lru = debugfs_create_file("dentry_lru",
  250. 0400,
  251. fsc->client->debugfs_dir,
  252. fsc,
  253. &dentry_lru_show_fops);
  254. if (!fsc->debugfs_dentry_lru)
  255. goto out;
  256. return 0;
  257. out:
  258. ceph_fs_debugfs_cleanup(fsc);
  259. return err;
  260. }
  261. #else /* CONFIG_DEBUG_FS */
  262. int ceph_fs_debugfs_init(struct ceph_fs_client *fsc)
  263. {
  264. return 0;
  265. }
  266. void ceph_fs_debugfs_cleanup(struct ceph_fs_client *fsc)
  267. {
  268. }
  269. #endif /* CONFIG_DEBUG_FS */