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/43215 Signed-off-by: Xiubo Li <xiubli@redhat.com> Reviewed-by: Jeff Layton <jlayton@kernel.org> Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
This commit is contained in:
		
							parent
							
								
									f9009efac4
								
							
						
					
					
						commit
						1af16d547f
					
				| @ -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); | ||||
|  | ||||
| @ -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 @@ out_unlock: | ||||
| 	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; | ||||
|  | ||||
| @ -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; | ||||
| } | ||||
| 
 | ||||
|  | ||||
| @ -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); | ||||
|  | ||||
| @ -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); | ||||
|  | ||||
| @ -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); | ||||
| } | ||||
|  | ||||
| @ -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 */ | ||||
|  | ||||
| @ -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; | ||||
| } | ||||
|  | ||||
| @ -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) | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user