]>
Commit | Line | Data |
---|---|---|
9ae326a6 DH |
1 | /* CacheFiles statistics |
2 | * | |
3 | * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved. | |
4 | * Written by David Howells (dhowells@redhat.com) | |
5 | * | |
6 | * This program is free software; you can redistribute it and/or | |
7 | * modify it under the terms of the GNU General Public Licence | |
8 | * as published by the Free Software Foundation; either version | |
9 | * 2 of the Licence, or (at your option) any later version. | |
10 | */ | |
11 | ||
12 | #include <linux/module.h> | |
13 | #include <linux/proc_fs.h> | |
14 | #include <linux/seq_file.h> | |
15 | #include "internal.h" | |
16 | ||
17 | atomic_t cachefiles_lookup_histogram[HZ]; | |
18 | atomic_t cachefiles_mkdir_histogram[HZ]; | |
19 | atomic_t cachefiles_create_histogram[HZ]; | |
20 | ||
21 | /* | |
22 | * display the latency histogram | |
23 | */ | |
24 | static int cachefiles_histogram_show(struct seq_file *m, void *v) | |
25 | { | |
26 | unsigned long index; | |
27 | unsigned x, y, z, t; | |
28 | ||
29 | switch ((unsigned long) v) { | |
30 | case 1: | |
31 | seq_puts(m, "JIFS SECS LOOKUPS MKDIRS CREATES\n"); | |
32 | return 0; | |
33 | case 2: | |
34 | seq_puts(m, "===== ===== ========= ========= =========\n"); | |
35 | return 0; | |
36 | default: | |
37 | index = (unsigned long) v - 3; | |
38 | x = atomic_read(&cachefiles_lookup_histogram[index]); | |
39 | y = atomic_read(&cachefiles_mkdir_histogram[index]); | |
40 | z = atomic_read(&cachefiles_create_histogram[index]); | |
41 | if (x == 0 && y == 0 && z == 0) | |
42 | return 0; | |
43 | ||
44 | t = (index * 1000) / HZ; | |
45 | ||
46 | seq_printf(m, "%4lu 0.%03u %9u %9u %9u\n", index, t, x, y, z); | |
47 | return 0; | |
48 | } | |
49 | } | |
50 | ||
51 | /* | |
52 | * set up the iterator to start reading from the first line | |
53 | */ | |
54 | static void *cachefiles_histogram_start(struct seq_file *m, loff_t *_pos) | |
55 | { | |
56 | if ((unsigned long long)*_pos >= HZ + 2) | |
57 | return NULL; | |
58 | if (*_pos == 0) | |
59 | *_pos = 1; | |
60 | return (void *)(unsigned long) *_pos; | |
61 | } | |
62 | ||
63 | /* | |
64 | * move to the next line | |
65 | */ | |
66 | static void *cachefiles_histogram_next(struct seq_file *m, void *v, loff_t *pos) | |
67 | { | |
68 | (*pos)++; | |
69 | return (unsigned long long)*pos > HZ + 2 ? | |
70 | NULL : (void *)(unsigned long) *pos; | |
71 | } | |
72 | ||
73 | /* | |
74 | * clean up after reading | |
75 | */ | |
76 | static void cachefiles_histogram_stop(struct seq_file *m, void *v) | |
77 | { | |
78 | } | |
79 | ||
80 | static const struct seq_operations cachefiles_histogram_ops = { | |
81 | .start = cachefiles_histogram_start, | |
82 | .stop = cachefiles_histogram_stop, | |
83 | .next = cachefiles_histogram_next, | |
84 | .show = cachefiles_histogram_show, | |
85 | }; | |
86 | ||
87 | /* | |
88 | * open "/proc/fs/cachefiles/XXX" which provide statistics summaries | |
89 | */ | |
90 | static int cachefiles_histogram_open(struct inode *inode, struct file *file) | |
91 | { | |
92 | return seq_open(file, &cachefiles_histogram_ops); | |
93 | } | |
94 | ||
95 | static const struct file_operations cachefiles_histogram_fops = { | |
96 | .owner = THIS_MODULE, | |
97 | .open = cachefiles_histogram_open, | |
98 | .read = seq_read, | |
99 | .llseek = seq_lseek, | |
100 | .release = seq_release, | |
101 | }; | |
102 | ||
103 | /* | |
104 | * initialise the /proc/fs/cachefiles/ directory | |
105 | */ | |
106 | int __init cachefiles_proc_init(void) | |
107 | { | |
108 | _enter(""); | |
109 | ||
110 | if (!proc_mkdir("fs/cachefiles", NULL)) | |
111 | goto error_dir; | |
112 | ||
113 | if (!proc_create("fs/cachefiles/histogram", S_IFREG | 0444, NULL, | |
114 | &cachefiles_histogram_fops)) | |
115 | goto error_histogram; | |
116 | ||
117 | _leave(" = 0"); | |
118 | return 0; | |
119 | ||
120 | error_histogram: | |
121 | remove_proc_entry("fs/cachefiles", NULL); | |
122 | error_dir: | |
123 | _leave(" = -ENOMEM"); | |
124 | return -ENOMEM; | |
125 | } | |
126 | ||
127 | /* | |
128 | * clean up the /proc/fs/cachefiles/ directory | |
129 | */ | |
130 | void cachefiles_proc_cleanup(void) | |
131 | { | |
132 | remove_proc_entry("fs/cachefiles/histogram", NULL); | |
133 | remove_proc_entry("fs/cachefiles", NULL); | |
134 | } |