From: Xiubo Li <xiubli@xxxxxxxxxx>
In client for each inode, it may have many opened files and may
have been pinned in more than one MDS servers. And some inodes
are idle, which have no any opened files.
This patch will show these metrics in the debugfs, likes:
item total
-----------------------------------------
opened files / total inodes 14 / 5
pinned i_caps / total inodes 7 / 5
opened inodes / total inodes 3 / 5
Will send these metrics to ceph, which will be used by the `fs top`,
later.
URL: https://tracker.ceph.com/issues/47005
Signed-off-by: Xiubo Li <xiubli@xxxxxxxxxx>
---
fs/ceph/caps.c | 27 +++++++++++++++++++++++++--
fs/ceph/debugfs.c | 11 +++++++++++
fs/ceph/file.c | 5 +++--
fs/ceph/inode.c | 7 +++++++
fs/ceph/metric.c | 14 ++++++++++++++
fs/ceph/metric.h | 7 +++++++
fs/ceph/super.h | 1 +
7 files changed, 68 insertions(+), 4 deletions(-)
diff --git a/fs/ceph/caps.c b/fs/ceph/caps.c
index ad69c411afba..6916def40b3d 100644
--- a/fs/ceph/caps.c
+++ b/fs/ceph/caps.c
@@ -4283,13 +4283,23 @@ void __ceph_touch_fmode(struct ceph_inode_info *ci,
void ceph_get_fmode(struct ceph_inode_info *ci, int fmode, int count)
{
- int i;
+ struct ceph_mds_client *mdsc = ceph_ci_to_mdsc(ci);
int bits = (fmode << 1) | 1;
+ int i;
+
+ if (count == 1)
+ atomic64_inc(&mdsc->metric.opened_files);
+
spin_lock(&ci->i_ceph_lock);
for (i = 0; i < CEPH_FILE_MODE_BITS; i++) {
if (bits & (1 << i))
ci->i_nr_by_mode[i] += count;
}
+
+ if (!ci->is_opened && fmode) {
+ ci->is_opened = true;
+ percpu_counter_inc(&mdsc->metric.opened_inodes);
+ }
spin_unlock(&ci->i_ceph_lock);
}
@@ -4300,15 +4310,28 @@ void ceph_get_fmode(struct ceph_inode_info *ci, int fmode, int count)
*/
void ceph_put_fmode(struct ceph_inode_info *ci, int fmode, int count)
{
- int i;
+ struct ceph_mds_client *mdsc = ceph_ci_to_mdsc(ci);
int bits = (fmode << 1) | 1;
+ bool empty = true;
+ int i;
+
+ if (count == 1)
+ atomic64_dec(&mdsc->metric.opened_files);
+
spin_lock(&ci->i_ceph_lock);
for (i = 0; i < CEPH_FILE_MODE_BITS; i++) {
if (bits & (1 << i)) {
BUG_ON(ci->i_nr_by_mode[i] < count);
ci->i_nr_by_mode[i] -= count;
+ if (ci->i_nr_by_mode[i] && i) /* Skip the pin ref */
+ empty = false;
}
}
+
+ if (ci->is_opened && empty && fmode) {
+ ci->is_opened = false;
+ percpu_counter_dec(&mdsc->metric.opened_inodes);
+ }
spin_unlock(&ci->i_ceph_lock);
}
diff --git a/fs/ceph/debugfs.c b/fs/ceph/debugfs.c
index 97539b497e4c..9efd3982230d 100644
--- a/fs/ceph/debugfs.c
+++ b/fs/ceph/debugfs.c
@@ -148,6 +148,17 @@ static int metric_show(struct seq_file *s, void *p)
int nr_caps = 0;
s64 total, sum, avg, min, max, sq;
+ sum = percpu_counter_sum(&m->total_inodes);
+ seq_printf(s, "item total\n");
+ seq_printf(s, "------------------------------------------\n");
+ seq_printf(s, "%-35s%lld / %lld\n", "opened files / total inodes",
+ atomic64_read(&m->opened_files), sum);
+ seq_printf(s, "%-35s%lld / %lld\n", "pinned i_caps / total inodes",
+ atomic64_read(&m->total_caps), sum);
+ seq_printf(s, "%-35s%lld / %lld\n", "opened inodes / total inodes",
+ percpu_counter_sum(&m->opened_inodes), sum);
+
+ seq_printf(s, "\n");
seq_printf(s, "item total avg_lat(us) min_lat(us) max_lat(us) stdev(us)\n");
seq_printf(s, "-----------------------------------------------------------------------------------\n");
diff --git a/fs/ceph/file.c b/fs/ceph/file.c
index c788cce7885b..6e2aed0f7f75 100644
--- a/fs/ceph/file.c
+++ b/fs/ceph/file.c
@@ -211,8 +211,9 @@ static int ceph_init_file_info(struct inode *inode, struct file *file,
BUG_ON(inode->i_fop->release != ceph_release);
if (isdir) {
- struct ceph_dir_file_info *dfi =
- kmem_cache_zalloc(ceph_dir_file_cachep, GFP_KERNEL);
+ struct ceph_dir_file_info *dfi;
+
+ dfi = kmem_cache_zalloc(ceph_dir_file_cachep, GFP_KERNEL);
if (!dfi)
return -ENOMEM;
diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c
index 39b1007903d9..1bedbe4737ec 100644
--- a/fs/ceph/inode.c
+++ b/fs/ceph/inode.c
@@ -426,6 +426,7 @@ static int ceph_fill_fragtree(struct inode *inode,
*/
struct inode *ceph_alloc_inode(struct super_block *sb)
{
+ struct ceph_mds_client *mdsc = ceph_sb_to_mdsc(sb);
struct ceph_inode_info *ci;
int i;
@@ -485,6 +486,7 @@ struct inode *ceph_alloc_inode(struct super_block *sb)
ci->i_last_rd = ci->i_last_wr = jiffies - 3600 * HZ;
for (i = 0; i < CEPH_FILE_MODE_BITS; i++)
ci->i_nr_by_mode[i] = 0;
+ ci->is_opened = false;
mutex_init(&ci->i_truncate_mutex);
ci->i_truncate_seq = 0;
@@ -525,6 +527,8 @@ struct inode *ceph_alloc_inode(struct super_block *sb)
ci->i_meta_err = 0;
+ percpu_counter_inc(&mdsc->metric.total_inodes);
+
return &ci->vfs_inode;
}
@@ -539,6 +543,7 @@ void ceph_free_inode(struct inode *inode)
void ceph_evict_inode(struct inode *inode)
{
struct ceph_inode_info *ci = ceph_inode(inode);
+ struct ceph_mds_client *mdsc = ceph_inode_to_mdsc(inode);
struct ceph_inode_frag *frag;
struct rb_node *n;
@@ -592,6 +597,8 @@ void ceph_evict_inode(struct inode *inode)
ceph_put_string(rcu_dereference_raw(ci->i_layout.pool_ns));
ceph_put_string(rcu_dereference_raw(ci->i_cached_layout.pool_ns));
+
+ percpu_counter_dec(&mdsc->metric.total_inodes);