linux/fs/ceph/debugfs.c
<<
>>
Prefs
   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#include "super.h"
  17
  18#ifdef CONFIG_DEBUG_FS
  19
  20#include "mds_client.h"
  21
  22static int mdsmap_show(struct seq_file *s, void *p)
  23{
  24        int i;
  25        struct ceph_fs_client *fsc = s->private;
  26        struct ceph_mdsmap *mdsmap;
  27
  28        if (!fsc->mdsc || !fsc->mdsc->mdsmap)
  29                return 0;
  30        mdsmap = fsc->mdsc->mdsmap;
  31        seq_printf(s, "epoch %d\n", mdsmap->m_epoch);
  32        seq_printf(s, "root %d\n", mdsmap->m_root);
  33        seq_printf(s, "max_mds %d\n", mdsmap->m_max_mds);
  34        seq_printf(s, "session_timeout %d\n", mdsmap->m_session_timeout);
  35        seq_printf(s, "session_autoclose %d\n", mdsmap->m_session_autoclose);
  36        for (i = 0; i < mdsmap->possible_max_rank; i++) {
  37                struct ceph_entity_addr *addr = &mdsmap->m_info[i].addr;
  38                int state = mdsmap->m_info[i].state;
  39                seq_printf(s, "\tmds%d\t%s\t(%s)\n", i,
  40                               ceph_pr_addr(addr),
  41                               ceph_mds_state_name(state));
  42        }
  43        return 0;
  44}
  45
  46/*
  47 * mdsc debugfs
  48 */
  49static int mdsc_show(struct seq_file *s, void *p)
  50{
  51        struct ceph_fs_client *fsc = s->private;
  52        struct ceph_mds_client *mdsc = fsc->mdsc;
  53        struct ceph_mds_request *req;
  54        struct rb_node *rp;
  55        int pathlen = 0;
  56        u64 pathbase;
  57        char *path;
  58
  59        mutex_lock(&mdsc->mutex);
  60        for (rp = rb_first(&mdsc->request_tree); rp; rp = rb_next(rp)) {
  61                req = rb_entry(rp, struct ceph_mds_request, r_node);
  62
  63                if (req->r_request && req->r_session)
  64                        seq_printf(s, "%lld\tmds%d\t", req->r_tid,
  65                                   req->r_session->s_mds);
  66                else if (!req->r_request)
  67                        seq_printf(s, "%lld\t(no request)\t", req->r_tid);
  68                else
  69                        seq_printf(s, "%lld\t(no session)\t", req->r_tid);
  70
  71                seq_printf(s, "%s", ceph_mds_op_name(req->r_op));
  72
  73                if (test_bit(CEPH_MDS_R_GOT_UNSAFE, &req->r_req_flags))
  74                        seq_puts(s, "\t(unsafe)");
  75                else
  76                        seq_puts(s, "\t");
  77
  78                if (req->r_inode) {
  79                        seq_printf(s, " #%llx", ceph_ino(req->r_inode));
  80                } else if (req->r_dentry) {
  81                        path = ceph_mdsc_build_path(req->r_dentry, &pathlen,
  82                                                    &pathbase, 0);
  83                        if (IS_ERR(path))
  84                                path = NULL;
  85                        spin_lock(&req->r_dentry->d_lock);
  86                        seq_printf(s, " #%llx/%pd (%s)",
  87                                   ceph_ino(d_inode(req->r_dentry->d_parent)),
  88                                   req->r_dentry,
  89                                   path ? path : "");
  90                        spin_unlock(&req->r_dentry->d_lock);
  91                        ceph_mdsc_free_path(path, pathlen);
  92                } else if (req->r_path1) {
  93                        seq_printf(s, " #%llx/%s", req->r_ino1.ino,
  94                                   req->r_path1);
  95                } else {
  96                        seq_printf(s, " #%llx", req->r_ino1.ino);
  97                }
  98
  99                if (req->r_old_dentry) {
 100                        path = ceph_mdsc_build_path(req->r_old_dentry, &pathlen,
 101                                                    &pathbase, 0);
 102                        if (IS_ERR(path))
 103                                path = NULL;
 104                        spin_lock(&req->r_old_dentry->d_lock);
 105                        seq_printf(s, " #%llx/%pd (%s)",
 106                                   req->r_old_dentry_dir ?
 107                                   ceph_ino(req->r_old_dentry_dir) : 0,
 108                                   req->r_old_dentry,
 109                                   path ? path : "");
 110                        spin_unlock(&req->r_old_dentry->d_lock);
 111                        ceph_mdsc_free_path(path, pathlen);
 112                } else if (req->r_path2 && req->r_op != CEPH_MDS_OP_SYMLINK) {
 113                        if (req->r_ino2.ino)
 114                                seq_printf(s, " #%llx/%s", req->r_ino2.ino,
 115                                           req->r_path2);
 116                        else
 117                                seq_printf(s, " %s", req->r_path2);
 118                }
 119
 120                seq_puts(s, "\n");
 121        }
 122        mutex_unlock(&mdsc->mutex);
 123
 124        return 0;
 125}
 126
 127static int caps_show_cb(struct inode *inode, struct ceph_cap *cap, void *p)
 128{
 129        struct seq_file *s = p;
 130
 131        seq_printf(s, "0x%-17llx%-17s%-17s\n", ceph_ino(inode),
 132                   ceph_cap_string(cap->issued),
 133                   ceph_cap_string(cap->implemented));
 134        return 0;
 135}
 136
 137static int caps_show(struct seq_file *s, void *p)
 138{
 139        struct ceph_fs_client *fsc = s->private;
 140        struct ceph_mds_client *mdsc = fsc->mdsc;
 141        int total, avail, used, reserved, min, i;
 142        struct cap_wait *cw;
 143
 144        ceph_reservation_status(fsc, &total, &avail, &used, &reserved, &min);
 145        seq_printf(s, "total\t\t%d\n"
 146                   "avail\t\t%d\n"
 147                   "used\t\t%d\n"
 148                   "reserved\t%d\n"
 149                   "min\t\t%d\n\n",
 150                   total, avail, used, reserved, min);
 151        seq_printf(s, "ino                issued           implemented\n");
 152        seq_printf(s, "-----------------------------------------------\n");
 153
 154        mutex_lock(&mdsc->mutex);
 155        for (i = 0; i < mdsc->max_sessions; i++) {
 156                struct ceph_mds_session *session;
 157
 158                session = __ceph_lookup_mds_session(mdsc, i);
 159                if (!session)
 160                        continue;
 161                mutex_unlock(&mdsc->mutex);
 162                mutex_lock(&session->s_mutex);
 163                ceph_iterate_session_caps(session, caps_show_cb, s);
 164                mutex_unlock(&session->s_mutex);
 165                ceph_put_mds_session(session);
 166                mutex_lock(&mdsc->mutex);
 167        }
 168        mutex_unlock(&mdsc->mutex);
 169
 170        seq_printf(s, "\n\nWaiters:\n--------\n");
 171        seq_printf(s, "tgid         ino                need             want\n");
 172        seq_printf(s, "-----------------------------------------------------\n");
 173
 174        spin_lock(&mdsc->caps_list_lock);
 175        list_for_each_entry(cw, &mdsc->cap_wait_list, list) {
 176                seq_printf(s, "%-13d0x%-17llx%-17s%-17s\n", cw->tgid, cw->ino,
 177                                ceph_cap_string(cw->need),
 178                                ceph_cap_string(cw->want));
 179        }
 180        spin_unlock(&mdsc->caps_list_lock);
 181
 182        return 0;
 183}
 184
 185static int mds_sessions_show(struct seq_file *s, void *ptr)
 186{
 187        struct ceph_fs_client *fsc = s->private;
 188        struct ceph_mds_client *mdsc = fsc->mdsc;
 189        struct ceph_auth_client *ac = fsc->client->monc.auth;
 190        struct ceph_options *opt = fsc->client->options;
 191        int mds = -1;
 192
 193        mutex_lock(&mdsc->mutex);
 194
 195        /* The 'num' portion of an 'entity name' */
 196        seq_printf(s, "global_id %llu\n", ac->global_id);
 197
 198        /* The -o name mount argument */
 199        seq_printf(s, "name \"%s\"\n", opt->name ? opt->name : "");
 200
 201        /* The list of MDS session rank+state */
 202        for (mds = 0; mds < mdsc->max_sessions; mds++) {
 203                struct ceph_mds_session *session =
 204                        __ceph_lookup_mds_session(mdsc, mds);
 205                if (!session) {
 206                        continue;
 207                }
 208                mutex_unlock(&mdsc->mutex);
 209                seq_printf(s, "mds.%d %s\n",
 210                                session->s_mds,
 211                                ceph_session_state_name(session->s_state));
 212
 213                ceph_put_mds_session(session);
 214                mutex_lock(&mdsc->mutex);
 215        }
 216        mutex_unlock(&mdsc->mutex);
 217
 218        return 0;
 219}
 220
 221DEFINE_SHOW_ATTRIBUTE(mdsmap);
 222DEFINE_SHOW_ATTRIBUTE(mdsc);
 223DEFINE_SHOW_ATTRIBUTE(caps);
 224DEFINE_SHOW_ATTRIBUTE(mds_sessions);
 225
 226
 227/*
 228 * debugfs
 229 */
 230static int congestion_kb_set(void *data, u64 val)
 231{
 232        struct ceph_fs_client *fsc = (struct ceph_fs_client *)data;
 233
 234        fsc->mount_options->congestion_kb = (int)val;
 235        return 0;
 236}
 237
 238static int congestion_kb_get(void *data, u64 *val)
 239{
 240        struct ceph_fs_client *fsc = (struct ceph_fs_client *)data;
 241
 242        *val = (u64)fsc->mount_options->congestion_kb;
 243        return 0;
 244}
 245
 246DEFINE_SIMPLE_ATTRIBUTE(congestion_kb_fops, congestion_kb_get,
 247                        congestion_kb_set, "%llu\n");
 248
 249
 250void ceph_fs_debugfs_cleanup(struct ceph_fs_client *fsc)
 251{
 252        dout("ceph_fs_debugfs_cleanup\n");
 253        debugfs_remove(fsc->debugfs_bdi);
 254        debugfs_remove(fsc->debugfs_congestion_kb);
 255        debugfs_remove(fsc->debugfs_mdsmap);
 256        debugfs_remove(fsc->debugfs_mds_sessions);
 257        debugfs_remove(fsc->debugfs_caps);
 258        debugfs_remove(fsc->debugfs_mdsc);
 259}
 260
 261void ceph_fs_debugfs_init(struct ceph_fs_client *fsc)
 262{
 263        char name[100];
 264
 265        dout("ceph_fs_debugfs_init\n");
 266        fsc->debugfs_congestion_kb =
 267                debugfs_create_file("writeback_congestion_kb",
 268                                    0600,
 269                                    fsc->client->debugfs_dir,
 270                                    fsc,
 271                                    &congestion_kb_fops);
 272
 273        snprintf(name, sizeof(name), "../../bdi/%s",
 274                 bdi_dev_name(fsc->sb->s_bdi));
 275        fsc->debugfs_bdi =
 276                debugfs_create_symlink("bdi",
 277                                       fsc->client->debugfs_dir,
 278                                       name);
 279
 280        fsc->debugfs_mdsmap = debugfs_create_file("mdsmap",
 281                                        0400,
 282                                        fsc->client->debugfs_dir,
 283                                        fsc,
 284                                        &mdsmap_fops);
 285
 286        fsc->debugfs_mds_sessions = debugfs_create_file("mds_sessions",
 287                                        0400,
 288                                        fsc->client->debugfs_dir,
 289                                        fsc,
 290                                        &mds_sessions_fops);
 291
 292        fsc->debugfs_mdsc = debugfs_create_file("mdsc",
 293                                                0400,
 294                                                fsc->client->debugfs_dir,
 295                                                fsc,
 296                                                &mdsc_fops);
 297
 298        fsc->debugfs_caps = debugfs_create_file("caps",
 299                                                   0400,
 300                                                   fsc->client->debugfs_dir,
 301                                                   fsc,
 302                                                   &caps_fops);
 303}
 304
 305
 306#else  /* CONFIG_DEBUG_FS */
 307
 308void ceph_fs_debugfs_init(struct ceph_fs_client *fsc)
 309{
 310}
 311
 312void ceph_fs_debugfs_cleanup(struct ceph_fs_client *fsc)
 313{
 314}
 315
 316#endif  /* CONFIG_DEBUG_FS */
 317