From patchwork Wed Mar 18 14:05:51 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Xiubo Li X-Patchwork-Id: 11445313 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 955A413B1 for ; Wed, 18 Mar 2020 14:06:33 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 6133D2076C for ; Wed, 18 Mar 2020 14:06:33 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="BBe3zSRi" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727100AbgCROGc (ORCPT ); Wed, 18 Mar 2020 10:06:32 -0400 Received: from us-smtp-delivery-74.mimecast.com ([63.128.21.74]:50703 "EHLO us-smtp-delivery-74.mimecast.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726893AbgCROGb (ORCPT ); Wed, 18 Mar 2020 10:06:31 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1584540390; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:in-reply-to:in-reply-to:references:references; bh=3PZejNqXiiotPE3xmjNsx0W90xodTUrmHTom9fRGL9M=; b=BBe3zSRizo30MCIFeHflJ9Zetl8RTS9KmslRTzDlrX1PD7swChX6/9m9Y0G2X2liQipQsk 9Ns97KOfpNWx/yVw2llgSUs8DMSrCJbQykIr//ZFMWMKC3lWy+WLJv4w0ZHi+umFGKkgix wUU1VQLaESexHTNhAEmd5MmtrXpa5CY= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-110-2sucodt3P2KB26eLuTA3bg-1; Wed, 18 Mar 2020 10:06:14 -0400 X-MC-Unique: 2sucodt3P2KB26eLuTA3bg-1 Received: from smtp.corp.redhat.com (int-mx07.intmail.prod.int.phx2.redhat.com [10.5.11.22]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id E6A70800D5A; Wed, 18 Mar 2020 14:06:12 +0000 (UTC) Received: from lxbceph0.gsslab.pek2.redhat.com (vm36-245.gsslab.pek2.redhat.com [10.72.36.245]) by smtp.corp.redhat.com (Postfix) with ESMTP id 4DD5510027A3; Wed, 18 Mar 2020 14:06:10 +0000 (UTC) From: xiubli@redhat.com To: jlayton@kernel.org Cc: sage@redhat.com, idryomov@gmail.com, gfarnum@redhat.com, zyan@redhat.com, pdonnell@redhat.com, ceph-devel@vger.kernel.org, Xiubo Li Subject: [PATCH v10 1/6] ceph: add dentry lease metric support Date: Wed, 18 Mar 2020 10:05:51 -0400 Message-Id: <1584540356-5885-2-git-send-email-xiubli@redhat.com> In-Reply-To: <1584540356-5885-1-git-send-email-xiubli@redhat.com> References: <1584540356-5885-1-git-send-email-xiubli@redhat.com> X-Scanned-By: MIMEDefang 2.84 on 10.5.11.22 Sender: ceph-devel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: ceph-devel@vger.kernel.org From: Xiubo Li 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 --- fs/ceph/Makefile | 2 +- fs/ceph/debugfs.c | 33 +++++++++++++++++++++++++++++---- fs/ceph/dir.c | 12 ++++++++++++ fs/ceph/mds_client.c | 16 ++++++++++++++-- fs/ceph/mds_client.h | 4 ++++ fs/ceph/metric.c | 35 +++++++++++++++++++++++++++++++++++ fs/ceph/metric.h | 17 +++++++++++++++++ fs/ceph/super.h | 1 + 8 files changed, 113 insertions(+), 7 deletions(-) create mode 100644 fs/ceph/metric.c create mode 100644 fs/ceph/metric.h diff --git a/fs/ceph/Makefile b/fs/ceph/Makefile index 0a0823d..50c635d 100644 --- a/fs/ceph/Makefile +++ b/fs/ceph/Makefile @@ -8,7 +8,7 @@ obj-$(CONFIG_CEPH_FS) += ceph.o ceph-y := super.o inode.o dir.o file.o locks.o addr.o ioctl.o \ export.o caps.o snap.o xattr.o quota.o io.o \ mds_client.o mdsmap.o strings.o ceph_frag.o \ - debugfs.o util.o + debugfs.o util.o metric.o ceph-$(CONFIG_CEPH_FSCACHE) += cache.o ceph-$(CONFIG_CEPH_FS_POSIX_ACL) += acl.o diff --git a/fs/ceph/debugfs.c b/fs/ceph/debugfs.c index 481ac97..60cdb8f 100644 --- a/fs/ceph/debugfs.c +++ b/fs/ceph/debugfs.c @@ -124,6 +124,23 @@ static int mdsc_show(struct seq_file *s, void *p) return 0; } +static int metric_show(struct seq_file *s, void *p) +{ + struct ceph_fs_client *fsc = s->private; + struct ceph_mds_client *mdsc = fsc->mdsc; + struct ceph_client_metric *m = &mdsc->metric; + + seq_printf(s, "item total miss hit\n"); + seq_printf(s, "-------------------------------------------------\n"); + + seq_printf(s, "%-14s%-16lld%-16lld%lld\n", "d_lease", + atomic64_read(&m->total_dentries), + percpu_counter_sum(&m->d_lease_mis), + percpu_counter_sum(&m->d_lease_hit)); + + return 0; +} + static int caps_show_cb(struct inode *inode, struct ceph_cap *cap, void *p) { struct seq_file *s = p; @@ -222,6 +239,7 @@ static int mds_sessions_show(struct seq_file *s, void *ptr) DEFINE_SHOW_ATTRIBUTE(mdsc); DEFINE_SHOW_ATTRIBUTE(caps); DEFINE_SHOW_ATTRIBUTE(mds_sessions); +DEFINE_SHOW_ATTRIBUTE(metric); /* @@ -255,6 +273,7 @@ void ceph_fs_debugfs_cleanup(struct ceph_fs_client *fsc) debugfs_remove(fsc->debugfs_mdsmap); debugfs_remove(fsc->debugfs_mds_sessions); debugfs_remove(fsc->debugfs_caps); + debugfs_remove(fsc->debugfs_metric); debugfs_remove(fsc->debugfs_mdsc); } @@ -295,11 +314,17 @@ void ceph_fs_debugfs_init(struct ceph_fs_client *fsc) fsc, &mdsc_fops); + fsc->debugfs_metric = debugfs_create_file("metrics", + 0400, + fsc->client->debugfs_dir, + fsc, + &metric_fops); + fsc->debugfs_caps = debugfs_create_file("caps", - 0400, - fsc->client->debugfs_dir, - fsc, - &caps_fops); + 0400, + fsc->client->debugfs_dir, + fsc, + &caps_fops); } diff --git a/fs/ceph/dir.c b/fs/ceph/dir.c index d594c26..8097a86 100644 --- a/fs/ceph/dir.c +++ b/fs/ceph/dir.c @@ -38,6 +38,8 @@ static int ceph_d_init(struct dentry *dentry) { struct ceph_dentry_info *di; + struct ceph_fs_client *fsc = ceph_sb_to_client(dentry->d_sb); + struct ceph_mds_client *mdsc = fsc->mdsc; di = kmem_cache_zalloc(ceph_dentry_cachep, GFP_KERNEL); if (!di) @@ -48,6 +50,9 @@ static int ceph_d_init(struct dentry *dentry) di->time = jiffies; dentry->d_fsdata = di; INIT_LIST_HEAD(&di->lease_list); + + atomic64_inc(&mdsc->metric.total_dentries); + return 0; } @@ -1709,6 +1714,8 @@ static int ceph_d_revalidate(struct dentry *dentry, unsigned int flags) if (flags & LOOKUP_RCU) return -ECHILD; + percpu_counter_inc(&mdsc->metric.d_lease_mis); + op = ceph_snap(dir) == CEPH_SNAPDIR ? CEPH_MDS_OP_LOOKUPSNAP : CEPH_MDS_OP_LOOKUP; req = ceph_mdsc_create_request(mdsc, op, USE_ANY_MDS); @@ -1740,6 +1747,8 @@ static int ceph_d_revalidate(struct dentry *dentry, unsigned int flags) dout("d_revalidate %p lookup result=%d\n", dentry, err); } + } else { + percpu_counter_inc(&mdsc->metric.d_lease_hit); } dout("d_revalidate %p %s\n", dentry, valid ? "valid" : "invalid"); @@ -1782,9 +1791,12 @@ static int ceph_d_delete(const struct dentry *dentry) static void ceph_d_release(struct dentry *dentry) { struct ceph_dentry_info *di = ceph_dentry(dentry); + struct ceph_fs_client *fsc = ceph_sb_to_client(dentry->d_sb); dout("d_release %p\n", dentry); + atomic64_dec(&fsc->mdsc->metric.total_dentries); + spin_lock(&dentry->d_lock); __dentry_lease_unlist(di); dentry->d_fsdata = NULL; diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c index 486f91f..1e242d8 100644 --- a/fs/ceph/mds_client.c +++ b/fs/ceph/mds_client.c @@ -4325,6 +4325,7 @@ int ceph_mdsc_init(struct ceph_fs_client *fsc) { struct ceph_mds_client *mdsc; + int err; mdsc = kzalloc(sizeof(struct ceph_mds_client), GFP_NOFS); if (!mdsc) @@ -4333,8 +4334,8 @@ int ceph_mdsc_init(struct ceph_fs_client *fsc) mutex_init(&mdsc->mutex); mdsc->mdsmap = kzalloc(sizeof(*mdsc->mdsmap), GFP_NOFS); if (!mdsc->mdsmap) { - kfree(mdsc); - return -ENOMEM; + err = -ENOMEM; + goto err_mdsc; } fsc->mdsc = mdsc; @@ -4373,6 +4374,9 @@ int ceph_mdsc_init(struct ceph_fs_client *fsc) init_waitqueue_head(&mdsc->cap_flushing_wq); INIT_WORK(&mdsc->cap_reclaim_work, ceph_cap_reclaim_work); atomic_set(&mdsc->cap_reclaim_pending, 0); + err = ceph_metric_init(&mdsc->metric); + if (err) + goto err_mdsmap; spin_lock_init(&mdsc->dentry_list_lock); INIT_LIST_HEAD(&mdsc->dentry_leases); @@ -4391,6 +4395,12 @@ int ceph_mdsc_init(struct ceph_fs_client *fsc) strscpy(mdsc->nodename, utsname()->nodename, sizeof(mdsc->nodename)); return 0; + +err_mdsmap: + kfree(mdsc->mdsmap); +err_mdsc: + kfree(mdsc); + return err; } /* @@ -4648,6 +4658,8 @@ void ceph_mdsc_destroy(struct ceph_fs_client *fsc) ceph_mdsc_stop(mdsc); + ceph_metric_destroy(&mdsc->metric); + fsc->mdsc = NULL; kfree(mdsc); dout("mdsc_destroy %p done\n", mdsc); diff --git a/fs/ceph/mds_client.h b/fs/ceph/mds_client.h index 4e5be79b..ae1d01c 100644 --- a/fs/ceph/mds_client.h +++ b/fs/ceph/mds_client.h @@ -16,6 +16,8 @@ #include #include +#include "metric.h" + /* The first 8 bits are reserved for old ceph releases */ enum ceph_feature_type { CEPHFS_FEATURE_MIMIC = 8, @@ -454,6 +456,8 @@ struct ceph_mds_client { struct list_head dentry_leases; /* fifo list */ struct list_head dentry_dir_leases; /* lru list */ + struct ceph_client_metric metric; + spinlock_t snapid_map_lock; struct rb_root snapid_map_tree; struct list_head snapid_map_lru; diff --git a/fs/ceph/metric.c b/fs/ceph/metric.c new file mode 100644 index 0000000..873a376 --- /dev/null +++ b/fs/ceph/metric.c @@ -0,0 +1,35 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +#include +#include + +#include "metric.h" + +int ceph_metric_init(struct ceph_client_metric *m) +{ + int ret; + + if (!m) + return -EINVAL; + + atomic64_set(&m->total_dentries, 0); + ret = percpu_counter_init(&m->d_lease_hit, 0, GFP_KERNEL); + if (ret) + return ret; + ret = percpu_counter_init(&m->d_lease_mis, 0, GFP_KERNEL); + if (ret) { + percpu_counter_destroy(&m->d_lease_hit); + return ret; + } + + return 0; +} + +void ceph_metric_destroy(struct ceph_client_metric *m) +{ + if (!m) + return; + + percpu_counter_destroy(&m->d_lease_mis); + percpu_counter_destroy(&m->d_lease_hit); +} diff --git a/fs/ceph/metric.h b/fs/ceph/metric.h new file mode 100644 index 0000000..da725da --- /dev/null +++ b/fs/ceph/metric.h @@ -0,0 +1,17 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _FS_CEPH_MDS_METRIC_H +#define _FS_CEPH_MDS_METRIC_H + +#include +#include + +/* This is the global metrics */ +struct ceph_client_metric { + atomic64_t total_dentries; + struct percpu_counter d_lease_hit; + struct percpu_counter d_lease_mis; +}; + +extern int ceph_metric_init(struct ceph_client_metric *m); +extern void ceph_metric_destroy(struct ceph_client_metric *m); +#endif /* _FS_CEPH_MDS_METRIC_H */ diff --git a/fs/ceph/super.h b/fs/ceph/super.h index 60aac3a..5c73cf1 100644 --- a/fs/ceph/super.h +++ b/fs/ceph/super.h @@ -128,6 +128,7 @@ struct ceph_fs_client { struct dentry *debugfs_congestion_kb; struct dentry *debugfs_bdi; struct dentry *debugfs_mdsc, *debugfs_mdsmap; + struct dentry *debugfs_metric; struct dentry *debugfs_mds_sessions; #endif From patchwork Wed Mar 18 14:05:52 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Xiubo Li X-Patchwork-Id: 11445315 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id F0F23159A for ; Wed, 18 Mar 2020 14:06:36 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id BCAFE2076C for ; Wed, 18 Mar 2020 14:06:36 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="dzfo6NmH" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727104AbgCROGf (ORCPT ); Wed, 18 Mar 2020 10:06:35 -0400 Received: from us-smtp-delivery-74.mimecast.com ([216.205.24.74]:22833 "EHLO us-smtp-delivery-74.mimecast.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726893AbgCROGe (ORCPT ); Wed, 18 Mar 2020 10:06:34 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1584540393; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:in-reply-to:in-reply-to:references:references; bh=+N0KhDK5yE6ml49RFFudsUTUY3ab8n/TmKG0u4Os7ng=; b=dzfo6NmH/n3hJ64dSp60LAa2JHq5Mn9Ii5W5TUTy5O5qEt/YN6eX9x7nlJW47ogkAyKn5d Gz4CU24rLu4Cw9xyoqCzMFAekaNbOyDydLuCq0e9FietHmzFoXOuOa6IQDEQWexcPRNJr6 4EQHhMffa3syc4pGWNOnbuSuYb6B2As= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-485-Mw_7_pWKPnuD6XssripQ9A-1; Wed, 18 Mar 2020 10:06:17 -0400 X-MC-Unique: Mw_7_pWKPnuD6XssripQ9A-1 Received: from smtp.corp.redhat.com (int-mx07.intmail.prod.int.phx2.redhat.com [10.5.11.22]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 1202D184D26B; Wed, 18 Mar 2020 14:06:16 +0000 (UTC) Received: from lxbceph0.gsslab.pek2.redhat.com (vm36-245.gsslab.pek2.redhat.com [10.72.36.245]) by smtp.corp.redhat.com (Postfix) with ESMTP id 692C71001DC0; Wed, 18 Mar 2020 14:06:13 +0000 (UTC) From: xiubli@redhat.com To: jlayton@kernel.org Cc: sage@redhat.com, idryomov@gmail.com, gfarnum@redhat.com, zyan@redhat.com, pdonnell@redhat.com, ceph-devel@vger.kernel.org, Xiubo Li Subject: [PATCH v10 2/6] ceph: add caps perf metric for each session Date: Wed, 18 Mar 2020 10:05:52 -0400 Message-Id: <1584540356-5885-3-git-send-email-xiubli@redhat.com> In-Reply-To: <1584540356-5885-1-git-send-email-xiubli@redhat.com> References: <1584540356-5885-1-git-send-email-xiubli@redhat.com> X-Scanned-By: MIMEDefang 2.84 on 10.5.11.22 Sender: ceph-devel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: ceph-devel@vger.kernel.org From: Xiubo Li Count hits and misses in the caps cache. If the client has all of the necessary caps when a task needs references, then it's counted as a hit. Any other situation is a miss. URL: https://tracker.ceph.com/issues/43215 Signed-off-by: Xiubo Li --- fs/ceph/acl.c | 2 +- fs/ceph/caps.c | 19 +++++++++++++++++++ fs/ceph/debugfs.c | 16 ++++++++++++++++ fs/ceph/dir.c | 5 +++-- fs/ceph/inode.c | 4 ++-- fs/ceph/metric.c | 26 ++++++++++++++++++++++---- fs/ceph/metric.h | 13 +++++++++++++ fs/ceph/super.h | 8 +++++--- fs/ceph/xattr.c | 4 ++-- 9 files changed, 83 insertions(+), 14 deletions(-) diff --git a/fs/ceph/acl.c b/fs/ceph/acl.c index 26be652..e046574 100644 --- a/fs/ceph/acl.c +++ b/fs/ceph/acl.c @@ -22,7 +22,7 @@ static inline void ceph_set_cached_acl(struct inode *inode, struct ceph_inode_info *ci = ceph_inode(inode); spin_lock(&ci->i_ceph_lock); - if (__ceph_caps_issued_mask(ci, CEPH_CAP_XATTR_SHARED, 0)) + if (__ceph_caps_issued_mask_metric(ci, CEPH_CAP_XATTR_SHARED, 0)) set_cached_acl(inode, type, acl); else forget_cached_acl(inode, type); diff --git a/fs/ceph/caps.c b/fs/ceph/caps.c index 185db76..7794338 100644 --- a/fs/ceph/caps.c +++ b/fs/ceph/caps.c @@ -912,6 +912,20 @@ int __ceph_caps_issued_mask(struct ceph_inode_info *ci, int mask, int touch) return 0; } +int __ceph_caps_issued_mask_metric(struct ceph_inode_info *ci, int mask, + int touch) +{ + struct ceph_fs_client *fsc = ceph_sb_to_client(ci->vfs_inode.i_sb); + int r; + + r = __ceph_caps_issued_mask(ci, mask, touch); + if (r) + ceph_update_cap_hit(&fsc->mdsc->metric); + else + ceph_update_cap_mis(&fsc->mdsc->metric); + return r; +} + /* * Return true if mask caps are currently being revoked by an MDS. */ @@ -2685,6 +2699,11 @@ static int try_get_cap_refs(struct inode *inode, int need, int want, if (snap_rwsem_locked) up_read(&mdsc->snap_rwsem); + if (!ret) + ceph_update_cap_mis(&mdsc->metric); + else if (ret == 1) + ceph_update_cap_hit(&mdsc->metric); + dout("get_cap_refs %p ret %d got %s\n", inode, ret, ceph_cap_string(*got)); return ret; diff --git a/fs/ceph/debugfs.c b/fs/ceph/debugfs.c index 60cdb8f..66b9622 100644 --- a/fs/ceph/debugfs.c +++ b/fs/ceph/debugfs.c @@ -129,6 +129,7 @@ static int metric_show(struct seq_file *s, void *p) struct ceph_fs_client *fsc = s->private; struct ceph_mds_client *mdsc = fsc->mdsc; struct ceph_client_metric *m = &mdsc->metric; + int i, nr_caps = 0; seq_printf(s, "item total miss hit\n"); seq_printf(s, "-------------------------------------------------\n"); @@ -138,6 +139,21 @@ static int metric_show(struct seq_file *s, void *p) percpu_counter_sum(&m->d_lease_mis), percpu_counter_sum(&m->d_lease_hit)); + mutex_lock(&mdsc->mutex); + for (i = 0; i < mdsc->max_sessions; i++) { + struct ceph_mds_session *s; + + s = __ceph_lookup_mds_session(mdsc, i); + if (!s) + continue; + nr_caps += s->s_nr_caps; + ceph_put_mds_session(s); + } + mutex_unlock(&mdsc->mutex); + seq_printf(s, "%-14s%-16d%-16lld%lld\n", "caps", nr_caps, + percpu_counter_sum(&m->i_caps_mis), + percpu_counter_sum(&m->i_caps_hit)); + return 0; } diff --git a/fs/ceph/dir.c b/fs/ceph/dir.c index 8097a86..10d528a 100644 --- a/fs/ceph/dir.c +++ b/fs/ceph/dir.c @@ -349,8 +349,9 @@ static int ceph_readdir(struct file *file, struct dir_context *ctx) !ceph_test_mount_opt(fsc, NOASYNCREADDIR) && ceph_snap(inode) != CEPH_SNAPDIR && __ceph_dir_is_complete_ordered(ci) && - __ceph_caps_issued_mask(ci, CEPH_CAP_FILE_SHARED, 1)) { + __ceph_caps_issued_mask_metric(ci, CEPH_CAP_FILE_SHARED, 1)) { int shared_gen = atomic_read(&ci->i_shared_gen); + spin_unlock(&ci->i_ceph_lock); err = __dcache_readdir(file, ctx, shared_gen); if (err != -EAGAIN) @@ -767,7 +768,7 @@ static struct dentry *ceph_lookup(struct inode *dir, struct dentry *dentry, !is_root_ceph_dentry(dir, dentry) && ceph_test_mount_opt(fsc, DCACHE) && __ceph_dir_is_complete(ci) && - (__ceph_caps_issued_mask(ci, CEPH_CAP_FILE_SHARED, 1))) { + __ceph_caps_issued_mask_metric(ci, CEPH_CAP_FILE_SHARED, 1)) { __ceph_touch_fmode(ci, mdsc, CEPH_FILE_MODE_RD); spin_unlock(&ci->i_ceph_lock); dout(" dir %p complete, -ENOENT\n", dir); diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c index 7fef94f..357c937 100644 --- a/fs/ceph/inode.c +++ b/fs/ceph/inode.c @@ -2288,8 +2288,8 @@ int __ceph_do_getattr(struct inode *inode, struct page *locked_page, dout("do_getattr inode %p mask %s mode 0%o\n", inode, ceph_cap_string(mask), inode->i_mode); - if (!force && ceph_caps_issued_mask(ceph_inode(inode), mask, 1)) - return 0; + if (!force && ceph_caps_issued_mask_metric(ceph_inode(inode), mask, 1)) + return 0; mode = (mask & CEPH_STAT_RSTAT) ? USE_AUTH_MDS : USE_ANY_MDS; req = ceph_mdsc_create_request(mdsc, CEPH_MDS_OP_GETATTR, mode); diff --git a/fs/ceph/metric.c b/fs/ceph/metric.c index 873a376..2a4b739 100644 --- a/fs/ceph/metric.c +++ b/fs/ceph/metric.c @@ -16,13 +16,29 @@ int ceph_metric_init(struct ceph_client_metric *m) ret = percpu_counter_init(&m->d_lease_hit, 0, GFP_KERNEL); if (ret) return ret; + ret = percpu_counter_init(&m->d_lease_mis, 0, GFP_KERNEL); - if (ret) { - percpu_counter_destroy(&m->d_lease_hit); - return ret; - } + if (ret) + goto err_d_lease_mis; + + ret = percpu_counter_init(&m->i_caps_hit, 0, GFP_KERNEL); + if (ret) + goto err_i_caps_hit; + + ret = percpu_counter_init(&m->i_caps_mis, 0, GFP_KERNEL); + if (ret) + goto err_i_caps_mis; return 0; + +err_i_caps_mis: + percpu_counter_destroy(&m->i_caps_hit); +err_i_caps_hit: + percpu_counter_destroy(&m->d_lease_mis); +err_d_lease_mis: + percpu_counter_destroy(&m->d_lease_hit); + + return ret; } void ceph_metric_destroy(struct ceph_client_metric *m) @@ -30,6 +46,8 @@ void ceph_metric_destroy(struct ceph_client_metric *m) if (!m) return; + percpu_counter_destroy(&m->i_caps_mis); + percpu_counter_destroy(&m->i_caps_hit); percpu_counter_destroy(&m->d_lease_mis); percpu_counter_destroy(&m->d_lease_hit); } diff --git a/fs/ceph/metric.h b/fs/ceph/metric.h index da725da..098ee8a 100644 --- a/fs/ceph/metric.h +++ b/fs/ceph/metric.h @@ -10,8 +10,21 @@ struct ceph_client_metric { atomic64_t total_dentries; struct percpu_counter d_lease_hit; struct percpu_counter d_lease_mis; + + struct percpu_counter i_caps_hit; + struct percpu_counter i_caps_mis; }; extern int ceph_metric_init(struct ceph_client_metric *m); extern void ceph_metric_destroy(struct ceph_client_metric *m); + +static inline void ceph_update_cap_hit(struct ceph_client_metric *m) +{ + percpu_counter_inc(&m->i_caps_hit); +} + +static inline void ceph_update_cap_mis(struct ceph_client_metric *m) +{ + percpu_counter_inc(&m->i_caps_mis); +} #endif /* _FS_CEPH_MDS_METRIC_H */ diff --git a/fs/ceph/super.h b/fs/ceph/super.h index 5c73cf1..47cfd89 100644 --- a/fs/ceph/super.h +++ b/fs/ceph/super.h @@ -645,6 +645,8 @@ static inline bool __ceph_is_any_real_caps(struct ceph_inode_info *ci) extern int __ceph_caps_issued(struct ceph_inode_info *ci, int *implemented); extern int __ceph_caps_issued_mask(struct ceph_inode_info *ci, int mask, int t); +extern int __ceph_caps_issued_mask_metric(struct ceph_inode_info *ci, int mask, + int t); extern int __ceph_caps_issued_other(struct ceph_inode_info *ci, struct ceph_cap *cap); @@ -657,12 +659,12 @@ static inline int ceph_caps_issued(struct ceph_inode_info *ci) return issued; } -static inline int ceph_caps_issued_mask(struct ceph_inode_info *ci, int mask, - int touch) +static inline int ceph_caps_issued_mask_metric(struct ceph_inode_info *ci, + int mask, int touch) { int r; spin_lock(&ci->i_ceph_lock); - r = __ceph_caps_issued_mask(ci, mask, touch); + r = __ceph_caps_issued_mask_metric(ci, mask, touch); spin_unlock(&ci->i_ceph_lock); return r; } diff --git a/fs/ceph/xattr.c b/fs/ceph/xattr.c index 7b8a070..71ee34d 100644 --- a/fs/ceph/xattr.c +++ b/fs/ceph/xattr.c @@ -856,7 +856,7 @@ ssize_t __ceph_getxattr(struct inode *inode, const char *name, void *value, if (ci->i_xattrs.version == 0 || !((req_mask & CEPH_CAP_XATTR_SHARED) || - __ceph_caps_issued_mask(ci, CEPH_CAP_XATTR_SHARED, 1))) { + __ceph_caps_issued_mask_metric(ci, CEPH_CAP_XATTR_SHARED, 1))) { spin_unlock(&ci->i_ceph_lock); /* security module gets xattr while filling trace */ @@ -914,7 +914,7 @@ ssize_t ceph_listxattr(struct dentry *dentry, char *names, size_t size) ci->i_xattrs.version, ci->i_xattrs.index_version); if (ci->i_xattrs.version == 0 || - !__ceph_caps_issued_mask(ci, CEPH_CAP_XATTR_SHARED, 1)) { + !__ceph_caps_issued_mask_metric(ci, CEPH_CAP_XATTR_SHARED, 1)) { spin_unlock(&ci->i_ceph_lock); err = ceph_do_getattr(inode, CEPH_STAT_CAP_XATTR, true); if (err) From patchwork Wed Mar 18 14:05:53 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Xiubo Li X-Patchwork-Id: 11445317 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 7C5F5159A for ; Wed, 18 Mar 2020 14:06:41 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 52B072076C for ; Wed, 18 Mar 2020 14:06:41 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="LUXoEAl+" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727110AbgCROGi (ORCPT ); Wed, 18 Mar 2020 10:06:38 -0400 Received: from us-smtp-delivery-74.mimecast.com ([216.205.24.74]:60768 "EHLO us-smtp-delivery-74.mimecast.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726893AbgCROGh (ORCPT ); Wed, 18 Mar 2020 10:06:37 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1584540396; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:in-reply-to:in-reply-to:references:references; bh=rddQ2fzm+lG7L7rOzpszUflD3FsocJUn/+j/Lf822vA=; b=LUXoEAl+Ed+bOD3MAiLFJY4YqtFwjo+QfyAvPisR9wOubSoSC0KvUQCBlt+kcbGfAR5TjY LtDXybkd4efhTEL99Bsi4aGb62Ecah2tZwUORko9MZegj1MOk5rRFM90tl1s0Lv01Z6b+Q hLcJnmtTbTA/JnNHxrHuT19SivzbPFM= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-255-BxA9EZ86Mq-topofJklakw-1; Wed, 18 Mar 2020 10:06:20 -0400 X-MC-Unique: BxA9EZ86Mq-topofJklakw-1 Received: from smtp.corp.redhat.com (int-mx07.intmail.prod.int.phx2.redhat.com [10.5.11.22]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 33725184D26B; Wed, 18 Mar 2020 14:06:19 +0000 (UTC) Received: from lxbceph0.gsslab.pek2.redhat.com (vm36-245.gsslab.pek2.redhat.com [10.72.36.245]) by smtp.corp.redhat.com (Postfix) with ESMTP id 876501001DC0; Wed, 18 Mar 2020 14:06:16 +0000 (UTC) From: xiubli@redhat.com To: jlayton@kernel.org Cc: sage@redhat.com, idryomov@gmail.com, gfarnum@redhat.com, zyan@redhat.com, pdonnell@redhat.com, ceph-devel@vger.kernel.org, Xiubo Li Subject: [PATCH v10 3/6] ceph: add read/write latency metric support Date: Wed, 18 Mar 2020 10:05:53 -0400 Message-Id: <1584540356-5885-4-git-send-email-xiubli@redhat.com> In-Reply-To: <1584540356-5885-1-git-send-email-xiubli@redhat.com> References: <1584540356-5885-1-git-send-email-xiubli@redhat.com> X-Scanned-By: MIMEDefang 2.84 on 10.5.11.22 Sender: ceph-devel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: ceph-devel@vger.kernel.org From: Xiubo Li Calculate the latency for OSD read requests. Add a new r_end_stamp field to struct ceph_osd_request that will hold the time of that the reply was received. Use that to calculate the RTT for each call, and divide the sum of those by number of calls to get averate RTT. Keep a tally of RTT for OSD writes and number of calls to track average latency of OSD writes. URL: https://tracker.ceph.com/issues/43215 Signed-off-by: Xiubo Li --- fs/ceph/addr.c | 18 ++++++++++++++++++ fs/ceph/debugfs.c | 17 +++++++++++++++++ fs/ceph/file.c | 26 ++++++++++++++++++++++++++ fs/ceph/metric.c | 28 ++++++++++++++++++++++++++++ fs/ceph/metric.h | 30 ++++++++++++++++++++++++++++++ include/linux/ceph/osd_client.h | 1 + net/ceph/osd_client.c | 2 ++ 7 files changed, 122 insertions(+) diff --git a/fs/ceph/addr.c b/fs/ceph/addr.c index 6f4678d..f359619 100644 --- a/fs/ceph/addr.c +++ b/fs/ceph/addr.c @@ -216,6 +216,9 @@ static int ceph_sync_readpages(struct ceph_fs_client *fsc, if (!rc) rc = ceph_osdc_wait_request(osdc, req); + ceph_update_read_latency(&fsc->mdsc->metric, req->r_start_stamp, + req->r_end_stamp, rc); + ceph_osdc_put_request(req); dout("readpages result %d\n", rc); return rc; @@ -299,6 +302,7 @@ static int ceph_readpage(struct file *filp, struct page *page) static void finish_read(struct ceph_osd_request *req) { struct inode *inode = req->r_inode; + struct ceph_fs_client *fsc = ceph_inode_to_client(inode); struct ceph_osd_data *osd_data; int rc = req->r_result <= 0 ? req->r_result : 0; int bytes = req->r_result >= 0 ? req->r_result : 0; @@ -336,6 +340,10 @@ static void finish_read(struct ceph_osd_request *req) put_page(page); bytes -= PAGE_SIZE; } + + ceph_update_read_latency(&fsc->mdsc->metric, req->r_start_stamp, + req->r_end_stamp, rc); + kfree(osd_data->pages); } @@ -643,6 +651,9 @@ static int ceph_sync_writepages(struct ceph_fs_client *fsc, if (!rc) rc = ceph_osdc_wait_request(osdc, req); + ceph_update_write_latency(&fsc->mdsc->metric, req->r_start_stamp, + req->r_end_stamp, rc); + ceph_osdc_put_request(req); if (rc == 0) rc = len; @@ -794,6 +805,9 @@ static void writepages_finish(struct ceph_osd_request *req) ceph_clear_error_write(ci); } + ceph_update_write_latency(&fsc->mdsc->metric, req->r_start_stamp, + req->r_end_stamp, rc); + /* * We lost the cache cap, need to truncate the page before * it is unlocked, otherwise we'd truncate it later in the @@ -1852,6 +1866,10 @@ int ceph_uninline_data(struct file *filp, struct page *locked_page) err = ceph_osdc_start_request(&fsc->client->osdc, req, false); if (!err) err = ceph_osdc_wait_request(&fsc->client->osdc, req); + + ceph_update_write_latency(&fsc->mdsc->metric, req->r_start_stamp, + req->r_end_stamp, err); + out_put: ceph_osdc_put_request(req); if (err == -ECANCELED) diff --git a/fs/ceph/debugfs.c b/fs/ceph/debugfs.c index 66b9622..f2bb997 100644 --- a/fs/ceph/debugfs.c +++ b/fs/ceph/debugfs.c @@ -130,7 +130,24 @@ static int metric_show(struct seq_file *s, void *p) struct ceph_mds_client *mdsc = fsc->mdsc; struct ceph_client_metric *m = &mdsc->metric; int i, nr_caps = 0; + s64 total, sum, avg = 0; + seq_printf(s, "item total avg_lat(us)\n"); + seq_printf(s, "-------------------------------------\n"); + + total = percpu_counter_sum(&m->total_reads); + sum = percpu_counter_sum(&m->read_latency_sum); + avg = total ? DIV64_U64_ROUND_CLOSEST(sum, total) : 0; + avg = jiffies_to_usecs(avg); + seq_printf(s, "%-14s%-12lld%lld\n", "read", total, avg); + + total = percpu_counter_sum(&m->total_writes); + sum = percpu_counter_sum(&m->write_latency_sum); + avg = total ? DIV64_U64_ROUND_CLOSEST(sum, total) : 0; + avg = jiffies_to_usecs(avg); + seq_printf(s, "%-14s%-12lld%lld\n", "write", total, avg); + + seq_printf(s, "\n"); seq_printf(s, "item total miss hit\n"); seq_printf(s, "-------------------------------------------------\n"); diff --git a/fs/ceph/file.c b/fs/ceph/file.c index 4a5ccbb..8e40022 100644 --- a/fs/ceph/file.c +++ b/fs/ceph/file.c @@ -906,6 +906,10 @@ static ssize_t ceph_sync_read(struct kiocb *iocb, struct iov_iter *to, ret = ceph_osdc_start_request(osdc, req, false); if (!ret) ret = ceph_osdc_wait_request(osdc, req); + + ceph_update_read_latency(&fsc->mdsc->metric, req->r_start_stamp, + req->r_end_stamp, ret); + ceph_osdc_put_request(req); i_size = i_size_read(inode); @@ -1044,6 +1048,8 @@ static void ceph_aio_complete_req(struct ceph_osd_request *req) struct inode *inode = req->r_inode; struct ceph_aio_request *aio_req = req->r_priv; struct ceph_osd_data *osd_data = osd_req_op_extent_osd_data(req, 0); + struct ceph_fs_client *fsc = ceph_inode_to_client(inode); + struct ceph_client_metric *metric = &fsc->mdsc->metric; BUG_ON(osd_data->type != CEPH_OSD_DATA_TYPE_BVECS); BUG_ON(!osd_data->num_bvecs); @@ -1051,6 +1057,16 @@ static void ceph_aio_complete_req(struct ceph_osd_request *req) dout("ceph_aio_complete_req %p rc %d bytes %u\n", inode, rc, osd_data->bvec_pos.iter.bi_size); + /* r_start_stamp == 0 means the request was not submitted */ + if (req->r_start_stamp) { + if (aio_req->write) + ceph_update_write_latency(metric, req->r_start_stamp, + req->r_end_stamp, rc); + else + ceph_update_read_latency(metric, req->r_start_stamp, + req->r_end_stamp, rc); + } + if (rc == -EOLDSNAPC) { struct ceph_aio_work *aio_work; BUG_ON(!aio_req->write); @@ -1179,6 +1195,7 @@ static void ceph_aio_retry_work(struct work_struct *work) struct inode *inode = file_inode(file); struct ceph_inode_info *ci = ceph_inode(inode); struct ceph_fs_client *fsc = ceph_inode_to_client(inode); + struct ceph_client_metric *metric = &fsc->mdsc->metric; struct ceph_vino vino; struct ceph_osd_request *req; struct bio_vec *bvecs; @@ -1295,6 +1312,13 @@ static void ceph_aio_retry_work(struct work_struct *work) if (!ret) ret = ceph_osdc_wait_request(&fsc->client->osdc, req); + if (write) + ceph_update_write_latency(metric, req->r_start_stamp, + req->r_end_stamp, ret); + else + ceph_update_read_latency(metric, req->r_start_stamp, + req->r_end_stamp, ret); + size = i_size_read(inode); if (!write) { if (ret == -ENOENT) @@ -1466,6 +1490,8 @@ static void ceph_aio_retry_work(struct work_struct *work) if (!ret) ret = ceph_osdc_wait_request(&fsc->client->osdc, req); + ceph_update_write_latency(&fsc->mdsc->metric, req->r_start_stamp, + req->r_end_stamp, ret); out: ceph_osdc_put_request(req); if (ret != 0) { diff --git a/fs/ceph/metric.c b/fs/ceph/metric.c index 2a4b739..1d34d8c 100644 --- a/fs/ceph/metric.c +++ b/fs/ceph/metric.c @@ -29,8 +29,32 @@ int ceph_metric_init(struct ceph_client_metric *m) if (ret) goto err_i_caps_mis; + ret = percpu_counter_init(&m->total_reads, 0, GFP_KERNEL); + if (ret) + goto err_total_reads; + + ret = percpu_counter_init(&m->read_latency_sum, 0, GFP_KERNEL); + if (ret) + goto err_read_latency_sum; + + ret = percpu_counter_init(&m->total_writes, 0, GFP_KERNEL); + if (ret) + goto err_total_writes; + + ret = percpu_counter_init(&m->write_latency_sum, 0, GFP_KERNEL); + if (ret) + goto err_write_latency_sum; + return 0; +err_write_latency_sum: + percpu_counter_destroy(&m->total_writes); +err_total_writes: + percpu_counter_destroy(&m->read_latency_sum); +err_read_latency_sum: + percpu_counter_destroy(&m->total_reads); +err_total_reads: + percpu_counter_destroy(&m->i_caps_mis); err_i_caps_mis: percpu_counter_destroy(&m->i_caps_hit); err_i_caps_hit: @@ -46,6 +70,10 @@ void ceph_metric_destroy(struct ceph_client_metric *m) if (!m) return; + percpu_counter_destroy(&m->write_latency_sum); + percpu_counter_destroy(&m->total_writes); + percpu_counter_destroy(&m->read_latency_sum); + percpu_counter_destroy(&m->total_reads); percpu_counter_destroy(&m->i_caps_mis); percpu_counter_destroy(&m->i_caps_hit); percpu_counter_destroy(&m->d_lease_mis); diff --git a/fs/ceph/metric.h b/fs/ceph/metric.h index 098ee8a..b1b45b0 100644 --- a/fs/ceph/metric.h +++ b/fs/ceph/metric.h @@ -13,6 +13,12 @@ struct ceph_client_metric { struct percpu_counter i_caps_hit; struct percpu_counter i_caps_mis; + + struct percpu_counter total_reads; + struct percpu_counter read_latency_sum; + + struct percpu_counter total_writes; + struct percpu_counter write_latency_sum; }; extern int ceph_metric_init(struct ceph_client_metric *m); @@ -27,4 +33,28 @@ static inline void ceph_update_cap_mis(struct ceph_client_metric *m) { percpu_counter_inc(&m->i_caps_mis); } + +static inline void ceph_update_read_latency(struct ceph_client_metric *m, + unsigned long r_start, + unsigned long r_end, + int rc) +{ + if (rc < 0 && rc != -ENOENT && rc != -ETIMEDOUT) + return; + + percpu_counter_inc(&m->total_reads); + percpu_counter_add(&m->read_latency_sum, r_end - r_start); +} + +static inline void ceph_update_write_latency(struct ceph_client_metric *m, + unsigned long r_start, + unsigned long r_end, + int rc) +{ + if (rc && rc != -ETIMEDOUT) + return; + + percpu_counter_inc(&m->total_writes); + percpu_counter_add(&m->write_latency_sum, r_end - r_start); +} #endif /* _FS_CEPH_MDS_METRIC_H */ diff --git a/include/linux/ceph/osd_client.h b/include/linux/ceph/osd_client.h index 9d9f745..02ff3a3 100644 --- a/include/linux/ceph/osd_client.h +++ b/include/linux/ceph/osd_client.h @@ -213,6 +213,7 @@ struct ceph_osd_request { /* internal */ unsigned long r_stamp; /* jiffies, send or check time */ unsigned long r_start_stamp; /* jiffies */ + unsigned long r_end_stamp; /* jiffies */ int r_attempts; u32 r_map_dne_bound; diff --git a/net/ceph/osd_client.c b/net/ceph/osd_client.c index 998e26b..28e33e0 100644 --- a/net/ceph/osd_client.c +++ b/net/ceph/osd_client.c @@ -2389,6 +2389,8 @@ static void finish_request(struct ceph_osd_request *req) WARN_ON(lookup_request_mc(&osdc->map_checks, req->r_tid)); dout("%s req %p tid %llu\n", __func__, req, req->r_tid); + req->r_end_stamp = jiffies; + if (req->r_osd) unlink_request(req->r_osd, req); atomic_dec(&osdc->num_requests); From patchwork Wed Mar 18 14:05:54 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Xiubo Li X-Patchwork-Id: 11445321 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 2DFCC13B1 for ; Wed, 18 Mar 2020 14:06:43 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 0C9772076C for ; Wed, 18 Mar 2020 14:06:43 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="XfwH9nVm" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727121AbgCROGm (ORCPT ); Wed, 18 Mar 2020 10:06:42 -0400 Received: from us-smtp-delivery-74.mimecast.com ([216.205.24.74]:56373 "EHLO us-smtp-delivery-74.mimecast.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727114AbgCROGl (ORCPT ); Wed, 18 Mar 2020 10:06:41 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1584540400; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:in-reply-to:in-reply-to:references:references; bh=9w14tFwK7/NCfH3WHhgl/t3gMHSf8zTWJQFjoBudlnQ=; b=XfwH9nVm8XTYVQraei95o4ayevThu6aBxnkPjqEbDL+E5JLgavXXsvHPQ7yWR1gUhi/1/i fpr6P9SkTHATTWfR1OmNnBnLYlasW2O6l84mq8sNh0s3T2+lptpz5ez4aonGwADmPpYUCx aMZ94gJrsO5wu1oGtoJ301YNxnz+WWs= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-261-LepuTVD4PCC33h2R_XdlGA-1; Wed, 18 Mar 2020 10:06:23 -0400 X-MC-Unique: LepuTVD4PCC33h2R_XdlGA-1 Received: from smtp.corp.redhat.com (int-mx07.intmail.prod.int.phx2.redhat.com [10.5.11.22]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 4F369800D53; Wed, 18 Mar 2020 14:06:22 +0000 (UTC) Received: from lxbceph0.gsslab.pek2.redhat.com (vm36-245.gsslab.pek2.redhat.com [10.72.36.245]) by smtp.corp.redhat.com (Postfix) with ESMTP id A5A9D10027A3; Wed, 18 Mar 2020 14:06:19 +0000 (UTC) From: xiubli@redhat.com To: jlayton@kernel.org Cc: sage@redhat.com, idryomov@gmail.com, gfarnum@redhat.com, zyan@redhat.com, pdonnell@redhat.com, ceph-devel@vger.kernel.org, Xiubo Li Subject: [PATCH v10 4/6] ceph: add metadata perf metric support Date: Wed, 18 Mar 2020 10:05:54 -0400 Message-Id: <1584540356-5885-5-git-send-email-xiubli@redhat.com> In-Reply-To: <1584540356-5885-1-git-send-email-xiubli@redhat.com> References: <1584540356-5885-1-git-send-email-xiubli@redhat.com> X-Scanned-By: MIMEDefang 2.84 on 10.5.11.22 Sender: ceph-devel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: ceph-devel@vger.kernel.org From: Xiubo Li Add a new "r_ended" field to struct ceph_mds_request and use that to maintain the average latency of MDS requests. URL: https://tracker.ceph.com/issues/43215 Signed-off-by: Xiubo Li --- fs/ceph/debugfs.c | 6 ++++++ fs/ceph/mds_client.c | 5 +++++ fs/ceph/mds_client.h | 3 ++- fs/ceph/metric.c | 14 ++++++++++++++ fs/ceph/metric.h | 15 +++++++++++++++ 5 files changed, 42 insertions(+), 1 deletion(-) diff --git a/fs/ceph/debugfs.c b/fs/ceph/debugfs.c index f2bb997..b04344e 100644 --- a/fs/ceph/debugfs.c +++ b/fs/ceph/debugfs.c @@ -147,6 +147,12 @@ static int metric_show(struct seq_file *s, void *p) avg = jiffies_to_usecs(avg); seq_printf(s, "%-14s%-12lld%lld\n", "write", total, avg); + total = percpu_counter_sum(&m->total_metadatas); + sum = percpu_counter_sum(&m->metadata_latency_sum); + avg = total ? DIV64_U64_ROUND_CLOSEST(sum, total) : 0; + avg = jiffies_to_usecs(avg); + seq_printf(s, "%-14s%-12lld%lld\n", "metadata", total, avg); + seq_printf(s, "\n"); seq_printf(s, "item total miss hit\n"); seq_printf(s, "-------------------------------------------------\n"); diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c index 1e242d8..b3f985a 100644 --- a/fs/ceph/mds_client.c +++ b/fs/ceph/mds_client.c @@ -2547,6 +2547,8 @@ static struct ceph_msg *create_request_message(struct ceph_mds_client *mdsc, static void complete_request(struct ceph_mds_client *mdsc, struct ceph_mds_request *req) { + req->r_ended = jiffies; + if (req->r_callback) req->r_callback(mdsc, req); complete_all(&req->r_completion); @@ -3155,6 +3157,9 @@ static void handle_reply(struct ceph_mds_session *session, struct ceph_msg *msg) /* kick calling process */ complete_request(mdsc, req); + + ceph_update_metadata_latency(&mdsc->metric, req->r_started, + req->r_ended, err); out: ceph_mdsc_put_request(req); return; diff --git a/fs/ceph/mds_client.h b/fs/ceph/mds_client.h index ae1d01c..9018fa7 100644 --- a/fs/ceph/mds_client.h +++ b/fs/ceph/mds_client.h @@ -298,7 +298,8 @@ struct ceph_mds_request { u32 r_readdir_offset; unsigned long r_timeout; /* optional. jiffies, 0 is "wait forever" */ - unsigned long r_started; /* start time to measure timeout against */ + unsigned long r_started; /* start time to measure timeout against and latency */ + unsigned long r_ended; /* finish time to measure latency */ unsigned long r_request_started; /* start time for mds request only, used to measure lease durations */ diff --git a/fs/ceph/metric.c b/fs/ceph/metric.c index 1d34d8c..629a328 100644 --- a/fs/ceph/metric.c +++ b/fs/ceph/metric.c @@ -45,8 +45,20 @@ int ceph_metric_init(struct ceph_client_metric *m) if (ret) goto err_write_latency_sum; + ret = percpu_counter_init(&m->total_metadatas, 0, GFP_KERNEL); + if (ret) + goto err_total_metadatas; + + ret = percpu_counter_init(&m->metadata_latency_sum, 0, GFP_KERNEL); + if (ret) + goto err_metadata_latency_sum; + return 0; +err_metadata_latency_sum: + percpu_counter_destroy(&m->total_metadatas); +err_total_metadatas: + percpu_counter_destroy(&m->write_latency_sum); err_write_latency_sum: percpu_counter_destroy(&m->total_writes); err_total_writes: @@ -70,6 +82,8 @@ void ceph_metric_destroy(struct ceph_client_metric *m) if (!m) return; + percpu_counter_destroy(&m->metadata_latency_sum); + percpu_counter_destroy(&m->total_metadatas); percpu_counter_destroy(&m->write_latency_sum); percpu_counter_destroy(&m->total_writes); percpu_counter_destroy(&m->read_latency_sum); diff --git a/fs/ceph/metric.h b/fs/ceph/metric.h index b1b45b0..aaf9979 100644 --- a/fs/ceph/metric.h +++ b/fs/ceph/metric.h @@ -19,6 +19,9 @@ struct ceph_client_metric { struct percpu_counter total_writes; struct percpu_counter write_latency_sum; + + struct percpu_counter total_metadatas; + struct percpu_counter metadata_latency_sum; }; extern int ceph_metric_init(struct ceph_client_metric *m); @@ -57,4 +60,16 @@ static inline void ceph_update_write_latency(struct ceph_client_metric *m, percpu_counter_inc(&m->total_writes); percpu_counter_add(&m->write_latency_sum, r_end - r_start); } + +static inline void ceph_update_metadata_latency(struct ceph_client_metric *m, + unsigned long r_start, + unsigned long r_end, + int rc) +{ + if (rc && rc != -ENOENT) + return; + + percpu_counter_inc(&m->total_metadatas); + percpu_counter_add(&m->metadata_latency_sum, r_end - r_start); +} #endif /* _FS_CEPH_MDS_METRIC_H */ From patchwork Wed Mar 18 14:05:55 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Xiubo Li X-Patchwork-Id: 11445319 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 6565613B1 for ; Wed, 18 Mar 2020 14:06:42 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 3BC5F2076C for ; Wed, 18 Mar 2020 14:06:42 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="GAj3yBHc" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727119AbgCROGl (ORCPT ); Wed, 18 Mar 2020 10:06:41 -0400 Received: from us-smtp-delivery-74.mimecast.com ([63.128.21.74]:42865 "EHLO us-smtp-delivery-74.mimecast.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726893AbgCROGl (ORCPT ); Wed, 18 Mar 2020 10:06:41 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1584540399; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:in-reply-to:in-reply-to:references:references; bh=S3DXrMSseFSEGRdLbWNjrV+E8YB5AdAmVwUayCiNBNo=; b=GAj3yBHcYra63JVELKpyKQeCBvnH++jdJ4F3Z1eO948c/0bug5cEoU7iFv87P65eib8Fuc 3ShyuMq3cFiXDzm530rivbLSHaVteUW/IX9hbJaQ4cSi1fQNwDQT0CegQkVGdTr61WH11G NAAoZz16SYUeyJREZqzv9NZgjuXw+Q4= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-188-S0-Aeq1FPDORL23Db9olmQ-1; Wed, 18 Mar 2020 10:06:29 -0400 X-MC-Unique: S0-Aeq1FPDORL23Db9olmQ-1 Received: from smtp.corp.redhat.com (int-mx07.intmail.prod.int.phx2.redhat.com [10.5.11.22]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id E83B91857BE0; Wed, 18 Mar 2020 14:06:27 +0000 (UTC) Received: from lxbceph0.gsslab.pek2.redhat.com (vm36-245.gsslab.pek2.redhat.com [10.72.36.245]) by smtp.corp.redhat.com (Postfix) with ESMTP id C6CF01001920; Wed, 18 Mar 2020 14:06:22 +0000 (UTC) From: xiubli@redhat.com To: jlayton@kernel.org Cc: sage@redhat.com, idryomov@gmail.com, gfarnum@redhat.com, zyan@redhat.com, pdonnell@redhat.com, ceph-devel@vger.kernel.org, Xiubo Li Subject: [PATCH v10 5/6] ceph: add min/max latency support for read/write/metadata metrics Date: Wed, 18 Mar 2020 10:05:55 -0400 Message-Id: <1584540356-5885-6-git-send-email-xiubli@redhat.com> In-Reply-To: <1584540356-5885-1-git-send-email-xiubli@redhat.com> References: <1584540356-5885-1-git-send-email-xiubli@redhat.com> X-Scanned-By: MIMEDefang 2.84 on 10.5.11.22 Sender: ceph-devel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: ceph-devel@vger.kernel.org From: Xiubo Li These will be very useful help diagnose problems. URL: https://tracker.ceph.com/issues/44533 Signed-off-by: Xiubo Li --- fs/ceph/debugfs.c | 71 ++++++++++++++++++++++++++++++++++++++----------------- fs/ceph/metric.c | 9 +++++++ fs/ceph/metric.h | 48 ++++++++++++++++++++++++++++++++++--- 3 files changed, 103 insertions(+), 25 deletions(-) diff --git a/fs/ceph/debugfs.c b/fs/ceph/debugfs.c index b04344e..00c39a2 100644 --- a/fs/ceph/debugfs.c +++ b/fs/ceph/debugfs.c @@ -124,34 +124,61 @@ static int mdsc_show(struct seq_file *s, void *p) return 0; } +static s64 get_avg(struct percpu_counter *totalp, struct percpu_counter *sump, + s64 *total) +{ + s64 t, sum, avg = 0; + + t = percpu_counter_sum(totalp); + sum = percpu_counter_sum(sump); + + if (likely(t)) + avg = DIV64_U64_ROUND_CLOSEST(sum, t); + + *total = t; + return avg; +} + +#define CEPH_METRIC_SHOW(name, total, avg, min, max) { \ + s64 _avg, _min, _max; \ + _avg = jiffies_to_usecs(avg); \ + _min = jiffies_to_usecs(min == S64_MAX ? 0 : min); \ + _max = jiffies_to_usecs(max); \ + seq_printf(s, "%-14s%-12lld%-16lld%-16lld%lld\n", \ + name, total, _avg, _min, _max); \ +} + static int metric_show(struct seq_file *s, void *p) { struct ceph_fs_client *fsc = s->private; struct ceph_mds_client *mdsc = fsc->mdsc; struct ceph_client_metric *m = &mdsc->metric; int i, nr_caps = 0; - s64 total, sum, avg = 0; - - seq_printf(s, "item total avg_lat(us)\n"); - seq_printf(s, "-------------------------------------\n"); - - total = percpu_counter_sum(&m->total_reads); - sum = percpu_counter_sum(&m->read_latency_sum); - avg = total ? DIV64_U64_ROUND_CLOSEST(sum, total) : 0; - avg = jiffies_to_usecs(avg); - seq_printf(s, "%-14s%-12lld%lld\n", "read", total, avg); - - total = percpu_counter_sum(&m->total_writes); - sum = percpu_counter_sum(&m->write_latency_sum); - avg = total ? DIV64_U64_ROUND_CLOSEST(sum, total) : 0; - avg = jiffies_to_usecs(avg); - seq_printf(s, "%-14s%-12lld%lld\n", "write", total, avg); - - total = percpu_counter_sum(&m->total_metadatas); - sum = percpu_counter_sum(&m->metadata_latency_sum); - avg = total ? DIV64_U64_ROUND_CLOSEST(sum, total) : 0; - avg = jiffies_to_usecs(avg); - seq_printf(s, "%-14s%-12lld%lld\n", "metadata", total, avg); + s64 total, avg, min, max; + + seq_printf(s, "item total avg_lat(us) min_lat(us) max_lat(us)\n"); + seq_printf(s, "---------------------------------------------------------------------\n"); + + avg = get_avg(&mdsc->metric.total_reads, + &mdsc->metric.read_latency_sum, + &total); + min = atomic64_read(&m->read_latency_min); + max = atomic64_read(&m->read_latency_max); + CEPH_METRIC_SHOW("read", total, avg, min, max); + + avg = get_avg(&mdsc->metric.total_writes, + &mdsc->metric.write_latency_sum, + &total); + min = atomic64_read(&m->write_latency_min); + max = atomic64_read(&m->write_latency_max); + CEPH_METRIC_SHOW("write", total, avg, min, max); + + avg = get_avg(&mdsc->metric.total_metadatas, + &mdsc->metric.metadata_latency_sum, + &total); + min = atomic64_read(&m->metadata_latency_min); + max = atomic64_read(&m->metadata_latency_max); + CEPH_METRIC_SHOW("metadata", total, avg, min, max); seq_printf(s, "\n"); seq_printf(s, "item total miss hit\n"); diff --git a/fs/ceph/metric.c b/fs/ceph/metric.c index 629a328..c0158f6 100644 --- a/fs/ceph/metric.c +++ b/fs/ceph/metric.c @@ -37,6 +37,9 @@ int ceph_metric_init(struct ceph_client_metric *m) if (ret) goto err_read_latency_sum; + atomic64_set(&m->read_latency_min, S64_MAX); + atomic64_set(&m->read_latency_max, 0); + ret = percpu_counter_init(&m->total_writes, 0, GFP_KERNEL); if (ret) goto err_total_writes; @@ -45,6 +48,9 @@ int ceph_metric_init(struct ceph_client_metric *m) if (ret) goto err_write_latency_sum; + atomic64_set(&m->write_latency_min, S64_MAX); + atomic64_set(&m->write_latency_max, 0); + ret = percpu_counter_init(&m->total_metadatas, 0, GFP_KERNEL); if (ret) goto err_total_metadatas; @@ -53,6 +59,9 @@ int ceph_metric_init(struct ceph_client_metric *m) if (ret) goto err_metadata_latency_sum; + atomic64_set(&m->metadata_latency_min, S64_MAX); + atomic64_set(&m->metadata_latency_max, 0); + return 0; err_metadata_latency_sum: diff --git a/fs/ceph/metric.h b/fs/ceph/metric.h index aaf9979..3f90875 100644 --- a/fs/ceph/metric.h +++ b/fs/ceph/metric.h @@ -16,12 +16,18 @@ struct ceph_client_metric { struct percpu_counter total_reads; struct percpu_counter read_latency_sum; + atomic64_t read_latency_min; + atomic64_t read_latency_max; struct percpu_counter total_writes; struct percpu_counter write_latency_sum; + atomic64_t write_latency_min; + atomic64_t write_latency_max; struct percpu_counter total_metadatas; struct percpu_counter metadata_latency_sum; + atomic64_t metadata_latency_min; + atomic64_t metadata_latency_max; }; extern int ceph_metric_init(struct ceph_client_metric *m); @@ -37,16 +43,44 @@ static inline void ceph_update_cap_mis(struct ceph_client_metric *m) percpu_counter_inc(&m->i_caps_mis); } +static inline void __update_min_latency(atomic64_t *min, unsigned long lat) +{ + unsigned long cur, old; + + cur = atomic64_read(min); + do { + old = cur; + if (likely(lat >= old)) + break; + } while (unlikely((cur = atomic64_cmpxchg(min, old, lat)) != old)); +} + +static inline void __update_max_latency(atomic64_t *max, unsigned long lat) +{ + unsigned long cur, old; + + cur = atomic64_read(max); + do { + old = cur; + if (likely(lat <= old)) + break; + } while (unlikely((cur = atomic64_cmpxchg(max, old, lat)) != old)); +} + static inline void ceph_update_read_latency(struct ceph_client_metric *m, unsigned long r_start, unsigned long r_end, int rc) { + unsigned long lat = r_end - r_start; + if (rc < 0 && rc != -ENOENT && rc != -ETIMEDOUT) return; percpu_counter_inc(&m->total_reads); - percpu_counter_add(&m->read_latency_sum, r_end - r_start); + percpu_counter_add(&m->read_latency_sum, lat); + __update_min_latency(&m->read_latency_min, lat); + __update_max_latency(&m->read_latency_max, lat); } static inline void ceph_update_write_latency(struct ceph_client_metric *m, @@ -54,11 +88,15 @@ static inline void ceph_update_write_latency(struct ceph_client_metric *m, unsigned long r_end, int rc) { + unsigned long lat = r_end - r_start; + if (rc && rc != -ETIMEDOUT) return; percpu_counter_inc(&m->total_writes); - percpu_counter_add(&m->write_latency_sum, r_end - r_start); + percpu_counter_add(&m->write_latency_sum, lat); + __update_min_latency(&m->write_latency_min, lat); + __update_max_latency(&m->write_latency_max, lat); } static inline void ceph_update_metadata_latency(struct ceph_client_metric *m, @@ -66,10 +104,14 @@ static inline void ceph_update_metadata_latency(struct ceph_client_metric *m, unsigned long r_end, int rc) { + unsigned long lat = r_end - r_start; + if (rc && rc != -ENOENT) return; percpu_counter_inc(&m->total_metadatas); - percpu_counter_add(&m->metadata_latency_sum, r_end - r_start); + percpu_counter_add(&m->metadata_latency_sum, lat); + __update_min_latency(&m->metadata_latency_min, lat); + __update_max_latency(&m->metadata_latency_max, lat); } #endif /* _FS_CEPH_MDS_METRIC_H */ From patchwork Wed Mar 18 14:05:56 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Xiubo Li X-Patchwork-Id: 11445323 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 532391667 for ; Wed, 18 Mar 2020 14:06:51 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 1FCA420773 for ; Wed, 18 Mar 2020 14:06:51 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="IkocARXS" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727131AbgCROGu (ORCPT ); Wed, 18 Mar 2020 10:06:50 -0400 Received: from us-smtp-delivery-74.mimecast.com ([216.205.24.74]:33105 "EHLO us-smtp-delivery-74.mimecast.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727114AbgCROGu (ORCPT ); Wed, 18 Mar 2020 10:06:50 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1584540408; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:in-reply-to:in-reply-to:references:references; bh=7lSWtp+wV6Otq97NpqsVk644c8GKG6OKklvAI4WxIFs=; b=IkocARXSb13YKf1C9yUI9H42TKY+2r8FxnCdn9GwhTbpVZ7w5vtV0rq1rfdmXZIFvIgb8A 0/VjJF/nWzGrCmXrPDsjqlKVacYw1MVOIdqazCNWfhCBChZxGExq+CbFheHxr5HgJ2uYUf qFxD7O3Na6eaLq8X9omLY8iM1Pq5RMI= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-375-HDfLCVPvM5-27mFfmslkOg-1; Wed, 18 Mar 2020 10:06:42 -0400 X-MC-Unique: HDfLCVPvM5-27mFfmslkOg-1 Received: from smtp.corp.redhat.com (int-mx07.intmail.prod.int.phx2.redhat.com [10.5.11.22]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id D47EB100A5F4; Wed, 18 Mar 2020 14:06:41 +0000 (UTC) Received: from lxbceph0.gsslab.pek2.redhat.com (vm36-245.gsslab.pek2.redhat.com [10.72.36.245]) by smtp.corp.redhat.com (Postfix) with ESMTP id 6C7F910027A8; Wed, 18 Mar 2020 14:06:28 +0000 (UTC) From: xiubli@redhat.com To: jlayton@kernel.org Cc: sage@redhat.com, idryomov@gmail.com, gfarnum@redhat.com, zyan@redhat.com, pdonnell@redhat.com, ceph-devel@vger.kernel.org, Xiubo Li Subject: [PATCH v10 6/6] ceph: add standard deviation support for read/write/metadata perf metric Date: Wed, 18 Mar 2020 10:05:56 -0400 Message-Id: <1584540356-5885-7-git-send-email-xiubli@redhat.com> In-Reply-To: <1584540356-5885-1-git-send-email-xiubli@redhat.com> References: <1584540356-5885-1-git-send-email-xiubli@redhat.com> X-Scanned-By: MIMEDefang 2.84 on 10.5.11.22 Sender: ceph-devel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: ceph-devel@vger.kernel.org From: Xiubo Li Switch {read/write/metadata}_latency_sum to atomic type and remove {read/write/metadata}_latency_sum showing in the debugfs, which makes no sense. URL: https://tracker.ceph.com/issues/44534 Signed-off-by: Xiubo Li --- fs/ceph/debugfs.c | 61 +++++++++++++-------- fs/ceph/metric.c | 159 ++++++++++++++++++++++++++++++++++++++++++------------ fs/ceph/metric.h | 101 +++++++++------------------------- 3 files changed, 187 insertions(+), 134 deletions(-) diff --git a/fs/ceph/debugfs.c b/fs/ceph/debugfs.c index 00c39a2..7c95ae5 100644 --- a/fs/ceph/debugfs.c +++ b/fs/ceph/debugfs.c @@ -124,13 +124,15 @@ static int mdsc_show(struct seq_file *s, void *p) return 0; } -static s64 get_avg(struct percpu_counter *totalp, struct percpu_counter *sump, +static s64 get_avg(atomic64_t *totalp, atomic64_t *sump, spinlock_t *lockp, s64 *total) { s64 t, sum, avg = 0; - t = percpu_counter_sum(totalp); - sum = percpu_counter_sum(sump); + spin_lock(lockp); + t = atomic64_read(totalp); + sum = atomic64_read(sump); + spin_unlock(lockp); if (likely(t)) avg = DIV64_U64_ROUND_CLOSEST(sum, t); @@ -139,13 +141,22 @@ static s64 get_avg(struct percpu_counter *totalp, struct percpu_counter *sump, return avg; } -#define CEPH_METRIC_SHOW(name, total, avg, min, max) { \ - s64 _avg, _min, _max; \ - _avg = jiffies_to_usecs(avg); \ - _min = jiffies_to_usecs(min == S64_MAX ? 0 : min); \ - _max = jiffies_to_usecs(max); \ - seq_printf(s, "%-14s%-12lld%-16lld%-16lld%lld\n", \ - name, total, _avg, _min, _max); \ +#define CEPH_METRIC_SHOW(name, total, avg, min, max, sq) { \ + s64 _total, _avg, _min, _max, _sq, _st, _re = 0; \ + _avg = jiffies_to_usecs(avg); \ + _min = jiffies_to_usecs(min == S64_MAX ? 0 : min); \ + _max = jiffies_to_usecs(max); \ + _total = total - 1; \ + _sq = _total > 0 ? DIV64_U64_ROUND_CLOSEST(sq, _total) : 0; \ + _sq = jiffies_to_usecs(_sq); \ + _st = int_sqrt64(_sq); \ + if (_st > 0) { \ + _re = 5 * (_sq - (_st * _st)); \ + _re = _re > 0 ? _re - 1 : 0; \ + _re = _st > 0 ? div64_s64(_re, _st) : 0; \ + } \ + seq_printf(s, "%-14s%-12lld%-16lld%-16lld%-16lld%lld.%lld\n", \ + name, total, _avg, _min, _max, _st, _re); \ } static int metric_show(struct seq_file *s, void *p) @@ -154,31 +165,37 @@ static int metric_show(struct seq_file *s, void *p) struct ceph_mds_client *mdsc = fsc->mdsc; struct ceph_client_metric *m = &mdsc->metric; int i, nr_caps = 0; - s64 total, avg, min, max; + s64 total, avg, min, max, sq; - seq_printf(s, "item total avg_lat(us) min_lat(us) max_lat(us)\n"); - 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"); avg = get_avg(&mdsc->metric.total_reads, &mdsc->metric.read_latency_sum, + &mdsc->metric.read_latency_lock, &total); - min = atomic64_read(&m->read_latency_min); - max = atomic64_read(&m->read_latency_max); - CEPH_METRIC_SHOW("read", total, avg, min, max); + min = atomic64_read(&mdsc->metric.read_latency_min); + max = atomic64_read(&mdsc->metric.read_latency_max); + sq = percpu_counter_sum(&mdsc->metric.read_latency_sq_sum); + CEPH_METRIC_SHOW("read", total, avg, min, max, sq); avg = get_avg(&mdsc->metric.total_writes, &mdsc->metric.write_latency_sum, + &mdsc->metric.write_latency_lock, &total); - min = atomic64_read(&m->write_latency_min); - max = atomic64_read(&m->write_latency_max); - CEPH_METRIC_SHOW("write", total, avg, min, max); + min = atomic64_read(&mdsc->metric.write_latency_min); + max = atomic64_read(&mdsc->metric.write_latency_max); + sq = percpu_counter_sum(&mdsc->metric.write_latency_sq_sum); + CEPH_METRIC_SHOW("write", total, avg, min, max, sq); avg = get_avg(&mdsc->metric.total_metadatas, &mdsc->metric.metadata_latency_sum, + &mdsc->metric.metadata_latency_lock, &total); - min = atomic64_read(&m->metadata_latency_min); - max = atomic64_read(&m->metadata_latency_max); - CEPH_METRIC_SHOW("metadata", total, avg, min, max); + min = atomic64_read(&mdsc->metric.metadata_latency_min); + max = atomic64_read(&mdsc->metric.metadata_latency_max); + sq = percpu_counter_sum(&mdsc->metric.metadata_latency_sq_sum); + CEPH_METRIC_SHOW("metadata", total, avg, min, max, sq); seq_printf(s, "\n"); seq_printf(s, "item total miss hit\n"); diff --git a/fs/ceph/metric.c b/fs/ceph/metric.c index c0158f6..ac1e800 100644 --- a/fs/ceph/metric.c +++ b/fs/ceph/metric.c @@ -2,6 +2,7 @@ #include #include +#include #include "metric.h" @@ -29,52 +30,43 @@ int ceph_metric_init(struct ceph_client_metric *m) if (ret) goto err_i_caps_mis; - ret = percpu_counter_init(&m->total_reads, 0, GFP_KERNEL); + ret = percpu_counter_init(&m->read_latency_sq_sum, 0, GFP_KERNEL); if (ret) - goto err_total_reads; - - ret = percpu_counter_init(&m->read_latency_sum, 0, GFP_KERNEL); - if (ret) - goto err_read_latency_sum; + goto err_read_latency_sq_sum; + spin_lock_init(&m->read_latency_lock); + atomic64_set(&m->total_reads, 0); + atomic64_set(&m->read_latency_sum, 0); atomic64_set(&m->read_latency_min, S64_MAX); atomic64_set(&m->read_latency_max, 0); - ret = percpu_counter_init(&m->total_writes, 0, GFP_KERNEL); + ret = percpu_counter_init(&m->write_latency_sq_sum, 0, GFP_KERNEL); if (ret) - goto err_total_writes; - - ret = percpu_counter_init(&m->write_latency_sum, 0, GFP_KERNEL); - if (ret) - goto err_write_latency_sum; + goto err_write_latency_sq_sum; + spin_lock_init(&m->write_latency_lock); + atomic64_set(&m->total_writes, 0); + atomic64_set(&m->write_latency_sum, 0); atomic64_set(&m->write_latency_min, S64_MAX); atomic64_set(&m->write_latency_max, 0); - ret = percpu_counter_init(&m->total_metadatas, 0, GFP_KERNEL); - if (ret) - goto err_total_metadatas; - - ret = percpu_counter_init(&m->metadata_latency_sum, 0, GFP_KERNEL); + ret = percpu_counter_init(&m->metadata_latency_sq_sum, 0, GFP_KERNEL); if (ret) - goto err_metadata_latency_sum; + goto err_metadata_latency_sq_sum; + spin_lock_init(&m->metadata_latency_lock); + atomic64_set(&m->total_metadatas, 0); + atomic64_set(&m->metadata_latency_sum, 0); atomic64_set(&m->metadata_latency_min, S64_MAX); atomic64_set(&m->metadata_latency_max, 0); return 0; -err_metadata_latency_sum: - percpu_counter_destroy(&m->total_metadatas); -err_total_metadatas: - percpu_counter_destroy(&m->write_latency_sum); -err_write_latency_sum: - percpu_counter_destroy(&m->total_writes); -err_total_writes: - percpu_counter_destroy(&m->read_latency_sum); -err_read_latency_sum: - percpu_counter_destroy(&m->total_reads); -err_total_reads: +err_metadata_latency_sq_sum: + percpu_counter_destroy(&m->write_latency_sq_sum); +err_write_latency_sq_sum: + percpu_counter_destroy(&m->read_latency_sq_sum); +err_read_latency_sq_sum: percpu_counter_destroy(&m->i_caps_mis); err_i_caps_mis: percpu_counter_destroy(&m->i_caps_hit); @@ -91,14 +83,111 @@ void ceph_metric_destroy(struct ceph_client_metric *m) if (!m) return; - percpu_counter_destroy(&m->metadata_latency_sum); - percpu_counter_destroy(&m->total_metadatas); - percpu_counter_destroy(&m->write_latency_sum); - percpu_counter_destroy(&m->total_writes); - percpu_counter_destroy(&m->read_latency_sum); - percpu_counter_destroy(&m->total_reads); + percpu_counter_destroy(&m->metadata_latency_sq_sum); + percpu_counter_destroy(&m->write_latency_sq_sum); + percpu_counter_destroy(&m->read_latency_sq_sum); percpu_counter_destroy(&m->i_caps_mis); percpu_counter_destroy(&m->i_caps_hit); percpu_counter_destroy(&m->d_lease_mis); percpu_counter_destroy(&m->d_lease_hit); } + +static inline void __update_min_latency(atomic64_t *min, unsigned long lat) +{ + unsigned long cur, old; + + cur = atomic64_read(min); + do { + old = cur; + if (likely(lat >= old)) + break; + } while (unlikely((cur = atomic64_cmpxchg(min, old, lat)) != old)); +} + +static inline void __update_max_latency(atomic64_t *max, unsigned long lat) +{ + unsigned long cur, old; + + cur = atomic64_read(max); + do { + old = cur; + if (likely(lat <= old)) + break; + } while (unlikely((cur = atomic64_cmpxchg(max, old, lat)) != old)); +} + +static inline void __update_avg_and_sq(atomic64_t *totalp, atomic64_t *lat_sump, + struct percpu_counter *sq_sump, + spinlock_t *lockp, unsigned long lat) +{ + s64 total, avg, sq, lsum; + + spin_lock(lockp); + total = atomic64_inc_return(totalp); + lsum = atomic64_add_return(lat, lat_sump); + spin_unlock(lockp); + + if (unlikely(total == 1)) + return; + + /* the sq is (lat - old_avg) * (lat - new_avg) */ + avg = DIV64_U64_ROUND_CLOSEST((lsum - lat), (total - 1)); + sq = lat - avg; + avg = DIV64_U64_ROUND_CLOSEST(lsum, total); + sq = sq * (lat - avg); + percpu_counter_add(sq_sump, sq); +} + +void ceph_update_read_latency(struct ceph_client_metric *m, + unsigned long r_start, + unsigned long r_end, + int rc) +{ + unsigned long lat = r_end - r_start; + + if (rc < 0 && rc != -ENOENT && rc != -ETIMEDOUT) + return; + + __update_min_latency(&m->read_latency_min, lat); + __update_max_latency(&m->read_latency_max, lat); + __update_avg_and_sq(&m->total_reads, &m->read_latency_sum, + &m->read_latency_sq_sum, + &m->read_latency_lock, + lat); +} + +void ceph_update_write_latency(struct ceph_client_metric *m, + unsigned long r_start, + unsigned long r_end, + int rc) +{ + unsigned long lat = r_end - r_start; + + if (rc && rc != -ETIMEDOUT) + return; + + __update_min_latency(&m->write_latency_min, lat); + __update_max_latency(&m->write_latency_max, lat); + __update_avg_and_sq(&m->total_writes, &m->write_latency_sum, + &m->write_latency_sq_sum, + &m->write_latency_lock, + lat); +} + +void ceph_update_metadata_latency(struct ceph_client_metric *m, + unsigned long r_start, + unsigned long r_end, + int rc) +{ + unsigned long lat = r_end - r_start; + + if (rc && rc != -ENOENT) + return; + + __update_min_latency(&m->metadata_latency_min, lat); + __update_max_latency(&m->metadata_latency_max, lat); + __update_avg_and_sq(&m->total_metadatas, &m->metadata_latency_sum, + &m->metadata_latency_sq_sum, + &m->metadata_latency_lock, + lat); +} diff --git a/fs/ceph/metric.h b/fs/ceph/metric.h index 3f90875..fc1ffb1 100644 --- a/fs/ceph/metric.h +++ b/fs/ceph/metric.h @@ -14,18 +14,24 @@ struct ceph_client_metric { struct percpu_counter i_caps_hit; struct percpu_counter i_caps_mis; - struct percpu_counter total_reads; - struct percpu_counter read_latency_sum; + struct percpu_counter read_latency_sq_sum; + spinlock_t read_latency_lock; + atomic64_t total_reads; + atomic64_t read_latency_sum; atomic64_t read_latency_min; atomic64_t read_latency_max; - struct percpu_counter total_writes; - struct percpu_counter write_latency_sum; + struct percpu_counter write_latency_sq_sum; + spinlock_t write_latency_lock; + atomic64_t total_writes; + atomic64_t write_latency_sum; atomic64_t write_latency_min; atomic64_t write_latency_max; - struct percpu_counter total_metadatas; - struct percpu_counter metadata_latency_sum; + struct percpu_counter metadata_latency_sq_sum; + spinlock_t metadata_latency_lock; + atomic64_t total_metadatas; + atomic64_t metadata_latency_sum; atomic64_t metadata_latency_min; atomic64_t metadata_latency_max; }; @@ -43,75 +49,16 @@ static inline void ceph_update_cap_mis(struct ceph_client_metric *m) percpu_counter_inc(&m->i_caps_mis); } -static inline void __update_min_latency(atomic64_t *min, unsigned long lat) -{ - unsigned long cur, old; - - cur = atomic64_read(min); - do { - old = cur; - if (likely(lat >= old)) - break; - } while (unlikely((cur = atomic64_cmpxchg(min, old, lat)) != old)); -} - -static inline void __update_max_latency(atomic64_t *max, unsigned long lat) -{ - unsigned long cur, old; - - cur = atomic64_read(max); - do { - old = cur; - if (likely(lat <= old)) - break; - } while (unlikely((cur = atomic64_cmpxchg(max, old, lat)) != old)); -} - -static inline void ceph_update_read_latency(struct ceph_client_metric *m, - unsigned long r_start, - unsigned long r_end, - int rc) -{ - unsigned long lat = r_end - r_start; - - if (rc < 0 && rc != -ENOENT && rc != -ETIMEDOUT) - return; - - percpu_counter_inc(&m->total_reads); - percpu_counter_add(&m->read_latency_sum, lat); - __update_min_latency(&m->read_latency_min, lat); - __update_max_latency(&m->read_latency_max, lat); -} - -static inline void ceph_update_write_latency(struct ceph_client_metric *m, - unsigned long r_start, - unsigned long r_end, - int rc) -{ - unsigned long lat = r_end - r_start; - - if (rc && rc != -ETIMEDOUT) - return; - - percpu_counter_inc(&m->total_writes); - percpu_counter_add(&m->write_latency_sum, lat); - __update_min_latency(&m->write_latency_min, lat); - __update_max_latency(&m->write_latency_max, lat); -} - -static inline void ceph_update_metadata_latency(struct ceph_client_metric *m, - unsigned long r_start, - unsigned long r_end, - int rc) -{ - unsigned long lat = r_end - r_start; - - if (rc && rc != -ENOENT) - return; - - percpu_counter_inc(&m->total_metadatas); - percpu_counter_add(&m->metadata_latency_sum, lat); - __update_min_latency(&m->metadata_latency_min, lat); - __update_max_latency(&m->metadata_latency_max, lat); -} +extern void ceph_update_read_latency(struct ceph_client_metric *m, + unsigned long r_start, + unsigned long r_end, + int rc); +extern void ceph_update_write_latency(struct ceph_client_metric *m, + unsigned long r_start, + unsigned long r_end, + int rc); +extern void ceph_update_metadata_latency(struct ceph_client_metric *m, + unsigned long r_start, + unsigned long r_end, + int rc); #endif /* _FS_CEPH_MDS_METRIC_H */