Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ceph: add dentry lease metric support

For dentry leases, only count the hit/miss info triggered from the vfs
calls. For the cases like request reply handling and ceph_trim_dentries,
ignore them.

For now, these are only viewable using debugfs. Future patches will
allow the client to send the stats to the MDS.

The output looks like:

item total miss hit
-------------------------------------------------
d_lease 11 7 141

URL: https://tracker.ceph.com/issues/43215
Signed-off-by: Xiubo Li <xiubli@redhat.com>
Reviewed-by: Jeff Layton <jlayton@kernel.org>
Signed-off-by: Ilya Dryomov <idryomov@gmail.com>

authored by

Xiubo Li and committed by
Ilya Dryomov
f9009efa 3d77e6a8

+113 -7
+1 -1
fs/ceph/Makefile
··· 8 8 ceph-y := super.o inode.o dir.o file.o locks.o addr.o ioctl.o \ 9 9 export.o caps.o snap.o xattr.o quota.o io.o \ 10 10 mds_client.o mdsmap.o strings.o ceph_frag.o \ 11 - debugfs.o util.o 11 + debugfs.o util.o metric.o 12 12 13 13 ceph-$(CONFIG_CEPH_FSCACHE) += cache.o 14 14 ceph-$(CONFIG_CEPH_FS_POSIX_ACL) += acl.o
+29 -4
fs/ceph/debugfs.c
··· 124 124 return 0; 125 125 } 126 126 127 + static int metric_show(struct seq_file *s, void *p) 128 + { 129 + struct ceph_fs_client *fsc = s->private; 130 + struct ceph_mds_client *mdsc = fsc->mdsc; 131 + struct ceph_client_metric *m = &mdsc->metric; 132 + 133 + seq_printf(s, "item total miss hit\n"); 134 + seq_printf(s, "-------------------------------------------------\n"); 135 + 136 + seq_printf(s, "%-14s%-16lld%-16lld%lld\n", "d_lease", 137 + atomic64_read(&m->total_dentries), 138 + percpu_counter_sum(&m->d_lease_mis), 139 + percpu_counter_sum(&m->d_lease_hit)); 140 + 141 + return 0; 142 + } 143 + 127 144 static int caps_show_cb(struct inode *inode, struct ceph_cap *cap, void *p) 128 145 { 129 146 struct seq_file *s = p; ··· 239 222 DEFINE_SHOW_ATTRIBUTE(mdsc); 240 223 DEFINE_SHOW_ATTRIBUTE(caps); 241 224 DEFINE_SHOW_ATTRIBUTE(mds_sessions); 225 + DEFINE_SHOW_ATTRIBUTE(metric); 242 226 243 227 244 228 /* ··· 273 255 debugfs_remove(fsc->debugfs_mdsmap); 274 256 debugfs_remove(fsc->debugfs_mds_sessions); 275 257 debugfs_remove(fsc->debugfs_caps); 258 + debugfs_remove(fsc->debugfs_metric); 276 259 debugfs_remove(fsc->debugfs_mdsc); 277 260 } 278 261 ··· 314 295 fsc, 315 296 &mdsc_fops); 316 297 298 + fsc->debugfs_metric = debugfs_create_file("metrics", 299 + 0400, 300 + fsc->client->debugfs_dir, 301 + fsc, 302 + &metric_fops); 303 + 317 304 fsc->debugfs_caps = debugfs_create_file("caps", 318 - 0400, 319 - fsc->client->debugfs_dir, 320 - fsc, 321 - &caps_fops); 305 + 0400, 306 + fsc->client->debugfs_dir, 307 + fsc, 308 + &caps_fops); 322 309 } 323 310 324 311
+12
fs/ceph/dir.c
··· 38 38 static int ceph_d_init(struct dentry *dentry) 39 39 { 40 40 struct ceph_dentry_info *di; 41 + struct ceph_fs_client *fsc = ceph_sb_to_client(dentry->d_sb); 42 + struct ceph_mds_client *mdsc = fsc->mdsc; 41 43 42 44 di = kmem_cache_zalloc(ceph_dentry_cachep, GFP_KERNEL); 43 45 if (!di) ··· 50 48 di->time = jiffies; 51 49 dentry->d_fsdata = di; 52 50 INIT_LIST_HEAD(&di->lease_list); 51 + 52 + atomic64_inc(&mdsc->metric.total_dentries); 53 + 53 54 return 0; 54 55 } 55 56 ··· 1714 1709 if (flags & LOOKUP_RCU) 1715 1710 return -ECHILD; 1716 1711 1712 + percpu_counter_inc(&mdsc->metric.d_lease_mis); 1713 + 1717 1714 op = ceph_snap(dir) == CEPH_SNAPDIR ? 1718 1715 CEPH_MDS_OP_LOOKUPSNAP : CEPH_MDS_OP_LOOKUP; 1719 1716 req = ceph_mdsc_create_request(mdsc, op, USE_ANY_MDS); ··· 1747 1740 dout("d_revalidate %p lookup result=%d\n", 1748 1741 dentry, err); 1749 1742 } 1743 + } else { 1744 + percpu_counter_inc(&mdsc->metric.d_lease_hit); 1750 1745 } 1751 1746 1752 1747 dout("d_revalidate %p %s\n", dentry, valid ? "valid" : "invalid"); ··· 1791 1782 static void ceph_d_release(struct dentry *dentry) 1792 1783 { 1793 1784 struct ceph_dentry_info *di = ceph_dentry(dentry); 1785 + struct ceph_fs_client *fsc = ceph_sb_to_client(dentry->d_sb); 1794 1786 1795 1787 dout("d_release %p\n", dentry); 1788 + 1789 + atomic64_dec(&fsc->mdsc->metric.total_dentries); 1796 1790 1797 1791 spin_lock(&dentry->d_lock); 1798 1792 __dentry_lease_unlist(di);
+14 -2
fs/ceph/mds_client.c
··· 4323 4323 4324 4324 { 4325 4325 struct ceph_mds_client *mdsc; 4326 + int err; 4326 4327 4327 4328 mdsc = kzalloc(sizeof(struct ceph_mds_client), GFP_NOFS); 4328 4329 if (!mdsc) ··· 4332 4331 mutex_init(&mdsc->mutex); 4333 4332 mdsc->mdsmap = kzalloc(sizeof(*mdsc->mdsmap), GFP_NOFS); 4334 4333 if (!mdsc->mdsmap) { 4335 - kfree(mdsc); 4336 - return -ENOMEM; 4334 + err = -ENOMEM; 4335 + goto err_mdsc; 4337 4336 } 4338 4337 4339 4338 fsc->mdsc = mdsc; ··· 4372 4371 init_waitqueue_head(&mdsc->cap_flushing_wq); 4373 4372 INIT_WORK(&mdsc->cap_reclaim_work, ceph_cap_reclaim_work); 4374 4373 atomic_set(&mdsc->cap_reclaim_pending, 0); 4374 + err = ceph_metric_init(&mdsc->metric); 4375 + if (err) 4376 + goto err_mdsmap; 4375 4377 4376 4378 spin_lock_init(&mdsc->dentry_list_lock); 4377 4379 INIT_LIST_HEAD(&mdsc->dentry_leases); ··· 4393 4389 strscpy(mdsc->nodename, utsname()->nodename, 4394 4390 sizeof(mdsc->nodename)); 4395 4391 return 0; 4392 + 4393 + err_mdsmap: 4394 + kfree(mdsc->mdsmap); 4395 + err_mdsc: 4396 + kfree(mdsc); 4397 + return err; 4396 4398 } 4397 4399 4398 4400 /* ··· 4655 4645 ceph_msgr_flush(); 4656 4646 4657 4647 ceph_mdsc_stop(mdsc); 4648 + 4649 + ceph_metric_destroy(&mdsc->metric); 4658 4650 4659 4651 fsc->mdsc = NULL; 4660 4652 kfree(mdsc);
+4
fs/ceph/mds_client.h
··· 16 16 #include <linux/ceph/mdsmap.h> 17 17 #include <linux/ceph/auth.h> 18 18 19 + #include "metric.h" 20 + 19 21 /* The first 8 bits are reserved for old ceph releases */ 20 22 enum ceph_feature_type { 21 23 CEPHFS_FEATURE_MIMIC = 8, ··· 455 453 spinlock_t dentry_list_lock; 456 454 struct list_head dentry_leases; /* fifo list */ 457 455 struct list_head dentry_dir_leases; /* lru list */ 456 + 457 + struct ceph_client_metric metric; 458 458 459 459 spinlock_t snapid_map_lock; 460 460 struct rb_root snapid_map_tree;
+35
fs/ceph/metric.c
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + 3 + #include <linux/types.h> 4 + #include <linux/percpu_counter.h> 5 + 6 + #include "metric.h" 7 + 8 + int ceph_metric_init(struct ceph_client_metric *m) 9 + { 10 + int ret; 11 + 12 + if (!m) 13 + return -EINVAL; 14 + 15 + atomic64_set(&m->total_dentries, 0); 16 + ret = percpu_counter_init(&m->d_lease_hit, 0, GFP_KERNEL); 17 + if (ret) 18 + return ret; 19 + ret = percpu_counter_init(&m->d_lease_mis, 0, GFP_KERNEL); 20 + if (ret) { 21 + percpu_counter_destroy(&m->d_lease_hit); 22 + return ret; 23 + } 24 + 25 + return 0; 26 + } 27 + 28 + void ceph_metric_destroy(struct ceph_client_metric *m) 29 + { 30 + if (!m) 31 + return; 32 + 33 + percpu_counter_destroy(&m->d_lease_mis); 34 + percpu_counter_destroy(&m->d_lease_hit); 35 + }
+17
fs/ceph/metric.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + #ifndef _FS_CEPH_MDS_METRIC_H 3 + #define _FS_CEPH_MDS_METRIC_H 4 + 5 + #include <linux/types.h> 6 + #include <linux/percpu_counter.h> 7 + 8 + /* This is the global metrics */ 9 + struct ceph_client_metric { 10 + atomic64_t total_dentries; 11 + struct percpu_counter d_lease_hit; 12 + struct percpu_counter d_lease_mis; 13 + }; 14 + 15 + extern int ceph_metric_init(struct ceph_client_metric *m); 16 + extern void ceph_metric_destroy(struct ceph_client_metric *m); 17 + #endif /* _FS_CEPH_MDS_METRIC_H */
+1
fs/ceph/super.h
··· 128 128 struct dentry *debugfs_congestion_kb; 129 129 struct dentry *debugfs_bdi; 130 130 struct dentry *debugfs_mdsc, *debugfs_mdsmap; 131 + struct dentry *debugfs_metric; 131 132 struct dentry *debugfs_mds_sessions; 132 133 #endif 133 134