18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/* CacheFiles statistics 38c2ecf20Sopenharmony_ci * 48c2ecf20Sopenharmony_ci * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved. 58c2ecf20Sopenharmony_ci * Written by David Howells (dhowells@redhat.com) 68c2ecf20Sopenharmony_ci */ 78c2ecf20Sopenharmony_ci 88c2ecf20Sopenharmony_ci#include <linux/module.h> 98c2ecf20Sopenharmony_ci#include <linux/proc_fs.h> 108c2ecf20Sopenharmony_ci#include <linux/seq_file.h> 118c2ecf20Sopenharmony_ci#include "internal.h" 128c2ecf20Sopenharmony_ci 138c2ecf20Sopenharmony_ciatomic_t cachefiles_lookup_histogram[HZ]; 148c2ecf20Sopenharmony_ciatomic_t cachefiles_mkdir_histogram[HZ]; 158c2ecf20Sopenharmony_ciatomic_t cachefiles_create_histogram[HZ]; 168c2ecf20Sopenharmony_ci 178c2ecf20Sopenharmony_ci/* 188c2ecf20Sopenharmony_ci * display the latency histogram 198c2ecf20Sopenharmony_ci */ 208c2ecf20Sopenharmony_cistatic int cachefiles_histogram_show(struct seq_file *m, void *v) 218c2ecf20Sopenharmony_ci{ 228c2ecf20Sopenharmony_ci unsigned long index; 238c2ecf20Sopenharmony_ci unsigned x, y, z, t; 248c2ecf20Sopenharmony_ci 258c2ecf20Sopenharmony_ci switch ((unsigned long) v) { 268c2ecf20Sopenharmony_ci case 1: 278c2ecf20Sopenharmony_ci seq_puts(m, "JIFS SECS LOOKUPS MKDIRS CREATES\n"); 288c2ecf20Sopenharmony_ci return 0; 298c2ecf20Sopenharmony_ci case 2: 308c2ecf20Sopenharmony_ci seq_puts(m, "===== ===== ========= ========= =========\n"); 318c2ecf20Sopenharmony_ci return 0; 328c2ecf20Sopenharmony_ci default: 338c2ecf20Sopenharmony_ci index = (unsigned long) v - 3; 348c2ecf20Sopenharmony_ci x = atomic_read(&cachefiles_lookup_histogram[index]); 358c2ecf20Sopenharmony_ci y = atomic_read(&cachefiles_mkdir_histogram[index]); 368c2ecf20Sopenharmony_ci z = atomic_read(&cachefiles_create_histogram[index]); 378c2ecf20Sopenharmony_ci if (x == 0 && y == 0 && z == 0) 388c2ecf20Sopenharmony_ci return 0; 398c2ecf20Sopenharmony_ci 408c2ecf20Sopenharmony_ci t = (index * 1000) / HZ; 418c2ecf20Sopenharmony_ci 428c2ecf20Sopenharmony_ci seq_printf(m, "%4lu 0.%03u %9u %9u %9u\n", index, t, x, y, z); 438c2ecf20Sopenharmony_ci return 0; 448c2ecf20Sopenharmony_ci } 458c2ecf20Sopenharmony_ci} 468c2ecf20Sopenharmony_ci 478c2ecf20Sopenharmony_ci/* 488c2ecf20Sopenharmony_ci * set up the iterator to start reading from the first line 498c2ecf20Sopenharmony_ci */ 508c2ecf20Sopenharmony_cistatic void *cachefiles_histogram_start(struct seq_file *m, loff_t *_pos) 518c2ecf20Sopenharmony_ci{ 528c2ecf20Sopenharmony_ci if ((unsigned long long)*_pos >= HZ + 2) 538c2ecf20Sopenharmony_ci return NULL; 548c2ecf20Sopenharmony_ci if (*_pos == 0) 558c2ecf20Sopenharmony_ci *_pos = 1; 568c2ecf20Sopenharmony_ci return (void *)(unsigned long) *_pos; 578c2ecf20Sopenharmony_ci} 588c2ecf20Sopenharmony_ci 598c2ecf20Sopenharmony_ci/* 608c2ecf20Sopenharmony_ci * move to the next line 618c2ecf20Sopenharmony_ci */ 628c2ecf20Sopenharmony_cistatic void *cachefiles_histogram_next(struct seq_file *m, void *v, loff_t *pos) 638c2ecf20Sopenharmony_ci{ 648c2ecf20Sopenharmony_ci (*pos)++; 658c2ecf20Sopenharmony_ci return (unsigned long long)*pos > HZ + 2 ? 668c2ecf20Sopenharmony_ci NULL : (void *)(unsigned long) *pos; 678c2ecf20Sopenharmony_ci} 688c2ecf20Sopenharmony_ci 698c2ecf20Sopenharmony_ci/* 708c2ecf20Sopenharmony_ci * clean up after reading 718c2ecf20Sopenharmony_ci */ 728c2ecf20Sopenharmony_cistatic void cachefiles_histogram_stop(struct seq_file *m, void *v) 738c2ecf20Sopenharmony_ci{ 748c2ecf20Sopenharmony_ci} 758c2ecf20Sopenharmony_ci 768c2ecf20Sopenharmony_cistatic const struct seq_operations cachefiles_histogram_ops = { 778c2ecf20Sopenharmony_ci .start = cachefiles_histogram_start, 788c2ecf20Sopenharmony_ci .stop = cachefiles_histogram_stop, 798c2ecf20Sopenharmony_ci .next = cachefiles_histogram_next, 808c2ecf20Sopenharmony_ci .show = cachefiles_histogram_show, 818c2ecf20Sopenharmony_ci}; 828c2ecf20Sopenharmony_ci 838c2ecf20Sopenharmony_ci/* 848c2ecf20Sopenharmony_ci * initialise the /proc/fs/cachefiles/ directory 858c2ecf20Sopenharmony_ci */ 868c2ecf20Sopenharmony_ciint __init cachefiles_proc_init(void) 878c2ecf20Sopenharmony_ci{ 888c2ecf20Sopenharmony_ci _enter(""); 898c2ecf20Sopenharmony_ci 908c2ecf20Sopenharmony_ci if (!proc_mkdir("fs/cachefiles", NULL)) 918c2ecf20Sopenharmony_ci goto error_dir; 928c2ecf20Sopenharmony_ci 938c2ecf20Sopenharmony_ci if (!proc_create_seq("fs/cachefiles/histogram", S_IFREG | 0444, NULL, 948c2ecf20Sopenharmony_ci &cachefiles_histogram_ops)) 958c2ecf20Sopenharmony_ci goto error_histogram; 968c2ecf20Sopenharmony_ci 978c2ecf20Sopenharmony_ci _leave(" = 0"); 988c2ecf20Sopenharmony_ci return 0; 998c2ecf20Sopenharmony_ci 1008c2ecf20Sopenharmony_cierror_histogram: 1018c2ecf20Sopenharmony_ci remove_proc_entry("fs/cachefiles", NULL); 1028c2ecf20Sopenharmony_cierror_dir: 1038c2ecf20Sopenharmony_ci _leave(" = -ENOMEM"); 1048c2ecf20Sopenharmony_ci return -ENOMEM; 1058c2ecf20Sopenharmony_ci} 1068c2ecf20Sopenharmony_ci 1078c2ecf20Sopenharmony_ci/* 1088c2ecf20Sopenharmony_ci * clean up the /proc/fs/cachefiles/ directory 1098c2ecf20Sopenharmony_ci */ 1108c2ecf20Sopenharmony_civoid cachefiles_proc_cleanup(void) 1118c2ecf20Sopenharmony_ci{ 1128c2ecf20Sopenharmony_ci remove_proc_entry("fs/cachefiles/histogram", NULL); 1138c2ecf20Sopenharmony_ci remove_proc_entry("fs/cachefiles", NULL); 1148c2ecf20Sopenharmony_ci} 115