Commit 1af16d54 authored by Xiubo Li's avatar Xiubo Li Committed by Ilya Dryomov

ceph: add caps perf metric for each superblock

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/43215Signed-off-by: default avatarXiubo Li <xiubli@redhat.com>
Reviewed-by: default avatarJeff Layton <jlayton@kernel.org>
Signed-off-by: default avatarIlya Dryomov <idryomov@gmail.com>
parent f9009efa
...@@ -22,7 +22,7 @@ static inline void ceph_set_cached_acl(struct inode *inode, ...@@ -22,7 +22,7 @@ static inline void ceph_set_cached_acl(struct inode *inode,
struct ceph_inode_info *ci = ceph_inode(inode); struct ceph_inode_info *ci = ceph_inode(inode);
spin_lock(&ci->i_ceph_lock); 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); set_cached_acl(inode, type, acl);
else else
forget_cached_acl(inode, type); forget_cached_acl(inode, type);
......
...@@ -912,6 +912,20 @@ int __ceph_caps_issued_mask(struct ceph_inode_info *ci, int mask, int touch) ...@@ -912,6 +912,20 @@ int __ceph_caps_issued_mask(struct ceph_inode_info *ci, int mask, int touch)
return 0; 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. * 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, ...@@ -2685,6 +2699,11 @@ static int try_get_cap_refs(struct inode *inode, int need, int want,
if (snap_rwsem_locked) if (snap_rwsem_locked)
up_read(&mdsc->snap_rwsem); 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, dout("get_cap_refs %p ret %d got %s\n", inode,
ret, ceph_cap_string(*got)); ret, ceph_cap_string(*got));
return ret; return ret;
......
...@@ -129,6 +129,7 @@ static int metric_show(struct seq_file *s, void *p) ...@@ -129,6 +129,7 @@ static int metric_show(struct seq_file *s, void *p)
struct ceph_fs_client *fsc = s->private; struct ceph_fs_client *fsc = s->private;
struct ceph_mds_client *mdsc = fsc->mdsc; struct ceph_mds_client *mdsc = fsc->mdsc;
struct ceph_client_metric *m = &mdsc->metric; struct ceph_client_metric *m = &mdsc->metric;
int i, nr_caps = 0;
seq_printf(s, "item total miss hit\n"); seq_printf(s, "item total miss hit\n");
seq_printf(s, "-------------------------------------------------\n"); seq_printf(s, "-------------------------------------------------\n");
...@@ -138,6 +139,21 @@ static int metric_show(struct seq_file *s, void *p) ...@@ -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_mis),
percpu_counter_sum(&m->d_lease_hit)); 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; return 0;
} }
......
...@@ -349,8 +349,9 @@ static int ceph_readdir(struct file *file, struct dir_context *ctx) ...@@ -349,8 +349,9 @@ static int ceph_readdir(struct file *file, struct dir_context *ctx)
!ceph_test_mount_opt(fsc, NOASYNCREADDIR) && !ceph_test_mount_opt(fsc, NOASYNCREADDIR) &&
ceph_snap(inode) != CEPH_SNAPDIR && ceph_snap(inode) != CEPH_SNAPDIR &&
__ceph_dir_is_complete_ordered(ci) && __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); int shared_gen = atomic_read(&ci->i_shared_gen);
spin_unlock(&ci->i_ceph_lock); spin_unlock(&ci->i_ceph_lock);
err = __dcache_readdir(file, ctx, shared_gen); err = __dcache_readdir(file, ctx, shared_gen);
if (err != -EAGAIN) if (err != -EAGAIN)
...@@ -767,7 +768,7 @@ static struct dentry *ceph_lookup(struct inode *dir, struct dentry *dentry, ...@@ -767,7 +768,7 @@ static struct dentry *ceph_lookup(struct inode *dir, struct dentry *dentry,
!is_root_ceph_dentry(dir, dentry) && !is_root_ceph_dentry(dir, dentry) &&
ceph_test_mount_opt(fsc, DCACHE) && ceph_test_mount_opt(fsc, DCACHE) &&
__ceph_dir_is_complete(ci) && __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); __ceph_touch_fmode(ci, mdsc, CEPH_FILE_MODE_RD);
spin_unlock(&ci->i_ceph_lock); spin_unlock(&ci->i_ceph_lock);
dout(" dir %p complete, -ENOENT\n", dir); dout(" dir %p complete, -ENOENT\n", dir);
......
...@@ -2288,8 +2288,8 @@ int __ceph_do_getattr(struct inode *inode, struct page *locked_page, ...@@ -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", dout("do_getattr inode %p mask %s mode 0%o\n",
inode, ceph_cap_string(mask), inode->i_mode); inode, ceph_cap_string(mask), inode->i_mode);
if (!force && ceph_caps_issued_mask(ceph_inode(inode), mask, 1)) if (!force && ceph_caps_issued_mask_metric(ceph_inode(inode), mask, 1))
return 0; return 0;
mode = (mask & CEPH_STAT_RSTAT) ? USE_AUTH_MDS : USE_ANY_MDS; mode = (mask & CEPH_STAT_RSTAT) ? USE_AUTH_MDS : USE_ANY_MDS;
req = ceph_mdsc_create_request(mdsc, CEPH_MDS_OP_GETATTR, mode); req = ceph_mdsc_create_request(mdsc, CEPH_MDS_OP_GETATTR, mode);
......
...@@ -16,13 +16,29 @@ int ceph_metric_init(struct ceph_client_metric *m) ...@@ -16,13 +16,29 @@ int ceph_metric_init(struct ceph_client_metric *m)
ret = percpu_counter_init(&m->d_lease_hit, 0, GFP_KERNEL); ret = percpu_counter_init(&m->d_lease_hit, 0, GFP_KERNEL);
if (ret) if (ret)
return ret; return ret;
ret = percpu_counter_init(&m->d_lease_mis, 0, GFP_KERNEL); ret = percpu_counter_init(&m->d_lease_mis, 0, GFP_KERNEL);
if (ret) { if (ret)
percpu_counter_destroy(&m->d_lease_hit); goto err_d_lease_mis;
return ret;
} 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; 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) void ceph_metric_destroy(struct ceph_client_metric *m)
...@@ -30,6 +46,8 @@ void ceph_metric_destroy(struct ceph_client_metric *m) ...@@ -30,6 +46,8 @@ void ceph_metric_destroy(struct ceph_client_metric *m)
if (!m) if (!m)
return; 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_mis);
percpu_counter_destroy(&m->d_lease_hit); percpu_counter_destroy(&m->d_lease_hit);
} }
...@@ -10,8 +10,21 @@ struct ceph_client_metric { ...@@ -10,8 +10,21 @@ struct ceph_client_metric {
atomic64_t total_dentries; atomic64_t total_dentries;
struct percpu_counter d_lease_hit; struct percpu_counter d_lease_hit;
struct percpu_counter d_lease_mis; 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 int ceph_metric_init(struct ceph_client_metric *m);
extern void ceph_metric_destroy(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 */ #endif /* _FS_CEPH_MDS_METRIC_H */
...@@ -645,6 +645,8 @@ static inline bool __ceph_is_any_real_caps(struct ceph_inode_info *ci) ...@@ -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(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(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, extern int __ceph_caps_issued_other(struct ceph_inode_info *ci,
struct ceph_cap *cap); struct ceph_cap *cap);
...@@ -657,12 +659,12 @@ static inline int ceph_caps_issued(struct ceph_inode_info *ci) ...@@ -657,12 +659,12 @@ static inline int ceph_caps_issued(struct ceph_inode_info *ci)
return issued; return issued;
} }
static inline int ceph_caps_issued_mask(struct ceph_inode_info *ci, int mask, static inline int ceph_caps_issued_mask_metric(struct ceph_inode_info *ci,
int touch) int mask, int touch)
{ {
int r; int r;
spin_lock(&ci->i_ceph_lock); 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); spin_unlock(&ci->i_ceph_lock);
return r; return r;
} }
......
...@@ -856,7 +856,7 @@ ssize_t __ceph_getxattr(struct inode *inode, const char *name, void *value, ...@@ -856,7 +856,7 @@ ssize_t __ceph_getxattr(struct inode *inode, const char *name, void *value,
if (ci->i_xattrs.version == 0 || if (ci->i_xattrs.version == 0 ||
!((req_mask & CEPH_CAP_XATTR_SHARED) || !((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); spin_unlock(&ci->i_ceph_lock);
/* security module gets xattr while filling trace */ /* security module gets xattr while filling trace */
...@@ -914,7 +914,7 @@ ssize_t ceph_listxattr(struct dentry *dentry, char *names, size_t size) ...@@ -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); ci->i_xattrs.version, ci->i_xattrs.index_version);
if (ci->i_xattrs.version == 0 || 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); spin_unlock(&ci->i_ceph_lock);
err = ceph_do_getattr(inode, CEPH_STAT_CAP_XATTR, true); err = ceph_do_getattr(inode, CEPH_STAT_CAP_XATTR, true);
if (err) if (err)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment