proc.c 2.5 KB

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