| .. | .. |
|---|
| 7 | 7 | #include <linux/ctype.h> |
|---|
| 8 | 8 | #include <linux/debugfs.h> |
|---|
| 9 | 9 | #include <linux/seq_file.h> |
|---|
| 10 | +#include <linux/math64.h> |
|---|
| 11 | +#include <linux/ktime.h> |
|---|
| 10 | 12 | |
|---|
| 11 | 13 | #include <linux/ceph/libceph.h> |
|---|
| 12 | 14 | #include <linux/ceph/mon_client.h> |
|---|
| .. | .. |
|---|
| 18 | 20 | #ifdef CONFIG_DEBUG_FS |
|---|
| 19 | 21 | |
|---|
| 20 | 22 | #include "mds_client.h" |
|---|
| 23 | +#include "metric.h" |
|---|
| 21 | 24 | |
|---|
| 22 | 25 | static int mdsmap_show(struct seq_file *s, void *p) |
|---|
| 23 | 26 | { |
|---|
| .. | .. |
|---|
| 33 | 36 | seq_printf(s, "max_mds %d\n", mdsmap->m_max_mds); |
|---|
| 34 | 37 | seq_printf(s, "session_timeout %d\n", mdsmap->m_session_timeout); |
|---|
| 35 | 38 | seq_printf(s, "session_autoclose %d\n", mdsmap->m_session_autoclose); |
|---|
| 36 | | - for (i = 0; i < mdsmap->m_num_mds; i++) { |
|---|
| 39 | + for (i = 0; i < mdsmap->possible_max_rank; i++) { |
|---|
| 37 | 40 | struct ceph_entity_addr *addr = &mdsmap->m_info[i].addr; |
|---|
| 38 | 41 | int state = mdsmap->m_info[i].state; |
|---|
| 39 | 42 | seq_printf(s, "\tmds%d\t%s\t(%s)\n", i, |
|---|
| 40 | | - ceph_pr_addr(&addr->in_addr), |
|---|
| 43 | + ceph_pr_addr(addr), |
|---|
| 41 | 44 | ceph_mds_state_name(state)); |
|---|
| 42 | 45 | } |
|---|
| 43 | 46 | return 0; |
|---|
| .. | .. |
|---|
| 52 | 55 | struct ceph_mds_client *mdsc = fsc->mdsc; |
|---|
| 53 | 56 | struct ceph_mds_request *req; |
|---|
| 54 | 57 | struct rb_node *rp; |
|---|
| 55 | | - int pathlen; |
|---|
| 58 | + int pathlen = 0; |
|---|
| 56 | 59 | u64 pathbase; |
|---|
| 57 | 60 | char *path; |
|---|
| 58 | 61 | |
|---|
| .. | .. |
|---|
| 88 | 91 | req->r_dentry, |
|---|
| 89 | 92 | path ? path : ""); |
|---|
| 90 | 93 | spin_unlock(&req->r_dentry->d_lock); |
|---|
| 91 | | - kfree(path); |
|---|
| 94 | + ceph_mdsc_free_path(path, pathlen); |
|---|
| 92 | 95 | } else if (req->r_path1) { |
|---|
| 93 | 96 | seq_printf(s, " #%llx/%s", req->r_ino1.ino, |
|---|
| 94 | 97 | req->r_path1); |
|---|
| .. | .. |
|---|
| 108 | 111 | req->r_old_dentry, |
|---|
| 109 | 112 | path ? path : ""); |
|---|
| 110 | 113 | spin_unlock(&req->r_old_dentry->d_lock); |
|---|
| 111 | | - kfree(path); |
|---|
| 114 | + ceph_mdsc_free_path(path, pathlen); |
|---|
| 112 | 115 | } else if (req->r_path2 && req->r_op != CEPH_MDS_OP_SYMLINK) { |
|---|
| 113 | 116 | if (req->r_ino2.ino) |
|---|
| 114 | 117 | seq_printf(s, " #%llx/%s", req->r_ino2.ino, |
|---|
| .. | .. |
|---|
| 124 | 127 | return 0; |
|---|
| 125 | 128 | } |
|---|
| 126 | 129 | |
|---|
| 130 | +#define CEPH_METRIC_SHOW(name, total, avg, min, max, sq) { \ |
|---|
| 131 | + s64 _total, _avg, _min, _max, _sq, _st; \ |
|---|
| 132 | + _avg = ktime_to_us(avg); \ |
|---|
| 133 | + _min = ktime_to_us(min == KTIME_MAX ? 0 : min); \ |
|---|
| 134 | + _max = ktime_to_us(max); \ |
|---|
| 135 | + _total = total - 1; \ |
|---|
| 136 | + _sq = _total > 0 ? DIV64_U64_ROUND_CLOSEST(sq, _total) : 0; \ |
|---|
| 137 | + _st = int_sqrt64(_sq); \ |
|---|
| 138 | + _st = ktime_to_us(_st); \ |
|---|
| 139 | + seq_printf(s, "%-14s%-12lld%-16lld%-16lld%-16lld%lld\n", \ |
|---|
| 140 | + name, total, _avg, _min, _max, _st); \ |
|---|
| 141 | +} |
|---|
| 142 | + |
|---|
| 143 | +static int metric_show(struct seq_file *s, void *p) |
|---|
| 144 | +{ |
|---|
| 145 | + struct ceph_fs_client *fsc = s->private; |
|---|
| 146 | + struct ceph_mds_client *mdsc = fsc->mdsc; |
|---|
| 147 | + struct ceph_client_metric *m = &mdsc->metric; |
|---|
| 148 | + int nr_caps = 0; |
|---|
| 149 | + s64 total, sum, avg, min, max, sq; |
|---|
| 150 | + |
|---|
| 151 | + sum = percpu_counter_sum(&m->total_inodes); |
|---|
| 152 | + seq_printf(s, "item total\n"); |
|---|
| 153 | + seq_printf(s, "------------------------------------------\n"); |
|---|
| 154 | + seq_printf(s, "%-35s%lld / %lld\n", "opened files / total inodes", |
|---|
| 155 | + atomic64_read(&m->opened_files), sum); |
|---|
| 156 | + seq_printf(s, "%-35s%lld / %lld\n", "pinned i_caps / total inodes", |
|---|
| 157 | + atomic64_read(&m->total_caps), sum); |
|---|
| 158 | + seq_printf(s, "%-35s%lld / %lld\n", "opened inodes / total inodes", |
|---|
| 159 | + percpu_counter_sum(&m->opened_inodes), sum); |
|---|
| 160 | + |
|---|
| 161 | + seq_printf(s, "\n"); |
|---|
| 162 | + seq_printf(s, "item total avg_lat(us) min_lat(us) max_lat(us) stdev(us)\n"); |
|---|
| 163 | + seq_printf(s, "-----------------------------------------------------------------------------------\n"); |
|---|
| 164 | + |
|---|
| 165 | + spin_lock(&m->read_latency_lock); |
|---|
| 166 | + total = m->total_reads; |
|---|
| 167 | + sum = m->read_latency_sum; |
|---|
| 168 | + avg = total > 0 ? DIV64_U64_ROUND_CLOSEST(sum, total) : 0; |
|---|
| 169 | + min = m->read_latency_min; |
|---|
| 170 | + max = m->read_latency_max; |
|---|
| 171 | + sq = m->read_latency_sq_sum; |
|---|
| 172 | + spin_unlock(&m->read_latency_lock); |
|---|
| 173 | + CEPH_METRIC_SHOW("read", total, avg, min, max, sq); |
|---|
| 174 | + |
|---|
| 175 | + spin_lock(&m->write_latency_lock); |
|---|
| 176 | + total = m->total_writes; |
|---|
| 177 | + sum = m->write_latency_sum; |
|---|
| 178 | + avg = total > 0 ? DIV64_U64_ROUND_CLOSEST(sum, total) : 0; |
|---|
| 179 | + min = m->write_latency_min; |
|---|
| 180 | + max = m->write_latency_max; |
|---|
| 181 | + sq = m->write_latency_sq_sum; |
|---|
| 182 | + spin_unlock(&m->write_latency_lock); |
|---|
| 183 | + CEPH_METRIC_SHOW("write", total, avg, min, max, sq); |
|---|
| 184 | + |
|---|
| 185 | + spin_lock(&m->metadata_latency_lock); |
|---|
| 186 | + total = m->total_metadatas; |
|---|
| 187 | + sum = m->metadata_latency_sum; |
|---|
| 188 | + avg = total > 0 ? DIV64_U64_ROUND_CLOSEST(sum, total) : 0; |
|---|
| 189 | + min = m->metadata_latency_min; |
|---|
| 190 | + max = m->metadata_latency_max; |
|---|
| 191 | + sq = m->metadata_latency_sq_sum; |
|---|
| 192 | + spin_unlock(&m->metadata_latency_lock); |
|---|
| 193 | + CEPH_METRIC_SHOW("metadata", total, avg, min, max, sq); |
|---|
| 194 | + |
|---|
| 195 | + seq_printf(s, "\n"); |
|---|
| 196 | + seq_printf(s, "item total miss hit\n"); |
|---|
| 197 | + seq_printf(s, "-------------------------------------------------\n"); |
|---|
| 198 | + |
|---|
| 199 | + seq_printf(s, "%-14s%-16lld%-16lld%lld\n", "d_lease", |
|---|
| 200 | + atomic64_read(&m->total_dentries), |
|---|
| 201 | + percpu_counter_sum(&m->d_lease_mis), |
|---|
| 202 | + percpu_counter_sum(&m->d_lease_hit)); |
|---|
| 203 | + |
|---|
| 204 | + nr_caps = atomic64_read(&m->total_caps); |
|---|
| 205 | + seq_printf(s, "%-14s%-16d%-16lld%lld\n", "caps", nr_caps, |
|---|
| 206 | + percpu_counter_sum(&m->i_caps_mis), |
|---|
| 207 | + percpu_counter_sum(&m->i_caps_hit)); |
|---|
| 208 | + |
|---|
| 209 | + return 0; |
|---|
| 210 | +} |
|---|
| 211 | + |
|---|
| 212 | +static int caps_show_cb(struct inode *inode, struct ceph_cap *cap, void *p) |
|---|
| 213 | +{ |
|---|
| 214 | + struct seq_file *s = p; |
|---|
| 215 | + |
|---|
| 216 | + seq_printf(s, "0x%-17llx%-3d%-17s%-17s\n", ceph_ino(inode), |
|---|
| 217 | + cap->session->s_mds, |
|---|
| 218 | + ceph_cap_string(cap->issued), |
|---|
| 219 | + ceph_cap_string(cap->implemented)); |
|---|
| 220 | + return 0; |
|---|
| 221 | +} |
|---|
| 222 | + |
|---|
| 127 | 223 | static int caps_show(struct seq_file *s, void *p) |
|---|
| 128 | 224 | { |
|---|
| 129 | 225 | struct ceph_fs_client *fsc = s->private; |
|---|
| 130 | | - int total, avail, used, reserved, min; |
|---|
| 226 | + struct ceph_mds_client *mdsc = fsc->mdsc; |
|---|
| 227 | + int total, avail, used, reserved, min, i; |
|---|
| 228 | + struct cap_wait *cw; |
|---|
| 131 | 229 | |
|---|
| 132 | 230 | ceph_reservation_status(fsc, &total, &avail, &used, &reserved, &min); |
|---|
| 133 | 231 | seq_printf(s, "total\t\t%d\n" |
|---|
| 134 | 232 | "avail\t\t%d\n" |
|---|
| 135 | 233 | "used\t\t%d\n" |
|---|
| 136 | 234 | "reserved\t%d\n" |
|---|
| 137 | | - "min\t%d\n", |
|---|
| 235 | + "min\t\t%d\n\n", |
|---|
| 138 | 236 | total, avail, used, reserved, min); |
|---|
| 139 | | - return 0; |
|---|
| 140 | | -} |
|---|
| 237 | + seq_printf(s, "ino mds issued implemented\n"); |
|---|
| 238 | + seq_printf(s, "--------------------------------------------------\n"); |
|---|
| 141 | 239 | |
|---|
| 142 | | -static int dentry_lru_show(struct seq_file *s, void *ptr) |
|---|
| 143 | | -{ |
|---|
| 144 | | - struct ceph_fs_client *fsc = s->private; |
|---|
| 145 | | - struct ceph_mds_client *mdsc = fsc->mdsc; |
|---|
| 146 | | - struct ceph_dentry_info *di; |
|---|
| 240 | + mutex_lock(&mdsc->mutex); |
|---|
| 241 | + for (i = 0; i < mdsc->max_sessions; i++) { |
|---|
| 242 | + struct ceph_mds_session *session; |
|---|
| 147 | 243 | |
|---|
| 148 | | - spin_lock(&mdsc->dentry_lru_lock); |
|---|
| 149 | | - list_for_each_entry(di, &mdsc->dentry_lru, lru) { |
|---|
| 150 | | - struct dentry *dentry = di->dentry; |
|---|
| 151 | | - seq_printf(s, "%p %p\t%pd\n", |
|---|
| 152 | | - di, dentry, dentry); |
|---|
| 244 | + session = __ceph_lookup_mds_session(mdsc, i); |
|---|
| 245 | + if (!session) |
|---|
| 246 | + continue; |
|---|
| 247 | + mutex_unlock(&mdsc->mutex); |
|---|
| 248 | + mutex_lock(&session->s_mutex); |
|---|
| 249 | + ceph_iterate_session_caps(session, caps_show_cb, s); |
|---|
| 250 | + mutex_unlock(&session->s_mutex); |
|---|
| 251 | + ceph_put_mds_session(session); |
|---|
| 252 | + mutex_lock(&mdsc->mutex); |
|---|
| 153 | 253 | } |
|---|
| 154 | | - spin_unlock(&mdsc->dentry_lru_lock); |
|---|
| 254 | + mutex_unlock(&mdsc->mutex); |
|---|
| 255 | + |
|---|
| 256 | + seq_printf(s, "\n\nWaiters:\n--------\n"); |
|---|
| 257 | + seq_printf(s, "tgid ino need want\n"); |
|---|
| 258 | + seq_printf(s, "-----------------------------------------------------\n"); |
|---|
| 259 | + |
|---|
| 260 | + spin_lock(&mdsc->caps_list_lock); |
|---|
| 261 | + list_for_each_entry(cw, &mdsc->cap_wait_list, list) { |
|---|
| 262 | + seq_printf(s, "%-13d0x%-17llx%-17s%-17s\n", cw->tgid, cw->ino, |
|---|
| 263 | + ceph_cap_string(cw->need), |
|---|
| 264 | + ceph_cap_string(cw->want)); |
|---|
| 265 | + } |
|---|
| 266 | + spin_unlock(&mdsc->caps_list_lock); |
|---|
| 155 | 267 | |
|---|
| 156 | 268 | return 0; |
|---|
| 157 | 269 | } |
|---|
| .. | .. |
|---|
| 162 | 274 | struct ceph_mds_client *mdsc = fsc->mdsc; |
|---|
| 163 | 275 | struct ceph_auth_client *ac = fsc->client->monc.auth; |
|---|
| 164 | 276 | struct ceph_options *opt = fsc->client->options; |
|---|
| 165 | | - int mds = -1; |
|---|
| 277 | + int mds; |
|---|
| 166 | 278 | |
|---|
| 167 | 279 | mutex_lock(&mdsc->mutex); |
|---|
| 168 | 280 | |
|---|
| .. | .. |
|---|
| 192 | 304 | return 0; |
|---|
| 193 | 305 | } |
|---|
| 194 | 306 | |
|---|
| 195 | | -CEPH_DEFINE_SHOW_FUNC(mdsmap_show) |
|---|
| 196 | | -CEPH_DEFINE_SHOW_FUNC(mdsc_show) |
|---|
| 197 | | -CEPH_DEFINE_SHOW_FUNC(caps_show) |
|---|
| 198 | | -CEPH_DEFINE_SHOW_FUNC(dentry_lru_show) |
|---|
| 199 | | -CEPH_DEFINE_SHOW_FUNC(mds_sessions_show) |
|---|
| 307 | +DEFINE_SHOW_ATTRIBUTE(mdsmap); |
|---|
| 308 | +DEFINE_SHOW_ATTRIBUTE(mdsc); |
|---|
| 309 | +DEFINE_SHOW_ATTRIBUTE(caps); |
|---|
| 310 | +DEFINE_SHOW_ATTRIBUTE(mds_sessions); |
|---|
| 311 | +DEFINE_SHOW_ATTRIBUTE(metric); |
|---|
| 200 | 312 | |
|---|
| 201 | 313 | |
|---|
| 202 | 314 | /* |
|---|
| .. | .. |
|---|
| 230 | 342 | debugfs_remove(fsc->debugfs_mdsmap); |
|---|
| 231 | 343 | debugfs_remove(fsc->debugfs_mds_sessions); |
|---|
| 232 | 344 | debugfs_remove(fsc->debugfs_caps); |
|---|
| 345 | + debugfs_remove(fsc->debugfs_metric); |
|---|
| 233 | 346 | debugfs_remove(fsc->debugfs_mdsc); |
|---|
| 234 | | - debugfs_remove(fsc->debugfs_dentry_lru); |
|---|
| 235 | 347 | } |
|---|
| 236 | 348 | |
|---|
| 237 | | -int ceph_fs_debugfs_init(struct ceph_fs_client *fsc) |
|---|
| 349 | +void ceph_fs_debugfs_init(struct ceph_fs_client *fsc) |
|---|
| 238 | 350 | { |
|---|
| 239 | 351 | char name[100]; |
|---|
| 240 | | - int err = -ENOMEM; |
|---|
| 241 | 352 | |
|---|
| 242 | 353 | dout("ceph_fs_debugfs_init\n"); |
|---|
| 243 | | - BUG_ON(!fsc->client->debugfs_dir); |
|---|
| 244 | 354 | fsc->debugfs_congestion_kb = |
|---|
| 245 | 355 | debugfs_create_file("writeback_congestion_kb", |
|---|
| 246 | 356 | 0600, |
|---|
| 247 | 357 | fsc->client->debugfs_dir, |
|---|
| 248 | 358 | fsc, |
|---|
| 249 | 359 | &congestion_kb_fops); |
|---|
| 250 | | - if (!fsc->debugfs_congestion_kb) |
|---|
| 251 | | - goto out; |
|---|
| 252 | 360 | |
|---|
| 253 | 361 | snprintf(name, sizeof(name), "../../bdi/%s", |
|---|
| 254 | 362 | bdi_dev_name(fsc->sb->s_bdi)); |
|---|
| .. | .. |
|---|
| 256 | 364 | debugfs_create_symlink("bdi", |
|---|
| 257 | 365 | fsc->client->debugfs_dir, |
|---|
| 258 | 366 | name); |
|---|
| 259 | | - if (!fsc->debugfs_bdi) |
|---|
| 260 | | - goto out; |
|---|
| 261 | 367 | |
|---|
| 262 | 368 | fsc->debugfs_mdsmap = debugfs_create_file("mdsmap", |
|---|
| 263 | 369 | 0400, |
|---|
| 264 | 370 | fsc->client->debugfs_dir, |
|---|
| 265 | 371 | fsc, |
|---|
| 266 | | - &mdsmap_show_fops); |
|---|
| 267 | | - if (!fsc->debugfs_mdsmap) |
|---|
| 268 | | - goto out; |
|---|
| 372 | + &mdsmap_fops); |
|---|
| 269 | 373 | |
|---|
| 270 | 374 | fsc->debugfs_mds_sessions = debugfs_create_file("mds_sessions", |
|---|
| 271 | 375 | 0400, |
|---|
| 272 | 376 | fsc->client->debugfs_dir, |
|---|
| 273 | 377 | fsc, |
|---|
| 274 | | - &mds_sessions_show_fops); |
|---|
| 275 | | - if (!fsc->debugfs_mds_sessions) |
|---|
| 276 | | - goto out; |
|---|
| 378 | + &mds_sessions_fops); |
|---|
| 277 | 379 | |
|---|
| 278 | 380 | fsc->debugfs_mdsc = debugfs_create_file("mdsc", |
|---|
| 279 | 381 | 0400, |
|---|
| 280 | 382 | fsc->client->debugfs_dir, |
|---|
| 281 | 383 | fsc, |
|---|
| 282 | | - &mdsc_show_fops); |
|---|
| 283 | | - if (!fsc->debugfs_mdsc) |
|---|
| 284 | | - goto out; |
|---|
| 384 | + &mdsc_fops); |
|---|
| 385 | + |
|---|
| 386 | + fsc->debugfs_metric = debugfs_create_file("metrics", |
|---|
| 387 | + 0400, |
|---|
| 388 | + fsc->client->debugfs_dir, |
|---|
| 389 | + fsc, |
|---|
| 390 | + &metric_fops); |
|---|
| 285 | 391 | |
|---|
| 286 | 392 | fsc->debugfs_caps = debugfs_create_file("caps", |
|---|
| 287 | | - 0400, |
|---|
| 288 | | - fsc->client->debugfs_dir, |
|---|
| 289 | | - fsc, |
|---|
| 290 | | - &caps_show_fops); |
|---|
| 291 | | - if (!fsc->debugfs_caps) |
|---|
| 292 | | - goto out; |
|---|
| 293 | | - |
|---|
| 294 | | - fsc->debugfs_dentry_lru = debugfs_create_file("dentry_lru", |
|---|
| 295 | | - 0400, |
|---|
| 296 | | - fsc->client->debugfs_dir, |
|---|
| 297 | | - fsc, |
|---|
| 298 | | - &dentry_lru_show_fops); |
|---|
| 299 | | - if (!fsc->debugfs_dentry_lru) |
|---|
| 300 | | - goto out; |
|---|
| 301 | | - |
|---|
| 302 | | - return 0; |
|---|
| 303 | | - |
|---|
| 304 | | -out: |
|---|
| 305 | | - ceph_fs_debugfs_cleanup(fsc); |
|---|
| 306 | | - return err; |
|---|
| 393 | + 0400, |
|---|
| 394 | + fsc->client->debugfs_dir, |
|---|
| 395 | + fsc, |
|---|
| 396 | + &caps_fops); |
|---|
| 307 | 397 | } |
|---|
| 308 | 398 | |
|---|
| 309 | 399 | |
|---|
| 310 | 400 | #else /* CONFIG_DEBUG_FS */ |
|---|
| 311 | 401 | |
|---|
| 312 | | -int ceph_fs_debugfs_init(struct ceph_fs_client *fsc) |
|---|
| 402 | +void ceph_fs_debugfs_init(struct ceph_fs_client *fsc) |
|---|
| 313 | 403 | { |
|---|
| 314 | | - return 0; |
|---|
| 315 | 404 | } |
|---|
| 316 | 405 | |
|---|
| 317 | 406 | void ceph_fs_debugfs_cleanup(struct ceph_fs_client *fsc) |
|---|