linux/fs/cachefiles/proc.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/* CacheFiles statistics
   3 *
   4 * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
   5 * Written by David Howells (dhowells@redhat.com)
   6 */
   7
   8#include <linux/module.h>
   9#include <linux/proc_fs.h>
  10#include <linux/seq_file.h>
  11#include "internal.h"
  12
  13atomic_t cachefiles_lookup_histogram[HZ];
  14atomic_t cachefiles_mkdir_histogram[HZ];
  15atomic_t cachefiles_create_histogram[HZ];
  16
  17/*
  18 * display the latency histogram
  19 */
  20static int cachefiles_histogram_show(struct seq_file *m, void *v)
  21{
  22        unsigned long index;
  23        unsigned x, y, z, t;
  24
  25        switch ((unsigned long) v) {
  26        case 1:
  27                seq_puts(m, "JIFS  SECS  LOOKUPS   MKDIRS    CREATES\n");
  28                return 0;
  29        case 2:
  30                seq_puts(m, "===== ===== ========= ========= =========\n");
  31                return 0;
  32        default:
  33                index = (unsigned long) v - 3;
  34                x = atomic_read(&cachefiles_lookup_histogram[index]);
  35                y = atomic_read(&cachefiles_mkdir_histogram[index]);
  36                z = atomic_read(&cachefiles_create_histogram[index]);
  37                if (x == 0 && y == 0 && z == 0)
  38                        return 0;
  39
  40                t = (index * 1000) / HZ;
  41
  42                seq_printf(m, "%4lu  0.%03u %9u %9u %9u\n", index, t, x, y, z);
  43                return 0;
  44        }
  45}
  46
  47/*
  48 * set up the iterator to start reading from the first line
  49 */
  50static void *cachefiles_histogram_start(struct seq_file *m, loff_t *_pos)
  51{
  52        if ((unsigned long long)*_pos >= HZ + 2)
  53                return NULL;
  54        if (*_pos == 0)
  55                *_pos = 1;
  56        return (void *)(unsigned long) *_pos;
  57}
  58
  59/*
  60 * move to the next line
  61 */
  62static void *cachefiles_histogram_next(struct seq_file *m, void *v, loff_t *pos)
  63{
  64        (*pos)++;
  65        return (unsigned long long)*pos > HZ + 2 ?
  66                NULL : (void *)(unsigned long) *pos;
  67}
  68
  69/*
  70 * clean up after reading
  71 */
  72static void cachefiles_histogram_stop(struct seq_file *m, void *v)
  73{
  74}
  75
  76static const struct seq_operations cachefiles_histogram_ops = {
  77        .start          = cachefiles_histogram_start,
  78        .stop           = cachefiles_histogram_stop,
  79        .next           = cachefiles_histogram_next,
  80        .show           = cachefiles_histogram_show,
  81};
  82
  83/*
  84 * initialise the /proc/fs/cachefiles/ directory
  85 */
  86int __init cachefiles_proc_init(void)
  87{
  88        _enter("");
  89
  90        if (!proc_mkdir("fs/cachefiles", NULL))
  91                goto error_dir;
  92
  93        if (!proc_create_seq("fs/cachefiles/histogram", S_IFREG | 0444, NULL,
  94                         &cachefiles_histogram_ops))
  95                goto error_histogram;
  96
  97        _leave(" = 0");
  98        return 0;
  99
 100error_histogram:
 101        remove_proc_entry("fs/cachefiles", NULL);
 102error_dir:
 103        _leave(" = -ENOMEM");
 104        return -ENOMEM;
 105}
 106
 107/*
 108 * clean up the /proc/fs/cachefiles/ directory
 109 */
 110void cachefiles_proc_cleanup(void)
 111{
 112        remove_proc_entry("fs/cachefiles/histogram", NULL);
 113        remove_proc_entry("fs/cachefiles", NULL);
 114}
 115