Merge branch 'collectd-5.7'
[collectd.git] / src / fscache.c
1 /**
2  * collectd - src/fscache.c
3  * Copyright (C) 2009 Edward "Koko" Konetzko
4  *
5  * This program is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License as published by the
7  * Free Software Foundation; only version 2 of the License is applicable.
8  *
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License along
15  * with this program; if not, write to the Free Software Foundation, Inc.,
16  * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
17  *
18  * Authors:
19  *   Edward "Koko" Konetzko <konetzed at quixoticagony.com>
20  **/
21
22 #include "collectd.h"
23
24 #include <stdio.h>  /* a header needed for FILE */
25 #include <stdlib.h> /* used for atoi */
26 #include <string.h> /* a header needed for scanf function */
27 #include "common.h"
28 #include "plugin.h"
29
30 #if !KERNEL_LINUX
31 #error "This module only supports the Linux implementation of fscache"
32 #endif
33
34 #define BUFSIZE 1024
35
36 /*
37 see /proc/fs/fscache/stats
38 see Documentation/filesystems/caching/fscache.txt in linux kernel >= 2.6.30
39
40 This shows counts of a number of events that can happen in FS-Cache:
41
42 CLASS   EVENT   MEANING
43 ======= ======= =======================================================
44 Cookies idx=N   Number of index cookies allocated
45         dat=N   Number of data storage cookies allocated
46         spc=N   Number of special cookies allocated
47 Objects alc=N   Number of objects allocated
48         nal=N   Number of object allocation failures
49         avl=N   Number of objects that reached the available state
50         ded=N   Number of objects that reached the dead state
51 ChkAux  non=N   Number of objects that didn't have a coherency check
52         ok=N    Number of objects that passed a coherency check
53         upd=N   Number of objects that needed a coherency data update
54         obs=N   Number of objects that were declared obsolete
55 Pages   mrk=N   Number of pages marked as being cached
56         unc=N   Number of uncache page requests seen
57 Acquire n=N Number of acquire cookie requests seen
58         nul=N   Number of acq reqs given a NULL parent
59         noc=N   Number of acq reqs rejected due to no cache available
60         ok=N    Number of acq reqs succeeded
61         nbf=N   Number of acq reqs rejected due to error
62         oom=N   Number of acq reqs failed on ENOMEM
63 Lookups n=N Number of lookup calls made on cache backends
64         neg=N   Number of negative lookups made
65         pos=N   Number of positive lookups made
66         crt=N   Number of objects created by lookup
67 Updates n=N Number of update cookie requests seen
68         nul=N   Number of upd reqs given a NULL parent
69         run=N   Number of upd reqs granted CPU time
70 Relinqs n=N Number of relinquish cookie requests seen
71         nul=N   Number of rlq reqs given a NULL parent
72         wcr=N   Number of rlq reqs waited on completion of creation
73 AttrChg n=N Number of attribute changed requests seen
74         ok=N    Number of attr changed requests queued
75         nbf=N   Number of attr changed rejected -ENOBUFS
76         oom=N   Number of attr changed failed -ENOMEM
77         run=N   Number of attr changed ops given CPU time
78 Allocs  n=N Number of allocation requests seen
79         ok=N    Number of successful alloc reqs
80         wt=N    Number of alloc reqs that waited on lookup completion
81         nbf=N   Number of alloc reqs rejected -ENOBUFS
82         ops=N   Number of alloc reqs submitted
83         owt=N   Number of alloc reqs waited for CPU time
84 Retrvls n=N Number of retrieval (read) requests seen
85         ok=N    Number of successful retr reqs
86         wt=N    Number of retr reqs that waited on lookup completion
87         nod=N   Number of retr reqs returned -ENODATA
88         nbf=N   Number of retr reqs rejected -ENOBUFS
89         int=N   Number of retr reqs aborted -ERESTARTSYS
90         oom=N   Number of retr reqs failed -ENOMEM
91         ops=N   Number of retr reqs submitted
92         owt=N   Number of retr reqs waited for CPU time
93 Stores  n=N Number of storage (write) requests seen
94         ok=N    Number of successful store reqs
95         agn=N   Number of store reqs on a page already pending storage
96         nbf=N   Number of store reqs rejected -ENOBUFS
97         oom=N   Number of store reqs failed -ENOMEM
98         ops=N   Number of store reqs submitted
99         run=N   Number of store reqs granted CPU time
100 Ops pend=N  Number of times async ops added to pending queues
101         run=N   Number of times async ops given CPU time
102         enq=N   Number of times async ops queued for processing
103         dfr=N   Number of async ops queued for deferred release
104         rel=N   Number of async ops released
105         gc=N    Number of deferred-release async ops garbage collected
106
107 63 events to collect in 13 groups
108 */
109 static void fscache_submit(const char *section, const char *name,
110                            value_t value) {
111   value_list_t vl = VALUE_LIST_INIT;
112
113   vl.values = &value;
114   vl.values_len = 1;
115
116   sstrncpy(vl.plugin, "fscache", sizeof(vl.plugin));
117   sstrncpy(vl.plugin_instance, section, sizeof(vl.plugin_instance));
118   sstrncpy(vl.type, "fscache_stat", sizeof(vl.type));
119   sstrncpy(vl.type_instance, name, sizeof(vl.type_instance));
120
121   plugin_dispatch_values(&vl);
122 }
123
124 static void fscache_read_stats_file(FILE *fh) {
125   char section[DATA_MAX_NAME_LEN];
126   size_t section_len;
127
128   char linebuffer[BUFSIZE];
129
130   /*
131    *  cat /proc/fs/fscache/stats
132    *      FS-Cache statistics
133    *      Cookies: idx=2 dat=0 spc=0
134    *      Objects: alc=0 nal=0 avl=0 ded=0
135    *      ChkAux : non=0 ok=0 upd=0 obs=0
136    *      Pages  : mrk=0 unc=0
137    *      Acquire: n=2 nul=0 noc=0 ok=2 nbf=0 oom=0
138    *      Lookups: n=0 neg=0 pos=0 crt=0
139    *      Updates: n=0 nul=0 run=0
140    *      Relinqs: n=0 nul=0 wcr=0
141    *      AttrChg: n=0 ok=0 nbf=0 oom=0 run=0
142    *      Allocs : n=0 ok=0 wt=0 nbf=0
143    *      Allocs : ops=0 owt=0
144    *      Retrvls: n=0 ok=0 wt=0 nod=0 nbf=0 int=0 oom=0
145    *      Retrvls: ops=0 owt=0
146    *      Stores : n=0 ok=0 agn=0 nbf=0 oom=0
147    *      Stores : ops=0 run=0
148    *      Ops    : pend=0 run=0 enq=0
149    *      Ops    : dfr=0 rel=0 gc=0
150    */
151
152   /* Read file line by line */
153   while (fgets(linebuffer, sizeof(linebuffer), fh) != NULL) {
154     char *lineptr;
155     char *fields[32];
156     int fields_num;
157
158     /* Find the colon and replace it with a null byte */
159     lineptr = strchr(linebuffer, ':');
160     if (lineptr == NULL)
161       continue;
162     *lineptr = 0;
163     lineptr++;
164
165     /* Copy and clean up the section name */
166     sstrncpy(section, linebuffer, sizeof(section));
167     section_len = strlen(section);
168     while ((section_len > 0) && isspace((int)section[section_len - 1])) {
169       section_len--;
170       section[section_len] = 0;
171     }
172     if (section_len == 0)
173       continue;
174
175     fields_num = strsplit(lineptr, fields, STATIC_ARRAY_SIZE(fields));
176     if (fields_num <= 0)
177       continue;
178
179     for (int i = 0; i < fields_num; i++) {
180       char *field_name;
181       char *field_value_str;
182       value_t field_value_cnt;
183       int status;
184
185       field_name = fields[i];
186       assert(field_name != NULL);
187
188       field_value_str = strchr(field_name, '=');
189       if (field_value_str == NULL)
190         continue;
191       *field_value_str = 0;
192       field_value_str++;
193
194       status = parse_value(field_value_str, &field_value_cnt, DS_TYPE_DERIVE);
195       if (status != 0)
196         continue;
197
198       fscache_submit(section, field_name, field_value_cnt);
199     }
200   } /* while (fgets) */
201 } /* void fscache_read_stats_file */
202
203 static int fscache_read(void) {
204   FILE *fh;
205   fh = fopen("/proc/fs/fscache/stats", "r");
206   if (fh != NULL) {
207     fscache_read_stats_file(fh);
208     fclose(fh);
209
210   } else {
211     printf("cant open file\n");
212     return (-1);
213   }
214   return (0);
215 }
216
217 void module_register(void) {
218   plugin_register_read("fscache", fscache_read);
219 } /* void module_register */